22SET search_path = 'public';
33CREATE EXTENSION pg_pathman;
44CREATE SCHEMA test_exprs;
5+ /*
6+ * Test partitioning expression canonicalization process
7+ */
8+ CREATE TABLE test_exprs.canon(c JSONB NOT NULL);
9+ SELECT create_range_partitions('test_exprs.canon', '(C->>''key'')::int8', 1, 10, 2);
10+ create_range_partitions
11+ -------------------------
12+ 2
13+ (1 row)
14+
15+ SELECT expr FROM pathman_config; /* check expression */
16+ expr
17+ -------------------------------
18+ ((c ->> 'key'::text))::bigint
19+ (1 row)
20+
21+ INSERT INTO test_exprs.canon VALUES ('{ "key": 2, "value": 0 }');
22+ SELECT *, tableoid::REGCLASS FROM test_exprs.canon;
23+ c | tableoid
24+ ------------------------+--------------------
25+ {"key": 2, "value": 0} | test_exprs.canon_1
26+ (1 row)
27+
28+ DROP TABLE test_exprs.canon CASCADE;
29+ NOTICE: drop cascades to 3 other objects
30+ CREATE TABLE test_exprs.canon(val TEXT NOT NULL);
31+ CREATE SEQUENCE test_exprs.canon_seq;
32+ SELECT add_to_pathman_config('test_exprs.canon', 'VAL collate "C"', NULL);
33+ add_to_pathman_config
34+ -----------------------
35+ t
36+ (1 row)
37+
38+ SELECT add_range_partition('test_exprs.canon', 'a'::TEXT, 'b');
39+ add_range_partition
40+ ---------------------
41+ test_exprs.canon_1
42+ (1 row)
43+
44+ SELECT add_range_partition('test_exprs.canon', 'b'::TEXT, 'c');
45+ add_range_partition
46+ ---------------------
47+ test_exprs.canon_2
48+ (1 row)
49+
50+ SELECT add_range_partition('test_exprs.canon', 'c'::TEXT, 'd');
51+ add_range_partition
52+ ---------------------
53+ test_exprs.canon_3
54+ (1 row)
55+
56+ SELECT add_range_partition('test_exprs.canon', 'd'::TEXT, 'e');
57+ add_range_partition
58+ ---------------------
59+ test_exprs.canon_4
60+ (1 row)
61+
62+ SELECT expr FROM pathman_config; /* check expression */
63+ expr
64+ -------------------
65+ (val COLLATE "C")
66+ (1 row)
67+
68+ INSERT INTO test_exprs.canon VALUES ('b');
69+ SELECT *, tableoid::REGCLASS FROM test_exprs.canon;
70+ val | tableoid
71+ -----+--------------------
72+ b | test_exprs.canon_2
73+ (1 row)
74+
75+ EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.canon WHERE val COLLATE "C" < ALL (array['b', 'c']);
76+ QUERY PLAN
77+ ---------------------------
78+ Append
79+ -> Seq Scan on canon_1
80+ (2 rows)
81+
82+ EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.canon WHERE val COLLATE "POSIX" < ALL (array['b', 'c']);
83+ QUERY PLAN
84+ -----------------------------------------------------------
85+ Append
86+ -> Seq Scan on canon_1
87+ Filter: ((val)::text < 'b'::text COLLATE "POSIX")
88+ -> Seq Scan on canon_2
89+ Filter: ((val)::text < 'b'::text COLLATE "POSIX")
90+ -> Seq Scan on canon_3
91+ Filter: ((val)::text < 'b'::text COLLATE "POSIX")
92+ -> Seq Scan on canon_4
93+ Filter: ((val)::text < 'b'::text COLLATE "POSIX")
94+ (9 rows)
95+
96+ DROP TABLE test_exprs.canon CASCADE;
97+ NOTICE: drop cascades to 5 other objects
598/* We use this rel to check 'pathman_hooks_enabled' */
699CREATE TABLE test_exprs.canary(val INT4 NOT NULL);
7100CREATE TABLE test_exprs.canary_copy (LIKE test_exprs.canary);
@@ -27,43 +120,52 @@ SELECT COUNT(*) FROM test_exprs.hash_rel;
27120 5
28121(1 row)
29122
123+ \set VERBOSITY default
30124/* Try using constant expression */
31125SELECT create_hash_partitions('test_exprs.hash_rel', '1 + 1', 4);
32- ERROR: partitioning expression should reference table "hash_rel"
33- \set VERBOSITY default
126+ ERROR: failed to analyze partitioning expression "1 + 1"
127+ DETAIL: partitioning expression should reference table "hash_rel"
128+ CONTEXT: SQL statement "SELECT public.validate_expression(parent_relid, expression)"
129+ PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
130+ SQL statement "SELECT public.prepare_for_partitioning(parent_relid,
131+ expression,
132+ partition_data)"
133+ PL/pgSQL function create_hash_partitions(regclass,text,integer,boolean,text[],text[]) line 4 at PERFORM
134+ /* Try using multiple queries */
135+ SELECT create_hash_partitions('test_exprs.hash_rel',
136+ 'value, (select oid from pg_class limit 1)',
137+ 4);
138+ ERROR: failed to analyze partitioning expression "value, (select oid from pg_class limit 1)"
139+ DETAIL: subqueries are not allowed in partitioning expression
140+ CONTEXT: SQL statement "SELECT public.validate_expression(parent_relid, expression)"
141+ PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
142+ SQL statement "SELECT public.prepare_for_partitioning(parent_relid,
143+ expression,
144+ partition_data)"
145+ PL/pgSQL function create_hash_partitions(regclass,text,integer,boolean,text[],text[]) line 4 at PERFORM
34146/* Try using mutable expression */
35147SELECT create_hash_partitions('test_exprs.hash_rel', 'random()', 4);
36- ERROR: failed to analyze partitioning expression ( random())
148+ ERROR: failed to analyze partitioning expression " random()"
37149DETAIL: functions in partitioning expression must be marked IMMUTABLE
38150CONTEXT: SQL statement "SELECT public.validate_expression(parent_relid, expression)"
39151PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
40152SQL statement "SELECT public.prepare_for_partitioning(parent_relid,
41153 expression,
42154 partition_data)"
43155PL/pgSQL function create_hash_partitions(regclass,text,integer,boolean,text[],text[]) line 4 at PERFORM
44- /* Check that 'pathman_hooks_enabled' is true (1 partition in plan) */
45- EXPLAIN (COSTS OFF) INSERT INTO test_exprs.canary_copy
46- SELECT * FROM test_exprs.canary WHERE val = 1;
47- QUERY PLAN
48- ----------------------------------
49- Insert on canary_copy
50- -> Append
51- -> Seq Scan on canary_0
52- Filter: (val = 1)
53- (4 rows)
54-
55- /* Try using missing columns */
156+ /* Try using broken parentheses */
56157SELECT create_hash_partitions('test_exprs.hash_rel', 'value * value2))', 4);
57- ERROR: failed to parse partitioning expression ( value * value2)))
158+ ERROR: failed to parse partitioning expression " value * value2))"
58159DETAIL: syntax error at or near ")"
59160QUERY: SELECT public.validate_expression(parent_relid, expression)
60161CONTEXT: PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
61162SQL statement "SELECT public.prepare_for_partitioning(parent_relid,
62163 expression,
63164 partition_data)"
64165PL/pgSQL function create_hash_partitions(regclass,text,integer,boolean,text[],text[]) line 4 at PERFORM
166+ /* Try using missing columns */
65167SELECT create_hash_partitions('test_exprs.hash_rel', 'value * value3', 4);
66- ERROR: failed to analyze partitioning expression ( value * value3)
168+ ERROR: failed to analyze partitioning expression " value * value3"
67169DETAIL: column "value3" does not exist
68170HINT: Perhaps you meant to reference the column "hash_rel.value" or the column "hash_rel.value2".
69171QUERY: SELECT public.validate_expression(parent_relid, expression)
@@ -144,15 +246,22 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_exprs.hash_rel WHERE (value * value2) = 5
144246CREATE TABLE test_exprs.range_rel (id SERIAL PRIMARY KEY, dt TIMESTAMP, txt TEXT);
145247INSERT INTO test_exprs.range_rel (dt, txt)
146248SELECT g, md5(g::TEXT) FROM generate_series('2015-01-01', '2020-04-30', '1 month'::interval) as g;
249+ \set VERBOSITY default
147250/* Try using constant expression */
148251SELECT create_range_partitions('test_exprs.range_rel', '''16 years''::interval',
149252 '15 years'::INTERVAL, '1 year'::INTERVAL, 10);
150- ERROR: partitioning expression should reference table "range_rel"
151- \set VERBOSITY default
253+ ERROR: failed to analyze partitioning expression "'16 years'::interval"
254+ DETAIL: partitioning expression should reference table "range_rel"
255+ CONTEXT: SQL statement "SELECT public.validate_expression(parent_relid, expression)"
256+ PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
257+ SQL statement "SELECT public.prepare_for_partitioning(parent_relid,
258+ expression,
259+ partition_data)"
260+ PL/pgSQL function create_range_partitions(regclass,text,anyelement,interval,integer,boolean) line 12 at PERFORM
152261/* Try using mutable expression */
153262SELECT create_range_partitions('test_exprs.range_rel', 'RANDOM()',
154263 '15 years'::INTERVAL, '1 year'::INTERVAL, 10);
155- ERROR: failed to analyze partitioning expression ( RANDOM())
264+ ERROR: failed to analyze partitioning expression " RANDOM()"
156265DETAIL: functions in partitioning expression must be marked IMMUTABLE
157266CONTEXT: SQL statement "SELECT public.validate_expression(parent_relid, expression)"
158267PL/pgSQL function prepare_for_partitioning(regclass,text,boolean) line 9 at PERFORM
0 commit comments