@@ -807,17 +807,16 @@ RelationBuildRuleLock(Relation relation)
807807 * RelationBuildPartitionKey
808808 *Build and attach to relcache partition key data of relation
809809 *
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.
821820 */
822821static void
823822RelationBuildPartitionKey (Relation relation )
@@ -850,9 +849,9 @@ RelationBuildPartitionKey(Relation relation)
850849RelationGetRelationName (relation ),
851850MEMCONTEXT_COPY_NAME ,
852851ALLOCSET_SMALL_SIZES );
853- oldcxt = MemoryContextSwitchTo (partkeycxt );
854852
855- key = (PartitionKey )palloc0 (sizeof (PartitionKeyData ));
853+ key = (PartitionKey )MemoryContextAllocZero (partkeycxt ,
854+ sizeof (PartitionKeyData ));
856855
857856/* Fixed-length attributes */
858857form = (Form_pg_partitioned_table )GETSTRUCT (tuple );
@@ -894,17 +893,20 @@ RelationBuildPartitionKey(Relation relation)
894893/*
895894 * Run the expressions through const-simplification since the planner
896895 * 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.
900900 */
901- expr = eval_const_expressions (NULL , (Node * )expr );
901+ expr = eval_const_expressions (NULL ,expr );
902+ fix_opfuncids (expr );
902903
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 ) ;
906907}
907908
909+ oldcxt = MemoryContextSwitchTo (partkeycxt );
908910key -> partattrs = (AttrNumber * )palloc0 (key -> partnatts * sizeof (AttrNumber ));
909911key -> partopfamily = (Oid * )palloc0 (key -> partnatts * sizeof (Oid ));
910912key -> partopcintype = (Oid * )palloc0 (key -> partnatts * sizeof (Oid ));
@@ -919,8 +921,9 @@ RelationBuildPartitionKey(Relation relation)
919921key -> parttypbyval = (bool * )palloc0 (key -> partnatts * sizeof (bool ));
920922key -> parttypalign = (char * )palloc0 (key -> partnatts * sizeof (char ));
921923key -> parttypcoll = (Oid * )palloc0 (key -> partnatts * sizeof (Oid ));
924+ MemoryContextSwitchTo (oldcxt );
922925
923- /*For the hash partitioning, an extended hash functionwill be used. */
926+ /*determine support functionnumber to search for */
924927procnum = (key -> strategy == PARTITION_STRATEGY_HASH ) ?
925928HASHEXTENDED_PROC :BTORDER_PROC ;
926929
@@ -952,7 +955,7 @@ RelationBuildPartitionKey(Relation relation)
952955if (!OidIsValid (funcid ))
953956ereport (ERROR ,
954957(errcode (ERRCODE_INVALID_OBJECT_DEFINITION ),
955- errmsg ("operator class \"%s\" of access method %s is missing support function %d fordata type\"%s\" " ,
958+ errmsg ("operator class \"%s\" of access method %s is missing support function %d for type%s " ,
956959NameStr (opclassform -> opcname ),
957960(key -> strategy == PARTITION_STRATEGY_HASH ) ?
958961"hash" :"btree" ,
@@ -989,11 +992,13 @@ RelationBuildPartitionKey(Relation relation)
989992
990993ReleaseSysCache (tuple );
991994
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+ */
993999MemoryContextSetParent (partkeycxt ,CacheMemoryContext );
9941000relation -> rd_partkeycxt = partkeycxt ;
9951001relation -> rd_partkey = key ;
996- MemoryContextSwitchTo (oldcxt );
9971002}
9981003
9991004/*