@@ -77,15 +77,18 @@ static int cmp_range_entries(const void *p1, const void *p2, void *arg);
7777
7878static bool validate_range_constraint (const Expr * expr ,
7979const PartRelationInfo * prel ,
80+ const AttrNumber part_attno ,
8081Datum * min ,
8182Datum * max );
8283
8384static bool validate_hash_constraint (const Expr * expr ,
8485const PartRelationInfo * prel ,
86+ const AttrNumber part_attno ,
8587uint32 * part_hash );
8688
8789static bool read_opexpr_const (const OpExpr * opexpr ,
8890const PartRelationInfo * prel ,
91+ const AttrNumber part_attno ,
8992Datum * val );
9093
9194static int oid_cmp (const void * p1 ,const void * p2 );
@@ -347,6 +350,7 @@ init_shmem_config(void)
347350void
348351fill_prel_with_partitions (const Oid * partitions ,
349352const uint32 parts_count ,
353+ const char * part_column_name ,
350354PartRelationInfo * prel )
351355{
352356uint32 i ;
@@ -361,7 +365,18 @@ fill_prel_with_partitions(const Oid *partitions,
361365
362366for (i = 0 ;i < PrelChildrenCount (prel );i ++ )
363367{
364- con_expr = get_partition_constraint_expr (partitions [i ],prel -> attnum );
368+ AttrNumber part_attno ;
369+
370+ /* NOTE: Partitions may have different TupleDescs */
371+ part_attno = get_attnum (partitions [i ],part_column_name );
372+
373+ /* Raise ERROR if there's no such column */
374+ if (part_attno == InvalidAttrNumber )
375+ elog (ERROR ,"partition \"%s\" has no column \"%s\"" ,
376+ get_rel_name_or_relid (partitions [i ]),
377+ part_column_name );
378+
379+ con_expr = get_partition_constraint_expr (partitions [i ],part_attno );
365380
366381/* Perform a partitioning_type-dependent task */
367382switch (prel -> parttype )
@@ -370,13 +385,13 @@ fill_prel_with_partitions(const Oid *partitions,
370385{
371386uint32 hash ;/* hash value < parts_count */
372387
373- if (validate_hash_constraint (con_expr ,prel ,& hash ))
388+ if (validate_hash_constraint (con_expr ,prel ,part_attno , & hash ))
374389prel -> children [hash ]= partitions [i ];
375390else
376391{
377392DisablePathman ();/* disable pg_pathman since config is broken */
378393ereport (ERROR ,
379- (errmsg ("Wrong constraint format for HASH partition \"%s\"" ,
394+ (errmsg ("wrong constraint format for HASH partition \"%s\"" ,
380395get_rel_name_or_relid (partitions [i ])),
381396errhint (INIT_ERROR_HINT )));
382397}
@@ -387,7 +402,7 @@ fill_prel_with_partitions(const Oid *partitions,
387402{
388403Datum range_min ,range_max ;
389404
390- if (validate_range_constraint (con_expr ,prel ,
405+ if (validate_range_constraint (con_expr ,prel ,part_attno ,
391406& range_min ,& range_max ))
392407{
393408prel -> ranges [i ].child_oid = partitions [i ];
@@ -398,7 +413,7 @@ fill_prel_with_partitions(const Oid *partitions,
398413{
399414DisablePathman ();/* disable pg_pathman since config is broken */
400415ereport (ERROR ,
401- (errmsg ("Wrong constraint format for RANGE partition \"%s\"" ,
416+ (errmsg ("wrong constraint format for RANGE partition \"%s\"" ,
402417get_rel_name_or_relid (partitions [i ])),
403418errhint (INIT_ERROR_HINT )));
404419}
@@ -905,6 +920,7 @@ cmp_range_entries(const void *p1, const void *p2, void *arg)
905920static bool
906921validate_range_constraint (const Expr * expr ,
907922const PartRelationInfo * prel ,
923+ const AttrNumber part_attno ,
908924Datum * min ,
909925Datum * max )
910926{
@@ -928,23 +944,21 @@ validate_range_constraint(const Expr *expr,
928944
929945if (strategy == BTGreaterEqualStrategyNumber )
930946{
931- if (!read_opexpr_const (opexpr ,prel ,min ))
947+ if (!read_opexpr_const (opexpr ,prel ,part_attno , min ))
932948return false;
933949}
934- else
935- return false;
950+ else return false;
936951
937952/* check that right operand is < operator */
938953opexpr = (OpExpr * )lsecond (boolexpr -> args );
939954strategy = get_op_opfamily_strategy (opexpr -> opno ,tce -> btree_opf );
940955
941956if (strategy == BTLessStrategyNumber )
942957{
943- if (!read_opexpr_const (opexpr ,prel ,max ))
958+ if (!read_opexpr_const (opexpr ,prel ,part_attno , max ))
944959return false;
945960}
946- else
947- return false;
961+ else return false;
948962
949963return true;
950964}
@@ -957,6 +971,7 @@ validate_range_constraint(const Expr *expr,
957971static bool
958972read_opexpr_const (const OpExpr * opexpr ,
959973const PartRelationInfo * prel ,
974+ const AttrNumber part_attno ,
960975Datum * val )
961976{
962977const Node * left ;
@@ -990,7 +1005,7 @@ read_opexpr_const(const OpExpr *opexpr,
9901005else return false;
9911006
9921007/* VAR.attno == partitioned attribute number */
993- if (part_attr -> varoattno != prel -> attnum )
1008+ if (part_attr -> varoattno != part_attno )
9941009return false;
9951010
9961011/* CONST is NOT NULL */
@@ -1026,6 +1041,7 @@ read_opexpr_const(const OpExpr *opexpr,
10261041static bool
10271042validate_hash_constraint (const Expr * expr ,
10281043const PartRelationInfo * prel ,
1044+ const AttrNumber part_attno ,
10291045uint32 * part_hash )
10301046{
10311047const TypeCacheEntry * tce ;
@@ -1079,7 +1095,7 @@ validate_hash_constraint(const Expr *expr,
10791095var = (Var * )linitial (type_hash_proc_expr -> args );
10801096
10811097/* Check that 'var' is the partitioning key attribute */
1082- if (var -> varoattno != prel -> attnum )
1098+ if (var -> varoattno != part_attno )
10831099return false;
10841100
10851101/* Check that PARTITIONS_COUNT is equal to total amount of partitions */