Skip to content

Commit d7c018d

Browse files
committed
Add pglz compression method
Signed-off-by: Ildus Kurbangaliev <i.kurbangaliev@gmail.com>
1 parent b2539d7 commit d7c018d

File tree

6 files changed

+178
-3
lines changed

6 files changed

+178
-3
lines changed

src/backend/access/compression/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ subdir = src/backend/access/compression
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = cmapi.o
15+
OBJS = cm_pglz.o cmapi.o
1616

1717
include $(top_srcdir)/src/backend/common.mk
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* cm_pglz.c
4+
* pglz compression method
5+
*
6+
* Copyright (c) 2015-2018, PostgreSQL Global Development Group
7+
*
8+
*
9+
* IDENTIFICATION
10+
* src/backend/access/compression/cm_pglz.c
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
#include "postgres.h"
15+
#include "access/cmapi.h"
16+
#include "commands/defrem.h"
17+
#include "common/pg_lzcompress.h"
18+
#include "nodes/parsenodes.h"
19+
#include "utils/builtins.h"
20+
21+
#define PGLZ_OPTIONS_COUNT 6
22+
23+
static char *PGLZ_options[PGLZ_OPTIONS_COUNT] = {
24+
"min_input_size",
25+
"max_input_size",
26+
"min_comp_rate",
27+
"first_success_by",
28+
"match_size_good",
29+
"match_size_drop"
30+
};
31+
32+
/*
33+
* Convert value from reloptions to int32, and report if it is not correct.
34+
* Also checks parameter names
35+
*/
36+
static int32
37+
parse_option(char *name, char *value)
38+
{
39+
int i;
40+
41+
for (i = 0; i < PGLZ_OPTIONS_COUNT; i++)
42+
{
43+
if (strcmp(PGLZ_options[i], name) == 0)
44+
return pg_atoi(value, 4, 0);
45+
}
46+
47+
ereport(ERROR,
48+
(errcode(ERRCODE_UNDEFINED_PARAMETER),
49+
errmsg("unexpected parameter for pglz: \"%s\"", name)));
50+
}
51+
52+
/*
53+
* Check PGLZ options if specified
54+
*/
55+
static void
56+
pglz_cmcheck(Form_pg_attribute att, List *options)
57+
{
58+
ListCell *lc;
59+
60+
foreach(lc, options)
61+
{
62+
DefElem *def = (DefElem *) lfirst(lc);
63+
64+
parse_option(def->defname, defGetString(def));
65+
}
66+
}
67+
68+
/*
69+
* Configure PGLZ_Strategy struct for compression function
70+
*/
71+
static void *
72+
pglz_cminitstate(Oid acoid, List *options)
73+
{
74+
ListCell *lc;
75+
PGLZ_Strategy *strategy = palloc(sizeof(PGLZ_Strategy));
76+
77+
/* initialize with default strategy values */
78+
memcpy(strategy, PGLZ_strategy_default, sizeof(PGLZ_Strategy));
79+
foreach(lc, options)
80+
{
81+
DefElem *def = (DefElem *) lfirst(lc);
82+
int32 val = parse_option(def->defname, defGetString(def));
83+
84+
/* fill the strategy */
85+
if (strcmp(def->defname, "min_input_size") == 0)
86+
strategy->min_input_size = val;
87+
else if (strcmp(def->defname, "max_input_size") == 0)
88+
strategy->max_input_size = val;
89+
else if (strcmp(def->defname, "min_comp_rate") == 0)
90+
strategy->min_comp_rate = val;
91+
else if (strcmp(def->defname, "first_success_by") == 0)
92+
strategy->first_success_by = val;
93+
else if (strcmp(def->defname, "match_size_good") == 0)
94+
strategy->match_size_good = val;
95+
else if (strcmp(def->defname, "match_size_drop") == 0)
96+
strategy->match_size_drop = val;
97+
}
98+
return (void *) strategy;
99+
}
100+
101+
static struct varlena *
102+
pglz_cmcompress(CompressionAmOptions *cmoptions, const struct varlena *value)
103+
{
104+
int32 valsize,
105+
len;
106+
struct varlena *tmp = NULL;
107+
PGLZ_Strategy *strategy;
108+
109+
valsize = VARSIZE_ANY_EXHDR(DatumGetPointer(value));
110+
strategy = (PGLZ_Strategy *) cmoptions->acstate;
111+
112+
Assert(strategy != NULL);
113+
if (valsize < strategy->min_input_size ||
114+
valsize > strategy->max_input_size)
115+
return NULL;
116+
117+
tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
118+
VARHDRSZ_CUSTOM_COMPRESSED);
119+
len = pglz_compress(VARDATA_ANY(value),
120+
valsize,
121+
(char *) tmp + VARHDRSZ_CUSTOM_COMPRESSED,
122+
strategy);
123+
124+
if (len >= 0)
125+
{
126+
SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_CUSTOM_COMPRESSED);
127+
return tmp;
128+
}
129+
130+
pfree(tmp);
131+
return NULL;
132+
}
133+
134+
static struct varlena *
135+
pglz_cmdecompress(CompressionAmOptions *cmoptions, const struct varlena *value)
136+
{
137+
struct varlena *result;
138+
int32 resultlen;
139+
140+
Assert(VARATT_IS_CUSTOM_COMPRESSED(value));
141+
resultlen = VARRAWSIZE_4B_C(value) + VARHDRSZ;
142+
result = (struct varlena *) palloc(resultlen);
143+
144+
SET_VARSIZE(result, resultlen);
145+
if (pglz_decompress((char *) value + VARHDRSZ_CUSTOM_COMPRESSED,
146+
VARSIZE(value) - VARHDRSZ_CUSTOM_COMPRESSED,
147+
VARDATA(result),
148+
VARRAWSIZE_4B_C(value)) < 0)
149+
elog(ERROR, "pglz: compressed data is corrupted");
150+
151+
return result;
152+
}
153+
154+
/* pglz is the default compression method */
155+
Datum
156+
pglzhandler(PG_FUNCTION_ARGS)
157+
{
158+
CompressionAmRoutine *routine = makeNode(CompressionAmRoutine);
159+
160+
routine->cmcheck = pglz_cmcheck;
161+
routine->cminitstate = pglz_cminitstate;
162+
routine->cmcompress = pglz_cmcompress;
163+
routine->cmdecompress = pglz_cmdecompress;
164+
165+
PG_RETURN_POINTER(routine);
166+
}

src/include/access/cmapi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "nodes/pg_list.h"
2020

2121
#define IsBuiltinCompression(cmid) ((cmid) < FirstBootstrapObjectId)
22-
#define DefaultCompressionOid (InvalidOid)
22+
#define DefaultCompressionOid (PGLZ_AC_OID)
2323

2424
typedef struct CompressionAmRoutine CompressionAmRoutine;
2525

src/include/catalog/pg_am.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@
3333
{ oid => '3580', oid_symbol => 'BRIN_AM_OID',
3434
descr => 'block range index (BRIN) access method',
3535
amname => 'brin', amhandler => 'brinhandler', amtype => 'i' },
36+
{ oid => '4002', oid_symbol => 'PGLZ_COMPRESSION_AM_OID',
37+
descr => 'pglz compression access method',
38+
amname => 'pglz', amhandler => 'pglzhandler', amtype => 'c' },
3639

3740
]

src/include/catalog/pg_attr_compression.dat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818

1919
[
2020

21-
21+
{ acoid => '4002', acname => 'pglz' },
2222

2323
]

src/include/catalog/pg_proc.dat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,12 @@
909909
prorettype => 'void', proargtypes => 'regclass int8',
910910
prosrc => 'brin_desummarize_range' },
911911

912+
# Compression access method handlers
913+
{ oid => '4009', descr => 'pglz compression access method handler',
914+
proname => 'pglzhandler', provolatile => 'v',
915+
prorettype => 'compression_am_handler', proargtypes => 'internal',
916+
prosrc => 'pglzhandler' },
917+
912918
{ oid => '338', descr => 'validate an operator class',
913919
proname => 'amvalidate', provolatile => 'v', prorettype => 'bool',
914920
proargtypes => 'oid', prosrc => 'amvalidate' },

0 commit comments

Comments
 (0)