Skip to content

Commit 8d14756

Browse files
author
Nikita Glukhov
committed
Add null compression method to pg_type
1 parent 6c28edc commit 8d14756

File tree

18 files changed

+305
-212
lines changed

18 files changed

+305
-212
lines changed

src/backend/access/common/heaptuple.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -696,17 +696,26 @@ TupleDescGetAttributeCompression(TupleDesc tupdesc, AttrNumber attnum)
696696
Datum
697697
tuple_compress_attr(TupleDesc tupdesc, AttrNumber attnum, Datum value)
698698
{
699-
AttributeCompression *compression =
699+
AttributeCompression *ac =
700700
TupleDescGetAttributeCompression(tupdesc, attnum);
701-
return compression->routine->compress(value, compression->options);
701+
Datum tmp = ac->routineNull ?
702+
ac->routineNull->compress(value, NULL) :
703+
value;
704+
Datum res = ac->routine->compress(tmp, ac->options);
705+
706+
if (DatumGetPointer(tmp) != DatumGetPointer(value))
707+
pfree(DatumGetPointer(tmp));
708+
709+
return res;
702710
}
703711

704712
Datum
705713
tuple_decompress_attr(TupleDesc tupdesc, int attnum, Datum value)
706714
{
707715
AttributeCompression *compression =
708716
TupleDescGetAttributeCompression(tupdesc, attnum);
709-
return compression->routine->decompress(value, compression->options);
717+
return compression->routine->decompress ?
718+
compression->routine->decompress(value, compression->options) : value;
710719
}
711720

712721
/*
@@ -751,12 +760,7 @@ heap_form_tuple_compress(TupleDesc tupleDescriptor,
751760
break;
752761
}
753762
else if (compress ? compress[i] :
754-
(OidIsValid(tupleDescriptor->attrs[i]->attcompression) ||
755-
(tupleDescriptor->attrs[i]->attlen == -1 &&
756-
OidIsValid(tupleDescriptor->attrs[i]->attrelid) &&
757-
tupleDescriptor->tdcompression &&
758-
tupleDescriptor->tdcompression[i].routine &&
759-
VARATT_IS_EXTERNAL(DatumGetPointer(values[i])))))
763+
tuple_attr_needs_compression(tupleDescriptor, i, values[i]))
760764
{
761765
if (!oldValues)
762766
{

src/backend/access/common/tupdesc.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "utils/acl.h"
3131
#include "utils/builtins.h"
3232
#include "utils/datum.h"
33+
#include "utils/lsyscache.h"
3334
#include "utils/resowner_private.h"
3435
#include "utils/syscache.h"
3536

@@ -764,7 +765,8 @@ TupleDescInitAttrCompression(TupleDesc desc,
764765
List *optionsList,
765766
Datum optionsDatum)
766767
{
767-
AttributeCompression *ac;
768+
AttributeCompression *ac;
769+
Oid nullcmoid;
768770

769771
if (!desc->tdcompression)
770772
desc->tdcompression = (AttributeCompression *)
@@ -777,6 +779,14 @@ TupleDescInitAttrCompression(TupleDesc desc,
777779
ac->options = cmr->options && cmr->options->convert ?
778780
cmr->options->convert(desc->attrs[attnum - 1], optionsList) :
779781
optionsList;
782+
783+
nullcmoid = (cmr->flags & CM_EXTENDED_REPRESENTATION)
784+
? InvalidOid
785+
: get_base_typnullcm(desc->attrs[attnum - 1]->atttypid);
786+
787+
ac->routineNull = OidIsValid(nullcmoid)
788+
? GetCompressionMethodRoutineByCmId(nullcmoid)
789+
: NULL;
780790
}
781791

782792
/*

src/backend/access/heap/tuptoaster.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,10 +1302,7 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
13021302
}
13031303
}
13041304

1305-
if (OidIsValid(att[i]->attcompression) ||
1306-
(att[i]->attlen == -1 &&
1307-
OidIsValid(att[i]->attrelid) &&
1308-
VARATT_IS_EXTERNAL_EXTENDED(DatumGetPointer(new_value))))
1305+
if (tuple_attr_needs_compression(tupleDesc, i, new_value))
13091306
{
13101307
void *compressed_value = DatumGetPointer(
13111308
tuple_compress_attr(tupleDesc, i,

src/backend/catalog/heap.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,8 @@ AddNewRelationType(const char *typeName,
10021002
-1, /* typmod */
10031003
0, /* array dimensions for typBaseType */
10041004
false, /* Type NOT NULL */
1005-
InvalidOid); /* rowtypes never have a collation */
1005+
InvalidOid, /* rowtypes never have a collation */
1006+
InvalidOid); /* compression method - none */
10061007
}
10071008

10081009
/* --------------------------------
@@ -1272,7 +1273,8 @@ heap_create_with_catalog(const char *relname,
12721273
-1, /* typmod */
12731274
0, /* array dimensions for typBaseType */
12741275
false, /* Type NOT NULL */
1275-
InvalidOid); /* rowtypes never have a collation */
1276+
InvalidOid, /* rowtypes never have a collation */
1277+
InvalidOid); /* compression method - none */
12761278

12771279
pfree(relarrayname);
12781280
}

src/backend/catalog/pg_type.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "catalog/indexing.h"
2323
#include "catalog/objectaccess.h"
2424
#include "catalog/pg_collation.h"
25+
#include "catalog/pg_compression.h"
2526
#include "catalog/pg_namespace.h"
2627
#include "catalog/pg_proc.h"
2728
#include "catalog/pg_type.h"
@@ -119,6 +120,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
119120
values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
120121
values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
121122
values[Anum_pg_type_typdefaultcm - 1] = ObjectIdGetDatum(InvalidOid);
123+
values[Anum_pg_type_typnullcm - 1] = ObjectIdGetDatum(InvalidOid);
122124
nulls[Anum_pg_type_typdefaultbin - 1] = true;
123125
nulls[Anum_pg_type_typdefault - 1] = true;
124126
nulls[Anum_pg_type_typacl - 1] = true;
@@ -166,6 +168,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
166168
InvalidOid,
167169
InvalidOid,
168170
NULL,
171+
InvalidOid,
169172
false);
170173

171174
/* Post creation hook for new shell type */
@@ -223,7 +226,8 @@ TypeCreate(Oid newTypeOid,
223226
int32 typeMod,
224227
int32 typNDims, /* Array dimensions for baseType */
225228
bool typeNotNull,
226-
Oid typeCollation)
229+
Oid typeCollation,
230+
Oid nullcmOid)
227231
{
228232
Relation pg_type_desc;
229233
Oid typeObjectId;
@@ -364,6 +368,7 @@ TypeCreate(Oid newTypeOid,
364368
values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
365369
values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
366370
values[Anum_pg_type_typdefaultcm - 1] = ObjectIdGetDatum(InvalidOid);
371+
values[Anum_pg_type_typnullcm - 1] = ObjectIdGetDatum(nullcmOid);
367372

368373
/*
369374
* initialize the default binary value for this type. Check for nulls of
@@ -484,6 +489,7 @@ TypeCreate(Oid newTypeOid,
484489
(defaultTypeBin ?
485490
stringToNode(defaultTypeBin) :
486491
NULL),
492+
nullcmOid,
487493
rebuildDeps);
488494

489495
/* Post creation hook for new type */
@@ -528,6 +534,7 @@ GenerateTypeDependencies(Oid typeNamespace,
528534
Oid baseType,
529535
Oid typeCollation,
530536
Node *defaultExpr,
537+
Oid nullcmOid,
531538
bool rebuild)
532539
{
533540
ObjectAddress myself,
@@ -676,6 +683,12 @@ GenerateTypeDependencies(Oid typeNamespace,
676683
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
677684
}
678685

686+
if (OidIsValid(nullcmOid))
687+
{
688+
ObjectAddressSet(referenced, CompressionMethodRelationId, nullcmOid);
689+
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
690+
}
691+
679692
/* Normal dependency on the default expression. */
680693
if (defaultExpr)
681694
recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);

src/backend/commands/tablecmds.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,8 +1595,8 @@ GetColumnCompressionForAttribute(Form_pg_attribute att)
15951595
{
15961596
ColumnCompression *compression = makeNode(ColumnCompression);
15971597

1598-
compression->methodName = OidIsValid(att->attcompression) ?
1599-
get_compression_method_name(att->attcompression) : NULL;
1598+
compression->methodName = NULL;
1599+
compression->methodOid = att->attcompression;
16001600
compression->options = untransformRelOptions(
16011601
get_attcmoptions(att->attrelid, att->attnum));
16021602

@@ -1607,8 +1607,10 @@ static void
16071607
CheckCompressionMismatch(ColumnCompression *c1, ColumnCompression *c2,
16081608
const char *attributeName)
16091609
{
1610-
char *cmname1 = c1->methodName;
1611-
char *cmname2 = c2->methodName;
1610+
char *cmname1 = c1->methodName ? c1->methodName :
1611+
get_compression_method_name(c1->methodOid);
1612+
char *cmname2 = c2->methodName ? c2->methodName :
1613+
get_compression_method_name(c2->methodOid);
16121614

16131615
if (strcmp(cmname1, cmname2))
16141616
ereport(ERROR,
@@ -5223,14 +5225,17 @@ GetAttributeCompression(ColumnCompression *compression,
52235225
List **optionsList,
52245226
Datum *optionsDatum)
52255227
{
5226-
if (compression)
5228+
if (compression &&
5229+
(compression->methodName || OidIsValid(compression->methodOid)))
52275230
{
5228-
*cmid = get_compression_method_oid(compression->methodName, false);
5231+
*cmid = compression->methodName
5232+
? get_compression_method_oid(compression->methodName, false)
5233+
: compression->methodOid;
52295234
*optionsList = compression->options;
52305235
}
52315236
else
52325237
{
5233-
*cmid = InvalidOid;
5238+
*cmid = get_base_typnullcm(att->atttypid);
52345239
*optionsList = NIL;
52355240
}
52365241

@@ -9512,7 +9517,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
95129517
attTup->attbyval = tform->typbyval;
95139518
attTup->attalign = tform->typalign;
95149519
attTup->attstorage = tform->typstorage;
9515-
attTup->attcompression = InvalidOid;
9520+
attTup->attcompression = get_base_typnullcm(targettype);
95169521

95179522
ReleaseSysCache(typeTuple);
95189523

src/backend/commands/typecmds.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
135135
char alignment = 'i'; /* default alignment */
136136
char storage = 'p'; /* default TOAST storage method */
137137
Oid collation = InvalidOid;
138+
char *nullcmName = NULL;
138139
DefElem *likeTypeEl = NULL;
139140
DefElem *internalLengthEl = NULL;
140141
DefElem *inputNameEl = NULL;
@@ -153,6 +154,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
153154
DefElem *alignmentEl = NULL;
154155
DefElem *storageEl = NULL;
155156
DefElem *collatableEl = NULL;
157+
DefElem *nullcmNameEl = NULL;
156158
Oid inputOid;
157159
Oid outputOid;
158160
Oid receiveOid = InvalidOid;
@@ -164,6 +166,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
164166
Oid array_oid;
165167
Oid typoid;
166168
Oid resulttype;
169+
Oid nullcmOid = InvalidOid;
167170
ListCell *pl;
168171
ObjectAddress address;
169172

@@ -283,6 +286,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
283286
defelp = &storageEl;
284287
else if (pg_strcasecmp(defel->defname, "collatable") == 0)
285288
defelp = &collatableEl;
289+
else if (pg_strcasecmp(defel->defname, "nullcm") == 0)
290+
defelp = &nullcmNameEl;
286291
else
287292
{
288293
/* WARNING, not ERROR, for historical backwards-compatibility */
@@ -416,6 +421,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
416421
}
417422
if (collatableEl)
418423
collation = defGetBoolean(collatableEl) ? DEFAULT_COLLATION_OID : InvalidOid;
424+
if (nullcmNameEl)
425+
nullcmName = defGetString(nullcmNameEl);
419426

420427
/*
421428
* make sure we have our required definitions
@@ -516,6 +523,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
516523
if (analyzeName)
517524
analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
518525

526+
if (nullcmName)
527+
nullcmOid = get_compression_method_oid(nullcmName, false);
519528
/*
520529
* Check permissions on functions. We choose to require the creator/owner
521530
* of a type to also own the underlying functions. Since creating a type
@@ -635,7 +644,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
635644
-1, /* typMod (Domains only) */
636645
0, /* Array Dimensions of typbasetype */
637646
false, /* Type NOT NULL */
638-
collation); /* type's collation */
647+
collation, /* type's collation */
648+
nullcmOid); /* compression method */
639649
Assert(typoid == address.objectId);
640650

641651
/*
@@ -676,7 +686,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
676686
-1, /* typMod (Domains only) */
677687
0, /* Array dimensions of typbasetype */
678688
false, /* Type NOT NULL */
679-
collation); /* type's collation */
689+
collation, /* type's collation */
690+
InvalidOid); /* compression method - none */
680691

681692
pfree(array_type);
682693

@@ -1062,7 +1073,8 @@ DefineDomain(CreateDomainStmt *stmt)
10621073
basetypeMod, /* typeMod value */
10631074
typNDims, /* Array dimensions for base type */
10641075
typNotNull, /* Type NOT NULL */
1065-
domaincoll); /* type's collation */
1076+
domaincoll, /* type's collation */
1077+
InvalidOid); /* compression method - none */
10661078

10671079
/*
10681080
* Process constraints which refer to the domain ID returned by TypeCreate
@@ -1174,7 +1186,8 @@ DefineEnum(CreateEnumStmt *stmt)
11741186
-1, /* typMod (Domains only) */
11751187
0, /* Array dimensions of typbasetype */
11761188
false, /* Type NOT NULL */
1177-
InvalidOid); /* type's collation */
1189+
InvalidOid, /* type's collation */
1190+
InvalidOid); /* compression method - none */
11781191

11791192
/* Enter the enum's values into pg_enum */
11801193
EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
@@ -1214,7 +1227,8 @@ DefineEnum(CreateEnumStmt *stmt)
12141227
-1, /* typMod (Domains only) */
12151228
0, /* Array dimensions of typbasetype */
12161229
false, /* Type NOT NULL */
1217-
InvalidOid); /* type's collation */
1230+
InvalidOid, /* type's collation */
1231+
InvalidOid); /* compression method - none */
12181232

12191233
pfree(enumArrayName);
12201234

@@ -1502,7 +1516,8 @@ DefineRange(CreateRangeStmt *stmt)
15021516
-1, /* typMod (Domains only) */
15031517
0, /* Array dimensions of typbasetype */
15041518
false, /* Type NOT NULL */
1505-
InvalidOid); /* type's collation (ranges never have one) */
1519+
InvalidOid, /* type's collation (ranges never have one) */
1520+
InvalidOid); /* compression method - none */
15061521
Assert(typoid == address.objectId);
15071522

15081523
/* Create the entry in pg_range */
@@ -1544,7 +1559,8 @@ DefineRange(CreateRangeStmt *stmt)
15441559
-1, /* typMod (Domains only) */
15451560
0, /* Array dimensions of typbasetype */
15461561
false, /* Type NOT NULL */
1547-
InvalidOid); /* typcollation */
1562+
InvalidOid, /* typcollation */
1563+
InvalidOid); /* compression method - none */
15481564

15491565
pfree(rangeArrayName);
15501566

@@ -2242,6 +2258,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
22422258
typTup->typbasetype,
22432259
typTup->typcollation,
22442260
defaultExpr,
2261+
InvalidOid,
22452262
true); /* Rebuild is true */
22462263

22472264
InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
@@ -3639,6 +3656,9 @@ AlterTypeDefaultCompression(Oid typeid, ColumnCompression *compression)
36393656
? get_compression_method_oid(compression->methodName, false)
36403657
: InvalidOid;
36413658

3659+
if (cmoid == oldtype->typnullcm)
3660+
cmoid = InvalidOid;
3661+
36423662
if (oldtype->typdefaultcm != cmoid)
36433663
{
36443664
Relation typrel;
@@ -3665,9 +3685,12 @@ AlterTypeDefaultCompression(Oid typeid, ColumnCompression *compression)
36653685
heap_close(typrel, RowExclusiveLock);
36663686

36673687
if (OidIsValid(oldtype->typdefaultcm))
3688+
{
3689+
Assert(oldtype->typdefaultcm != oldtype->typnullcm);
36683690
deleteDependencyRecordsForClass(TypeRelationId, typeid, 0,
36693691
CompressionMethodRelationId,
36703692
DEPENDENCY_NORMAL);
3693+
}
36713694

36723695
if (OidIsValid(cmoid))
36733696
{

src/backend/parser/parse_utilcmd.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ transformColumnCompression(ColumnDef *column, RangeVar *relation,
497497
if (OidIsValid(cmoid))
498498
{
499499
column->compression = makeNode(ColumnCompression);
500-
column->compression->methodName = get_compression_method_name(cmoid);
500+
column->compression->methodName = NULL;
501+
column->compression->methodOid = cmoid;
501502
column->compression->options = NIL;
502503
}
503504
}

0 commit comments

Comments
 (0)