mirror of https://github.com/postgres/postgres
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 myselfpull/6/head
parent
148326b994
commit
3682025015
@ -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(); |
@ -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(); |
Loading…
Reference in new issue