From 57d8080a40f51e1ff9eedea602e96e2612161d77 Mon Sep 17 00:00:00 2001 From: Jan Wieck Date: Mon, 3 Jul 2000 23:10:14 +0000 Subject: [PATCH] TOAST WARNING: This is actually broken - we have self-deadlocks due to concurrent changes in buffer management. Vadim and me are working on it. Jan --- src/backend/access/common/heaptuple.c | 10 +- src/backend/access/common/tupdesc.c | 13 +- src/backend/access/gist/gist.c | 6 +- src/backend/access/heap/heapam.c | 38 +- src/backend/access/heap/tuptoaster.c | 974 +++++++++++++++++++++++++- src/backend/bootstrap/bootstrap.c | 4 +- src/backend/catalog/heap.c | 25 +- src/backend/catalog/pg_type.c | 16 +- src/backend/commands/command.c | 158 ++++- src/backend/commands/define.c | 30 +- src/backend/libpq/be-fsstubs.c | 4 +- src/backend/parser/gram.y | 13 +- src/backend/parser/keywords.c | 5 +- src/backend/tcop/fastpath.c | 4 +- src/backend/tcop/utility.c | 5 +- src/backend/utils/adt/arrayfuncs.c | 6 +- src/backend/utils/adt/cash.c | 4 +- src/backend/utils/adt/char.c | 4 +- src/backend/utils/adt/float.c | 6 +- src/backend/utils/adt/formatting.c | 6 +- src/backend/utils/adt/int.c | 6 +- src/backend/utils/adt/int8.c | 4 +- src/backend/utils/adt/lztext.c | 184 ++--- src/backend/utils/adt/mac.c | 6 +- src/backend/utils/adt/nabstime.c | 4 +- src/backend/utils/adt/network.c | 12 +- src/backend/utils/adt/oid.c | 4 +- src/backend/utils/adt/oracle_compat.c | 24 +- src/backend/utils/adt/pg_lzcompress.c | 14 +- src/backend/utils/adt/regproc.c | 4 +- src/backend/utils/adt/ruleutils.c | 10 +- src/backend/utils/adt/timestamp.c | 8 +- src/backend/utils/adt/varbit.c | 24 +- src/backend/utils/adt/varchar.c | 14 +- src/backend/utils/adt/varlena.c | 10 +- src/backend/utils/adt/version.c | 4 +- src/include/access/tuptoaster.h | 16 +- src/include/catalog/pg_attribute.h | 66 +- src/include/catalog/pg_class.h | 66 +- src/include/catalog/pg_type.h | 226 +++--- src/include/commands/command.h | 4 +- src/include/postgres.h | 33 +- src/include/utils/lztext.h | 9 +- 43 files changed, 1638 insertions(+), 445 deletions(-) diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index f93bf34db9..319cfff7ca 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.63 2000/07/02 22:00:24 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.64 2000/07/03 23:09:10 wieck Exp $ * * NOTES * The old interface functions have been converted to macros @@ -119,7 +119,11 @@ DataFill(char *data, { case -1: *infomask |= HEAP_HASVARLENA; - data_length = VARSIZE(DatumGetPointer(value[i])); + if (VARATT_IS_EXTERNAL(value[i])) + *infomask |= HEAP_HASEXTERNAL; + if (VARATT_IS_COMPRESSED(value[i])) + *infomask |= HEAP_HASCOMPRESSED; + data_length = VARATT_SIZE(DatumGetPointer(value[i])); memmove(data, DatumGetPointer(value[i]), data_length); break; case sizeof(char): @@ -816,7 +820,7 @@ heap_freetuple(HeapTuple htup) if (htup->t_data != NULL) if (htup->t_datamcxt != NULL && (char *) (htup->t_data) != ((char *) htup + HEAPTUPLESIZE)) - elog(NOTICE, "TELL Jan Wieck: heap_freetuple() found separate t_data"); + pfree(htup->t_data); pfree(htup); } diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 433bbe6b06..c878c50e0a 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.65 2000/05/30 00:49:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.66 2000/07/03 23:09:10 wieck Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -434,23 +434,16 @@ TupleDescInitEntry(TupleDesc desc, att->attlen = typeLen(t); att->attbyval = typeByVal(t); - att->attstorage = 'p'; } else { att->attlen = typeForm->typlen; att->attbyval = typeForm->typbyval; /* - * This will enable ALL variable size attributes of user - * relations for automatic move off into "secondary" relation. - * Jan + * Default to the types storage */ #ifdef TUPLE_TOASTER_ACTIVE -#ifdef TUPLE_TOASTER_ALL_TYPES - att->attstorage = (att->attlen == -1) ? 'e' : 'p'; -#else - att->attstorage = 'p'; -#endif + att->attstorage = typeForm->typstorage; #else att->attstorage = 'p'; #endif diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 4bf737dcd3..794685da2e 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.59 2000/06/17 23:41:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.60 2000/07/03 23:09:11 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -546,7 +546,7 @@ gistAdjustKeys(Relation r, oldud += sizeof(IndexTupleData); evec = (bytea *) palloc(2 * sizeof(GISTENTRY) + VARHDRSZ); - VARSIZE(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ; + VARATT_SIZEP(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ; /* insert decompressed oldud into entry vector */ gistdentryinit(giststate, &((GISTENTRY *) VARDATA(evec))[0], @@ -741,7 +741,7 @@ gistSplit(Relation r, else decompvec[maxoff + 1] = FALSE; - VARSIZE(entryvec) = (maxoff + 2) * sizeof(GISTENTRY) + VARHDRSZ; + VARATT_SIZEP(entryvec) = (maxoff + 2) * sizeof(GISTENTRY) + VARHDRSZ; /* now let the user-defined picksplit function set up the split vector */ FunctionCall2(&giststate->picksplitFn, diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 9f3a7ac714..1ece416e87 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.75 2000/07/03 02:54:15 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.76 2000/07/03 23:09:16 wieck Exp $ * * * INTERFACE ROUTINES @@ -1299,6 +1299,17 @@ heap_insert(Relation relation, HeapTuple tup) tup->t_data->t_infomask &= ~(HEAP_XACT_MASK); tup->t_data->t_infomask |= HEAP_XMAX_INVALID; +#ifdef TUPLE_TOASTER_ACTIVE + /* ---------- + * If the new tuple is too big for storage or contains already + * toasted attributes from some other relation, invoke the toaster. + * ---------- + */ + if (HeapTupleHasExtended(tup) || + (MAXALIGN(tup->t_len) > (MaxTupleSize / 4))) + heap_tuple_toast_attrs(relation, tup, NULL); +#endif + /* Find buffer for this tuple */ buffer = RelationGetBufferForTuple(relation, tup->t_len, InvalidBuffer); @@ -1328,8 +1339,8 @@ heap_insert(Relation relation, HeapTuple tup) } #endif - LockBuffer(buffer, BUFFER_LOCK_UNLOCK); WriteBuffer(buffer); + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); if (IsSystemRelationName(RelationGetRelationName(relation))) RelationMark4RollbackHeapTuple(relation, tup); @@ -1441,6 +1452,16 @@ l1: tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); +#ifdef TUPLE_TOASTER_ACTIVE + /* ---------- + * If the relation has toastable attributes, we need to delete + * no longer needed items there too. + * ---------- + */ + if (HeapTupleHasExtended(&tp)) + heap_tuple_toast_attrs(relation, NULL, &(tp)); +#endif + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); /* invalidate caches */ @@ -1559,6 +1580,19 @@ l2: oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); +#ifdef TUPLE_TOASTER_ACTIVE + /* ---------- + * If this relation is enabled for toasting, let the toaster + * delete not any longer needed entries and create new ones to + * make the new tuple fit again. + * ---------- + */ + if (HeapTupleHasExtended(&oldtup) || + HeapTupleHasExtended(newtup) || + (MAXALIGN(newtup->t_len) > (MaxTupleSize / 4))) + heap_tuple_toast_attrs(relation, newtup, &oldtup); +#endif + /* record address of new tuple in t_ctid of old one */ oldtup.t_data->t_ctid = newtup->t_self; diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 0af5db0caf..3221ed5b13 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.4 2000/05/30 00:49:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.5 2000/07/03 23:09:19 wieck Exp $ * * * INTERFACE ROUTINES @@ -16,26 +16,992 @@ * Try to make a given tuple fit into one page by compressing * or moving off attributes * + * heap_tuple_untoast_attr - + * Fetch back a given value from the "secondary" relation + * *------------------------------------------------------------------------- */ +#include +#include +#include +#include #include "postgres.h" +#include "access/heapam.h" +#include "access/genam.h" +#include "access/tuptoaster.h" +#include "catalog/catalog.h" +#include "utils/rel.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/pg_lzcompress.h" #ifdef TUPLE_TOASTER_ACTIVE +#undef TOAST_DEBUG +static void toast_delete(Relation rel, HeapTuple oldtup); +static void toast_delete_datum(Relation rel, Datum value); +static void toast_insert_or_update(Relation rel, HeapTuple newtup, + HeapTuple oldtup); +static Datum toast_compress_datum(Datum value); +static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value); + +static varattrib *toast_fetch_datum(varattrib *attr); + + +/* ---------- + * heap_tuple_toast_attrs - + * + * This is the central public entry point for toasting from heapam. + * + * Calls the appropriate event specific action. + * ---------- + */ void heap_tuple_toast_attrs(Relation rel, HeapTuple newtup, HeapTuple oldtup) { + if (newtup == NULL) + toast_delete(rel, oldtup); + else + toast_insert_or_update(rel, newtup, oldtup); +} + + +/* ---------- + * heap_tuple_untoast_attr - + * + * Public entry point to get back a toasted value from compression + * or external storage. + * ---------- + */ +varattrib * +heap_tuple_untoast_attr(varattrib *attr) +{ + varattrib *result; + + if (VARATT_IS_EXTERNAL(attr)) + { + if (VARATT_IS_COMPRESSED(attr)) + { + /* ---------- + * This is an external stored compressed value + * Fetch it from the toast heap and decompress. + * ---------- + */ + varattrib *tmp; + + tmp = toast_fetch_datum(attr); + result = (varattrib *)palloc(attr->va_content.va_external.va_rawsize + + VARHDRSZ); + VARATT_SIZEP(result) = attr->va_content.va_external.va_rawsize + + VARHDRSZ; + pglz_decompress((PGLZ_Header *)tmp, VARATT_DATA(result)); + + pfree(tmp); + } + else + { + /* ---------- + * This is an external stored plain value + * ---------- + */ + result = toast_fetch_datum(attr); + } + } + else if (VARATT_IS_COMPRESSED(attr)) + { + /* ---------- + * This is a compressed value inside of the main tuple + * ---------- + */ + result = (varattrib *)palloc(attr->va_content.va_compressed.va_rawsize + + VARHDRSZ); + VARATT_SIZEP(result) = attr->va_content.va_compressed.va_rawsize + + VARHDRSZ; + pglz_decompress((PGLZ_Header *)attr, VARATT_DATA(result)); + } + else + /* ---------- + * This is a plain value inside of the main tuple - why am I called? + * ---------- + */ + return attr; + + return result; +} + + +/* ---------- + * toast_delete - + * + * Cascaded delete toast-entries on DELETE + * ---------- + */ +static void +toast_delete(Relation rel, HeapTuple oldtup) +{ + TupleDesc tupleDesc; + Form_pg_attribute *att; + int numAttrs; + int i; + Datum value; + bool isnull; + + /* ---------- + * Get the tuple descriptor, the number of and attribute + * descriptors. + * ---------- + */ + tupleDesc = rel->rd_att; + numAttrs = tupleDesc->natts; + att = tupleDesc->attrs; + + /* ---------- + * Check for external stored attributes and delete them + * from the secondary relation. + * ---------- + */ + for (i = 0; i < numAttrs; i++) + { + value = heap_getattr(oldtup, i + 1, tupleDesc, &isnull); + if (!isnull && att[i]->attlen == -1) + if (VARATT_IS_EXTERNAL(value)) + toast_delete_datum(rel, value); + } +} + + +/* ---------- + * toast_insert_or_update - + * + * Delete no more used toast-entries and create new ones to + * make the new tuple fit on INSERT or UPDATE + * ---------- + */ +static void +toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) +{ + TupleDesc tupleDesc; + Form_pg_attribute *att; + int numAttrs; + int i; + bool old_isnull; + bool new_isnull; + + bool need_change = false; + bool need_free = false; + bool need_delold = false; + bool has_nulls = false; + + Size maxDataLen; + + char toast_action[MaxHeapAttributeNumber]; + char toast_nulls[MaxHeapAttributeNumber]; + Datum toast_values[MaxHeapAttributeNumber]; + int32 toast_sizes[MaxHeapAttributeNumber]; + bool toast_free[MaxHeapAttributeNumber]; + bool toast_delold[MaxHeapAttributeNumber]; + + /* ---------- + * Get the tuple descriptor, the number of and attribute + * descriptors and the location of the tuple values. + * ---------- + */ + tupleDesc = rel->rd_att; + numAttrs = tupleDesc->natts; + att = tupleDesc->attrs; + + /* ---------- + * Then collect information about the values given + * ---------- + */ + memset(toast_action, ' ', numAttrs * sizeof(char)); + memset(toast_nulls, ' ', numAttrs * sizeof(char)); + memset(toast_free, 0, numAttrs * sizeof(bool)); + memset(toast_delold, 0, numAttrs * sizeof(bool)); + for (i = 0; i < numAttrs; i++) + { + varattrib *old_value; + varattrib *new_value; + + if (oldtup != NULL) + { + /* ---------- + * For UPDATE get the old and new values of this attribute + * ---------- + */ + old_value = (varattrib *)DatumGetPointer( + heap_getattr(oldtup, i + 1, tupleDesc, &old_isnull)); + toast_values[i] = + heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); + new_value = (varattrib *)DatumGetPointer(toast_values[i]); + + /* ---------- + * If the old value is an external stored one, check if it + * has changed so we have to detele it later. + * ---------- + */ + if (!old_isnull && att[i]->attlen == -1 && + VARATT_IS_EXTERNAL(old_value)) + { + if (new_isnull || !VARATT_IS_EXTERNAL(new_value) || + old_value->va_content.va_external.va_rowid != + new_value->va_content.va_external.va_rowid || + old_value->va_content.va_external.va_attno != + new_value->va_content.va_external.va_attno) + { + /* ---------- + * The old external store value isn't needed any + * more after the update + * ---------- + */ + toast_delold[i] = true; + need_delold = true; + } + else + { + /* ---------- + * This attribute isn't changed by this update + * so we reuse the original reference to the old + * value in the new tuple. + * ---------- + */ + toast_action[i] = 'p'; + toast_sizes[i] = VARATT_SIZE(toast_values[i]); + continue; + } + } + } + else + { + /* ---------- + * For INSERT simply get the new value + * ---------- + */ + toast_values[i] = + heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); + } + + /* ---------- + * Handle NULL attributes + * ---------- + */ + if (new_isnull) + { + toast_action[i] = 'p'; + toast_nulls[i] = 'n'; + has_nulls = true; + continue; + } + + /* ---------- + * Now look at varsize attributes + * ---------- + */ + if (att[i]->attlen == -1) + { + /* ---------- + * If the tables attribute say's PLAIN allways, we + * do so below. + * ---------- + */ + if (att[i]->attstorage == 'p') + toast_action[i] = 'p'; + + /* ---------- + * We're running for UPDATE, so any TOASTed value we find + * still in the tuple must be someone elses we cannot reuse. + * Expand it to plain and eventually toast it again below. + * ---------- + */ + if (VARATT_IS_EXTENDED(DatumGetPointer(toast_values[i]))) + { + toast_values[i] = PointerGetDatum(heap_tuple_untoast_attr( + (varattrib *)DatumGetPointer(toast_values[i]))); + toast_free[i] = true; + need_change = true; + need_free = true; + } + + /* ---------- + * Remember the size of this attribute + * ---------- + */ + toast_sizes[i] = VARATT_SIZE(DatumGetPointer(toast_values[i])); + } + else + { + /* ---------- + * Not a variable size attribute, plain storage allways + * ---------- + */ + toast_action[i] = 'p'; + toast_sizes[i] = att[i]->attlen; + } + } + + /* ---------- + * Compress and/or save external until data fits + * + * 1: Inline compress attributes with attstorage 'x' + * 2: Store attributes with attstorage 'x' or 'e' external + * 3: Inline compress attributes with attstorage 'm' + * 4: Store attributes with attstorage 'm' external + * ---------- + */ + maxDataLen = offsetof(HeapTupleHeaderData, t_bits); + if (has_nulls) + maxDataLen += BITMAPLEN(numAttrs); + maxDataLen = (MaxTupleSize / 4) - MAXALIGN(maxDataLen); + + /* ---------- + * Look for attributes with attstorage 'x' to compress + * ---------- + */ + while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > + maxDataLen) + { + int biggest_attno = -1; + int32 biggest_size = MAXALIGN(sizeof(varattrib)); + Datum old_value; + + /* ---------- + * Search for the biggest yet uncompressed internal attribute + * ---------- + */ + for (i = 0; i < numAttrs; i++) + { + if (toast_action[i] == 'p') + continue; + if (VARATT_IS_EXTENDED(toast_values[i])) + continue; + if (att[i]->attstorage != 'x') + continue; + if (toast_sizes[i] > biggest_size) + { + biggest_attno = i; + biggest_size = toast_sizes[i]; + } + } + + if (biggest_attno < 0) + break; + + /* ---------- + * Compress it inline + * ---------- + */ + i = biggest_attno; + old_value = toast_values[i]; + + toast_values[i] = toast_compress_datum(toast_values[i]); + + if (toast_free[i]) + pfree(DatumGetPointer(old_value)); + + toast_free[i] = true; + toast_sizes[i] = VARATT_SIZE(toast_values[i]); + + need_change = true; + need_free = true; + } + + /* ---------- + * Second we look for attributes of attstorage 'x' or 'e' that + * are still inline. + * ---------- + */ + while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > + maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) + { + int biggest_attno = -1; + int32 biggest_size = MAXALIGN(sizeof(varattrib)); + Datum old_value; + + /* ---------- + * Search for the biggest yet inlined attribute with + * attstorage = 'x' or 'e' + * ---------- + */ + for (i = 0; i < numAttrs; i++) + { + if (toast_action[i] == 'p') + continue; + if (VARATT_IS_EXTERNAL(toast_values[i])) + continue; + if (att[i]->attstorage != 'x' && att[i]->attstorage != 'e') + continue; + if (toast_sizes[i] > biggest_size) + { + biggest_attno = i; + biggest_size = toast_sizes[i]; + } + } + + if (biggest_attno < 0) + break; + + /* ---------- + * Store this external + * ---------- + */ + i = biggest_attno; + old_value = toast_values[i]; + toast_action[i] = 'p'; + toast_values[i] = toast_save_datum(rel, + newtup->t_data->t_oid, + i + 1, + toast_values[i]); + if (toast_free[i]) + pfree(DatumGetPointer(old_value)); + + toast_free[i] = true; + toast_sizes[i] = VARATT_SIZE(toast_values[i]); + + need_change = true; + need_free = true; + } + + /* ---------- + * Round 3 - this time we take attributes with storage + * 'm' into compression + * ---------- + */ + while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > + maxDataLen) + { + int biggest_attno = -1; + int32 biggest_size = MAXALIGN(sizeof(varattrib)); + Datum old_value; + + /* ---------- + * Search for the biggest yet uncompressed internal attribute + * ---------- + */ + for (i = 0; i < numAttrs; i++) + { + if (toast_action[i] == 'p') + continue; + if (VARATT_IS_EXTENDED(toast_values[i])) + continue; + if (att[i]->attstorage != 'm') + continue; + if (toast_sizes[i] > biggest_size) + { + biggest_attno = i; + biggest_size = toast_sizes[i]; + } + } + + if (biggest_attno < 0) + break; + + /* ---------- + * Compress it inline + * ---------- + */ + i = biggest_attno; + old_value = toast_values[i]; + + toast_values[i] = toast_compress_datum(toast_values[i]); + + if (toast_free[i]) + pfree(DatumGetPointer(old_value)); + + toast_free[i] = true; + toast_sizes[i] = VARATT_SIZE(toast_values[i]); + + need_change = true; + need_free = true; + } + + /* ---------- + * Finally we store attributes of type 'm' external + * ---------- + */ + while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > + maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) + { + int biggest_attno = -1; + int32 biggest_size = MAXALIGN(sizeof(varattrib)); + Datum old_value; + + /* ---------- + * Search for the biggest yet inlined attribute with + * attstorage = 'x' or 'e' + * ---------- + */ + for (i = 0; i < numAttrs; i++) + { + if (toast_action[i] == 'p') + continue; + if (VARATT_IS_EXTERNAL(toast_values[i])) + continue; + if (att[i]->attstorage != 'm') + continue; + if (toast_sizes[i] > biggest_size) + { + biggest_attno = i; + biggest_size = toast_sizes[i]; + } + } + + if (biggest_attno < 0) + break; + + /* ---------- + * Store this external + * ---------- + */ + i = biggest_attno; + old_value = toast_values[i]; + toast_action[i] = 'p'; + toast_values[i] = toast_save_datum(rel, + newtup->t_data->t_oid, + i + 1, + toast_values[i]); + if (toast_free[i]) + pfree(DatumGetPointer(old_value)); + + toast_free[i] = true; + toast_sizes[i] = VARATT_SIZE(toast_values[i]); + + need_change = true; + need_free = true; + } + + /* ---------- + * In the case we toasted any values, we need to build + * a new heap tuple with the changed values. + * ---------- + */ + if (need_change) + { + char *new_data; + int32 new_len; + MemoryContext oldcxt; + HeapTupleHeader olddata; + + /* ---------- + * Calculate the new size of the tuple + * ---------- + */ + new_len = offsetof(HeapTupleHeaderData, t_bits); + if (has_nulls) + new_len += BITMAPLEN(numAttrs); + new_len = MAXALIGN(new_len); + new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls); + + /* ---------- + * Remember the old memory location of the tuple (for below), + * switch to the memory context of the HeapTuple structure + * and allocate the new tuple. + * ---------- + */ + olddata = newtup->t_data; + oldcxt = MemoryContextSwitchTo(newtup->t_datamcxt); + new_data = palloc(new_len); + + /* ---------- + * Put the tuple header and the changed values into place + * ---------- + */ + memcpy(new_data, newtup->t_data, newtup->t_data->t_hoff); + newtup->t_data = (HeapTupleHeader)new_data; + newtup->t_len = new_len; + + DataFill((char *)(MAXALIGN((long)new_data + + offsetof(HeapTupleHeaderData, t_bits) + + ((has_nulls) ? BITMAPLEN(numAttrs) : 0))), + tupleDesc, + toast_values, + toast_nulls, + &(newtup->t_data->t_infomask), + HeapTupleNoNulls(newtup) ? NULL : new_data); + + /* ---------- + * In the case we modified a previously modified tuple again, + * free the memory from the previous run + * ---------- + */ + if ((char *)olddata != ((char *)newtup + HEAPTUPLESIZE)) + pfree(olddata); + + /* ---------- + * Switch back to the old memory context + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + } + + + /* ---------- + * Free allocated temp values + * ---------- + */ + if (need_free) + for (i = 0; i < numAttrs; i++) + if (toast_free[i]) + pfree(DatumGetPointer(toast_values[i])); + + /* ---------- + * Delete external values from the old tuple + * ---------- + */ + if (need_delold) + for (i = 0; i < numAttrs; i++) + if (toast_delold[i]) + toast_delete_datum(rel, + heap_getattr(oldtup, i + 1, tupleDesc, &old_isnull)); + return; } -varattrib * -heap_tuple_untoast_attr(varattrib * attr) +/* ---------- + * toast_compress_datum - + * + * Create a compressed version of a datum + * ---------- + */ +static Datum +toast_compress_datum(Datum value) { - elog(ERROR, "heap_tuple_untoast_attr() called"); + varattrib *tmp; + + tmp = (varattrib *)palloc(sizeof(PGLZ_Header) + VARATT_SIZE(value)); + pglz_compress(VARATT_DATA(value), VARATT_SIZE(value) - VARHDRSZ, + (PGLZ_Header *)tmp, + PGLZ_strategy_default); + VARATT_SIZEP(tmp) |= VARATT_FLAG_COMPRESSED; + + return PointerGetDatum(tmp); +} + + +/* ---------- + * toast_save_datum - + * + * Save one single datum into the secondary relation and return + * a varattrib reference for it. + * ---------- + */ +static Datum +toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) +{ + Relation toastrel; + Relation toastidx; + HeapTuple toasttup; + InsertIndexResult idxres; + TupleDesc toasttupDesc; + Datum t_values[3]; + char t_nulls[4]; + varattrib *result; + char chunk_data[MaxTupleSize]; + int32 chunk_size; + int32 chunk_seq = 0; + char *data_p; + int32 data_todo; + + /* ---------- + * Create the varattrib reference + * ---------- + */ + result = (varattrib *)palloc(sizeof(varattrib)); + + result->va_header = sizeof(varattrib) | VARATT_FLAG_EXTERNAL; + if (VARATT_IS_COMPRESSED(value)) + { + result->va_header |= VARATT_FLAG_COMPRESSED; + result->va_content.va_external.va_rawsize = + ((varattrib *)value)->va_content.va_compressed.va_rawsize; + } + else + result->va_content.va_external.va_rawsize = VARATT_SIZE(value); + + result->va_content.va_external.va_extsize = + VARATT_SIZE(value) - VARHDRSZ; + result->va_content.va_external.va_valueid = newoid(); + result->va_content.va_external.va_toastrelid = + rel->rd_rel->reltoastrelid; + result->va_content.va_external.va_toastidxid = + rel->rd_rel->reltoastidxid; + result->va_content.va_external.va_rowid = mainoid; + result->va_content.va_external.va_attno = attno; + + /* ---------- + * Initialize constant parts of the tuple data + * ---------- + */ + t_values[0] = ObjectIdGetDatum(result->va_content.va_external.va_valueid); + t_values[2] = PointerGetDatum(chunk_data); + t_nulls[0] = ' '; + t_nulls[1] = ' '; + t_nulls[2] = ' '; + t_nulls[3] = '\0'; + + /* ---------- + * Get the data to process + * ---------- + */ + data_p = VARATT_DATA(value); + data_todo = VARATT_SIZE(value) - VARHDRSZ; + + /* ---------- + * Open the toast relation + * ---------- + */ + toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); + if (toastrel == NULL) + elog(ERROR, "Failed to open secondary relation of %s", + nameout(&(rel->rd_rel->relname))); + toasttupDesc = toastrel->rd_att; + toastidx = index_open(rel->rd_rel->reltoastidxid); + if (toastidx == NULL) + elog(ERROR, "Failed to open index for secondary relation of %s", + nameout(&(rel->rd_rel->relname))); + + /* ---------- + * Split up the item into chunks + * ---------- + */ + while (data_todo > 0) + { + /* ---------- + * Calculate the size of this chunk + * ---------- + */ + chunk_size = (TOAST_MAX_CHUNK_SIZE < data_todo) ? + TOAST_MAX_CHUNK_SIZE : data_todo; + + /* ---------- + * Build a tuple + * ---------- + */ + t_values[1] = (Datum)(chunk_seq++); + VARATT_SIZEP(chunk_data) = chunk_size + VARHDRSZ; + memcpy(VARATT_DATA(chunk_data), data_p, chunk_size); + toasttup = heap_formtuple(toasttupDesc, t_values, t_nulls); + if (!HeapTupleIsValid(toasttup)) + elog(ERROR, "Failed to build TOAST tuple"); + + /* ---------- + * Store it and create the index entry + * ---------- + */ + heap_insert(toastrel, toasttup); + idxres = index_insert(toastidx, t_values, t_nulls, + &(toasttup->t_self), + toastrel); + if (idxres == NULL) + elog(ERROR, "Failed to insert index entry for TOAST tuple"); + + /* ---------- + * Free memory + * ---------- + */ + heap_freetuple(toasttup); + pfree(idxres); + + /* ---------- + * Move on to next chunk + * ---------- + */ + data_todo -= chunk_size; + data_p += chunk_size; + } + + /* ---------- + * Done - close toast relation and return the reference + * ---------- + */ + index_close(toastidx); + heap_close(toastrel, RowExclusiveLock); + + return PointerGetDatum(result); +} + + +/* ---------- + * toast_delete_datum - + * + * Delete a single external stored value. + * ---------- + */ +static void +toast_delete_datum(Relation rel, Datum value) +{ + register varattrib *attr = (varattrib *)value; + Relation toastrel; + Relation toastidx; + ScanKeyData toastkey; + IndexScanDesc toastscan; + HeapTupleData toasttup; + RetrieveIndexResult indexRes; + Buffer buffer; + + if (!VARATT_IS_EXTERNAL(attr)) + return; + + /* ---------- + * Open the toast relation and it's index + * ---------- + */ + toastrel = heap_open(attr->va_content.va_external.va_toastrelid, + RowExclusiveLock); + if (toastrel == NULL) + elog(ERROR, "Failed to open secondary relation at TOAST fetch"); + toastidx = index_open(attr->va_content.va_external.va_toastidxid); + if (toastidx == NULL) + elog(ERROR, "Failed to open index of secondary relation at TOAST fetch"); + + /* ---------- + * Setup a scan key to fetch from the index by va_valueid + * ---------- + */ + ScanKeyEntryInitialize(&toastkey, + (bits16) 0, + (AttrNumber) 1, + (RegProcedure) F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); + + /* ---------- + * Read the chunks by index + * ---------- + */ + toastscan = index_beginscan(toastidx, false, 1, &toastkey); + while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL) + { + toasttup.t_self = indexRes->heap_iptr; + heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer); + pfree(indexRes); + + if (!toasttup.t_data) + continue; + + /* ---------- + * Have a chunk, delete it + * ---------- + */ + heap_delete(toastrel, &toasttup.t_self, NULL); + + ReleaseBuffer(buffer); + } + + /* ---------- + * End scan and close relations + * ---------- + */ + index_endscan(toastscan); + index_close(toastidx); + heap_close(toastrel, RowExclusiveLock); + + return; +} + + +/* ---------- + * toast_fetch_datum - + * + * Reconstruct an in memory varattrib from the chunks saved + * in the toast relation + * ---------- + */ +static varattrib * +toast_fetch_datum(varattrib *attr) +{ + Relation toastrel; + Relation toastidx; + ScanKeyData toastkey; + IndexScanDesc toastscan; + HeapTupleData toasttup; + HeapTuple ttup; + TupleDesc toasttupDesc; + RetrieveIndexResult indexRes; + Buffer buffer; + + varattrib *result; + int32 ressize; + int32 residx; + int numchunks; + Datum chunk; + bool isnull; + + ressize = attr->va_content.va_external.va_extsize; + numchunks = (ressize / TOAST_MAX_CHUNK_SIZE) + 1; + + result = (varattrib *)palloc(ressize + VARHDRSZ); + VARATT_SIZEP(result) = ressize + VARHDRSZ; + if (VARATT_IS_COMPRESSED(attr)) + VARATT_SIZEP(result) |= VARATT_FLAG_COMPRESSED; + + /* ---------- + * Open the toast relation and it's index + * ---------- + */ + toastrel = heap_open(attr->va_content.va_external.va_toastrelid, + AccessShareLock); + if (toastrel == NULL) + elog(ERROR, "Failed to open secondary relation at TOAST fetch"); + toasttupDesc = toastrel->rd_att; + toastidx = index_open(attr->va_content.va_external.va_toastidxid); + if (toastidx == NULL) + elog(ERROR, "Failed to open index of secondary relation at TOAST fetch"); + + /* ---------- + * Setup a scan key to fetch from the index by va_valueid + * ---------- + */ + ScanKeyEntryInitialize(&toastkey, + (bits16) 0, + (AttrNumber) 1, + (RegProcedure) F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); + + /* ---------- + * Read the chunks by index + * ---------- + */ + toastscan = index_beginscan(toastidx, false, 1, &toastkey); + while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL) + { + toasttup.t_self = indexRes->heap_iptr; + heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer); + pfree(indexRes); + + if (!toasttup.t_data) + continue; + ttup = &toasttup; + + /* ---------- + * Have a chunk, extract the sequence number and the data + * ---------- + */ + residx = (int32)heap_getattr(ttup, 2, toasttupDesc, &isnull); + chunk = heap_getattr(ttup, 3, toasttupDesc, &isnull); + + /* ---------- + * Copy the data into our result + * ---------- + */ + memcpy(((char *)VARATT_DATA(result)) + residx * TOAST_MAX_CHUNK_SIZE, + VARATT_DATA(chunk), + VARATT_SIZE(chunk) - VARHDRSZ); + + ReleaseBuffer(buffer); + } + + /* ---------- + * End scan and close relations + * ---------- + */ + index_endscan(toastscan); + index_close(toastidx); + heap_close(toastrel, AccessShareLock); + + return result; } diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 854b68e00d..1c52d098a1 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.89 2000/07/03 20:48:27 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.90 2000/07/03 23:09:23 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -571,7 +571,7 @@ DefineAttr(char *name, char *type, int attnum) attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */ attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen; attrtypes[attnum]->attbyval = Ap->am_typ.typbyval; - attrtypes[attnum]->attstorage = 'p'; + attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;; attrtypes[attnum]->attalign = Ap->am_typ.typalign; } else diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 721297680e..2187b8db44 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.136 2000/07/02 22:00:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.137 2000/07/03 23:09:27 wieck Exp $ * * * INTERFACE ROUTINES @@ -730,7 +730,8 @@ AddNewRelationType(char *typeName, Oid new_rel_oid) NULL, /* array element type - irrelevent */ "-", /* default type value */ (bool) 1, /* passed by value */ - 'i'); /* default alignment */ + 'i', /* default alignment */ + 'p'); /* Not TOASTable */ } /* -------------------------------- @@ -1423,6 +1424,7 @@ heap_drop_with_catalog(const char *relname) Relation rel; Oid rid; bool istemp = (get_temp_rel_by_username(relname) != NULL); + bool has_toasttable; /* ---------------- * Open and lock the relation. @@ -1520,6 +1522,11 @@ heap_drop_with_catalog(const char *relname) smgrunlink(DEFAULT_SMGR, rel); rel->rd_unlinked = true; + /* + * Remember if there is a toast relation for below + */ + has_toasttable = rel->rd_rel->reltoastrelid != InvalidOid; + /* * Close relcache entry, but *keep* AccessExclusiveLock on the * relation until transaction commit. This ensures no one else will @@ -1535,6 +1542,20 @@ heap_drop_with_catalog(const char *relname) if (istemp) remove_temp_relation(rid); + + if (has_toasttable) + { + char toast_relname[NAMEDATALEN]; + bool old_allow; + + old_allow = allowSystemTableMods; + allowSystemTableMods = true; + + sprintf(toast_relname, "pg_toast_%d", rid); + heap_drop_with_catalog(toast_relname); + + allowSystemTableMods = old_allow; + } } diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index bf706d5146..bd34ee0a20 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.52 2000/06/13 07:34:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.53 2000/07/03 23:09:28 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -186,7 +186,8 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName) values[i++] = (Datum) InvalidOid; /* 12 */ values[i++] = (Datum) InvalidOid; /* 13 */ values[i++] = (Datum) InvalidOid; /* 14 */ - values[i++] = (Datum) 'i'; /* 15 */ + values[i++] = (Datum) 'p'; /* 15 */ + values[i++] = (Datum) 'i'; /* 16 */ /* * ... and fill typdefault with a bogus value @@ -287,7 +288,8 @@ TypeCreate(char *typeName, char *elementTypeName, char *defaultTypeValue, /* internal rep */ bool passedByValue, - char alignment) + char alignment, + char storage) { int i, j; @@ -448,11 +450,17 @@ TypeCreate(char *typeName, */ values[i++] = (Datum) alignment; /* 15 */ + /* ---------------- + * set default storage for TOAST + * ---------------- + */ + values[i++] = (Datum) storage; /* 16 */ + /* ---------------- * initialize the default value for this type. * ---------------- */ - values[i] = (Datum) textin(PointerIsValid(defaultTypeValue) /* 16 */ + values[i] = (Datum) textin(PointerIsValid(defaultTypeValue) /* 17 */ ? defaultTypeValue : "-"); /* XXX default * typdefault */ diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index d0bd89fdfd..595c09dc4e 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.81 2000/06/28 03:31:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.82 2000/07/03 23:09:33 wieck Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -35,6 +35,7 @@ #include "catalog/pg_index.h" #include "parser/parse.h" #endif /* _DROP_COLUMN_HACK__ */ +#include "access/genam.h" /* -------------------------------- @@ -438,7 +439,7 @@ AlterTableAddColumn(const char *relationName, attribute->attbyval = tform->typbyval; attribute->attnelems = attnelems; attribute->attisset = (bool) (tform->typtype == 'c'); - attribute->attstorage = 'p'; + attribute->attstorage = tform->typstorage; attribute->attalign = tform->typalign; attribute->attnotnull = false; attribute->atthasdef = (colDef->raw_default != NULL || @@ -1170,6 +1171,159 @@ AlterTableDropConstraint(const char *relationName, +/* + * ALTER TABLE CREATE TOAST TABLE + */ +void +AlterTableCreateToastTable(const char *relationName) +{ + Relation rel; + Oid myrelid; + HeapTuple reltup; + TupleDesc tupdesc; + Form_pg_attribute *att; + Relation class_rel; + Relation ridescs[Num_pg_class_indices]; + Oid toast_relid = 2; + Oid toast_idxid = 2; + bool has_toastable_attrs = false; + bool old_allow; + int i; + + char toast_relname[NAMEDATALEN]; + char toast_idxname[NAMEDATALEN]; + char tmp_query[1024]; + Relation toast_rel; + + /* + * permissions checking. this would normally be done in utility.c, + * but this particular routine is recursive. + * + * normally, only the owner of a class can change its schema. + */ +/* + if (!allowSystemTableMods && IsSystemRelationName(relationName)) + elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", + relationName); +*/ +#ifndef NO_SECURITY + if (!pg_ownercheck(UserName, relationName, RELNAME)) + elog(ERROR, "ALTER TABLE: permission denied"); +#endif + + /* + * Grab an exclusive lock on the target table, which we will NOT + * release until end of transaction. + */ + rel = heap_openr(relationName, RowExclusiveLock); + myrelid = RelationGetRelid(rel); + + /* + * Check if there are any toastable attributes on the table + */ + tupdesc = rel->rd_att; + att = tupdesc->attrs; + for (i = 0; i < tupdesc->natts; i++) + { + if (att[i]->attstorage != 'p') + { + has_toastable_attrs = true; + break; + } + } + + if (!has_toastable_attrs) + elog(ERROR, "ALTER TABLE: relation \"%s\" has no toastable attributes", + relationName); + + /* + * Get the pg_class tuple for the relation + */ + reltup = SearchSysCacheTuple(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); + + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "ALTER TABLE: relation \"%s\" not found", + relationName); + + /* + * XXX is the following check sufficient? + */ + if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION) + { + elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", + relationName); + } + + if (((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid != InvalidOid) + elog(ERROR, "ALTER TABLE: relation \"%s\" already has a toast table", + relationName); + + /* + * Create the toast table and it's index + * This is bad and ugly, because we need to override + * allowSystemTableMods in order to keep the toast + * table- and index-name out of the users namespace. + */ + sprintf(toast_relname, "pg_toast_%d", myrelid); + sprintf(toast_idxname, "pg_toast_%d_idx", myrelid); + + old_allow = allowSystemTableMods; + allowSystemTableMods = true; + + sprintf(tmp_query, "create table \"%s\" (chunk_id oid, chunk_seq int4, chunk_data text)", + toast_relname); + pg_exec_query_dest(tmp_query, None, CurrentMemoryContext); + + sprintf(tmp_query, "create index \"%s\" on \"%s\" (chunk_id)", + toast_idxname, toast_relname); + pg_exec_query_dest(tmp_query, None, CurrentMemoryContext); + + allowSystemTableMods = old_allow; + + /* + * Get the OIDs of the newly created objects + */ + toast_rel = heap_openr(toast_relname, NoLock); + toast_relid = RelationGetRelid(toast_rel); + heap_close(toast_rel, NoLock); + toast_rel = index_openr(toast_idxname); + toast_idxid = RelationGetRelid(toast_rel); + index_close(toast_rel); + + /* + * Get the pg_class tuple for the relation + */ + class_rel = heap_openr(RelationRelationName, RowExclusiveLock); + + reltup = SearchSysCacheTupleCopy(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "ALTER TABLE: relation \"%s\" not found", + relationName); + + /* + * Store the toast table- and index-Oid's in the relation tuple + */ + ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; + ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid; + heap_update(class_rel, &reltup->t_self, reltup, NULL); + + /* keep catalog indices current */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); + CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup); + CatalogCloseIndices(Num_pg_class_indices, ridescs); + + heap_freetuple(reltup); + + heap_close(rel, NoLock); + heap_close(class_rel, NoLock); +} + + + /* * * LOCK TABLE diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index da87287217..d3da6cc2b2 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.43 2000/05/28 17:55:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.44 2000/07/03 23:09:33 wieck Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -597,6 +597,7 @@ DefineType(char *typeName, List *parameters) char *shadow_type; List *pl; char alignment = 'i';/* default alignment */ + char storage = 'p'; /* default storage in TOAST */ /* * Type names can only be 15 characters long, so that the shadow type @@ -650,6 +651,24 @@ DefineType(char *typeName, List *parameters) a); } } + else if (!strcasecmp(defel->defname, "storage")) + { + char *a = defGetString(defel); + + if (!strcasecmp(a, "plain")) + storage = 'p'; + else if (!strcasecmp(a, "external")) + storage = 'e'; + else if (!strcasecmp(a, "extended")) + storage = 'x'; + else if (!strcasecmp(a, "main")) + storage = 'm'; + else + { + elog(ERROR, "DefineType: \"%s\" storage not recognized", + a); + } + } else { elog(NOTICE, "DefineType: attribute \"%s\" not recognized", @@ -665,6 +684,9 @@ DefineType(char *typeName, List *parameters) if (outputName == NULL) elog(ERROR, "Define: \"output\" unspecified"); + if (internalLength != -1 && storage != 'p') + elog(ERROR, "Define: fixed size types must have storage PLAIN"); + /* ---------------- * now have TypeCreate do all the real work. * ---------------- @@ -682,7 +704,8 @@ DefineType(char *typeName, List *parameters) elemName, /* element type name */ defaultValue, /* default type value */ byValue, /* passed by value */ - alignment); + alignment, + storage); /* TOAST strategy */ /* ---------------- * When we create a true type (as opposed to a complex type) @@ -704,7 +727,8 @@ DefineType(char *typeName, List *parameters) typeName, /* element type name */ defaultValue, /* default type value */ false, /* never passed by value */ - alignment); + alignment, + 'p'); /* ARRAY doesn't support TOAST yet */ pfree(shadow_type); } diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c index 75f6562a8f..91769120f9 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.47 2000/06/28 03:31:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.48 2000/07/03 23:09:37 wieck Exp $ * * NOTES * This should be moved to a more appropriate place. It is here @@ -331,7 +331,7 @@ loread(PG_FUNCTION_ARGS) retval = (struct varlena *) palloc(VARHDRSZ + len); totalread = lo_read(fd, VARDATA(retval), len); - VARSIZE(retval) = totalread + VARHDRSZ; + VARATT_SIZEP(retval) = totalread + VARHDRSZ; PG_RETURN_POINTER(retval); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b17185e463..98a00acb8f 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.174 2000/06/22 22:31:18 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.175 2000/07/03 23:09:41 wieck Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -350,7 +350,7 @@ static void doNegateFloat(Value *v); OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL, REINDEX, RENAME, RESET, RETURNS, ROW, RULE, SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID, - TEMP, TRUNCATE, TRUSTED, + TEMP, TOAST, TRUNCATE, TRUSTED, UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION /* Special keywords, not in the query language - see the "lex" file */ @@ -931,6 +931,14 @@ AlterTableStmt: n->behavior = $8; $$ = (Node *)n; } +/* ALTER TABLE CREATE TOAST TABLE */ + | ALTER TABLE relation_name CREATE TOAST TABLE + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->subtype = 'E'; + n->relname = $3; + $$ = (Node *)n; + } ; alter_column_action: @@ -5460,6 +5468,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; } | TEMPORARY { $$ = "temporary"; } | TIMEZONE_HOUR { $$ = "timezone_hour"; } | TIMEZONE_MINUTE { $$ = "timezone_minute"; } + | TOAST { $$ = "toast"; } | TRIGGER { $$ = "trigger"; } | TRUNCATE { $$ = "truncate"; } | TRUSTED { $$ = "trusted"; } diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 76428b969c..982ca9116d 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -9,9 +9,9 @@ * * IDENTIFICATION <<<<<<< keywords.c - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.77 2000/06/12 19:40:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.78 2000/07/03 23:09:43 wieck Exp $ ======= - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.77 2000/06/12 19:40:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.78 2000/07/03 23:09:43 wieck Exp $ >>>>>>> 1.73 * *------------------------------------------------------------------------- @@ -245,6 +245,7 @@ static ScanKeyword ScanKeywords[] = { {"timezone_hour", TIMEZONE_HOUR}, {"timezone_minute", TIMEZONE_MINUTE}, {"to", TO}, + {"toast", TOAST}, {"trailing", TRAILING}, {"transaction", TRANSACTION}, {"trigger", TRIGGER}, diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index cbba122355..fd30bd58ac 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.42 2000/06/15 04:10:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.43 2000/07/03 23:09:46 wieck Exp $ * * NOTES * This cruft is the server side of PQfn. @@ -349,7 +349,7 @@ HandleFunctionRequest() p = palloc(argsize + VARHDRSZ + 1); /* Added +1 to solve * memory leak - Peter * 98 Jan 6 */ - VARSIZE(p) = argsize + VARHDRSZ; + VARATT_SIZEP(p) = argsize + VARHDRSZ; if (pq_getbytes(VARDATA(p), argsize)) return EOF; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 2459b6507c..17c77da850 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.89 2000/06/04 01:44:33 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.90 2000/07/03 23:09:46 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -360,6 +360,9 @@ ProcessUtility(Node *parsetree, case 'X': /* DROP CONSTRAINT */ AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior); break; + case 'E': /* CREATE TOAST TABLE */ + AlterTableCreateToastTable(stmt->relname); + break; default: /* oops */ elog(ERROR, "T_AlterTableStmt: unknown subtype"); break; diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index fe96d77f43..3fc0061304 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.59 2000/06/14 18:17:42 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.60 2000/07/03 23:09:50 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -813,7 +813,7 @@ array_dims(PG_FUNCTION_ARGS) sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1); p += strlen(p); } - VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ; + VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ; PG_RETURN_TEXT_P(result); } @@ -1151,7 +1151,7 @@ array_set(ArrayType *array, Int32GetDatum(SEEK_SET))) < 0) return array; v = (struct varlena *) palloc(elmlen + VARHDRSZ); - VARSIZE(v) = elmlen + VARHDRSZ; + VARATT_SIZEP(v) = elmlen + VARHDRSZ; ArrayCastAndSet(dataValue, elmbyval, elmlen, VARDATA(v)); #ifdef LOARRAY if (DatumGetInt32(DirectFunctionCall2(lowrite, diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index 484b8e8f94..09237e5275 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -9,7 +9,7 @@ * workings can be found in the book "Software Solutions in C" by * Dale Schumacher, Academic Press, ISBN: 0-12-632360-7. * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.40 2000/06/15 03:32:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.41 2000/07/03 23:09:50 wieck Exp $ */ #include @@ -730,7 +730,7 @@ cash_words_out(Cash *value) /* make a text type for output */ result = (text *) palloc(strlen(buf) + VARHDRSZ); - VARSIZE(result) = strlen(buf) + VARHDRSZ; + VARATT_SIZEP(result) = strlen(buf) + VARHDRSZ; memcpy(VARDATA(result), buf, strlen(buf)); return result; diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c index 04e40406f8..b2c3080ca3 100644 --- a/src/backend/utils/adt/char.c +++ b/src/backend/utils/adt/char.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.28 2000/06/05 07:28:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.29 2000/07/03 23:09:50 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -162,7 +162,7 @@ char_text(PG_FUNCTION_ARGS) char arg1 = PG_GETARG_CHAR(0); text *result = palloc(VARHDRSZ + 1); - VARSIZE(result) = VARHDRSZ + 1; + VARATT_SIZEP(result) = VARHDRSZ + 1; *(VARDATA(result)) = arg1; PG_RETURN_TEXT_P(result); diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index f8c3a3f156..f618a10eb8 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.61 2000/06/14 18:17:42 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.62 2000/07/03 23:09:50 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -953,7 +953,7 @@ float8_text(float64 num) result = palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); @@ -998,7 +998,7 @@ float4_text(float32 num) result = palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 2d1ae16c5e..cf7d361842 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.17 2000/07/03 16:01:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.18 2000/07/03 23:09:50 wieck Exp $ * * * Portions Copyright (c) 1999-2000, PostgreSQL, Inc @@ -2526,7 +2526,7 @@ timestamp_to_char(PG_FUNCTION_ARGS) result = (text *) palloc(len + 1 + VARHDRSZ); strcpy(VARDATA(result), VARDATA(result_tmp)); - VARSIZE(result) = len + VARHDRSZ; + VARATT_SIZEP(result) = len + VARHDRSZ; pfree(result_tmp); PG_RETURN_TEXT_P(result); @@ -3987,7 +3987,7 @@ do { \ result = (text *) palloc( len + 1 + VARHDRSZ); \ \ strcpy( VARDATA(result), VARDATA(result_tmp)); \ - VARSIZE(result) = len + VARHDRSZ; \ + VARATT_SIZEP(result) = len + VARHDRSZ; \ pfree(result_tmp); \ } while(0) diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index b5f66f1118..7029ca73b8 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.38 2000/06/14 18:17:44 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.39 2000/07/03 23:09:52 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -263,7 +263,7 @@ int2_text(PG_FUNCTION_ARGS) text *result = (text *) palloc(7+VARHDRSZ); /* sign,5 digits, '\0' */ itoa((int) arg1, VARDATA(result)); - VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ; + VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ; PG_RETURN_TEXT_P(result); } @@ -294,7 +294,7 @@ int4_text(PG_FUNCTION_ARGS) text *result = (text *) palloc(12+VARHDRSZ); /* sign,10 digits,'\0' */ ltoa(arg1, VARDATA(result)); - VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ; + VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ; PG_RETURN_TEXT_P(result); } diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index ea29ffaff5..63c0938461 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.21 2000/06/14 18:17:44 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.22 2000/07/03 23:09:52 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -581,7 +581,7 @@ int8_text(PG_FUNCTION_ARGS) result = (text *) palloc(VARHDRSZ + len); - VARSIZE(result) = len + VARHDRSZ; + VARATT_SIZEP(result) = len + VARHDRSZ; memcpy(VARDATA(result), s, len); pfree(s); diff --git a/src/backend/utils/adt/lztext.c b/src/backend/utils/adt/lztext.c index 4442d00351..412445e727 100644 --- a/src/backend/utils/adt/lztext.c +++ b/src/backend/utils/adt/lztext.c @@ -1,7 +1,7 @@ /* ---------- * lztext.c - * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/lztext.c,v 1.7 2000/05/30 00:49:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/lztext.c,v 1.8 2000/07/03 23:09:52 wieck Exp $ * * Text type with internal LZ compressed representation. Uses the * standard PostgreSQL compression method. @@ -34,8 +34,6 @@ lztextin(char *str) { lztext *result; int32 rawsize; - lztext *tmp; - int tmp_size; /* ---------- * Handle NULL @@ -44,35 +42,11 @@ lztextin(char *str) if (str == NULL) return NULL; - /* ---------- - * Determine input size and maximum output Datum size - * ---------- - */ rawsize = strlen(str); - tmp_size = PGLZ_MAX_OUTPUT(rawsize); + result = (lztext *)palloc(VARHDRSZ + rawsize); - /* ---------- - * Allocate a temporary result and compress into it - * ---------- - */ - tmp = (lztext *) palloc(tmp_size); - pglz_compress(str, rawsize, tmp, NULL); - - /* ---------- - * If we miss less than 25% bytes at the end of the temp value, - * so be it. Therefore we save a palloc()/memcpy()/pfree() - * sequence. - * ---------- - */ - if (tmp_size - tmp->varsize < 256 || - tmp_size - tmp->varsize < tmp_size / 4) - result = tmp; - else - { - result = (lztext *) palloc(tmp->varsize); - memcpy(result, tmp, tmp->varsize); - pfree(tmp); - } + VARATT_SIZEP(result) = VARHDRSZ + rawsize; + memcpy(VARATT_DATA(result), str, rawsize); return result; } @@ -88,6 +62,8 @@ char * lztextout(lztext *lz) { char *result; + void *tmp; + int32 rawsize; /* ---------- * Handle NULL @@ -101,25 +77,15 @@ lztextout(lztext *lz) return result; } - /* ---------- - * Allocate the result string - the required size is remembered - * in the lztext header so we don't need a temporary buffer or - * have to diddle with realloc's. - * ---------- - */ - result = (char *) palloc(PGLZ_RAW_SIZE(lz) + 1); + VARATT_GETPLAIN(lz, tmp); - /* ---------- - * Decompress and add terminating ZERO - * ---------- - */ - pglz_decompress(lz, result); - result[lz->rawsize] = '\0'; + rawsize = VARATT_SIZE(tmp) - VARHDRSZ; + result = (char *)palloc(rawsize + 1); + memcpy(result, VARATT_DATA(tmp), rawsize); + result[rawsize] = '\0'; + + VARATT_FREE(lz, tmp); - /* ---------- - * Return the result - * ---------- - */ return result; } @@ -167,7 +133,13 @@ lztextlen(lztext *lz) * without multibyte support, it's the remembered rawsize * ---------- */ - return PGLZ_RAW_SIZE(lz); + if (!VARATT_IS_EXTENDED(lz)) + return VARATT_SIZE(lz) - VARHDRSZ; + + if (VARATT_IS_EXTERNAL(lz)) + return lz->va_content.va_external.va_rawsize; + + return lz->va_content.va_compressed.va_rawsize; #endif } @@ -189,11 +161,10 @@ lztextoctetlen(lztext *lz) if (lz == NULL) return 0; - /* ---------- - * Return the varsize minus the VARSIZE field itself. - * ---------- - */ - return VARSIZE(lz) - VARHDRSZ; + if (!VARATT_IS_EXTERNAL(lz)) + return VARATT_SIZE(lz) - VARHDRSZ; + + return lz->va_content.va_external.va_extsize; } @@ -208,9 +179,6 @@ text_lztext(text *txt) { lztext *result; int32 rawsize; - lztext *tmp; - int tmp_size; - char *str; /* ---------- * Handle NULL @@ -220,35 +188,13 @@ text_lztext(text *txt) return NULL; /* ---------- - * Determine input size and eventually tuple size + * Copy the entire attribute * ---------- */ rawsize = VARSIZE(txt) - VARHDRSZ; - str = VARDATA(txt); - tmp_size = PGLZ_MAX_OUTPUT(rawsize); - - /* ---------- - * Allocate a temporary result and compress into it - * ---------- - */ - tmp = (lztext *) palloc(tmp_size); - pglz_compress(str, rawsize, tmp, NULL); - - /* ---------- - * If we miss less than 25% bytes at the end of the temp value, - * so be it. Therefore we save a palloc()/memcpy()/pfree() - * sequence. - * ---------- - */ - if (tmp_size - tmp->varsize < 256 || - tmp_size - tmp->varsize < tmp_size / 4) - result = tmp; - else - { - result = (lztext *) palloc(tmp->varsize); - memcpy(result, tmp, tmp->varsize); - pfree(tmp); - } + result = (lztext *)palloc(rawsize + VARHDRSZ); + VARATT_SIZEP(result) = rawsize + VARHDRSZ; + memcpy(VARATT_DATA(result), VARATT_DATA(txt), rawsize); return result; } @@ -264,6 +210,8 @@ text * lztext_text(lztext *lz) { text *result; + lztext *tmp; + int32 rawsize; /* ---------- * Handle NULL @@ -272,19 +220,14 @@ lztext_text(lztext *lz) if (lz == NULL) return NULL; - /* ---------- - * Allocate and initialize the text result - * ---------- - */ - result = (text *) palloc(PGLZ_RAW_SIZE(lz) + VARHDRSZ + 1); - VARSIZE(result) = lz->rawsize + VARHDRSZ; + VARATT_GETPLAIN(lz, tmp); + + rawsize = VARATT_SIZE(tmp) - VARHDRSZ; + result = (text *)palloc(rawsize + VARHDRSZ); + VARATT_SIZEP(result) = rawsize + VARHDRSZ; + memcpy(VARATT_DATA(result), VARATT_DATA(tmp), rawsize); - /* ---------- - * Decompress directly into the text data area. - * ---------- - */ - VARDATA(result)[lz->rawsize] = 0; - pglz_decompress(lz, VARDATA(result)); + VARATT_FREE(lz, tmp); return result; } @@ -322,43 +265,32 @@ lztext_cmp(lztext *lz1, lztext *lz2) #else /* !USE_LOCALE */ - PGLZ_DecompState ds1; - PGLZ_DecompState ds2; - int c1; - int c2; - int32 result = (int32) 0; + int result; + char *p1 = NULL; + char *p2 = NULL; + int size1; + int size2; if (lz1 == NULL || lz2 == NULL) - return (int32) 0; + return 0; - pglz_decomp_init(&ds1, lz1); - pglz_decomp_init(&ds2, lz2); + VARATT_GETPLAIN(lz1, p1); + VARATT_GETPLAIN(lz2, p2); - for (;;) - { - c1 = pglz_decomp_getchar(&ds1); - c2 = pglz_decomp_getchar(&ds2); + size1 = VARATT_SIZE(p1) - VARHDRSZ; + size2 = VARATT_SIZE(p2) - VARHDRSZ; + result = memcmp(VARATT_DATA(p1), VARATT_DATA(p2), + (size1 < size2) ? size1 : size2); + if (result == 0) + { + if (size1 > size2) + result = 1; + else if (size1 < size2) + result = -1; + } - if (c1 == EOF) - { - if (c2 != EOF) - result = (int32) -1; - break; - } - else - { - if (c2 == EOF) - result = (int32) 1; - } - if (c1 != c2) - { - result = (int32) (c1 - c2); - break; - } - } - - pglz_decomp_end(&ds1); - pglz_decomp_end(&ds2); + VARATT_FREE(lz2, p2); + VARATT_FREE(lz1, p1); return result; diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c index 02fc1863b6..9d880a4aa6 100644 --- a/src/backend/utils/adt/mac.c +++ b/src/backend/utils/adt/mac.c @@ -1,7 +1,7 @@ /* * PostgreSQL type definitions for MAC addresses. * - * $Id: mac.c,v 1.14 1999/12/16 01:30:49 momjian Exp $ + * $Id: mac.c,v 1.15 2000/07/03 23:09:52 wieck Exp $ */ @@ -314,14 +314,14 @@ macaddr_manuf(macaddr *addr) { result = palloc(VARHDRSZ + 1); memset(result, 0, VARHDRSZ + 1); - VARSIZE(result) = VARHDRSZ + 1; + VARATT_SIZEP(result) = VARHDRSZ + 1; } else { length = strlen(manuf->name) + 1; result = palloc(length + VARHDRSZ); memset(result, 0, length + VARHDRSZ); - VARSIZE(result) = length + VARHDRSZ; + VARATT_SIZEP(result) = length + VARHDRSZ; memcpy(VARDATA(result), manuf->name, length); } return result; diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 9a666ebd70..720517c953 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.70 2000/06/27 18:08:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.71 2000/07/03 23:09:52 wieck Exp $ * * NOTES * @@ -1945,7 +1945,7 @@ timeofday(PG_FUNCTION_ARGS) len = VARHDRSZ + strlen(buf); result = (text *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memcpy(VARDATA(result), buf, strlen(buf)); PG_RETURN_TEXT_P(result); } diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index 7e1a9ead66..a5127ece26 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -3,7 +3,7 @@ * is for IP V4 CIDR notation, but prepared for V6: just * add the necessary bits where the comments indicate. * - * $Id: network.c,v 1.21 2000/04/12 17:15:50 momjian Exp $ + * $Id: network.c,v 1.22 2000/07/03 23:09:52 wieck Exp $ * Jon Postel RIP 16 Oct 1998 */ @@ -61,7 +61,7 @@ network_in(char *src, int type) /* Go for an IPV6 address here, before faulting out: */ elog(ERROR, "could not parse \"%s\"", src); - VARSIZE(dst) = VARHDRSZ + VARATT_SIZEP(dst) = VARHDRSZ + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst)) + ip_addrsize(dst); ip_bits(dst) = bits; @@ -346,7 +346,7 @@ network_host(inet *ip) if (ret == NULL) elog(ERROR, "unable to allocate memory in network_host()"); - VARSIZE(ret) = len; + VARATT_SIZEP(ret) = len; strcpy(VARDATA(ret), tmp); return (ret); } @@ -396,7 +396,7 @@ network_broadcast(inet *ip) if (ret == NULL) elog(ERROR, "unable to allocate memory in network_broadcast()"); - VARSIZE(ret) = len; + VARATT_SIZEP(ret) = len; strcpy(VARDATA(ret), tmp); return (ret); } @@ -429,7 +429,7 @@ network_network(inet *ip) if (ret == NULL) elog(ERROR, "unable to allocate memory in network_network()"); - VARSIZE(ret) = len; + VARATT_SIZEP(ret) = len; strcpy(VARDATA(ret), tmp); return (ret); } @@ -466,7 +466,7 @@ network_netmask(inet *ip) if (ret == NULL) elog(ERROR, "unable to allocate memory in network_netmask()"); - VARSIZE(ret) = len; + VARATT_SIZEP(ret) = len; strcpy(VARDATA(ret), tmp); return (ret); } diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 156237862b..a51eadfc5e 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.36 2000/06/14 18:17:45 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.37 2000/07/03 23:09:52 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -231,7 +231,7 @@ oid_text(PG_FUNCTION_ARGS) result = (text *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memcpy(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 4455c04c55..5f0b1fa776 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1,7 +1,7 @@ /* * Edmund Mergl * - * $Id: oracle_compat.c,v 1.25 2000/06/13 07:35:07 tgl Exp $ + * $Id: oracle_compat.c,v 1.26 2000/07/03 23:09:52 wieck Exp $ * */ @@ -37,7 +37,7 @@ lower(text *string) return string; ret = (text *) palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + VARATT_SIZEP(ret) = VARSIZE(string); ptr = VARDATA(string); ptr_ret = VARDATA(ret); @@ -75,7 +75,7 @@ upper(text *string) return string; ret = (text *) palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + VARATT_SIZEP(ret) = VARSIZE(string); ptr = VARDATA(string); ptr_ret = VARDATA(ret); @@ -115,7 +115,7 @@ initcap(text *string) return string; ret = (text *) palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + VARATT_SIZEP(ret) = VARSIZE(string); ptr = VARDATA(string); ptr_ret = VARDATA(ret); @@ -169,7 +169,7 @@ lpad(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(string1); ret = (text *) palloc(VARHDRSZ + len); - VARSIZE(ret) = VARHDRSZ + len; + VARATT_SIZEP(ret) = VARHDRSZ + len; ptr2 = VARDATA(string2); ptr_ret = VARDATA(ret); @@ -224,7 +224,7 @@ rpad(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(string1); ret = (text *) palloc(VARHDRSZ + len); - VARSIZE(ret) = VARHDRSZ + len; + VARATT_SIZEP(ret) = VARHDRSZ + len; n = VARSIZE(string1) - VARHDRSZ; ptr1 = VARDATA(string1); @@ -316,7 +316,7 @@ btrim(text *string, text *set) ++m; ret = (text *) palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; + VARATT_SIZEP(ret) = VARHDRSZ + m; memcpy(VARDATA(ret), ptr, m); return ret; @@ -374,7 +374,7 @@ ltrim(text *string, text *set) ++m; ret = (text *) palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; + VARATT_SIZEP(ret) = VARHDRSZ + m; memcpy(VARDATA(ret), ptr, m); @@ -434,7 +434,7 @@ rtrim(text *string, text *set) ++m; ret = (text *) palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; + VARATT_SIZEP(ret) = VARHDRSZ + m; #ifdef NOT_USED memcpy(VARDATA(ret), ptr - VARSIZE(ret) + m, m); #endif @@ -528,7 +528,7 @@ translate(text *string, text *from, text *to) } } - VARSIZE(result) = retlen + VARHDRSZ; + VARATT_SIZEP(result) = retlen + VARHDRSZ; /* * There may be some wasted space in the result if deletions occurred, @@ -560,7 +560,7 @@ ichar(PG_FUNCTION_ARGS) text *result; result = (text *) palloc(VARHDRSZ + 1); - VARSIZE(result) = VARHDRSZ + 1; + VARATT_SIZEP(result) = VARHDRSZ + 1; *VARDATA(result) = (char) cvalue; PG_RETURN_TEXT_P(result); @@ -586,7 +586,7 @@ repeat(PG_FUNCTION_ARGS) result = (text *) palloc(tlen); - VARSIZE(result) = tlen; + VARATT_SIZEP(result) = tlen; cp = VARDATA(result); for (i = 0; i < count; i++) { diff --git a/src/backend/utils/adt/pg_lzcompress.c b/src/backend/utils/adt/pg_lzcompress.c index f4e6ac5be3..493b4e6446 100644 --- a/src/backend/utils/adt/pg_lzcompress.c +++ b/src/backend/utils/adt/pg_lzcompress.c @@ -1,7 +1,7 @@ /* ---------- * pg_lzcompress.c - * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.5 2000/05/30 00:49:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.6 2000/07/03 23:09:52 wieck Exp $ * * This is an implementation of LZ compression for PostgreSQL. * It uses a simple history table and generates 2-3 byte tags @@ -582,11 +582,15 @@ pglz_compress(char *source, int slen, PGLZ_Header *dest, PGLZ_Strategy *strategy * ---------- */ if (do_compress) - return (dest->varsize = result_size + sizeof(PGLZ_Header)); + { + dest->varsize = result_size + sizeof(PGLZ_Header); + return VARATT_SIZE(dest); + } else { memcpy(((char *) dest) + sizeof(PGLZ_Header), source, slen); - return (dest->varsize = slen + sizeof(PGLZ_Header)); + dest->varsize = slen + sizeof(PGLZ_Header); + return VARATT_SIZE(dest); } } @@ -609,10 +613,10 @@ pglz_decompress(PGLZ_Header *source, char *dest) int32 off; dp = ((unsigned char *) source) + sizeof(PGLZ_Header); - dend = ((unsigned char *) source) + source->varsize; + dend = ((unsigned char *) source) + VARATT_SIZE(source); bp = (unsigned char *) dest; - if (source->varsize == source->rawsize + sizeof(PGLZ_Header)) + if (VARATT_SIZE(source) == source->rawsize + sizeof(PGLZ_Header)) { memcpy(dest, dp, source->rawsize); return source->rawsize; diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index c5fbeadff6..6660d15f1d 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.56 2000/06/05 07:28:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.57 2000/07/03 23:09:52 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -282,7 +282,7 @@ oidvectortypes(PG_FUNCTION_ARGS) else strcat(VARDATA(result), "- "); } - VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ; + VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ; PG_RETURN_TEXT_P(result); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 5b2a2ea016..5bd339a5cc 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * out of its tuple * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.54 2000/06/13 07:35:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.55 2000/07/03 23:09:52 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -181,7 +181,7 @@ pg_get_ruledef(NameData *rname) if (SPI_finish() != SPI_OK_FINISH) elog(ERROR, "get_ruledef: SPI_finish() failed"); ruledef = SPI_palloc(VARHDRSZ + 1); - VARSIZE(ruledef) = VARHDRSZ + 1; + VARATT_SIZEP(ruledef) = VARHDRSZ + 1; VARDATA(ruledef)[0] = '-'; return ruledef; } @@ -197,7 +197,7 @@ pg_get_ruledef(NameData *rname) make_ruledef(&buf, ruletup, rulettc); len = buf.len + VARHDRSZ; ruledef = SPI_palloc(len); - VARSIZE(ruledef) = len; + VARATT_SIZEP(ruledef) = len; memcpy(VARDATA(ruledef), buf.data, buf.len); pfree(buf.data); @@ -296,7 +296,7 @@ pg_get_viewdef(NameData *rname) } len = buf.len + VARHDRSZ; ruledef = SPI_palloc(len); - VARSIZE(ruledef) = len; + VARATT_SIZEP(ruledef) = len; memcpy(VARDATA(ruledef), buf.data, buf.len); pfree(buf.data); @@ -530,7 +530,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS) */ len = buf.len + VARHDRSZ; indexdef = SPI_palloc(len); - VARSIZE(indexdef) = len; + VARATT_SIZEP(indexdef) = len; memcpy(VARDATA(indexdef), buf.data, buf.len); pfree(buf.data); pfree(keybuf.data); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 71549bb925..4b3f498a2a 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.30 2000/06/19 03:54:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.31 2000/07/03 23:09:53 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -1375,7 +1375,7 @@ timestamp_text(PG_FUNCTION_ARGS) result = palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); @@ -1430,7 +1430,7 @@ interval_text(PG_FUNCTION_ARGS) result = palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); @@ -2101,7 +2101,7 @@ timestamp_zone(PG_FUNCTION_ARGS) result = palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), buf, (len - VARHDRSZ)); } else diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 3e4abe828b..b5d2e18e10 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -4,7 +4,7 @@ * Functions for the built-in type bit() and varying bit(). * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.3 2000/06/15 03:32:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.4 2000/07/03 23:09:53 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -122,7 +122,7 @@ zpbit_in(char *s, int dummy, int32 atttypmod) result = (bits8 *) palloc(len); /* set to 0 so that *r is always initialised and strin is zero-padded */ memset(result, 0, len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; VARBITLEN(result) = atttypmod; /* @@ -353,7 +353,7 @@ varbit_in(char *s, int dummy, int32 atttypmod) result = (bits8 *) palloc(len); /* set to 0 so that *r is always initialised and strin is zero-padded */ memset(result, 0, len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; VARBITLEN(result) = bitlen; /* @@ -561,7 +561,7 @@ bitcat(bits8 *arg1, bits8 *arg2) bytelen = VARBITDATALEN(bitlen1 + bitlen2); result = (bits8 *) palloc(bytelen * sizeof(bits8)); - VARSIZE(result) = bytelen; + VARATT_SIZEP(result) = bytelen; VARBITLEN(result) = bitlen1 + bitlen2; /* Copy the first bitstring in */ memcpy(VARBITS(result), VARBITS(arg1), VARBITBYTES(arg1)); @@ -625,7 +625,7 @@ bitsubstr(bits8 *arg, int32 s, int32 l) len = VARBITDATALEN(0); result = (bits8 *) palloc(len); VARBITLEN(result) = 0; - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; } else { @@ -638,7 +638,7 @@ bitsubstr(bits8 *arg, int32 s, int32 l) len = VARBITDATALEN(rbitlen); result = (bits8 *) palloc(len); VARBITLEN(result) = rbitlen; - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; len -= VARHDRSZ + VARBITHDRSZ; /* Are we copying from a byte boundary? */ if ((s1 - 1) % BITSPERBYTE == 0) @@ -691,7 +691,7 @@ bitand(bits8 *arg1, bits8 *arg2) len = Min(VARSIZE(arg1), VARSIZE(arg2)); result = (bits8 *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2)); p1 = (bits8 *) VARBITS(arg1); @@ -725,7 +725,7 @@ bitor(bits8 *arg1, bits8 *arg2) len = Min(VARSIZE(arg1), VARSIZE(arg2)); result = (bits8 *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2)); p1 = (bits8 *) VARBITS(arg1); @@ -761,7 +761,7 @@ bitxor(bits8 *arg1, bits8 *arg2) len = Min(VARSIZE(arg1), VARSIZE(arg2)); result = (bits8 *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2)); p1 = (bits8 *) VARBITS(arg1); @@ -792,7 +792,7 @@ bitnot(bits8 *arg) return (bool) 0; result = (bits8 *) palloc(VARSIZE(arg)); - VARSIZE(result) = VARSIZE(arg); + VARATT_SIZEP(result) = VARSIZE(arg); VARBITLEN(result) = VARBITLEN(arg); p = (bits8 *) VARBITS(arg); @@ -828,7 +828,7 @@ bitshiftleft(bits8 *arg, int shft) return bitshiftright(arg, -shft); result = (bits8 *) palloc(VARSIZE(arg)); - VARSIZE(result) = VARSIZE(arg); + VARATT_SIZEP(result) = VARSIZE(arg); VARBITLEN(result) = VARBITLEN(arg); r = (bits8 *) VARBITS(result); @@ -879,7 +879,7 @@ bitshiftright(bits8 *arg, int shft) return bitshiftleft(arg, -shft); result = (bits8 *) palloc(VARSIZE(arg)); - VARSIZE(result) = VARSIZE(arg); + VARATT_SIZEP(result) = VARSIZE(arg); VARBITLEN(result) = VARBITLEN(arg); r = (bits8 *) VARBITS(result); diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 53c6ec4167..6f17cb589a 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.66 2000/06/19 03:54:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.67 2000/07/03 23:09:53 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -88,7 +88,7 @@ bpcharin(PG_FUNCTION_ARGS) len = atttypmod - VARHDRSZ; result = (BpChar *) palloc(atttypmod); - VARSIZE(result) = atttypmod; + VARATT_SIZEP(result) = atttypmod; r = VARDATA(result); for (i = 0; i < len; i++, r++, s++) { @@ -154,7 +154,7 @@ bpchar(PG_FUNCTION_ARGS) #endif result = (BpChar *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; r = VARDATA(result); #ifdef MULTIBYTE @@ -248,7 +248,7 @@ char_bpchar(PG_FUNCTION_ARGS) result = (BpChar *) palloc(VARHDRSZ + 1); - VARSIZE(result) = VARHDRSZ + 1; + VARATT_SIZEP(result) = VARHDRSZ + 1; *(VARDATA(result)) = c; PG_RETURN_BPCHAR_P(result); @@ -317,7 +317,7 @@ name_bpchar(NameData *s) result = (char *) palloc(VARHDRSZ + len); strncpy(VARDATA(result), NameStr(*s), len); - VARSIZE(result) = len + VARHDRSZ; + VARATT_SIZEP(result) = len + VARHDRSZ; return result; } /* name_bpchar() */ @@ -348,7 +348,7 @@ varcharin(PG_FUNCTION_ARGS) len = atttypmod; /* clip the string at max length */ result = (VarChar *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memcpy(VARDATA(result), s, len - VARHDRSZ); #ifdef CYR_RECODE @@ -407,7 +407,7 @@ varchar(PG_FUNCTION_ARGS) #endif result = (VarChar *) palloc(slen); - VARSIZE(result) = slen; + VARATT_SIZEP(result) = slen; memcpy(VARDATA(result), VARDATA(s), len); PG_RETURN_VARCHAR_P(result); diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index fedd29f0c3..114bcff29a 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.60 2000/06/14 18:17:45 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.61 2000/07/03 23:09:54 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -157,7 +157,7 @@ textin(char *inputText) len = strlen(inputText) + VARHDRSZ; result = (text *) palloc(len); - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; memmove(VARDATA(result), inputText, len - VARHDRSZ); @@ -288,7 +288,7 @@ textcat(text *t1, text *t2) result = palloc(len); /* Set size of result string... */ - VARSIZE(result) = len; + VARATT_SIZEP(result) = len; /* Fill data field of result string... */ ptr = VARDATA(result); @@ -374,7 +374,7 @@ text_substr(PG_FUNCTION_ARGS) #endif ret = (text *) palloc(VARHDRSZ + n); - VARSIZE(ret) = VARHDRSZ + n; + VARATT_SIZEP(ret) = VARHDRSZ + n; memcpy(VARDATA(ret), VARDATA(string) + m, n); @@ -842,7 +842,7 @@ name_text(NameData *s) result = palloc(VARHDRSZ + len); strncpy(VARDATA(result), NameStr(*s), len); - VARSIZE(result) = len + VARHDRSZ; + VARATT_SIZEP(result) = len + VARHDRSZ; return result; } /* name_text() */ diff --git a/src/backend/utils/adt/version.c b/src/backend/utils/adt/version.c index 4914acc8e3..0cf0b7859e 100644 --- a/src/backend/utils/adt/version.c +++ b/src/backend/utils/adt/version.c @@ -5,7 +5,7 @@ * * IDENTIFICATION * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/version.c,v 1.10 2000/07/02 15:20:51 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/version.c,v 1.11 2000/07/03 23:09:54 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -22,7 +22,7 @@ version(void) int n = strlen(PG_VERSION_STR) + VARHDRSZ; text *ret = (text *) palloc(n); - VARSIZE(ret) = n; + VARATT_SIZEP(ret) = n; memcpy(VARDATA(ret), PG_VERSION_STR, strlen(PG_VERSION_STR)); return ret; diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h index 9c4f1a5057..024bb1de91 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -6,7 +6,7 @@ * * Copyright (c) 2000, PostgreSQL Development Team * - * $Id: tuptoaster.h,v 1.2 2000/04/12 17:16:26 momjian Exp $ + * $Id: tuptoaster.h,v 1.3 2000/07/03 23:09:58 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -22,11 +22,23 @@ #include "utils/rel.h" +#define TOAST_MAX_CHUNK_SIZE ((MaxTupleSize - \ + MAXALIGN( \ + MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + \ + MAXALIGN(sizeof(Oid)) + \ + MAXALIGN(sizeof(int32)) + \ + MAXALIGN(VARHDRSZ))) / 4) + + extern void heap_tuple_toast_attrs(Relation rel, - HeapTuple newtup, HeapTuple oldtup); + HeapTuple newtup, HeapTuple oldtup); extern varattrib *heap_tuple_untoast_attr(varattrib * attr); +extern void heap_create_toast_table(Oid new_reloid, + TupleDesc new_tupdesc, bool istemp); + + #endif /* TUPLE_TOASTER_ACTIVE */ diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 899b249642..925328e2bd 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.60 2000/07/02 22:01:08 momjian Exp $ + * $Id: pg_attribute.h,v 1.61 2000/07/03 23:10:05 wieck Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -243,7 +243,8 @@ typedef FormData_pg_attribute *Form_pg_attribute; { 1247, {"typreceive"}, 24, 0, 4, 13, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1247, {"typdefault"}, 25, 0, -1, 16, 0, -1, -1, '\0' , 'p', '\0', 'i', '\0', '\0' } +{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1247, {"typdefault"}, 25, 0, -1, 17, 0, -1, -1, '\0' , 'p', '\0', 'i', '\0', '\0' } DATA(insert OID = 0 ( 1247 typname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f)); @@ -260,7 +261,8 @@ DATA(insert OID = 0 ( 1247 typoutput 24 0 4 12 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1247 typreceive 24 0 4 13 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1247 typdefault 25 0 -1 16 0 -1 -1 f p f i f f)); +DATA(insert OID = 0 ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1247 typdefault 25 0 -1 17 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); @@ -423,20 +425,21 @@ DATA(insert OID = 0 ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i f f)); { 1259, {"relam"}, 26, 0, 4, 4, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1259, {"relpages"}, 23, 0, 4, 5, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1259, {"reltuples"}, 23, 0, 4, 6, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ -{ 1259, {"rellongrelid"}, 26, 0, 4, 7, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ -{ 1259, {"relhasindex"}, 16, 0, 1, 8, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relisshared"}, 16, 0, 1, 9, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relkind"}, 18, 0, 1, 10, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relnatts"}, 21, 0, 2, 11, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"relchecks"}, 21, 0, 2, 12, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"reltriggers"}, 21, 0, 2, 13, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"relukeys"}, 21, 0, 2, 14, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"relfkeys"}, 21, 0, 2, 15, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"relrefs"}, 21, 0, 2, 16, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ -{ 1259, {"relhaspkey"}, 16, 0, 1, 17, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relhasrules"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relhassubclass"},16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relacl"}, 1034, 0, -1, 20, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } +{ 1259, {"reltoastrelid"}, 26, 0, 4, 7, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ +{ 1259, {"reltoastidxid"}, 26, 0, 4, 8, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ +{ 1259, {"relhasindex"}, 16, 0, 1, 9, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relisshared"}, 16, 0, 1, 10, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relkind"}, 18, 0, 1, 11, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relnatts"}, 21, 0, 2, 12, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"relchecks"}, 21, 0, 2, 13, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"reltriggers"}, 21, 0, 2, 14, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"relukeys"}, 21, 0, 2, 15, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"relfkeys"}, 21, 0, 2, 16, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"relrefs"}, 21, 0, 2, 17, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ +{ 1259, {"relhaspkey"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relhasrules"}, 16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relhassubclass"},16, 0, 1, 20, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relacl"}, 1034, 0, -1, 21, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } DATA(insert OID = 0 ( 1259 relname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 reltype 26 0 4 2 0 -1 -1 t p f i f f)); @@ -444,20 +447,21 @@ DATA(insert OID = 0 ( 1259 relowner 23 0 4 3 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 relam 26 0 4 4 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 relpages 23 0 4 5 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 reltuples 23 0 4 6 0 -1 -1 t p f i f f)); -DATA(insert OID = 0 ( 1259 rellongrelid 26 0 4 7 0 -1 -1 t p f i f f)); -DATA(insert OID = 0 ( 1259 relhasindex 16 0 1 8 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relisshared 16 0 1 9 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relkind 18 0 1 10 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relnatts 21 0 2 11 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 relchecks 21 0 2 12 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 reltriggers 21 0 2 13 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 relukeys 21 0 2 14 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 relfkeys 21 0 2 15 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 relrefs 21 0 2 16 0 -1 -1 t p f s f f)); -DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 17 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 18 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 19 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 20 0 -1 -1 f p f i f f)); +DATA(insert OID = 0 ( 1259 reltoastrelid 26 0 4 7 0 -1 -1 t p f i f f)); +DATA(insert OID = 0 ( 1259 reltoastidxid 26 0 4 8 0 -1 -1 t p f i f f)); +DATA(insert OID = 0 ( 1259 relhasindex 16 0 1 9 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relisshared 16 0 1 10 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relkind 18 0 1 11 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relnatts 21 0 2 12 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 relchecks 21 0 2 13 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 reltriggers 21 0 2 14 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 relukeys 21 0 2 15 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 relfkeys 21 0 2 16 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 relrefs 21 0 2 17 0 -1 -1 t p f s f f)); +DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 18 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 19 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 20 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 21 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 2744495960..1ea5b7b779 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_class.h,v 1.38 2000/06/17 04:56:31 tgl Exp $ + * $Id: pg_class.h,v 1.39 2000/07/03 23:10:05 wieck Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -52,7 +52,8 @@ CATALOG(pg_class) BOOTSTRAP Oid relam; int4 relpages; int4 reltuples; - Oid rellongrelid; + Oid reltoastrelid; + Oid reltoastidxid; bool relhasindex; bool relisshared; char relkind; @@ -98,59 +99,60 @@ typedef FormData_pg_class *Form_pg_class; * relacl field. * ---------------- */ -#define Natts_pg_class_fixed 19 -#define Natts_pg_class 20 +#define Natts_pg_class_fixed 20 +#define Natts_pg_class 21 #define Anum_pg_class_relname 1 #define Anum_pg_class_reltype 2 #define Anum_pg_class_relowner 3 #define Anum_pg_class_relam 4 #define Anum_pg_class_relpages 5 #define Anum_pg_class_reltuples 6 -#define Anum_pg_class_rellongrelid 7 -#define Anum_pg_class_relhasindex 8 -#define Anum_pg_class_relisshared 9 -#define Anum_pg_class_relkind 10 -#define Anum_pg_class_relnatts 11 -#define Anum_pg_class_relchecks 12 -#define Anum_pg_class_reltriggers 13 -#define Anum_pg_class_relukeys 14 -#define Anum_pg_class_relfkeys 15 -#define Anum_pg_class_relrefs 16 -#define Anum_pg_class_relhaspkey 17 -#define Anum_pg_class_relhasrules 18 -#define Anum_pg_class_relhassubclass 19 -#define Anum_pg_class_relacl 20 +#define Anum_pg_class_reltoastrelid 7 +#define Anum_pg_class_reltoastidxid 8 +#define Anum_pg_class_relhasindex 9 +#define Anum_pg_class_relisshared 10 +#define Anum_pg_class_relkind 11 +#define Anum_pg_class_relnatts 12 +#define Anum_pg_class_relchecks 13 +#define Anum_pg_class_reltriggers 14 +#define Anum_pg_class_relukeys 15 +#define Anum_pg_class_relfkeys 16 +#define Anum_pg_class_relrefs 17 +#define Anum_pg_class_relhaspkey 18 +#define Anum_pg_class_relhasrules 19 +#define Anum_pg_class_relhassubclass 20 +#define Anum_pg_class_relacl 21 /* ---------------- * initial contents of pg_class * ---------------- */ -DATA(insert OID = 1247 ( pg_type 71 PGUID 0 0 0 0 f f r 16 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1247 ( pg_type 71 PGUID 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 f f r 15 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 0 f f r 15 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 f f r 20 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 0 f f r 21 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1260 ( pg_shadow 86 PGUID 0 0 0 0 f t r 8 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1260 ( pg_shadow 86 PGUID 0 0 0 0 0 f t r 8 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1261 ( pg_group 87 PGUID 0 0 0 0 f t r 3 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1261 ( pg_group 87 PGUID 0 0 0 0 0 f t r 3 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1262 ( pg_database 88 PGUID 0 0 0 0 f t r 4 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1262 ( pg_database 88 PGUID 0 0 0 0 0 f t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1264 ( pg_variable 90 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1264 ( pg_variable 90 PGUID 0 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 376 ( pg_xactlock 0 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 376 ( pg_xactlock 0 PGUID 0 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 0 t t r 13 0 0 0 0 0 f f f _null_ )); +DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 0 0 t t r 13 0 0 0 0 0 f f f _null_ )); DESCR(""); #define RelOid_pg_type 1247 @@ -175,6 +177,6 @@ DESCR(""); #define RELKIND_SPECIAL 's' /* special (non-heap) */ #define RELKIND_SEQUENCE 'S' /* SEQUENCE relation */ #define RELKIND_UNCATALOGED 'u' /* temporary heap */ -#define RELKIND_LONGVALUE 'v' /* moved off huge values */ +#define RELKIND_TOASTVALUE 't' /* moved off huge values */ #endif /* PG_CLASS_H */ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index ce9ba3b474..b7a41b6a72 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.89 2000/06/05 07:29:01 tgl Exp $ + * $Id: pg_type.h,v 1.90 2000/07/03 23:10:05 wieck Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -106,6 +106,18 @@ CATALOG(pg_type) BOOTSTRAP * compiler will lay out the field in a struct representing a table row. * ---------------- */ + char typstorage; + + /* ---------------- + * typstorage tells if the type is prepared for toasting and what + * the default strategy for attributes of this type should be. + * + * 'p' PLAIN type not prepared for toasting + * 'e' EXTERNAL external storage possible, don't try to compress + * 'x' EXTENDED try to compress and store external if required + * 'm' MAIN like 'x' but try to keep in main tuple + * ---------------- + */ text typdefault; /* VARIABLE LENGTH FIELD */ } FormData_pg_type; @@ -120,7 +132,7 @@ typedef FormData_pg_type *Form_pg_type; * compiler constants for pg_type * ---------------- */ -#define Natts_pg_type 16 +#define Natts_pg_type 17 #define Anum_pg_type_typname 1 #define Anum_pg_type_typowner 2 #define Anum_pg_type_typlen 3 @@ -136,7 +148,8 @@ typedef FormData_pg_type *Form_pg_type; #define Anum_pg_type_typreceive 13 #define Anum_pg_type_typsend 14 #define Anum_pg_type_typalign 15 -#define Anum_pg_type_typdefault 16 +#define Anum_pg_type_typstorage 16 +#define Anum_pg_type_typdefault 17 /* ---------------- * initial contents of pg_type @@ -151,88 +164,88 @@ typedef FormData_pg_type *Form_pg_type; */ /* OIDS 1 - 99 */ -DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c _null_ )); +DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p _null_ )); DESCR("boolean, 'true'/'false'"); #define BOOLOID 16 -DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 18 byteain byteaout byteain byteaout i _null_ )); +DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 18 byteain byteaout byteain byteaout i p _null_ )); DESCR("variable-length string, binary values escaped"); #define BYTEAOID 17 -DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c _null_ )); +DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p _null_ )); DESCR("single character"); #define CHAROID 18 -DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i _null_ )); +DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p _null_ )); DESCR("31-character type for storing system identifiers"); #define NAMEOID 19 -DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d _null_ )); +DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p _null_ )); DESCR("~18 digit integer, 8-byte storage"); #define INT8OID 20 -DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s _null_ )); +DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p _null_ )); DESCR("-32 thousand to 32 thousand, 2-byte storage"); #define INT2OID 21 -DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i _null_ )); +DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ )); DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables"); #define INT2VECTOROID 22 -DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i _null_ )); +DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p _null_ )); DESCR("-2 billion to 2 billion integer, 4-byte storage"); #define INT4OID 23 -DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i _null_ )); +DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p _null_ )); DESCR("registered procedure"); #define REGPROCOID 24 -DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 18 textin textout textin textout i _null_ )); +DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 18 textin textout textin textout i p _null_ )); DESCR("variable-length string, no limit specified"); #define TEXTOID 25 -DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i _null_ )); +DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p _null_ )); DESCR("object identifier(oid), maximum 4 billion"); #define OIDOID 26 -DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i _null_ )); +DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p _null_ )); DESCR("(Block, offset), physical location of tuple"); #define TIDOID 27 -DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i _null_ )); +DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p _null_ )); DESCR("transaction id"); #define XIDOID 28 -DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i _null_ )); +DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p _null_ )); DESCR("command identifier type, sequence in transaction id"); #define CIDOID 29 -DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i _null_ )); +DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ )); DESCR("array of INDEX_MAX_KEYS oids, used in system tables"); #define OIDVECTOROID 30 -DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i _null_ )); +DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ )); DESCR("set of tuples"); -DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 90 ( pg_variable PGUID 4 4 t c t \054 1264 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 99 ( pg_log PGUID 4 4 t c t \054 1269 0 int4in int4out int4in int4out i _null_)); +DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 90 ( pg_variable PGUID 4 4 t c t \054 1264 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 99 ( pg_log PGUID 4 4 t c t \054 1269 0 int4in int4out int4in int4out i p _null_)); /* OIDS 100 - 199 */ -DATA(insert OID = 109 ( pg_attrdef PGUID 4 4 t c t \054 1215 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 110 ( pg_relcheck PGUID 4 4 t c t \054 1216 0 int4in int4out int4in int4out i _null_)); -DATA(insert OID = 111 ( pg_trigger PGUID 4 4 t c t \054 1219 0 int4in int4out int4in int4out i _null_)); +DATA(insert OID = 109 ( pg_attrdef PGUID 4 4 t c t \054 1215 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 110 ( pg_relcheck PGUID 4 4 t c t \054 1216 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 111 ( pg_trigger PGUID 4 4 t c t \054 1219 0 int4in int4out int4in int4out i p _null_)); /* OIDS 200 - 299 */ -DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s _null_ )); +DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ )); DESCR("storage manager"); /* OIDS 300 - 399 */ @@ -242,163 +255,163 @@ DESCR("storage manager"); /* OIDS 500 - 599 */ /* OIDS 600 - 699 */ -DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d _null_ )); +DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ )); DESCR("geometric point '(x, y)'"); #define POINTOID 600 -DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d _null_ )); +DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ )); DESCR("geometric line segment '(pt1,pt2)'"); #define LSEGOID 601 -DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 600 path_in path_out path_in path_out d _null_ )); +DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 600 path_in path_out path_in path_out d p _null_ )); DESCR("geometric path '(pt1,...)'"); #define PATHOID 602 -DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d _null_ )); +DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ )); DESCR("geometric box '(lower left,upper right)'"); #define BOXOID 603 -DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d _null_ )); +DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d p _null_ )); DESCR("geometric polygon '(pt1,...)'"); #define POLYGONOID 604 -DATA(insert OID = 605 ( filename PGUID 256 -1 f b t \054 0 18 filename_in filename_out filename_in filename_out i _null_ )); +DATA(insert OID = 605 ( filename PGUID 256 -1 f b t \054 0 18 filename_in filename_out filename_in filename_out i p _null_ )); DESCR("filename used in system tables"); -DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d _null_ )); +DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ )); DESCR("geometric line '(pt1,pt2)'"); #define LINEOID 628 -DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d _null_ )); +DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d p _null_ )); DESCR(""); /* OIDS 700 - 799 */ -DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i _null_ )); +DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p _null_ )); DESCR("single-precision floating point number, 4-byte storage"); #define FLOAT4OID 700 -DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d _null_ )); +DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p _null_ )); DESCR("double-precision floating point number, 8-byte storage"); #define FLOAT8OID 701 -DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i _null_ )); +DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ )); DESCR("absolute, limited-range date and time (Unix system time)"); #define ABSTIMEOID 702 -DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i _null_ )); +DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p _null_ )); DESCR("relative, limited-range time interval (Unix delta time)"); #define RELTIMEOID 703 -DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i _null_ )); +DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p _null_ )); DESCR("(abstime,abstime), time interval"); #define TINTERVALOID 704 -DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 18 textin textout textin textout i _null_ )); +DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 18 textin textout textin textout i p _null_ )); DESCR(""); #define UNKNOWNOID 705 -DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d _null_ )); +DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ )); DESCR("geometric circle '(center,radius)'"); #define CIRCLEOID 718 -DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i _null_ )); +DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ )); DESCR("$d,ddd.cc, money"); #define CASHOID 790 -DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i _null_ )); +DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i p _null_ )); /* OIDS 800 - 899 */ -DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i _null_ )); +DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ )); DESCR("XX:XX:XX:XX:XX, MAC address"); -DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i _null_ )); +DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ )); DESCR("IP address/netmask, host address, netmask optional"); #define INETOID 869 -DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i _null_ )); +DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ )); DESCR("network IP address/netmask, network address"); #define CIDROID 650 /* OIDS 900 - 999 */ /* OIDS 1000 - 1099 */ -DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1026 ( _filename PGUID -1 -1 f b t \054 0 605 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d _null_ )); +DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1026 ( _filename PGUID -1 -1 f b t \054 0 605 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d p _null_ )); /* * Note: the size of aclitem needs to match sizeof(AclItem) in acl.h. * Thanks to some padding, this will be 8 on all platforms. * We also have an Assert to make sure. */ #define ACLITEMSIZE 8 -DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i _null_ )); +DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ )); DESCR("access control list"); -DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 18 bpcharin bpcharout bpcharin bpcharout i _null_ )); +DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 18 bpcharin bpcharout bpcharin bpcharout i p _null_ )); DESCR("char(length), blank-padded string, fixed storage length"); #define BPCHAROID 1042 -DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 18 varcharin varcharout varcharin varcharout i _null_ )); +DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 18 varcharin varcharout varcharin varcharout i p _null_ )); DESCR("varchar(length), non-blank-padded string, variable storage length"); #define VARCHAROID 1043 -DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i _null_ )); +DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p _null_ )); DESCR("ANSI SQL date"); #define DATEOID 1082 -DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d _null_ )); +DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMEOID 1083 /* OIDS 1100 - 1199 */ -DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1184 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d _null_ )); +DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1184 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ )); DESCR("date and time"); #define TIMESTAMPOID 1184 -DATA(insert OID = 1185 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d _null_ )); -DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d _null_ )); +DATA(insert OID = 1185 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d p _null_ )); +DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ )); DESCR("@ , time interval"); #define INTERVALOID 1186 -DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d _null_ )); +DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d p _null_ )); /* OIDS 1200 - 1299 */ -DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d _null_ )); +DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMETZOID 1266 -DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d _null_ )); +DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d p _null_ )); /* OIDS 1500 - 1599 */ -DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 zpbit_in zpbit_out zpbit_in zpbit_out i _null_ )); +DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 zpbit_in zpbit_out zpbit_in zpbit_out i p _null_ )); DESCR("fixed-length bit string"); #define ZPBITOID 1560 -DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i _null_ )); -DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i _null_ )); +DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i p _null_ )); +DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i p _null_ )); DESCR("fixed-length bit string"); #define VARBITOID 1562 -DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i _null_ )); +DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i p _null_ )); /* OIDS 1600 - 1699 */ -DATA(insert OID = 1625 ( lztext PGUID -1 -1 f b t \054 0 0 lztextin lztextout lztextin lztextout i _null_ )); +DATA(insert OID = 1625 ( lztext PGUID -1 -1 f b t \054 0 0 lztextin lztextout lztextin lztextout i x _null_ )); DESCR("variable-length string, stored compressed"); #define LZTEXTOID 1625 /* OIDS 1700 - 1799 */ -DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i _null_ )); +DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i p _null_ )); DESCR("numeric(precision, decimal), arbitrary precision number"); #define NUMERICOID 1700 @@ -421,7 +434,8 @@ extern Oid TypeCreate(char *typeName, char *sendProcedure, char *elementTypeName, char *defaultTypeValue, - bool passedByValue, char alignment); + bool passedByValue, char alignment, + char storage); extern void TypeRename(const char *oldTypeName, const char *newTypeName); extern char *makeArrayTypeName(char *typeName); diff --git a/src/include/commands/command.h b/src/include/commands/command.h index 8cb31889fa..e870126355 100644 --- a/src/include/commands/command.h +++ b/src/include/commands/command.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: command.h,v 1.19 2000/06/28 03:32:57 tgl Exp $ + * $Id: command.h,v 1.20 2000/07/03 23:10:10 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -58,6 +58,8 @@ extern void AlterTableDropConstraint(const char *relationName, bool inh, const char *constrName, int behavior); +extern void AlterTableCreateToastTable(const char *relationName); + /* * LOCK */ diff --git a/src/include/postgres.h b/src/include/postgres.h index a4a7fda110..f11e28ed9f 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1995, Regents of the University of California * - * $Id: postgres.h,v 1.42 2000/06/28 03:32:56 tgl Exp $ + * $Id: postgres.h,v 1.43 2000/07/03 23:09:56 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -71,8 +71,12 @@ struct varlena char vl_dat[1]; }; +#define TUPLE_TOASTER_ACTIVE + +#ifndef TUPLE_TOASTER_ACTIVE #define VARSIZE(PTR) (((struct varlena *)(PTR))->vl_len) #define VARDATA(PTR) (((struct varlena *)(PTR))->vl_dat) +#endif #define VARHDRSZ ((int32) sizeof(int32)) /* @@ -89,8 +93,6 @@ typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */ * Proposed new layout for variable length attributes * DO NOT USE YET - Jan */ -#undef TUPLE_TOASTER_ACTIVE -#undef TUPLE_TOASTER_ALL_TYPES #ifdef TUPLE_TOASTER_ACTIVE typedef struct varattrib @@ -102,14 +104,17 @@ typedef struct varattrib struct { int32 va_rawsize; /* Plain data size */ + char va_data[1]; /* Compressed data */ } va_compressed; /* Compressed stored attribute */ struct { int32 va_rawsize; /* Plain data size */ + int32 va_extsize; /* External saved size */ Oid va_valueid; /* Unique identifier of value */ - Oid va_longrelid; /* RelID where to find chunks */ - Oid va_rowid; /* Main tables row Oid */ + Oid va_toastrelid; /* RelID where to find chunks */ + Oid va_toastidxid; /* Main tables row Oid */ + Oid va_rowid; /* Referencing row Oid */ int16 va_attno; /* Main tables attno */ } va_external;/* External stored attribute */ @@ -117,14 +122,18 @@ typedef struct varattrib } va_content; } varattrib; -#define VARATT_FLAG_EXTERNAL 0x8000 -#define VARATT_FLAG_COMPRESSED 0x4000 -#define VARATT_MASK_FLAGS 0xc000 -#define VARATT_MASK_SIZE 0x3fff +#define VARATT_FLAG_EXTERNAL 0x80000000 +#define VARATT_FLAG_COMPRESSED 0x40000000 +#define VARATT_MASK_FLAGS 0xc0000000 +#define VARATT_MASK_SIZE 0x3fffffff #define VARATT_SIZEP(_PTR) (((varattrib *)(_PTR))->va_header) #define VARATT_SIZE(PTR) (VARATT_SIZEP(PTR) & VARATT_MASK_SIZE) #define VARATT_DATA(PTR) (((varattrib *)(PTR))->va_content.va_data) +#define VARATT_CDATA(PTR) (((varattrib *)(PTR))->va_content.va_compressed.va_data) + +#define VARSIZE(__PTR) VARATT_SIZE(__PTR) +#define VARDATA(__PTR) VARATT_DATA(__PTR) #define VARATT_IS_EXTENDED(PTR) \ ((VARATT_SIZEP(PTR) & VARATT_MASK_FLAGS) != 0) @@ -142,12 +151,12 @@ typedef struct varattrib extern varattrib *heap_tuple_untoast_attr(varattrib * attr); #define VARATT_GETPLAIN(_ARG,_VAR) { \ - if (VARATTR_IS_EXTENDED(_ARG)) \ + if (VARATT_IS_EXTENDED(_ARG)) \ (_VAR) = (void *)heap_tuple_untoast_attr(_ARG); \ else \ - (_VAR) = (_ARG); \ + (_VAR) = (void *)(_ARG); \ } -#define VARATT_FREE(_ARG,VAR) do { \ +#define VARATT_FREE(_ARG,_VAR) do { \ if ((void *)(_VAR) != (void *)(_ARG)) \ pfree((void *)(_VAR)); \ } while (0) diff --git a/src/include/utils/lztext.h b/src/include/utils/lztext.h index 8936ffb133..be57c7478b 100644 --- a/src/include/utils/lztext.h +++ b/src/include/utils/lztext.h @@ -1,7 +1,7 @@ /* ---------- * lztext.h * - * $Header: /cvsroot/pgsql/src/include/utils/Attic/lztext.h,v 1.3 2000/04/12 17:16:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/include/utils/Attic/lztext.h,v 1.4 2000/07/03 23:10:14 wieck Exp $ * * Definitions for the lztext compressed data type * ---------- @@ -10,13 +10,10 @@ #ifndef _LZTEXT_H_ #define _LZTEXT_H_ -#include "utils/pg_lzcompress.h" - - /* ---------- - * The internal storage format of an LZ compressed text field + * The internal storage format of an LZ compressed text field is varattrib * ---------- */ -typedef PGLZ_Header lztext; +typedef varattrib lztext; #endif /* _LZTEXT_H_ */