Skip to content

Commit 7421589

Browse files
committed
fix COPY (columns) TO statement (issue #50)
1 parent f603e6c commit 7421589

File tree

3 files changed

+165
-80
lines changed

3 files changed

+165
-80
lines changed

expected/pathman_copy_stmt_hooking.out

Lines changed: 92 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
\set VERBOSITY terse
22
CREATE EXTENSION pg_pathman;
33
CREATE SCHEMA copy_stmt_hooking;
4-
CREATE TABLE copy_stmt_hooking.test(val int not null, comment text);
4+
CREATE TABLE copy_stmt_hooking.test(
5+
val int not null,
6+
comment text,
7+
c3 int,
8+
c4 int);
59
INSERT INTO copy_stmt_hooking.test SELECT generate_series(1, 20), 'comment';
610
CREATE INDEX ON copy_stmt_hooking.test(val);
711
/* test for RANGE partitioning */
@@ -20,47 +24,47 @@ VACUUM FULL copy_stmt_hooking.test_3;
2024
VACUUM FULL copy_stmt_hooking.test_4;
2125
/* COPY TO */
2226
COPY copy_stmt_hooking.test TO stdout;
23-
1 comment
24-
2 comment
25-
3 comment
26-
4 comment
27-
5 comment
28-
6 comment
29-
7 comment
30-
8 comment
31-
9 comment
32-
10 comment
33-
11 comment
34-
12 comment
35-
13 comment
36-
14 comment
37-
15 comment
38-
16 comment
39-
17 comment
40-
18 comment
41-
19 comment
42-
20 comment
27+
1 comment \N \N
28+
2 comment \N \N
29+
3 comment \N \N
30+
4 comment \N \N
31+
5 comment \N \N
32+
6 comment \N \N
33+
7 comment \N \N
34+
8 comment \N \N
35+
9 comment \N \N
36+
10 comment \N \N
37+
11 comment \N \N
38+
12 comment \N \N
39+
13 comment \N \N
40+
14 comment \N \N
41+
15 comment \N \N
42+
16 comment \N \N
43+
17 comment \N \N
44+
18 comment \N \N
45+
19 comment \N \N
46+
20 comment \N \N
4347
\copy copy_stmt_hooking.test to stdout (format csv)
44-
1,comment
45-
2,comment
46-
3,comment
47-
4,comment
48-
5,comment
49-
6,comment
50-
7,comment
51-
8,comment
52-
9,comment
53-
10,comment
54-
11,comment
55-
12,comment
56-
13,comment
57-
14,comment
58-
15,comment
59-
16,comment
60-
17,comment
61-
18,comment
62-
19,comment
63-
20,comment
48+
1,comment,,
49+
2,comment,,
50+
3,comment,,
51+
4,comment,,
52+
5,comment,,
53+
6,comment,,
54+
7,comment,,
55+
8,comment,,
56+
9,comment,,
57+
10,comment,,
58+
11,comment,,
59+
12,comment,,
60+
13,comment,,
61+
14,comment,,
62+
15,comment,,
63+
16,comment,,
64+
17,comment,,
65+
18,comment,,
66+
19,comment,,
67+
20,comment,,
6468
\copy copy_stmt_hooking.test(comment) to stdout
6569
comment
6670
comment
@@ -92,31 +96,62 @@ SELECT count(*) FROM ONLY copy_stmt_hooking.test;
9296
(1 row)
9397

9498
SELECT *, tableoid::REGCLASS FROM copy_stmt_hooking.test ORDER BY val;
95-
val | comment | tableoid
96-
-----+---------+--------------------------
97-
1 | test_1 | copy_stmt_hooking.test_1
98-
6 | test_2 | copy_stmt_hooking.test_2
99-
7 | test_2 | copy_stmt_hooking.test_2
100-
11 | test_3 | copy_stmt_hooking.test_3
101-
16 | test_4 | copy_stmt_hooking.test_4
99+
val | comment | c3 | c4 | tableoid
100+
-----+---------+----+----+--------------------------
101+
1 | test_1 | 0 | 0 | copy_stmt_hooking.test_1
102+
6 | test_2 | 0 | 0 | copy_stmt_hooking.test_2
103+
7 | test_2 | 0 | 0 | copy_stmt_hooking.test_2
104+
11 | test_3 | 0 | 0 | copy_stmt_hooking.test_3
105+
16 | test_4 | 0 | 0 | copy_stmt_hooking.test_4
102106
(5 rows)
103107

108+
/* perform VACUUM */
109+
VACUUM FULL copy_stmt_hooking.test;
110+
VACUUM FULL copy_stmt_hooking.test_1;
111+
VACUUM FULL copy_stmt_hooking.test_2;
112+
VACUUM FULL copy_stmt_hooking.test_3;
113+
VACUUM FULL copy_stmt_hooking.test_4;
114+
/* COPY FROM (specified columns) */
115+
COPY copy_stmt_hooking.test (val) TO stdout;
116+
1
117+
6
118+
7
119+
11
120+
16
121+
COPY copy_stmt_hooking.test (val, comment) TO stdout;
122+
1 test_1
123+
6 test_2
124+
7 test_2
125+
11 test_3
126+
16 test_4
127+
COPY copy_stmt_hooking.test (c3, val, comment) TO stdout;
128+
0 1 test_1
129+
0 6 test_2
130+
0 7 test_2
131+
0 11 test_3
132+
0 16 test_4
133+
COPY copy_stmt_hooking.test (val, comment, c3, c4) TO stdout;
134+
1 test_1 0 0
135+
6 test_2 0 0
136+
7 test_2 0 0
137+
11 test_3 0 0
138+
16 test_4 0 0
104139
/* COPY TO (partition does not exist, NOT allowed to create partitions) */
105140
SET pg_pathman.enable_auto_partition = OFF;
106141
COPY copy_stmt_hooking.test FROM stdin;
107142
ERROR: no suitable partition for key '21'
108143
SELECT * FROM copy_stmt_hooking.test WHERE val > 20;
109-
val | comment
110-
-----+---------
144+
val | comment | c3 | c4
145+
-----+---------+----+----
111146
(0 rows)
112147

113148
/* COPY TO (partition does not exist, allowed to create partitions) */
114149
SET pg_pathman.enable_auto_partition = ON;
115150
COPY copy_stmt_hooking.test FROM stdin;
116151
SELECT * FROM copy_stmt_hooking.test WHERE val > 20;
117-
val | comment
118-
-----+--------------
119-
21 | test_no_part
152+
val | comment | c3 | c4
153+
-----+--------------+----+----
154+
21 | test_no_part | 0 | 0
120155
(1 row)
121156

122157
/* COPY TO (partitioned column is not specified) */
@@ -147,10 +182,10 @@ SELECT count(*) FROM ONLY copy_stmt_hooking.test;
147182
(1 row)
148183

149184
SELECT * FROM copy_stmt_hooking.test ORDER BY val;
150-
val | comment
151-
-----+---------
152-
1 | hash_1
153-
6 | hash_2
185+
val | comment | c3 | c4
186+
-----+---------+----+----
187+
1 | hash_1 | 0 | 0
188+
6 | hash_2 | 0 | 0
154189
(2 rows)
155190

156191
DROP SCHEMA copy_stmt_hooking CASCADE;

sql/pathman_copy_stmt_hooking.sql

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ CREATE EXTENSION pg_pathman;
44
CREATE SCHEMA copy_stmt_hooking;
55

66

7-
CREATE TABLE copy_stmt_hooking.test(val int not null, comment text);
7+
CREATE TABLE copy_stmt_hooking.test(
8+
val int not null,
9+
comment text,
10+
c3 int,
11+
c4 int);
812
INSERT INTO copy_stmt_hooking.test SELECT generate_series(1, 20), 'comment';
913
CREATE INDEX ON copy_stmt_hooking.test(val);
1014

@@ -27,26 +31,39 @@ COPY copy_stmt_hooking.test TO stdout;
2731
/* DELETE ROWS, COPY FROM */
2832
DELETE FROM copy_stmt_hooking.test;
2933
COPY copy_stmt_hooking.test FROM stdin;
30-
1 test_1
31-
6 test_2
32-
7 test_2
33-
11 test_3
34-
16 test_4
34+
1 test_1 0 0
35+
6 test_2 0 0
36+
7 test_2 0 0
37+
11 test_3 0 0
38+
16 test_4 0 0
3539
\.
3640
SELECT count(*) FROM ONLY copy_stmt_hooking.test;
3741
SELECT *, tableoid::REGCLASS FROM copy_stmt_hooking.test ORDER BY val;
3842

43+
/* perform VACUUM */
44+
VACUUM FULL copy_stmt_hooking.test;
45+
VACUUM FULL copy_stmt_hooking.test_1;
46+
VACUUM FULL copy_stmt_hooking.test_2;
47+
VACUUM FULL copy_stmt_hooking.test_3;
48+
VACUUM FULL copy_stmt_hooking.test_4;
49+
50+
/* COPY FROM (specified columns) */
51+
COPY copy_stmt_hooking.test (val) TO stdout;
52+
COPY copy_stmt_hooking.test (val, comment) TO stdout;
53+
COPY copy_stmt_hooking.test (c3, val, comment) TO stdout;
54+
COPY copy_stmt_hooking.test (val, comment, c3, c4) TO stdout;
55+
3956
/* COPY TO (partition does not exist, NOT allowed to create partitions) */
4057
SET pg_pathman.enable_auto_partition = OFF;
4158
COPY copy_stmt_hooking.test FROM stdin;
42-
21 test_no_part
59+
21 test_no_part 0 0
4360
\.
4461
SELECT * FROM copy_stmt_hooking.test WHERE val > 20;
4562

4663
/* COPY TO (partition does not exist, allowed to create partitions) */
4764
SET pg_pathman.enable_auto_partition = ON;
4865
COPY copy_stmt_hooking.test FROM stdin;
49-
21 test_no_part
66+
21 test_no_part 0 0
5067
\.
5168
SELECT * FROM copy_stmt_hooking.test WHERE val > 20;
5269

@@ -66,8 +83,8 @@ SELECT create_hash_partitions('copy_stmt_hooking.test', 'val', 5);
6683
/* DELETE ROWS, COPY FROM */
6784
DELETE FROM copy_stmt_hooking.test;
6885
COPY copy_stmt_hooking.test FROM stdin;
69-
1 hash_1
70-
6 hash_2
86+
1 hash_1 0 0
87+
6 hash_2 0 0
7188
\.
7289
SELECT count(*) FROM ONLY copy_stmt_hooking.test;
7390
SELECT * FROM copy_stmt_hooking.test ORDER BY val;

src/copy_stmt_hooking.c

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,8 @@ PathmanDoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
269269
is_from == false) /* rewrite COPY table TO statements */
270270
{
271271
SelectStmt *select;
272-
ColumnRef *cr;
273-
ResTarget *target;
274272
RangeVar *from;
273+
List *target_list = NIL;
275274

276275
if (is_from)
277276
ereport(ERROR,
@@ -280,20 +279,54 @@ PathmanDoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
280279
errhint("Use INSERT statements instead.")));
281280

282281
/* Build target list */
283-
cr = makeNode(ColumnRef);
284-
285282
if (!stmt->attlist)
283+
{
284+
ColumnRef *cr;
285+
ResTarget *target;
286+
287+
cr = makeNode(ColumnRef);
286288
cr->fields = list_make1(makeNode(A_Star));
287-
else
288-
cr->fields = stmt->attlist;
289+
cr->location = -1;
289290

290-
cr->location = 1;
291+
/* Build the ResTarget and add the ColumnRef to it. */
292+
target = makeNode(ResTarget);
293+
target->name = NULL;
294+
target->indirection = NIL;
295+
target->val = (Node *) cr;
296+
target->location = -1;
291297

292-
target = makeNode(ResTarget);
293-
target->name = NULL;
294-
target->indirection = NIL;
295-
target->val = (Node *) cr;
296-
target->location = 1;
298+
target_list = list_make1(target);
299+
}
300+
else
301+
{
302+
ListCell *lc;
303+
304+
foreach(lc, stmt->attlist)
305+
{
306+
ColumnRef *cr;
307+
ResTarget *target;
308+
309+
/*
310+
* Build the ColumnRef for each column. The ColumnRef
311+
* 'fields' property is a String 'Value' node (see
312+
* nodes/value.h) that corresponds to the column name
313+
* respectively.
314+
*/
315+
cr = makeNode(ColumnRef);
316+
cr->fields = list_make1(lfirst(lc));
317+
cr->location = -1;
318+
319+
/* Build the ResTarget and add the ColumnRef to it. */
320+
target = makeNode(ResTarget);
321+
target->name = NULL;
322+
target->indirection = NIL;
323+
target->val = (Node *) cr;
324+
target->location = -1;
325+
326+
/* Add each column to the SELECT statements target list */
327+
target_list = lappend(target_list, target);
328+
}
329+
}
297330

298331
/*
299332
* Build RangeVar for from clause, fully qualified based on the
@@ -304,7 +337,7 @@ PathmanDoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
304337

305338
/* Build query */
306339
select = makeNode(SelectStmt);
307-
select->targetList = list_make1(target);
340+
select->targetList = target_list;
308341
select->fromClause = list_make1(from);
309342

310343
query = (Node *) select;

0 commit comments

Comments
 (0)