agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Ildus Kurbangaliev <[email protected]>
Subject: [PATCH 4/8] Add pglz compression method
Date: Mon, 18 Jun 2018 15:48:28 +0300
Signed-off-by: Ildus Kurbangaliev <[email protected]>
---
src/backend/access/compression/Makefile | 2 +-
src/backend/access/compression/cm_pglz.c | 166 ++++++++++++++++++++
src/include/access/cmapi.h | 2 +-
src/include/catalog/pg_am.dat | 3 +
src/include/catalog/pg_attr_compression.dat | 2 +-
src/include/catalog/pg_proc.dat | 6 +
6 files changed, 178 insertions(+), 3 deletions(-)
create mode 100644 src/backend/access/compression/cm_pglz.c
diff --git a/src/backend/access/compression/Makefile b/src/backend/access/compression/Makefile
index a09dc787ed..14286920d3 100644
--- a/src/backend/access/compression/Makefile
+++ b/src/backend/access/compression/Makefile
@@ -12,6 +12,6 @@ subdir = src/backend/access/compression
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = cmapi.o
+OBJS = cm_pglz.o cmapi.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/compression/cm_pglz.c b/src/backend/access/compression/cm_pglz.c
new file mode 100644
index 0000000000..b693cd09f2
--- /dev/null
+++ b/src/backend/access/compression/cm_pglz.c
@@ -0,0 +1,166 @@
+/*-------------------------------------------------------------------------
+ *
+ * cm_pglz.c
+ * pglz compression method
+ *
+ * Copyright (c) 2015-2018, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/access/compression/cm_pglz.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+#include "access/cmapi.h"
+#include "commands/defrem.h"
+#include "common/pg_lzcompress.h"
+#include "nodes/parsenodes.h"
+#include "utils/builtins.h"
+
+#define PGLZ_OPTIONS_COUNT 6
+
+static char *PGLZ_options[PGLZ_OPTIONS_COUNT] = {
+ "min_input_size",
+ "max_input_size",
+ "min_comp_rate",
+ "first_success_by",
+ "match_size_good",
+ "match_size_drop"
+};
+
+/*
+ * Convert value from reloptions to int32, and report if it is not correct.
+ * Also checks parameter names
+ */
+static int32
+parse_option(char *name, char *value)
+{
+ int i;
+
+ for (i = 0; i < PGLZ_OPTIONS_COUNT; i++)
+ {
+ if (strcmp(PGLZ_options[i], name) == 0)
+ return pg_atoi(value, 4, 0);
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_PARAMETER),
+ errmsg("unexpected parameter for pglz: \"%s\"", name)));
+}
+
+/*
+ * Check PGLZ options if specified
+ */
+static void
+pglz_cmcheck(Form_pg_attribute att, List *options)
+{
+ ListCell *lc;
+
+ foreach(lc, options)
+ {
+ DefElem *def = (DefElem *) lfirst(lc);
+
+ parse_option(def->defname, defGetString(def));
+ }
+}
+
+/*
+ * Configure PGLZ_Strategy struct for compression function
+ */
+static void *
+pglz_cminitstate(Oid acoid, List *options)
+{
+ ListCell *lc;
+ PGLZ_Strategy *strategy = palloc(sizeof(PGLZ_Strategy));
+
+ /* initialize with default strategy values */
+ memcpy(strategy, PGLZ_strategy_default, sizeof(PGLZ_Strategy));
+ foreach(lc, options)
+ {
+ DefElem *def = (DefElem *) lfirst(lc);
+ int32 val = parse_option(def->defname, defGetString(def));
+
+ /* fill the strategy */
+ if (strcmp(def->defname, "min_input_size") == 0)
+ strategy->min_input_size = val;
+ else if (strcmp(def->defname, "max_input_size") == 0)
+ strategy->max_input_size = val;
+ else if (strcmp(def->defname, "min_comp_rate") == 0)
+ strategy->min_comp_rate = val;
+ else if (strcmp(def->defname, "first_success_by") == 0)
+ strategy->first_success_by = val;
+ else if (strcmp(def->defname, "match_size_good") == 0)
+ strategy->match_size_good = val;
+ else if (strcmp(def->defname, "match_size_drop") == 0)
+ strategy->match_size_drop = val;
+ }
+ return (void *) strategy;
+}
+
+static struct varlena *
+pglz_cmcompress(CompressionAmOptions *cmoptions, const struct varlena *value)
+{
+ int32 valsize,
+ len;
+ struct varlena *tmp = NULL;
+ PGLZ_Strategy *strategy;
+
+ valsize = VARSIZE_ANY_EXHDR(DatumGetPointer(value));
+ strategy = (PGLZ_Strategy *) cmoptions->acstate;
+
+ Assert(strategy != NULL);
+ if (valsize < strategy->min_input_size ||
+ valsize > strategy->max_input_size)
+ return NULL;
+
+ tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
+ VARHDRSZ_CUSTOM_COMPRESSED);
+ len = pglz_compress(VARDATA_ANY(value),
+ valsize,
+ (char *) tmp + VARHDRSZ_CUSTOM_COMPRESSED,
+ strategy);
+
+ if (len >= 0)
+ {
+ SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_CUSTOM_COMPRESSED);
+ return tmp;
+ }
+
+ pfree(tmp);
+ return NULL;
+}
+
+static struct varlena *
+pglz_cmdecompress(CompressionAmOptions *cmoptions, const struct varlena *value)
+{
+ struct varlena *result;
+ int32 resultlen;
+
+ Assert(VARATT_IS_CUSTOM_COMPRESSED(value));
+ resultlen = VARRAWSIZE_4B_C(value) + VARHDRSZ;
+ result = (struct varlena *) palloc(resultlen);
+
+ SET_VARSIZE(result, resultlen);
+ if (pglz_decompress((char *) value + VARHDRSZ_CUSTOM_COMPRESSED,
+ VARSIZE(value) - VARHDRSZ_CUSTOM_COMPRESSED,
+ VARDATA(result),
+ VARRAWSIZE_4B_C(value)) < 0)
+ elog(ERROR, "pglz: compressed data is corrupted");
+
+ return result;
+}
+
+/* pglz is the default compression method */
+Datum
+pglzhandler(PG_FUNCTION_ARGS)
+{
+ CompressionAmRoutine *routine = makeNode(CompressionAmRoutine);
+
+ routine->cmcheck = pglz_cmcheck;
+ routine->cminitstate = pglz_cminitstate;
+ routine->cmcompress = pglz_cmcompress;
+ routine->cmdecompress = pglz_cmdecompress;
+
+ PG_RETURN_POINTER(routine);
+}
diff --git a/src/include/access/cmapi.h b/src/include/access/cmapi.h
index 9e48f0d49f..1be98a60a5 100644
--- a/src/include/access/cmapi.h
+++ b/src/include/access/cmapi.h
@@ -19,7 +19,7 @@
#include "nodes/pg_list.h"
#define IsBuiltinCompression(cmid) ((cmid) < FirstBootstrapObjectId)
-#define DefaultCompressionOid (InvalidOid)
+#define DefaultCompressionOid (PGLZ_AC_OID)
typedef struct CompressionAmRoutine CompressionAmRoutine;
diff --git a/src/include/catalog/pg_am.dat b/src/include/catalog/pg_am.dat
index 393b41dd68..4bf1c49d11 100644
--- a/src/include/catalog/pg_am.dat
+++ b/src/include/catalog/pg_am.dat
@@ -33,5 +33,8 @@
{ oid => '3580', oid_symbol => 'BRIN_AM_OID',
descr => 'block range index (BRIN) access method',
amname => 'brin', amhandler => 'brinhandler', amtype => 'i' },
+{ oid => '4002', oid_symbol => 'PGLZ_COMPRESSION_AM_OID',
+ descr => 'pglz compression access method',
+ amname => 'pglz', amhandler => 'pglzhandler', amtype => 'c' },
]
diff --git a/src/include/catalog/pg_attr_compression.dat b/src/include/catalog/pg_attr_compression.dat
index 30faae0de4..4e72bde16c 100644
--- a/src/include/catalog/pg_attr_compression.dat
+++ b/src/include/catalog/pg_attr_compression.dat
@@ -18,6 +18,6 @@
[
-
+{ acoid => '4002', acname => 'pglz' },
]
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4cfe44a8da..5ff8e886bd 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -909,6 +909,12 @@
prorettype => 'void', proargtypes => 'regclass int8',
prosrc => 'brin_desummarize_range' },
+# Compression access method handlers
+{ oid => '4009', descr => 'pglz compression access method handler',
+ proname => 'pglzhandler', provolatile => 'v',
+ prorettype => 'compression_am_handler', proargtypes => 'internal',
+ prosrc => 'pglzhandler' },
+
{ oid => '338', descr => 'validate an operator class',
proname => 'amvalidate', provolatile => 'v', prorettype => 'bool',
proargtypes => 'oid', prosrc => 'amvalidate' },
--
2.21.0
--MP_//XvyHCr_hJMvh/tp2R3=uJa
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=0005-Add-zlib-compression-method-v22.patch
view thread (8+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 4/8] Add pglz compression method
In-Reply-To: <no-message-id-225557@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox