diff options
| author | Robert Haas | 2013-07-02 17:35:14 +0000 |
|---|---|---|
| committer | Robert Haas | 2013-07-02 17:38:55 +0000 |
| commit | 3682025015390a8e802e0752589162db7bd70b5d (patch) | |
| tree | b72433fb328d27b2289204e2c19282de29633f22 /src/test/regress | |
| parent | 148326b9940c6f3aa554df83a70c7d4563f67d86 (diff) | |
Add support for multiple kinds of external toast datums.
To that end, support tags rather than lengths for external datums.
As an example of how this can be used, add support or "indirect"
tuples which point to some externally allocated memory containing
a toast tuple. Similar infrastructure could be used for other
purposes, including, perhaps, support for alternative compression
algorithms.
Andres Freund, reviewed by Hitoshi Harada and myself
Diffstat (limited to 'src/test/regress')
| -rw-r--r-- | src/test/regress/expected/indirect_toast.out | 151 | ||||
| -rw-r--r-- | src/test/regress/input/create_function_1.source | 5 | ||||
| -rw-r--r-- | src/test/regress/output/create_function_1.source | 4 | ||||
| -rw-r--r-- | src/test/regress/parallel_schedule | 2 | ||||
| -rw-r--r-- | src/test/regress/regress.c | 92 | ||||
| -rw-r--r-- | src/test/regress/serial_schedule | 1 | ||||
| -rw-r--r-- | src/test/regress/sql/indirect_toast.sql | 61 |
7 files changed, 315 insertions, 1 deletions
diff --git a/src/test/regress/expected/indirect_toast.out b/src/test/regress/expected/indirect_toast.out new file mode 100644 index 00000000000..4f4bf41973a --- /dev/null +++ b/src/test/regress/expected/indirect_toast.out @@ -0,0 +1,151 @@ +CREATE TABLE toasttest(descr text, cnt int DEFAULT 0, f1 text, f2 text); +INSERT INTO toasttest(descr, f1, f2) VALUES('two-compressed', repeat('1234567890',1000), repeat('1234567890',1000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('two-toasted', repeat('1234567890',30000), repeat('1234567890',50000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('one-compressed,one-null', NULL, repeat('1234567890',1000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null', NULL, repeat('1234567890',50000)); +-- check whether indirect tuples works on the most basic level +SELECT descr, substring(make_tuple_indirect(toasttest)::text, 1, 200) FROM toasttest; + descr | substring +-------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + two-compressed | (two-compressed,0,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 + two-toasted | (two-toasted,0,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + one-compressed,one-null | ("one-compressed,one-null",0,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + one-toasted,one-null | ("one-toasted,one-null",0,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- modification without changing varlenas +UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,1,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 + (two-toasted,1,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + ("one-compressed,one-null",1,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",1,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- modification without modifying asigned value +UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,2,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 + (two-toasted,2,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + ("one-compressed,one-null",2,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",2,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- modification modifying, but effectively not changing +UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,3,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 + (two-toasted,3,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + ("one-compressed,one-null",3,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",3,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- check we didn't screw with main/toast tuple visiblity +VACUUM FREEZE toasttest; +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,4,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",4,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- now create a trigger that forces all Datums to be indirect ones +CREATE FUNCTION update_using_indirect() + RETURNS trigger + LANGUAGE plpgsql AS $$ +BEGIN + NEW := make_tuple_indirect(NEW); + RETURN NEW; +END$$; +CREATE TRIGGER toasttest_update_indirect + BEFORE INSERT OR UPDATE + ON toasttest + FOR EACH ROW + EXECUTE PROCEDURE update_using_indirect(); +-- modification without changing varlenas +UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,5,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,5,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",5,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",5,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- modification without modifying asigned value +UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,6,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,6,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",6,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",6,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +-- modification modifying, but effectively not changing +UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,7,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + (two-toasted,7,-1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + ("one-compressed,one-null",7,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",7,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + (two-toasted,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + ("one-compressed,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +(4 rows) + +INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null, via indirect', repeat('1234567890',30000), NULL); +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + (two-toasted,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + ("one-compressed,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + ("one-toasted,one-null, via indirect",0,1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 +(5 rows) + +-- check we didn't screw with main/toast tuple visiblity +VACUUM FREEZE toasttest; +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + substring +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + (two-compressed,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + (two-toasted,8,--123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + ("one-compressed,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 + ("one-toasted,one-null",8,,12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + ("one-toasted,one-null, via indirect",0,1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 +(5 rows) + +DROP TABLE toasttest; +DROP FUNCTION update_using_indirect(); diff --git a/src/test/regress/input/create_function_1.source b/src/test/regress/input/create_function_1.source index a72dd9861c5..aef15182874 100644 --- a/src/test/regress/input/create_function_1.source +++ b/src/test/regress/input/create_function_1.source @@ -52,6 +52,11 @@ CREATE FUNCTION set_ttdummy (int4) AS '@libdir@/regress@DLSUFFIX@' LANGUAGE C STRICT; +CREATE FUNCTION make_tuple_indirect (record) + RETURNS record + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT; + -- Things that shouldn't work: CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source index 61b87ed953a..9761d127e1f 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -47,6 +47,10 @@ CREATE FUNCTION set_ttdummy (int4) RETURNS int4 AS '@libdir@/regress@DLSUFFIX@' LANGUAGE C STRICT; +CREATE FUNCTION make_tuple_indirect (record) + RETURNS record + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT; -- Things that shouldn't work: CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL AS 'SELECT ''not an integer'';'; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 2af28b15029..4bb9cc78579 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -98,7 +98,7 @@ test: event_trigger # ---------- # Another group of parallel tests # ---------- -test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json +test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json indirect_toast # ---------- # Another group of parallel tests diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index e5136cfa7c8..3bd8a152859 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -7,7 +7,9 @@ #include <float.h> #include <math.h> +#include "access/htup_details.h" #include "access/transam.h" +#include "access/tuptoaster.h" #include "access/xact.h" #include "catalog/pg_type.h" #include "commands/sequence.h" @@ -17,6 +19,8 @@ #include "utils/builtins.h" #include "utils/geo_decls.h" #include "utils/rel.h" +#include "utils/typcache.h" +#include "utils/memutils.h" #define P_MAXDIG 12 @@ -35,6 +39,7 @@ extern char *reverse_name(char *string); extern int oldstyle_length(int n, text *t); extern Datum int44in(PG_FUNCTION_ARGS); extern Datum int44out(PG_FUNCTION_ARGS); +extern Datum make_tuple_indirect(PG_FUNCTION_ARGS); #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; @@ -737,3 +742,90 @@ int44out(PG_FUNCTION_ARGS) *--walk = '\0'; PG_RETURN_CSTRING(result); } + +PG_FUNCTION_INFO_V1(make_tuple_indirect); +Datum +make_tuple_indirect(PG_FUNCTION_ARGS) +{ + HeapTupleHeader rec = PG_GETARG_HEAPTUPLEHEADER(0); + HeapTupleData tuple; + int ncolumns; + Datum *values; + bool *nulls; + + Oid tupType; + int32 tupTypmod; + TupleDesc tupdesc; + + HeapTuple newtup; + + int i; + + MemoryContext old_context; + + /* Extract type info from the tuple itself */ + tupType = HeapTupleHeaderGetTypeId(rec); + tupTypmod = HeapTupleHeaderGetTypMod(rec); + tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + ncolumns = tupdesc->natts; + + /* Build a temporary HeapTuple control structure */ + tuple.t_len = HeapTupleHeaderGetDatumLength(rec); + ItemPointerSetInvalid(&(tuple.t_self)); + tuple.t_tableOid = InvalidOid; + tuple.t_data = rec; + + values = (Datum *) palloc(ncolumns * sizeof(Datum)); + nulls = (bool *) palloc(ncolumns * sizeof(bool)); + + heap_deform_tuple(&tuple, tupdesc, values, nulls); + + old_context = MemoryContextSwitchTo(TopTransactionContext); + + for (i = 0; i < ncolumns; i++) + { + struct varlena *attr; + struct varlena *new_attr; + struct varatt_indirect redirect_pointer; + + /* only work on existing, not-null varlenas */ + if (tupdesc->attrs[i]->attisdropped || + nulls[i] || + tupdesc->attrs[i]->attlen != -1) + continue; + + attr = (struct varlena *) DatumGetPointer(values[i]); + + /* don't recursively indirect */ + if (VARATT_IS_EXTERNAL_INDIRECT(attr)) + continue; + + /* copy datum, so it still lives later */ + if (VARATT_IS_EXTERNAL_ONDISK(attr)) + attr = heap_tuple_fetch_attr(attr); + else + { + struct varlena *oldattr = attr; + attr = palloc0(VARSIZE_ANY(oldattr)); + memcpy(attr, oldattr, VARSIZE_ANY(oldattr)); + } + + /* build indirection Datum */ + new_attr = (struct varlena *) palloc0(INDIRECT_POINTER_SIZE); + redirect_pointer.pointer = attr; + SET_VARTAG_EXTERNAL(new_attr, VARTAG_INDIRECT); + memcpy(VARDATA_EXTERNAL(new_attr), &redirect_pointer, + sizeof(redirect_pointer)); + + values[i] = PointerGetDatum(new_attr); + } + + newtup = heap_form_tuple(tupdesc, values, nulls); + pfree(values); + pfree(nulls); + ReleaseTupleDesc(tupdesc); + + MemoryContextSwitchTo(old_context); + + PG_RETURN_HEAPTUPLEHEADER(newtup->t_data); +} diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index d6eaa7aa4da..ceeca734d3a 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -117,6 +117,7 @@ test: xmlmap test: functional_deps test: advisory_lock test: json +test: indirect_toast test: plancache test: limit test: plpgsql diff --git a/src/test/regress/sql/indirect_toast.sql b/src/test/regress/sql/indirect_toast.sql new file mode 100644 index 00000000000..d502480ad3f --- /dev/null +++ b/src/test/regress/sql/indirect_toast.sql @@ -0,0 +1,61 @@ +CREATE TABLE toasttest(descr text, cnt int DEFAULT 0, f1 text, f2 text); + +INSERT INTO toasttest(descr, f1, f2) VALUES('two-compressed', repeat('1234567890',1000), repeat('1234567890',1000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('two-toasted', repeat('1234567890',30000), repeat('1234567890',50000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('one-compressed,one-null', NULL, repeat('1234567890',1000)); +INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null', NULL, repeat('1234567890',50000)); + +-- check whether indirect tuples works on the most basic level +SELECT descr, substring(make_tuple_indirect(toasttest)::text, 1, 200) FROM toasttest; + +-- modification without changing varlenas +UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); + +-- modification without modifying asigned value +UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); + +-- modification modifying, but effectively not changing +UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); + +UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); + +SELECT substring(toasttest::text, 1, 200) FROM toasttest; +-- check we didn't screw with main/toast tuple visiblity +VACUUM FREEZE toasttest; +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + +-- now create a trigger that forces all Datums to be indirect ones +CREATE FUNCTION update_using_indirect() + RETURNS trigger + LANGUAGE plpgsql AS $$ +BEGIN + NEW := make_tuple_indirect(NEW); + RETURN NEW; +END$$; + +CREATE TRIGGER toasttest_update_indirect + BEFORE INSERT OR UPDATE + ON toasttest + FOR EACH ROW + EXECUTE PROCEDURE update_using_indirect(); + +-- modification without changing varlenas +UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); + +-- modification without modifying asigned value +UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); + +-- modification modifying, but effectively not changing +UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); + +UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); + +INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null, via indirect', repeat('1234567890',30000), NULL); + +SELECT substring(toasttest::text, 1, 200) FROM toasttest; +-- check we didn't screw with main/toast tuple visiblity +VACUUM FREEZE toasttest; +SELECT substring(toasttest::text, 1, 200) FROM toasttest; + +DROP TABLE toasttest; +DROP FUNCTION update_using_indirect(); |
