diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-06-05 01:55:05 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-06-05 01:55:05 +0000 |
commit | ae93e5fd6e8a7e2321e87d23165d9d7660cde598 (patch) | |
tree | a8e22c4835283c61e137285ba2dabfe3feead1a9 /src/backend/access/common/heaptuple.c | |
parent | 8f2ea8b7b53a02078ba0393e6892ac5356a3631e (diff) | |
download | postgresql-ae93e5fd6e8a7e2321e87d23165d9d7660cde598.tar.gz postgresql-ae93e5fd6e8a7e2321e87d23165d9d7660cde598.zip |
Make the world very nearly safe for composite-type columns in tables.
1. Solve the problem of not having TOAST references hiding inside composite
values by establishing the rule that toasting only goes one level deep:
a tuple can contain toasted fields, but a composite-type datum that is
to be inserted into a tuple cannot. Enforcing this in heap_formtuple
is relatively cheap and it avoids a large increase in the cost of running
the tuptoaster during final storage of a row.
2. Fix some interesting problems in expansion of inherited queries that
reference whole-row variables. We never really did this correctly before,
but it's now relatively painless to solve by expanding the parent's
whole-row Var into a RowExpr() selecting the proper columns from the
child.
If you dike out the preventive check in CheckAttributeType(),
composite-type columns now seem to actually work. However, we surely
cannot ship them like this --- without I/O for composite types, you
can't get pg_dump to dump tables containing them. So a little more
work still to do.
Diffstat (limited to 'src/backend/access/common/heaptuple.c')
-rw-r--r-- | src/backend/access/common/heaptuple.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 266cf3bdcc2..88a9631e8cc 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.91 2004/06/04 20:35:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.92 2004/06/05 01:55:04 tgl Exp $ * * NOTES * The old interface functions have been converted to macros @@ -21,6 +21,7 @@ #include "postgres.h" #include "access/heapam.h" +#include "access/tuptoaster.h" #include "catalog/pg_type.h" @@ -567,8 +568,9 @@ heap_formtuple(TupleDesc tupleDescriptor, unsigned long len; int hoff; bool hasnull = false; - int i; + Form_pg_attribute *att = tupleDescriptor->attrs; int numberOfAttributes = tupleDescriptor->natts; + int i; if (numberOfAttributes > MaxTupleAttributeNumber) ereport(ERROR, @@ -577,17 +579,34 @@ heap_formtuple(TupleDesc tupleDescriptor, numberOfAttributes, MaxTupleAttributeNumber))); /* - * Determine total space needed + * Check for nulls and embedded tuples; expand any toasted attributes + * in embedded tuples. This preserves the invariant that toasting can + * only go one level deep. + * + * We can skip calling toast_flatten_tuple_attribute() if the attribute + * couldn't possibly be of composite type. All composite datums are + * varlena and have alignment 'd'; furthermore they aren't arrays. + * Also, if an attribute is already toasted, it must have been sent to + * disk already and so cannot contain toasted attributes. */ for (i = 0; i < numberOfAttributes; i++) { if (nulls[i] != ' ') - { hasnull = true; - break; + else if (att[i]->attlen == -1 && + att[i]->attalign == 'd' && + att[i]->attndims == 0 && + !VARATT_IS_EXTENDED(values[i])) + { + values[i] = toast_flatten_tuple_attribute(values[i], + att[i]->atttypid, + att[i]->atttypmod); } } + /* + * Determine total space needed + */ len = offsetof(HeapTupleHeaderData, t_bits); if (hasnull) @@ -744,7 +763,11 @@ heap_deformtuple(HeapTuple tuple, bool slow = false; /* can we use/set attcacheoff? */ natts = tup->t_natts; - /* This min() operation is pure paranoia */ + /* + * In inheritance situations, it is possible that the given tuple actually + * has more fields than the caller is expecting. Don't run off the end + * of the caller's arrays. + */ natts = Min(natts, tdesc_natts); tp = (char *) tup + tup->t_hoff; |