Thread: Re: [HACKERS] Re: varchar() troubles (fwd)
Forwarded message: > > The problem was that some things were copied using VARSIZE rather than > > subtracting out VARHDRSZ first (actually, I think it might have use > > sizeof(int) and other dangers too). I patched that near the end of the year > > and my 980101.d tree and 980106.d tree do not exhibit the symptom: > > > > postgres=> create table t (v varchar(80),i int); > > CREATE > > postgres=> insert into t values ('hi', 1); > > INSERT 643562 1 > > postgres=> select * from t; > > v |i > > --+- > > hi|1 > > (1 row) > > I have found that ExecEvalVar() uses a descriptor that has the attr > length set to the maximum, instead of -1. The ExecTypeFromTL() comment > says: > > /* ---------------------------------------------------------------- > * ExecTypeFromTL > * > * Currently there are about 4 different places where we create > * TupleDescriptors. They should all be merged, or perhaps > * be rewritten to call BuildDesc(). > * > > Clearly stating that the tuple descriptors in the system are created in > several places. Some places have the length set wrong. I am going to > have to take a look at all those places, and make sure they have > consistent behaviour. Vadim, can you look at this for me. If you set a break at ExecEvalVar before executing the SELECT, you will see its tupledescriptor->attrs[0].attlen is the max length, and not -1 as it should be. I can't figure out where that is getting set. Can you also check the other tupledescriptor initializations to see they have the -1 for varchar too. I am stumped. -- Bruce Momjian maillist@candle.pha.pa.us
Bruce Momjian wrote: > > > > > I have found that ExecEvalVar() uses a descriptor that has the attr > > length set to the maximum, instead of -1. The ExecTypeFromTL() comment ... > > Vadim, can you look at this for me. If you set a break at ExecEvalVar > before executing the SELECT, you will see its > tupledescriptor->attrs[0].attlen is the max length, and not -1 as it > should be. > > I can't figure out where that is getting set. Can you also check the > other tupledescriptor initializations to see they have the -1 for > varchar too. I am stumped. Why attlen should be -1 ? attlen in pg_attribute for v in table t is 84, why run-time attlen should be -1 ? How else maxlen constraint could be checked ? IMHO, you have to change heap_getattr() to check is atttype == VARCHAROID and use vl_len if yes. Also, other places where attlen is used must be changed too - e.g. ExecEvalVar(): { len = tuple_type->attrs[attnum - 1]->attlen; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false; } execConstByVal = byval; execConstLen = len; ^^^^^^^^^^^^^^^^^^ - used in nodeHash.c Vadim
> > Bruce Momjian wrote: > > > > > > > > I have found that ExecEvalVar() uses a descriptor that has the attr > > > length set to the maximum, instead of -1. The ExecTypeFromTL() comment > ... > > > > Vadim, can you look at this for me. If you set a break at ExecEvalVar > > before executing the SELECT, you will see its > > tupledescriptor->attrs[0].attlen is the max length, and not -1 as it > > should be. > > > > I can't figure out where that is getting set. Can you also check the > > other tupledescriptor initializations to see they have the -1 for > > varchar too. I am stumped. > > Why attlen should be -1 ? > attlen in pg_attribute for v in table t is 84, why run-time attlen > should be -1 ? How else maxlen constraint could be checked ? > IMHO, you have to change heap_getattr() to check is atttype == VARCHAROID > and use vl_len if yes. Also, other places where attlen is used must be > changed too - e.g. ExecEvalVar(): > > { > len = tuple_type->attrs[attnum - 1]->attlen; > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false; > } > > execConstByVal = byval; > execConstLen = len; > ^^^^^^^^^^^^^^^^^^ - used in nodeHash.c > The major problem is that TupleDesc comes from several places, and attlen means several things. There are some cases where TupleDesc (int numatt, Attrs[]) is created on-the-fly (tupdesc.c), and the attlen is the length of the type. In other cases, we get attlen from opening the relation, heap_open(), and in these cases it is the length as defined for the particular attribute. Certainly a bad situation. I am not sure about a fix. -- Bruce Momjian maillist@candle.pha.pa.us