Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/heaptuple.c10
-rw-r--r--src/backend/access/common/tupdesc.c13
-rw-r--r--src/backend/access/gist/gist.c6
-rw-r--r--src/backend/access/heap/heapam.c38
-rw-r--r--src/backend/access/heap/tuptoaster.c974
-rw-r--r--src/backend/bootstrap/bootstrap.c4
-rw-r--r--src/backend/catalog/heap.c25
-rw-r--r--src/backend/catalog/pg_type.c16
-rw-r--r--src/backend/commands/command.c158
-rw-r--r--src/backend/commands/define.c30
-rw-r--r--src/backend/libpq/be-fsstubs.c4
-rw-r--r--src/backend/parser/gram.y13
-rw-r--r--src/backend/parser/keywords.c5
-rw-r--r--src/backend/tcop/fastpath.c4
-rw-r--r--src/backend/tcop/utility.c5
-rw-r--r--src/backend/utils/adt/arrayfuncs.c6
-rw-r--r--src/backend/utils/adt/cash.c4
-rw-r--r--src/backend/utils/adt/char.c4
-rw-r--r--src/backend/utils/adt/float.c6
-rw-r--r--src/backend/utils/adt/formatting.c6
-rw-r--r--src/backend/utils/adt/int.c6
-rw-r--r--src/backend/utils/adt/int8.c4
-rw-r--r--src/backend/utils/adt/lztext.c188
-rw-r--r--src/backend/utils/adt/mac.c6
-rw-r--r--src/backend/utils/adt/nabstime.c4
-rw-r--r--src/backend/utils/adt/network.c12
-rw-r--r--src/backend/utils/adt/oid.c4
-rw-r--r--src/backend/utils/adt/oracle_compat.c24
-rw-r--r--src/backend/utils/adt/pg_lzcompress.c14
-rw-r--r--src/backend/utils/adt/regproc.c4
-rw-r--r--src/backend/utils/adt/ruleutils.c10
-rw-r--r--src/backend/utils/adt/timestamp.c8
-rw-r--r--src/backend/utils/adt/varbit.c24
-rw-r--r--src/backend/utils/adt/varchar.c14
-rw-r--r--src/backend/utils/adt/varlena.c10
-rw-r--r--src/backend/utils/adt/version.c4
36 files changed, 1410 insertions, 257 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index f93bf34db90..319cfff7ca3 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 433bbe6b06b..c878c50e0af 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 4bf737dcd36..794685da2e1 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 9f3a7ac7140..1ece416e874 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 0af5db0cafd..3221ed5b134 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
#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;
+}
+
+
+/* ----------
+ * toast_compress_datum -
+ *
+ * Create a compressed version of a datum
+ * ----------
+ */
+static Datum
+toast_compress_datum(Datum value)
+{
+ 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;
}
-varattrib *
-heap_tuple_untoast_attr(varattrib * attr)
+/* ----------
+ * toast_fetch_datum -
+ *
+ * Reconstruct an in memory varattrib from the chunks saved
+ * in the toast relation
+ * ----------
+ */
+static varattrib *
+toast_fetch_datum(varattrib *attr)
{
- elog(ERROR, "heap_tuple_untoast_attr() called");
+ 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 854b68e00d2..1c52d098a1a 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 721297680ed..2187b8db443 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.
@@ -1521,6 +1523,11 @@ heap_drop_with_catalog(const char *relname)
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
* try to do something with the doomed relation.
@@ -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 bf706d5146c..bd34ee0a200 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;
@@ -449,10 +451,16 @@ 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 d0bd89fdfd2..595c09dc4ec 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 ||
@@ -1171,6 +1172,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 da872872175..d3da6cc2b27 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 75f6562a8f6..91769120f95 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 b17185e4639..98a00acb8fc 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 <name> 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 76428b969c5..982ca9116dc 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 cbba1223555..fd30bd58ac5 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 2459b6507cd..17c77da8504 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 fe96d77f43a..3fc00613042 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 484b8e8f942..09237e52755 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 <limits.h>
@@ -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 04e40406f8b..b2c3080ca3c 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 f8c3a3f1560..f618a10eb8e 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 2d1ae16c5eb..cf7d3618426 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 b5f66f11188..7029ca73b89 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 ea29ffaff55..63c09384612 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 4442d00351f..412445e727f 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);
-
- /* ----------
- * Allocate a temporary result and compress into it
- * ----------
- */
- tmp = (lztext *) palloc(tmp_size);
- pglz_compress(str, rawsize, tmp, NULL);
+ result = (lztext *)palloc(VARHDRSZ + rawsize);
- /* ----------
- * 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;
-
- pglz_decomp_init(&ds1, lz1);
- pglz_decomp_init(&ds2, lz2);
-
- for (;;)
- {
- c1 = pglz_decomp_getchar(&ds1);
- c2 = pglz_decomp_getchar(&ds2);
-
- 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;
- }
- }
+ return 0;
- pglz_decomp_end(&ds1);
- pglz_decomp_end(&ds2);
+ VARATT_GETPLAIN(lz1, p1);
+ VARATT_GETPLAIN(lz2, p2);
+
+ 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;
+ }
+
+ 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 02fc1863b60..9d880a4aa69 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 9a666ebd708..720517c9536 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 7e1a9ead666..a5127ece26f 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 156237862b1..a51eadfc5ef 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 4455c04c556..5f0b1fa776a 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -1,7 +1,7 @@
/*
* Edmund Mergl <E.Mergl@bawue.de>
*
- * $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 f4e6ac5be37..493b4e64465 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 c5fbeadff6a..6660d15f1d6 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 5b2a2ea0163..5bd339a5cc9 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 71549bb9256..4b3f498a2af 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 3e4abe828bb..b5d2e18e104 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 53c6ec41677..6f17cb589ae 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 fedd29f0c3e..114bcff29a4 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 4914acc8e35..0cf0b7859e8 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;