Skip to content

Commit 5db1fd7

Browse files
committed
Fix interaction of TOAST compression with expression indexes.
Before, trying to compress a value for insertion into an expression index would crash. Dilip Kumar, with some editing by me. Report by Jaime Casanova. Discussion: http://postgr.es/m/CAJKUy5gcs0zGOp6JXU2mMVdthYhuQpFk=S3V8DOKT=LZC1L36Q@mail.gmail.com
1 parent 71f4c8c commit 5db1fd7

File tree

6 files changed

+54
-5
lines changed

6 files changed

+54
-5
lines changed

src/backend/access/brin/brin_tuple.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,12 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
220220

221221
/*
222222
* If the BRIN summary and indexed attribute use the same data
223-
* type, we can use the same compression method. Otherwise we
224-
* have to use the default method.
223+
* type and it has a valid compression method, we can use the
224+
* same compression method. Otherwise we have to use the
225+
* default method.
225226
*/
226-
if (att->atttypid == atttype->type_id)
227+
if (att->atttypid == atttype->type_id &&
228+
CompressionMethodIsValid(att->attcompression))
227229
compression = att->attcompression;
228230
else
229231
compression = GetDefaultToastCompression();

src/backend/access/common/indextuple.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,19 @@ index_form_tuple(TupleDesc tupleDescriptor,
103103
(att->attstorage == TYPSTORAGE_EXTENDED ||
104104
att->attstorage == TYPSTORAGE_MAIN))
105105
{
106-
Datum cvalue = toast_compress_datum(untoasted_values[i],
107-
att->attcompression);
106+
Datum cvalue;
107+
char compression = att->attcompression;
108+
109+
/*
110+
* If the compression method is not valid, use the default. We
111+
* don't expect this to happen for regular index columns, which
112+
* inherit the setting from the corresponding table column, but
113+
* we do expect it to happen whenever an expression is indexed.
114+
*/
115+
if (!CompressionMethodIsValid(compression))
116+
compression = GetDefaultToastCompression();
117+
118+
cvalue = toast_compress_datum(untoasted_values[i], compression);
108119

109120
if (DatumGetPointer(cvalue) != NULL)
110121
{

src/backend/catalog/index.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "access/relscan.h"
3131
#include "access/sysattr.h"
3232
#include "access/tableam.h"
33+
#include "access/toast_compression.h"
3334
#include "access/transam.h"
3435
#include "access/visibilitymap.h"
3536
#include "access/xact.h"
@@ -379,6 +380,15 @@ ConstructTupleDescriptor(Relation heapRelation,
379380
to->attalign = typeTup->typalign;
380381
to->atttypmod = exprTypmod(indexkey);
381382

383+
/*
384+
* For expression columns, set attcompression invalid, since
385+
* there's no table column from which to copy the value. Whenever
386+
* we actually need to compress a value, we'll use whatever the
387+
* current value of default_compression_method is at that point
388+
* in time.
389+
*/
390+
to->attcompression = InvalidCompressionMethod;
391+
382392
ReleaseSysCache(tuple);
383393

384394
/*

src/test/regress/expected/compression.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,12 @@ SELECT pg_column_compression(f1) FROM cmdata;
313313
lz4
314314
(2 rows)
315315

316+
-- test expression index
317+
DROP TABLE cmdata2;
318+
CREATE TABLE cmdata2 (f1 TEXT COMPRESSION pglz, f2 TEXT COMPRESSION lz4);
319+
CREATE UNIQUE INDEX idx1 ON cmdata2 ((f1 || f2));
320+
INSERT INTO cmdata2 VALUES((SELECT array_agg(md5(g::TEXT))::TEXT FROM
321+
generate_series(1, 50) g), VERSION());
316322
-- check data is ok
317323
SELECT length(f1) FROM cmdata;
318324
length

src/test/regress/expected/compression_1.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,19 @@ SELECT pg_column_compression(f1) FROM cmdata;
309309
pglz
310310
(2 rows)
311311

312+
-- test expression index
313+
DROP TABLE cmdata2;
314+
CREATE TABLE cmdata2 (f1 TEXT COMPRESSION pglz, f2 TEXT COMPRESSION lz4);
315+
ERROR: unsupported LZ4 compression method
316+
DETAIL: This functionality requires the server to be built with lz4 support.
317+
HINT: You need to rebuild PostgreSQL using --with-lz4.
318+
CREATE UNIQUE INDEX idx1 ON cmdata2 ((f1 || f2));
319+
ERROR: relation "cmdata2" does not exist
320+
INSERT INTO cmdata2 VALUES((SELECT array_agg(md5(g::TEXT))::TEXT FROM
321+
generate_series(1, 50) g), VERSION());
322+
ERROR: relation "cmdata2" does not exist
323+
LINE 1: INSERT INTO cmdata2 VALUES((SELECT array_agg(md5(g::TEXT))::...
324+
^
312325
-- check data is ok
313326
SELECT length(f1) FROM cmdata;
314327
length

src/test/regress/sql/compression.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ SELECT pg_column_compression(f1) FROM cmdata;
130130
VACUUM FULL cmdata;
131131
SELECT pg_column_compression(f1) FROM cmdata;
132132

133+
-- test expression index
134+
DROP TABLE cmdata2;
135+
CREATE TABLE cmdata2 (f1 TEXT COMPRESSION pglz, f2 TEXT COMPRESSION lz4);
136+
CREATE UNIQUE INDEX idx1 ON cmdata2 ((f1 || f2));
137+
INSERT INTO cmdata2 VALUES((SELECT array_agg(md5(g::TEXT))::TEXT FROM
138+
generate_series(1, 50) g), VERSION());
139+
133140
-- check data is ok
134141
SELECT length(f1) FROM cmdata;
135142
SELECT length(f1) FROM cmdata1;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy