Re: [HACKERS] Re: varchar() troubles (fwd)
От | Bruce Momjian |
---|---|
Тема | Re: [HACKERS] Re: varchar() troubles (fwd) |
Дата | |
Msg-id | 199801160505.AAA06221@candle.pha.pa.us обсуждение исходный текст |
Список | pgsql-hackers |
Forwarded message: > > 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. OK, here is a temporary fix to the problem. It does the heap_open(), then replaces the attrs for VARCHAR with attlen of -1. You can't just change the field, because the data is in a cache and you are just returned a pointer. Can I add an 'attdeflen' for "attributed defined length" field to pg_attribute, and change the attlen references needed to the new field? This is the only proper way to fix it. --------------------------------------------------------------------------- *** ./backend/executor/execAmi.c.orig Thu Jan 15 22:42:13 1998 --- ./backend/executor/execAmi.c Thu Jan 15 23:54:37 1998 *************** *** 42,47 **** --- 42,48 ---- #include "access/genam.h" #include "access/heapam.h" #include "catalog/heap.h" + #include "catalog/pg_type.h" static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys, *************** *** 124,129 **** --- 125,155 ---- if (relation == NULL) elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed."); + { + int i; + Relation trel = palloc(sizeof(RelationData)); + TupleDesc tdesc = palloc(sizeof(struct tupleDesc)); + AttributeTupleForm *tatt = + palloc(sizeof(AttributeTupleForm*)*relation->rd_att->natts); + + memcpy(trel, relation, sizeof(RelationData)); + memcpy(tdesc, relation->rd_att, sizeof(struct tupleDesc)); + trel->rd_att = tdesc; + tdesc->attrs = tatt; + + for (i = 0; i < relation->rd_att->natts; i++) + { + if (relation->rd_att->attrs[i]->atttypid != VARCHAROID) + tdesc->attrs[i] = relation->rd_att->attrs[i]; + else + { + tdesc->attrs[i] = palloc(sizeof(FormData_pg_attribute)); + memcpy(tdesc->attrs[i], relation->rd_att->attrs[i], + sizeof(FormData_pg_attribute)); + tdesc->attrs[i]->attlen = -1; + } + } + } return relation; } -- Bruce Momjian maillist@candle.pha.pa.us
В списке pgsql-hackers по дате отправления: