v3-0001-Change-how-list-partition-constraint-is-emitted-efujita-2.patch
text/x-diff
Filename: v3-0001-Change-how-list-partition-constraint-is-emitted-efujita-2.patch
Type: text/x-diff
Part: 0
Message:
Re: list partition constraint shape
Patch
Format: context
Series: patch v3-0001
| File | + | − |
|---|---|---|
| src/backend/catalog/partition.c | 65 | 0 |
| src/test/regress/expected/create_table.out | 15 | 0 |
| src/test/regress/expected/foreign_data.out | 3 | 0 |
| src/test/regress/expected/partition_prune.out | 2 | 0 |
| src/test/regress/sql/create_table.sql | 6 | 0 |
*** a/src/backend/catalog/partition.c
--- b/src/backend/catalog/partition.c
***************
*** 1625,1642 **** make_partition_op_expr(PartitionKey key, int keynum,
{
case PARTITION_STRATEGY_LIST:
{
! ScalarArrayOpExpr *saopexpr;
! /* Build leftop = ANY (rightop) */
! saopexpr = makeNode(ScalarArrayOpExpr);
! saopexpr->opno = operoid;
! saopexpr->opfuncid = get_opcode(operoid);
! saopexpr->useOr = true;
! saopexpr->inputcollid = key->partcollation[keynum];
! saopexpr->args = list_make2(arg1, arg2);
! saopexpr->location = -1;
! result = (Expr *) saopexpr;
break;
}
--- 1625,1684 ----
{
case PARTITION_STRATEGY_LIST:
{
! List *elems = (List *) arg2;
! int nelems = list_length(elems);
! Assert(nelems >= 1);
! Assert(keynum == 0);
! if (nelems > 1 &&
! !type_is_array(key->parttypid[keynum]))
! {
! ArrayExpr *arrexpr;
! ScalarArrayOpExpr *saopexpr;
!
! /* Construct an ArrayExpr for the right-hand inputs */
! arrexpr = makeNode(ArrayExpr);
! arrexpr->array_typeid =
! get_array_type(key->parttypid[keynum]);
! arrexpr->array_collid = key->parttypcoll[keynum];
! arrexpr->element_typeid = key->parttypid[keynum];
! arrexpr->elements = elems;
! arrexpr->multidims = false;
! arrexpr->location = -1;
!
! /* Build leftop = ANY (rightop) */
! saopexpr = makeNode(ScalarArrayOpExpr);
! saopexpr->opno = operoid;
! saopexpr->opfuncid = get_opcode(operoid);
! saopexpr->useOr = true;
! saopexpr->inputcollid = key->partcollation[keynum];
! saopexpr->args = list_make2(arg1, arrexpr);
! saopexpr->location = -1;
!
! result = (Expr *) saopexpr;
! }
! else
! {
! List *elemops = NIL;
! ListCell *lc;
!
! foreach (lc, elems)
! {
! Expr *elem = lfirst(lc),
! *elemop;
!
! elemop = make_opclause(operoid,
! BOOLOID,
! false,
! arg1, elem,
! InvalidOid,
! key->partcollation[keynum]);
! elemops = lappend(elemops, elemop);
! }
!
! result = nelems > 1 ? makeBoolExpr(OR_EXPR, elemops, -1) : linitial(elemops);
! }
break;
}
***************
*** 1758,1768 **** get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
PartitionKey key = RelationGetPartitionKey(parent);
List *result;
Expr *keyCol;
- ArrayExpr *arr;
Expr *opexpr;
NullTest *nulltest;
ListCell *cell;
! List *arrelems = NIL;
bool list_has_null = false;
/*
--- 1800,1809 ----
PartitionKey key = RelationGetPartitionKey(parent);
List *result;
Expr *keyCol;
Expr *opexpr;
NullTest *nulltest;
ListCell *cell;
! List *elems = NIL;
bool list_has_null = false;
/*
***************
*** 1828,1834 **** get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
false, /* isnull */
key->parttypbyval[0]);
! arrelems = lappend(arrelems, val);
}
}
else
--- 1869,1875 ----
false, /* isnull */
key->parttypbyval[0]);
! elems = lappend(elems, val);
}
}
else
***************
*** 1843,1872 **** get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
if (val->constisnull)
list_has_null = true;
else
! arrelems = lappend(arrelems, copyObject(val));
}
}
! if (arrelems)
{
! /* Construct an ArrayExpr for the non-null partition values */
! arr = makeNode(ArrayExpr);
! arr->array_typeid = !type_is_array(key->parttypid[0])
! ? get_array_type(key->parttypid[0])
! : key->parttypid[0];
! arr->array_collid = key->parttypcoll[0];
! arr->element_typeid = key->parttypid[0];
! arr->elements = arrelems;
! arr->multidims = false;
! arr->location = -1;
!
! /* Generate the main expression, i.e., keyCol = ANY (arr) */
opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
! keyCol, (Expr *) arr);
}
else
{
! /* If there are no partition values, we don't need an = ANY expr */
opexpr = NULL;
}
--- 1884,1908 ----
if (val->constisnull)
list_has_null = true;
else
! elems = lappend(elems, copyObject(val));
}
}
! if (elems)
{
! /*
! * Generate the operator expression from the non-null partition
! * values.
! */
opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
! keyCol, (Expr *) elems);
}
else
{
! /*
! * If there are no partition values, we don't need an operator
! * expression.
! */
opexpr = NULL;
}
*** a/src/test/regress/expected/create_table.out
--- b/src/test/regress/expected/create_table.out
***************
*** 737,743 **** CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10);
a | text | | | | extended | |
b | integer | | not null | 1 | plain | |
Partition of: parted FOR VALUES IN ('b')
! Partition constraint: ((a IS NOT NULL) AND (a = ANY (ARRAY['b'::text])))
Check constraints:
"check_a" CHECK (length(a) > 0)
"part_b_b_check" CHECK (b >= 0)
--- 737,743 ----
a | text | | | | extended | |
b | integer | | not null | 1 | plain | |
Partition of: parted FOR VALUES IN ('b')
! Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text))
Check constraints:
"check_a" CHECK (length(a) > 0)
"part_b_b_check" CHECK (b >= 0)
***************
*** 750,756 **** Check constraints:
a | text | | | | extended | |
b | integer | | not null | 0 | plain | |
Partition of: parted FOR VALUES IN ('c')
! Partition constraint: ((a IS NOT NULL) AND (a = ANY (ARRAY['c'::text])))
Partition key: RANGE (b)
Check constraints:
"check_a" CHECK (length(a) > 0)
--- 750,756 ----
a | text | | | | extended | |
b | integer | | not null | 0 | plain | |
Partition of: parted FOR VALUES IN ('c')
! Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text))
Partition key: RANGE (b)
Check constraints:
"check_a" CHECK (length(a) > 0)
***************
*** 764,770 **** Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10)
a | text | | | | extended | |
b | integer | | not null | 0 | plain | |
Partition of: part_c FOR VALUES FROM (1) TO (10)
! Partition constraint: ((a IS NOT NULL) AND (a = ANY (ARRAY['c'::text])) AND (b IS NOT NULL) AND (b >= 1) AND (b < 10))
Check constraints:
"check_a" CHECK (length(a) > 0)
--- 764,770 ----
a | text | | | | extended | |
b | integer | | not null | 0 | plain | |
Partition of: part_c FOR VALUES FROM (1) TO (10)
! Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text) AND (b IS NOT NULL) AND (b >= 1) AND (b < 10))
Check constraints:
"check_a" CHECK (length(a) > 0)
***************
*** 863,865 **** Partition key: LIST (a)
--- 863,877 ----
Number of partitions: 0
DROP TABLE parted_col_comment;
+ -- list partitioning on array type column
+ CREATE TABLE arrlp (a int[]) PARTITION BY LIST (a);
+ CREATE TABLE arrlp12 PARTITION OF arrlp FOR VALUES IN ('{1}', '{2}');
+ \d+ arrlp12
+ Table "public.arrlp12"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+ --------+-----------+-----------+----------+---------+----------+--------------+-------------
+ a | integer[] | | | | extended | |
+ Partition of: arrlp FOR VALUES IN ('{1}', '{2}')
+ Partition constraint: ((a IS NOT NULL) AND (((a)::anyarray OPERATOR(pg_catalog.=) '{1}'::integer[]) OR ((a)::anyarray OPERATOR(pg_catalog.=) '{2}'::integer[])))
+
+ DROP TABLE arrlp;
*** a/src/test/regress/expected/foreign_data.out
--- b/src/test/regress/expected/foreign_data.out
***************
*** 1863,1869 **** Partitions: pt2_1 FOR VALUES IN (1)
c2 | text | | | | | extended | |
c3 | date | | | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1])))
Server: s0
FDW options: (delimiter ',', quote '"', "be quoted" 'value')
--- 1863,1869 ----
c2 | text | | | | | extended | |
c3 | date | | | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
Server: s0
FDW options: (delimiter ',', quote '"', "be quoted" 'value')
***************
*** 1935,1941 **** Partitions: pt2_1 FOR VALUES IN (1)
c2 | text | | | | | extended | |
c3 | date | | | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1])))
Server: s0
FDW options: (delimiter ',', quote '"', "be quoted" 'value')
--- 1935,1941 ----
c2 | text | | | | | extended | |
c3 | date | | | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
Server: s0
FDW options: (delimiter ',', quote '"', "be quoted" 'value')
***************
*** 1963,1969 **** Partitions: pt2_1 FOR VALUES IN (1)
c2 | text | | | | | extended | |
c3 | date | | not null | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1])))
Check constraints:
"p21chk" CHECK (c2 <> ''::text)
Server: s0
--- 1963,1969 ----
c2 | text | | | | | extended | |
c3 | date | | not null | | | plain | |
Partition of: pt2 FOR VALUES IN (1)
! Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
Check constraints:
"p21chk" CHECK (c2 <> ''::text)
Server: s0
*** a/src/test/regress/expected/partition_prune.out
--- b/src/test/regress/expected/partition_prune.out
***************
*** 1014,1036 **** explain (costs off) select * from boolpart where a = false;
Append
-> Seq Scan on boolpart_f
Filter: (NOT a)
- -> Seq Scan on boolpart_t
- Filter: (NOT a)
-> Seq Scan on boolpart_default
Filter: (NOT a)
! (7 rows)
explain (costs off) select * from boolpart where not a = false;
QUERY PLAN
------------------------------------
Append
- -> Seq Scan on boolpart_f
- Filter: a
-> Seq Scan on boolpart_t
Filter: a
-> Seq Scan on boolpart_default
Filter: a
! (7 rows)
explain (costs off) select * from boolpart where a is true or a is not true;
QUERY PLAN
--- 1014,1032 ----
Append
-> Seq Scan on boolpart_f
Filter: (NOT a)
-> Seq Scan on boolpart_default
Filter: (NOT a)
! (5 rows)
explain (costs off) select * from boolpart where not a = false;
QUERY PLAN
------------------------------------
Append
-> Seq Scan on boolpart_t
Filter: a
-> Seq Scan on boolpart_default
Filter: a
! (5 rows)
explain (costs off) select * from boolpart where a is true or a is not true;
QUERY PLAN
*** a/src/test/regress/sql/create_table.sql
--- b/src/test/regress/sql/create_table.sql
***************
*** 707,709 **** COMMENT ON COLUMN parted_col_comment.a IS 'Partition key';
--- 707,715 ----
SELECT obj_description('parted_col_comment'::regclass);
\d+ parted_col_comment
DROP TABLE parted_col_comment;
+
+ -- list partitioning on array type column
+ CREATE TABLE arrlp (a int[]) PARTITION BY LIST (a);
+ CREATE TABLE arrlp12 PARTITION OF arrlp FOR VALUES IN ('{1}', '{2}');
+ \d+ arrlp12
+ DROP TABLE arrlp;