Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+5-3
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

+13-2
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

+10
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

+6
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

+13
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

+7
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)