Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7d1bf40

Browse files
committed
light refactoring, enable composite partitioning key (record(...)::TYPE)
1 parent 90c48a5 commit 7d1bf40

File tree

5 files changed

+284
-45
lines changed

5 files changed

+284
-45
lines changed

expected/pathman_expressions.out

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,110 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.canon WHERE val COLLATE "POSIX" < A
9595

9696
DROP TABLE test_exprs.canon CASCADE;
9797
NOTICE: drop cascades to 5 other objects
98+
/*
99+
* Test composite key.
100+
*/
101+
CREATE TABLE test_exprs.composite(a INT4 NOT NULL, b TEXT NOT NULL);
102+
CREATE SEQUENCE test_exprs.composite_seq;
103+
SELECT add_to_pathman_config('test_exprs.composite',
104+
'(a, b)::test_exprs.composite',
105+
NULL);
106+
add_to_pathman_config
107+
-----------------------
108+
t
109+
(1 row)
110+
111+
SELECT add_range_partition('test_exprs.composite',
112+
'(1, ''a'')'::test_exprs.composite,
113+
'(10, ''a'')'::test_exprs.composite);
114+
add_range_partition
115+
------------------------
116+
test_exprs.composite_1
117+
(1 row)
118+
119+
SELECT add_range_partition('test_exprs.composite',
120+
'(10, ''a'')'::test_exprs.composite,
121+
'(20, ''a'')'::test_exprs.composite);
122+
add_range_partition
123+
------------------------
124+
test_exprs.composite_2
125+
(1 row)
126+
127+
SELECT add_range_partition('test_exprs.composite',
128+
'(20, ''a'')'::test_exprs.composite,
129+
'(30, ''a'')'::test_exprs.composite);
130+
add_range_partition
131+
------------------------
132+
test_exprs.composite_3
133+
(1 row)
134+
135+
SELECT add_range_partition('test_exprs.composite',
136+
'(30, ''a'')'::test_exprs.composite,
137+
'(40, ''a'')'::test_exprs.composite);
138+
add_range_partition
139+
------------------------
140+
test_exprs.composite_4
141+
(1 row)
142+
143+
SELECT expr FROM pathman_config; /* check expression */
144+
expr
145+
---------------------------------
146+
ROW(a, b)::test_exprs.composite
147+
(1 row)
148+
149+
INSERT INTO test_exprs.composite VALUES(2, 'a');
150+
INSERT INTO test_exprs.composite VALUES(11, 'a');
151+
INSERT INTO test_exprs.composite VALUES(2, 'b');
152+
INSERT INTO test_exprs.composite VALUES(50, 'b');
153+
ERROR: cannot spawn new partition for key '(50,b)'
154+
SELECT *, tableoid::REGCLASS FROM test_exprs.composite;
155+
a | b | tableoid
156+
----+---+------------------------
157+
2 | a | test_exprs.composite_1
158+
2 | b | test_exprs.composite_1
159+
11 | a | test_exprs.composite_2
160+
(3 rows)
161+
162+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b)::test_exprs.composite < (21, 0)::test_exprs.composite;
163+
QUERY PLAN
164+
----------------------------------------------------------------------------------------------
165+
Append
166+
-> Seq Scan on composite_1
167+
-> Seq Scan on composite_2
168+
-> Seq Scan on composite_3
169+
Filter: (ROW(a, b)::test_exprs.composite < ROW(21, '0'::text)::test_exprs.composite)
170+
(5 rows)
171+
172+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b) < (21, 0)::test_exprs.composite;
173+
QUERY PLAN
174+
------------------------------------------------------------------------
175+
Append
176+
-> Seq Scan on composite_1
177+
Filter: (ROW(a, b) < ROW(21, '0'::text)::test_exprs.composite)
178+
-> Seq Scan on composite_2
179+
Filter: (ROW(a, b) < ROW(21, '0'::text)::test_exprs.composite)
180+
-> Seq Scan on composite_3
181+
Filter: (ROW(a, b) < ROW(21, '0'::text)::test_exprs.composite)
182+
-> Seq Scan on composite_4
183+
Filter: (ROW(a, b) < ROW(21, '0'::text)::test_exprs.composite)
184+
(9 rows)
185+
186+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b)::test_exprs.composite < (21, 0);
187+
QUERY PLAN
188+
----------------------------------------------------------------
189+
Append
190+
-> Seq Scan on composite_1
191+
Filter: (ROW(a, b)::test_exprs.composite < ROW(21, 0))
192+
-> Seq Scan on composite_2
193+
Filter: (ROW(a, b)::test_exprs.composite < ROW(21, 0))
194+
-> Seq Scan on composite_3
195+
Filter: (ROW(a, b)::test_exprs.composite < ROW(21, 0))
196+
-> Seq Scan on composite_4
197+
Filter: (ROW(a, b)::test_exprs.composite < ROW(21, 0))
198+
(9 rows)
199+
200+
DROP TABLE test_exprs.composite CASCADE;
201+
NOTICE: drop cascades to 5 other objects
98202
/* We use this rel to check 'pathman_hooks_enabled' */
99203
CREATE TABLE test_exprs.canary(val INT4 NOT NULL);
100204
CREATE TABLE test_exprs.canary_copy (LIKE test_exprs.canary);

sql/pathman_expressions.sql

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,38 @@ DROP TABLE test_exprs.canon CASCADE;
3434

3535

3636

37+
/*
38+
* Test composite key.
39+
*/
40+
CREATE TABLE test_exprs.composite(a INT4 NOT NULL, b TEXT NOT NULL);
41+
CREATE SEQUENCE test_exprs.composite_seq;
42+
SELECT add_to_pathman_config('test_exprs.composite',
43+
'(a, b)::test_exprs.composite',
44+
NULL);
45+
SELECT add_range_partition('test_exprs.composite',
46+
'(1, ''a'')'::test_exprs.composite,
47+
'(10, ''a'')'::test_exprs.composite);
48+
SELECT add_range_partition('test_exprs.composite',
49+
'(10, ''a'')'::test_exprs.composite,
50+
'(20, ''a'')'::test_exprs.composite);
51+
SELECT add_range_partition('test_exprs.composite',
52+
'(20, ''a'')'::test_exprs.composite,
53+
'(30, ''a'')'::test_exprs.composite);
54+
SELECT add_range_partition('test_exprs.composite',
55+
'(30, ''a'')'::test_exprs.composite,
56+
'(40, ''a'')'::test_exprs.composite);
57+
SELECT expr FROM pathman_config; /* check expression */
58+
INSERT INTO test_exprs.composite VALUES(2, 'a');
59+
INSERT INTO test_exprs.composite VALUES(11, 'a');
60+
INSERT INTO test_exprs.composite VALUES(2, 'b');
61+
INSERT INTO test_exprs.composite VALUES(50, 'b');
62+
SELECT *, tableoid::REGCLASS FROM test_exprs.composite;
63+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b)::test_exprs.composite < (21, 0)::test_exprs.composite;
64+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b) < (21, 0)::test_exprs.composite;
65+
EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.composite WHERE (a, b)::test_exprs.composite < (21, 0);
66+
DROP TABLE test_exprs.composite CASCADE;
67+
68+
3769
/* We use this rel to check 'pathman_hooks_enabled' */
3870
CREATE TABLE test_exprs.canary(val INT4 NOT NULL);
3971
CREATE TABLE test_exprs.canary_copy (LIKE test_exprs.canary);

src/include/pathman.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ typedef struct
157157
} while (0)
158158

159159
/* Check that WalkerContext contains ExprContext (plan execution stage) */
160-
#define WcxtHasExprContext(wcxt) ( (wcxt)->econtext )
160+
#define WcxtHasExprContext(wcxt) ( (wcxt)->econtext != NULL )
161161

162162
/* Examine expression in order to select partitions */
163163
WrapperNode *walk_expr_tree(Expr *expr, const WalkerContext *context);

src/partition_creation.c

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,29 @@ build_raw_range_check_tree(Node *raw_expression,
11711171
const Bound *end_value,
11721172
Oid value_type)
11731173
{
1174+
#define BuildConstExpr(node, value, value_type) \
1175+
do { \
1176+
(node)->val = make_string_value_struct( \
1177+
datum_to_cstring((value), (value_type))); \
1178+
(node)->location = -1; \
1179+
} while (0)
1180+
1181+
#define BuildCmpExpr(node, opname, expr, c) \
1182+
do { \
1183+
(node)->name = list_make1(makeString(opname)); \
1184+
(node)->kind = AEXPR_OP; \
1185+
(node)->lexpr = (Node *) (expr); \
1186+
(node)->rexpr = (Node *) (c); \
1187+
(node)->location = -1; \
1188+
} while (0)
1189+
1190+
#define CopyTypeCastExpr(node, src, argument) \
1191+
do { \
1192+
memcpy((node), (src), sizeof(TypeCast)); \
1193+
(node)->arg = (Node *) (argument); \
1194+
(node)->typeName = (TypeName *) copyObject((node)->typeName); \
1195+
} while (0)
1196+
11741197
BoolExpr *and_oper = makeNode(BoolExpr);
11751198
A_Expr *left_arg = makeNode(A_Expr),
11761199
*right_arg = makeNode(A_Expr);
@@ -1184,33 +1207,45 @@ build_raw_range_check_tree(Node *raw_expression,
11841207
/* Left comparison (VAR >= start_value) */
11851208
if (!IsInfinite(start_value))
11861209
{
1187-
/* Left boundary */
1188-
left_const->val = make_string_value_struct(
1189-
datum_to_cstring(BoundGetValue(start_value), value_type));
1190-
left_const->location = -1;
1210+
/* Build left boundary */
1211+
BuildConstExpr(left_const, BoundGetValue(start_value), value_type);
1212+
1213+
/* Build ">=" clause */
1214+
BuildCmpExpr(left_arg, ">=", raw_expression, left_const);
11911215

1192-
left_arg->name = list_make1(makeString(">="));
1193-
left_arg->kind = AEXPR_OP;
1194-
left_arg->lexpr = raw_expression;
1195-
left_arg->rexpr = (Node *) left_const;
1196-
left_arg->location = -1;
1216+
/* Cast const to expression's type (e.g. composite key, row type) */
1217+
if (IsA(raw_expression, TypeCast))
1218+
{
1219+
TypeCast *cast = makeNode(TypeCast);
1220+
1221+
/* Copy cast to expression's type */
1222+
CopyTypeCastExpr(cast, raw_expression, left_const);
1223+
1224+
left_arg->rexpr = (Node *) cast;
1225+
}
11971226

11981227
and_oper->args = lappend(and_oper->args, left_arg);
11991228
}
12001229

12011230
/* Right comparision (VAR < end_value) */
12021231
if (!IsInfinite(end_value))
12031232
{
1204-
/* Right boundary */
1205-
right_const->val = make_string_value_struct(
1206-
datum_to_cstring(BoundGetValue(end_value), value_type));
1207-
right_const->location = -1;
1233+
/* Build right boundary */
1234+
BuildConstExpr(right_const, BoundGetValue(end_value), value_type);
1235+
1236+
/* Build "<" clause */
1237+
BuildCmpExpr(right_arg, "<", raw_expression, right_const);
12081238

1209-
right_arg->name = list_make1(makeString("<"));
1210-
right_arg->kind = AEXPR_OP;
1211-
right_arg->lexpr = raw_expression;
1212-
right_arg->rexpr = (Node *) right_const;
1213-
right_arg->location = -1;
1239+
/* Cast const to expression's type (e.g. composite key, row type) */
1240+
if (IsA(raw_expression, TypeCast))
1241+
{
1242+
TypeCast *cast = makeNode(TypeCast);
1243+
1244+
/* Copy cast to expression's type */
1245+
CopyTypeCastExpr(cast, raw_expression, right_const);
1246+
1247+
right_arg->rexpr = (Node *) cast;
1248+
}
12141249

12151250
and_oper->args = lappend(and_oper->args, right_arg);
12161251
}
@@ -1220,6 +1255,10 @@ build_raw_range_check_tree(Node *raw_expression,
12201255
elog(ERROR, "cannot create partition with range (-inf, +inf)");
12211256

12221257
return (Node *) and_oper;
1258+
1259+
#undef BuildConstExpr
1260+
#undef BuildCmpExpr
1261+
#undef CopyTypeCastExpr
12231262
}
12241263

12251264
/* Build complete RANGE check constraint */

0 commit comments

Comments
 (0)