@@ -807,17 +807,16 @@ RelationBuildRuleLock(Relation relation)
807
807
* RelationBuildPartitionKey
808
808
* Build and attach to relcache partition key data of relation
809
809
*
810
- * Partitioning key data is stored in CacheMemoryContext to ensure it survives
811
- * as long as the relcache. To avoid leaking memory in that context in case
812
- * of an error partway through this function, we build the structure in the
813
- * working context (which must be short-lived) and copy the completed
814
- * structure into the cache memory.
815
- *
816
- * Also, since the structure being created here is sufficiently complex, we
817
- * make a private child context of CacheMemoryContext for each relation that
818
- * has associated partition key information. That means no complicated logic
819
- * to free individual elements whenever the relcache entry is flushed - just
820
- * delete the context.
810
+ * Partitioning key data is a complex structure; to avoid complicated logic to
811
+ * free individual elements whenever the relcache entry is flushed, we give it
812
+ * its own memory context, child of CacheMemoryContext, which can easily be
813
+ * deleted on its own. To avoid leaking memory in that context in case of an
814
+ * error partway through this function, the context is initially created as a
815
+ * child of CurTransactionContext and only re-parented to CacheMemoryContext
816
+ * at the end, when no further errors are possible. Also, we don't make this
817
+ * context the current context except in very brief code sections, out of fear
818
+ * that some of our callees allocate memory on their own which would be leaked
819
+ * permanently.
821
820
*/
822
821
static void
823
822
RelationBuildPartitionKey (Relation relation )
@@ -850,9 +849,9 @@ RelationBuildPartitionKey(Relation relation)
850
849
RelationGetRelationName (relation ),
851
850
MEMCONTEXT_COPY_NAME ,
852
851
ALLOCSET_SMALL_SIZES );
853
- oldcxt = MemoryContextSwitchTo (partkeycxt );
854
852
855
- key = (PartitionKey ) palloc0 (sizeof (PartitionKeyData ));
853
+ key = (PartitionKey ) MemoryContextAllocZero (partkeycxt ,
854
+ sizeof (PartitionKeyData ));
856
855
857
856
/* Fixed-length attributes */
858
857
form = (Form_pg_partitioned_table ) GETSTRUCT (tuple );
@@ -894,17 +893,20 @@ RelationBuildPartitionKey(Relation relation)
894
893
/*
895
894
* Run the expressions through const-simplification since the planner
896
895
* will be comparing them to similarly-processed qual clause operands,
897
- * and may fail to detect valid matches without this step. We don't
898
- * need to bother with canonicalize_qual() though, because partition
899
- * expressions are not full-fledged qualification clauses.
896
+ * and may fail to detect valid matches without this step; fix
897
+ * opfuncids while at it. We don't need to bother with
898
+ * canonicalize_qual() though, because partition expressions are not
899
+ * full-fledged qualification clauses.
900
900
*/
901
- expr = eval_const_expressions (NULL , (Node * ) expr );
901
+ expr = eval_const_expressions (NULL , expr );
902
+ fix_opfuncids (expr );
902
903
903
- /* May as well fix opfuncids too */
904
- fix_opfuncids (( Node * ) expr );
905
- key -> partexprs = ( List * ) expr ;
904
+ oldcxt = MemoryContextSwitchTo ( partkeycxt );
905
+ key -> partexprs = ( List * ) copyObject ( expr );
906
+ MemoryContextSwitchTo ( oldcxt ) ;
906
907
}
907
908
909
+ oldcxt = MemoryContextSwitchTo (partkeycxt );
908
910
key -> partattrs = (AttrNumber * ) palloc0 (key -> partnatts * sizeof (AttrNumber ));
909
911
key -> partopfamily = (Oid * ) palloc0 (key -> partnatts * sizeof (Oid ));
910
912
key -> partopcintype = (Oid * ) palloc0 (key -> partnatts * sizeof (Oid ));
@@ -919,8 +921,9 @@ RelationBuildPartitionKey(Relation relation)
919
921
key -> parttypbyval = (bool * ) palloc0 (key -> partnatts * sizeof (bool ));
920
922
key -> parttypalign = (char * ) palloc0 (key -> partnatts * sizeof (char ));
921
923
key -> parttypcoll = (Oid * ) palloc0 (key -> partnatts * sizeof (Oid ));
924
+ MemoryContextSwitchTo (oldcxt );
922
925
923
- /* For the hash partitioning, an extended hash function will be used. */
926
+ /* determine support function number to search for */
924
927
procnum = (key -> strategy == PARTITION_STRATEGY_HASH ) ?
925
928
HASHEXTENDED_PROC : BTORDER_PROC ;
926
929
@@ -952,7 +955,7 @@ RelationBuildPartitionKey(Relation relation)
952
955
if (!OidIsValid (funcid ))
953
956
ereport (ERROR ,
954
957
(errcode (ERRCODE_INVALID_OBJECT_DEFINITION ),
955
- errmsg ("operator class \"%s\" of access method %s is missing support function %d for data type \"%s\" " ,
958
+ errmsg ("operator class \"%s\" of access method %s is missing support function %d for type %s " ,
956
959
NameStr (opclassform -> opcname ),
957
960
(key -> strategy == PARTITION_STRATEGY_HASH ) ?
958
961
"hash" : "btree" ,
@@ -989,11 +992,13 @@ RelationBuildPartitionKey(Relation relation)
989
992
990
993
ReleaseSysCache (tuple );
991
994
992
- /* Success --- make the relcache point to the newly constructed key */
995
+ /*
996
+ * Success --- reparent our context and make the relcache point to the
997
+ * newly constructed key
998
+ */
993
999
MemoryContextSetParent (partkeycxt , CacheMemoryContext );
994
1000
relation -> rd_partkeycxt = partkeycxt ;
995
1001
relation -> rd_partkey = key ;
996
- MemoryContextSwitchTo (oldcxt );
997
1002
}
998
1003
999
1004
/*
0 commit comments