Skip to content

Commit 6543e14

Browse files
committed
Add compression catalog tables and the basic infrastructure
Signed-off-by: Ildus Kurbangaliev <i.kurbangaliev@gmail.com>
1 parent fb71d3c commit 6543e14

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2143
-200
lines changed

src/backend/access/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ subdir = src/backend/access
88
top_builddir = ../../..
99
include $(top_builddir)/src/Makefile.global
1010

11-
SUBDIRS = brin common gin gist hash heap index nbtree rmgrdesc spgist \
12-
table tablesample transam
11+
SUBDIRS = brin common compression gin gist hash heap index nbtree \
12+
rmgrdesc spgist table tablesample transam
1313

1414
include $(top_srcdir)/src/backend/common.mk

src/backend/access/common/indextuple.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,30 @@ index_form_tuple(TupleDesc tupleDescriptor,
7777

7878
/*
7979
* If value is stored EXTERNAL, must fetch it so we are not depending
80-
* on outside storage. This should be improved someday.
80+
* on outside storage. This should be improved someday. If value also
81+
* was compressed by custom compression method then we should
82+
* decompress it too.
8183
*/
8284
if (VARATT_IS_EXTERNAL(DatumGetPointer(values[i])))
85+
{
86+
struct varatt_external toast_pointer;
87+
88+
VARATT_EXTERNAL_GET_POINTER(toast_pointer, DatumGetPointer(values[i]));
89+
if (VARATT_EXTERNAL_IS_CUSTOM_COMPRESSED(toast_pointer))
90+
untoasted_values[i] =
91+
PointerGetDatum(heap_tuple_untoast_attr((struct varlena *)
92+
DatumGetPointer(values[i])));
93+
else
94+
untoasted_values[i] =
95+
PointerGetDatum(heap_tuple_fetch_attr((struct varlena *)
96+
DatumGetPointer(values[i])));
97+
untoasted_free[i] = true;
98+
}
99+
else if (VARATT_IS_CUSTOM_COMPRESSED(DatumGetPointer(values[i])))
83100
{
84101
untoasted_values[i] =
85-
PointerGetDatum(heap_tuple_fetch_attr((struct varlena *)
86-
DatumGetPointer(values[i])));
102+
PointerGetDatum(heap_tuple_untoast_attr((struct varlena *)
103+
DatumGetPointer(values[i])));
87104
untoasted_free[i] = true;
88105
}
89106

@@ -95,7 +112,7 @@ index_form_tuple(TupleDesc tupleDescriptor,
95112
VARSIZE(DatumGetPointer(untoasted_values[i])) > TOAST_INDEX_TARGET &&
96113
(att->attstorage == 'x' || att->attstorage == 'm'))
97114
{
98-
Datum cvalue = toast_compress_datum(untoasted_values[i]);
115+
Datum cvalue = toast_compress_datum(untoasted_values[i], InvalidOid);
99116

100117
if (DatumGetPointer(cvalue) != NULL)
101118
{

src/backend/access/common/reloptions.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,11 +988,100 @@ untransformRelOptions(Datum options)
988988
val = (Node *) makeString(pstrdup(p));
989989
}
990990
result = lappend(result, makeDefElem(pstrdup(s), val, -1));
991+
pfree(s);
991992
}
992993

993994
return result;
994995
}
995996

997+
/*
998+
* helper function for qsort to compare DefElem
999+
*/
1000+
static int
1001+
compare_options(const void *a, const void *b)
1002+
{
1003+
DefElem *da = (DefElem *) lfirst(*(ListCell **) a);
1004+
DefElem *db = (DefElem *) lfirst(*(ListCell **) b);
1005+
1006+
return strcmp(da->defname, db->defname);
1007+
}
1008+
1009+
/*
1010+
* Convert a DefElem list to the text array format that is used in
1011+
* pg_foreign_data_wrapper, pg_foreign_server, pg_user_mapping,
1012+
* pg_foreign_table and pg_attr_compression
1013+
*
1014+
* Returns the array in the form of a Datum, or PointerGetDatum(NULL)
1015+
* if the list is empty.
1016+
*
1017+
* Note: The array is usually stored to database without further
1018+
* processing, hence any validation should be done before this
1019+
* conversion.
1020+
*/
1021+
Datum
1022+
optionListToArray(List *options, bool sorted)
1023+
{
1024+
ArrayBuildState *astate = NULL;
1025+
ListCell *cell;
1026+
List *resoptions = NIL;
1027+
int len = list_length(options);
1028+
1029+
/* sort by option name if needed */
1030+
if (sorted && len > 1)
1031+
resoptions = list_qsort(options, compare_options);
1032+
else
1033+
resoptions = options;
1034+
1035+
foreach(cell, resoptions)
1036+
{
1037+
DefElem *def = lfirst(cell);
1038+
const char *value;
1039+
Size len;
1040+
text *t;
1041+
1042+
value = defGetString(def);
1043+
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
1044+
t = palloc(len + 1);
1045+
SET_VARSIZE(t, len);
1046+
sprintf(VARDATA(t), "%s=%s", def->defname, value);
1047+
1048+
astate = accumArrayResult(astate, PointerGetDatum(t),
1049+
false, TEXTOID,
1050+
CurrentMemoryContext);
1051+
}
1052+
1053+
/* free if the the modified version of list was used */
1054+
if (resoptions != options)
1055+
list_free(resoptions);
1056+
1057+
if (astate)
1058+
return makeArrayResult(astate, CurrentMemoryContext);
1059+
1060+
return PointerGetDatum(NULL);
1061+
}
1062+
1063+
/*
1064+
* Return human readable list of reloptions
1065+
*/
1066+
char *
1067+
formatRelOptions(List *options)
1068+
{
1069+
StringInfoData buf;
1070+
ListCell *cell;
1071+
1072+
initStringInfo(&buf);
1073+
1074+
foreach(cell, options)
1075+
{
1076+
DefElem *def = (DefElem *) lfirst(cell);
1077+
1078+
appendStringInfo(&buf, "%s%s=%s", buf.len > 0 ? ", " : "",
1079+
def->defname, defGetString(def));
1080+
}
1081+
1082+
return buf.data;
1083+
}
1084+
9961085
/*
9971086
* Extract and parse reloptions from a pg_class tuple.
9981087
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#-------------------------------------------------------------------------
2+
#
3+
# Makefile--
4+
# Makefile for access/compression
5+
#
6+
# IDENTIFICATION
7+
# src/backend/access/compression/Makefile
8+
#
9+
#-------------------------------------------------------------------------
10+
11+
subdir = src/backend/access/compression
12+
top_builddir = ../../../..
13+
include $(top_builddir)/src/Makefile.global
14+
15+
OBJS = cmapi.o
16+
17+
include $(top_srcdir)/src/backend/common.mk
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* compression/cmapi.c
4+
* Functions for compression access methods
5+
*
6+
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
*
10+
* IDENTIFICATION
11+
* src/backend/access/compression/cmapi.c
12+
*-------------------------------------------------------------------------
13+
*/
14+
15+
#include "postgres.h"
16+
#include "fmgr.h"
17+
#include "access/cmapi.h"
18+
#include "access/htup_details.h"
19+
#include "access/reloptions.h"
20+
#include "catalog/pg_am.h"
21+
#include "catalog/pg_attr_compression.h"
22+
#include "commands/defrem.h"
23+
#include "utils/syscache.h"
24+
25+
/*
26+
* InvokeCompressionAmHandler - call the specified access method handler routine to get
27+
* its CompressionAmRoutine struct, which will be palloc'd in the caller's context.
28+
*/
29+
CompressionAmRoutine *
30+
InvokeCompressionAmHandler(Oid amhandler)
31+
{
32+
Datum datum;
33+
CompressionAmRoutine *routine;
34+
35+
datum = OidFunctionCall0(amhandler);
36+
routine = (CompressionAmRoutine *) DatumGetPointer(datum);
37+
38+
if (routine == NULL || !IsA(routine, CompressionAmRoutine))
39+
elog(ERROR, "compression method handler function %u "
40+
"did not return an CompressionAmRoutine struct",
41+
amhandler);
42+
43+
return routine;
44+
}
45+
46+
/*
47+
* GetAttrCompressionOptions
48+
*
49+
* Parse array of attribute compression options and return it as a list.
50+
*/
51+
List *
52+
GetAttrCompressionOptions(Oid acoid)
53+
{
54+
HeapTuple tuple;
55+
List *result = NIL;
56+
bool isnull;
57+
Datum acoptions;
58+
59+
tuple = SearchSysCache1(ATTCOMPRESSIONOID, ObjectIdGetDatum(acoid));
60+
if (!HeapTupleIsValid(tuple))
61+
elog(ERROR, "cache lookup failed for an attribute compression %u", acoid);
62+
63+
/* options could be NULL, so we can't use form struct */
64+
acoptions = SysCacheGetAttr(ATTCOMPRESSIONOID, tuple,
65+
Anum_pg_attr_compression_acoptions, &isnull);
66+
67+
if (!isnull)
68+
result = untransformRelOptions(acoptions);
69+
70+
ReleaseSysCache(tuple);
71+
return result;
72+
}
73+
74+
/*
75+
* GetAttrCompressionAmOid
76+
*
77+
* Return access method Oid by attribute compression Oid
78+
*/
79+
Oid
80+
GetAttrCompressionAmOid(Oid acoid)
81+
{
82+
Oid result;
83+
HeapTuple tuple;
84+
Form_pg_attr_compression acform;
85+
86+
/* extract access method Oid */
87+
tuple = SearchSysCache1(ATTCOMPRESSIONOID, ObjectIdGetDatum(acoid));
88+
if (!HeapTupleIsValid(tuple))
89+
elog(ERROR, "cache lookup failed for attribute compression %u", acoid);
90+
91+
acform = (Form_pg_attr_compression) GETSTRUCT(tuple);
92+
result = get_compression_am_oid(NameStr(acform->acname), false);
93+
ReleaseSysCache(tuple);
94+
95+
return result;
96+
}

src/backend/access/heap/heapam.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,8 +2089,9 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid,
20892089
Assert(!HeapTupleHasExternal(tup));
20902090
return tup;
20912091
}
2092-
else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
2093-
return toast_insert_or_update(relation, tup, NULL, options);
2092+
else if (HeapTupleHasExternal(tup)
2093+
|| tup->t_len > TOAST_TUPLE_THRESHOLD)
2094+
return toast_insert_or_update(relation, tup, NULL, options, NULL);
20942095
else
20952096
return tup;
20962097
}
@@ -3508,7 +3509,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
35083509
if (need_toast)
35093510
{
35103511
/* Note we always use WAL and FSM during updates */
3511-
heaptup = toast_insert_or_update(relation, newtup, &oldtup, 0);
3512+
heaptup = toast_insert_or_update(relation, newtup, &oldtup, 0, NULL);
35123513
newtupsize = MAXALIGN(heaptup->t_len);
35133514
}
35143515
else

src/backend/access/heap/rewriteheap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
665665
options |= HEAP_INSERT_NO_LOGICAL;
666666

667667
heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL,
668-
options);
668+
options, NULL);
669669
}
670670
else
671671
heaptup = tup;

0 commit comments

Comments
 (0)