2424#include "catalog/pg_collation.h"
2525#include "catalog/pg_type.h"
2626#include "commands/defrem.h"
27+ #include "commands/tablecmds.h"
2728#include "miscadmin.h"
2829#include "parser/parse_type.h"
2930#include "utils/acl.h"
3031#include "utils/builtins.h"
32+ #include "utils/datum.h"
3133#include "utils/resowner_private.h"
3234#include "utils/syscache.h"
3335
@@ -91,7 +93,7 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
9193 */
9294desc -> natts = natts ;
9395desc -> constr = NULL ;
94- desc -> tdcmroutines = NULL ;
96+ desc -> tdcompression = NULL ;
9597desc -> tdtypeid = RECORDOID ;
9698desc -> tdtypmod = -1 ;
9799desc -> tdhasoid = hasoid ;
@@ -125,7 +127,7 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
125127desc -> attrs = attrs ;
126128desc -> natts = natts ;
127129desc -> constr = NULL ;
128- desc -> tdcmroutines = NULL ;
130+ desc -> tdcompression = NULL ;
129131desc -> tdtypeid = RECORDOID ;
130132desc -> tdtypmod = -1 ;
131133desc -> tdhasoid = hasoid ;
@@ -134,6 +136,35 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
134136return desc ;
135137}
136138
139+ static AttributeCompression *
140+ TupleDescCopyCompression (TupleDesc tupdesc )
141+ {
142+ AttributeCompression * src = tupdesc -> tdcompression ;
143+ AttributeCompression * dst = (AttributeCompression * )
144+ palloc0 (sizeof (* dst )* tupdesc -> natts );
145+ int i ;
146+
147+ for (i = 0 ;i < tupdesc -> natts ;i ++ )
148+ if (src [i ].routine )
149+ {
150+ dst [i ].routine = palloc (sizeof (* dst [i ].routine ));
151+
152+ memcpy (dst [i ].routine ,src [i ].routine ,sizeof (* dst [i ].routine ));
153+
154+ if (DatumGetPointer (src [i ].optionsDatum )!= NULL )
155+ dst [i ].optionsDatum = datumCopy (src [i ].optionsDatum , false,-1 );
156+ else
157+ dst [i ].optionsDatum = src [i ].optionsDatum ;
158+
159+ dst [i ].options = src [i ].routine -> options &&
160+ src [i ].routine -> options -> copy ?
161+ src [i ].routine -> options -> copy (src [i ].options ) :
162+ src [i ].options ;
163+ }
164+
165+ return dst ;
166+ }
167+
137168/*
138169 * CreateTupleDescCopy
139170 *This function creates a new TupleDesc by copying from an existing
@@ -160,6 +191,9 @@ CreateTupleDescCopy(TupleDesc tupdesc)
160191desc -> tdtypeid = tupdesc -> tdtypeid ;
161192desc -> tdtypmod = tupdesc -> tdtypmod ;
162193
194+ if (tupdesc -> tdcompression )
195+ desc -> tdcompression = TupleDescCopyCompression (tupdesc );
196+
163197return desc ;
164198}
165199
@@ -173,7 +207,6 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
173207{
174208TupleDesc desc ;
175209TupleConstr * constr = tupdesc -> constr ;
176- CompressionMethodRoutine * * cmroutines = tupdesc -> tdcmroutines ;
177210int i ;
178211
179212desc = CreateTemplateTupleDesc (tupdesc -> natts ,tupdesc -> tdhasoid );
@@ -218,20 +251,8 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
218251desc -> constr = cpy ;
219252}
220253
221- if (cmroutines )
222- {
223- CompressionMethodRoutine * * cmrs = (CompressionMethodRoutine * * )
224- palloc0 (sizeof (* cmrs )* tupdesc -> natts );
225-
226- for (i = 0 ;i < tupdesc -> natts ;i ++ )
227- if (cmroutines [i ])
228- {
229- cmrs [i ]= palloc (sizeof (* * cmrs ));
230- memcpy (cmrs [i ],cmroutines [i ],sizeof (* * cmrs ));
231- }
232-
233- desc -> tdcmroutines = cmrs ;
234- }
254+ if (tupdesc -> tdcompression )
255+ desc -> tdcompression = TupleDescCopyCompression (tupdesc );
235256
236257desc -> tdtypeid = tupdesc -> tdtypeid ;
237258desc -> tdtypmod = tupdesc -> tdtypmod ;
@@ -279,6 +300,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
279300dst -> attrs [dstAttno - 1 ]-> attnotnull = false;
280301dst -> attrs [dstAttno - 1 ]-> atthasdef = false;
281302dst -> attrs [dstAttno - 1 ]-> attidentity = '\0' ;
303+ dst -> attrs [dstAttno - 1 ]-> attcompression = InvalidOid ;
282304}
283305
284306/*
@@ -324,12 +346,20 @@ FreeTupleDesc(TupleDesc tupdesc)
324346pfree (tupdesc -> constr );
325347}
326348
327- if (tupdesc -> tdcmroutines )
349+ if (tupdesc -> tdcompression )
328350{
329351for (i = 0 ;i < tupdesc -> natts ;i ++ )
330- if (tupdesc -> tdcmroutines [i ])
331- pfree (tupdesc -> tdcmroutines [i ]);
332- pfree (tupdesc -> tdcmroutines );
352+ if (tupdesc -> tdcompression [i ].routine )
353+ {
354+ CompressionMethodRoutine * cmr = tupdesc -> tdcompression [i ].routine ;
355+
356+ if (cmr -> options && cmr -> options -> free )
357+ cmr -> options -> free (tupdesc -> tdcompression [i ].options );
358+
359+ pfree (cmr );
360+ }
361+
362+ pfree (tupdesc -> tdcompression );
333363}
334364
335365pfree (tupdesc );
@@ -506,9 +536,34 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
506536else if (tupdesc2 -> constr != NULL )
507537return false;
508538
509- if (tupdesc1 -> tdcmroutines != tupdesc2 -> tdcmroutines ) /* FIXME compare cmroutines[*] */
539+ if (( tupdesc1 -> tdcompression == NULL ) != ( tupdesc2 -> tdcompression == NULL ))
510540return false;
511541
542+ if (tupdesc1 -> tdcompression == NULL )
543+ return true;
544+
545+ for (i = 0 ;i < tupdesc1 -> natts ;i ++ )
546+ {
547+ AttributeCompression * ac1 = & tupdesc1 -> tdcompression [i ];
548+ AttributeCompression * ac2 = & tupdesc2 -> tdcompression [i ];
549+ CompressionMethodRoutine * cmr1 = ac1 -> routine ;
550+ CompressionMethodRoutine * cmr2 = ac2 -> routine ;
551+
552+ if (!cmr1 != !cmr2 )
553+ return false;
554+
555+ if (!cmr1 )
556+ continue ;
557+
558+ if (memcmp (cmr1 ,cmr2 ,sizeof (* cmr1 )))
559+ return false;
560+
561+ if (cmr1 -> options && cmr1 -> options -> equal
562+ ? !cmr1 -> options -> equal (ac1 -> options ,ac2 -> options )
563+ :ac1 -> options != ac2 -> options )
564+ return false;
565+ }
566+
512567return true;
513568}
514569
@@ -702,6 +757,27 @@ TupleDescInitEntryCollation(TupleDesc desc,
702757desc -> attrs [attributeNumber - 1 ]-> attcollation = collationid ;
703758}
704759
760+ void
761+ TupleDescInitAttrCompression (TupleDesc desc ,
762+ AttrNumber attnum ,
763+ CompressionMethodRoutine * cmr ,
764+ List * optionsList ,
765+ Datum optionsDatum )
766+ {
767+ AttributeCompression * ac ;
768+
769+ if (!desc -> tdcompression )
770+ desc -> tdcompression = (AttributeCompression * )
771+ palloc0 (desc -> natts * sizeof (AttributeCompression ));
772+
773+ ac = & desc -> tdcompression [attnum - 1 ];
774+
775+ ac -> routine = cmr ;
776+ ac -> optionsDatum = optionsDatum ;
777+ ac -> options = cmr -> options && cmr -> options -> convert ?
778+ cmr -> options -> convert (desc -> attrs [attnum - 1 ],optionsList ) :
779+ optionsList ;
780+ }
705781
706782/*
707783 * BuildDescForRelation
@@ -737,8 +813,11 @@ BuildDescForRelation(List *schema)
737813
738814foreach (l ,schema )
739815{
740- ColumnDef * entry = lfirst (l );
741- AclResult aclresult ;
816+ ColumnDef * entry = lfirst (l );
817+ AclResult aclresult ;
818+ CompressionMethodRoutine * cmroutine ;
819+ List * cmoptionsList ;
820+ Datum cmoptionsDatum ;
742821
743822/*
744823 * for each entry in the list, get the name and type information from
@@ -777,21 +856,15 @@ BuildDescForRelation(List *schema)
777856desc -> attrs [attnum - 1 ]-> attislocal = entry -> is_local ;
778857desc -> attrs [attnum - 1 ]-> attinhcount = entry -> inhcount ;
779858
780- if (entry -> compression )
781- {
782- /* Get compression method OID, throwing an error if it doesn't exist. */
783- Oid cmoid = GetCompressionMethodOid (entry -> compression -> methodName ,
784- false);
785- CompressionMethodRoutine * cmr =
786- GetCompressionMethodRoutineByCmId (cmoid );
787-
788- desc -> attrs [attnum - 1 ]-> attcompression = cmoid ;
859+ /* entry->compression is handled in subsequent ALTER TABLE statement */
860+ GetAttributeCompression (NULL ,
861+ desc -> attrs [attnum - 1 ],
862+ & desc -> attrs [attnum - 1 ]-> attcompression ,
863+ & cmroutine ,& cmoptionsList ,& cmoptionsDatum );
789864
790- if (cmr -> addAttr )
791- (* cmr -> addAttr )(desc -> attrs [attnum - 1 ]);
792-
793- /* TODO attcmoptions */
794- }
865+ if (OidIsValid (desc -> attrs [attnum - 1 ]-> attcompression ))
866+ TupleDescInitAttrCompression (desc ,attnum ,cmroutine ,
867+ cmoptionsList ,cmoptionsDatum );
795868}
796869
797870if (has_not_null )