4 c text not null default 'stuff',
8 CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS '
10 NEW.e := ''before trigger fired''::text;
14 CREATE FUNCTION fn_x_after () RETURNS TRIGGER AS '
16 UPDATE x set e=''after trigger fired'' where c=''stuff'';
20 CREATE TRIGGER trg_x_after AFTER INSERT ON x
21 FOR EACH ROW EXECUTE PROCEDURE fn_x_after();
22 CREATE TRIGGER trg_x_before BEFORE INSERT ON x
23 FOR EACH ROW EXECUTE PROCEDURE fn_x_before();
24 COPY x (a, b, c, d, e) from stdin;
25 COPY x (b, d) from stdin;
26 COPY x (b, d) from stdin;
27 COPY x (a, b, c, d, e) from stdin;
28 -- non-existent column in column list: should fail
29 COPY x (xyz) from stdin;
30 ERROR: column "xyz" of relation "x" does not exist
32 COPY x from stdin (format CSV, FORMAT CSV);
33 ERROR: conflicting or redundant options
34 LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
36 COPY x from stdin (freeze off, freeze on);
37 ERROR: conflicting or redundant options
38 LINE 1: COPY x from stdin (freeze off, freeze on);
40 COPY x from stdin (delimiter ',', delimiter ',');
41 ERROR: conflicting or redundant options
42 LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
44 COPY x from stdin (null ' ', null ' ');
45 ERROR: conflicting or redundant options
46 LINE 1: COPY x from stdin (null ' ', null ' ');
48 COPY x from stdin (header off, header on);
49 ERROR: conflicting or redundant options
50 LINE 1: COPY x from stdin (header off, header on);
52 COPY x from stdin (quote ':', quote ':');
53 ERROR: conflicting or redundant options
54 LINE 1: COPY x from stdin (quote ':', quote ':');
56 COPY x from stdin (escape ':', escape ':');
57 ERROR: conflicting or redundant options
58 LINE 1: COPY x from stdin (escape ':', escape ':');
60 COPY x from stdin (force_quote (a), force_quote *);
61 ERROR: conflicting or redundant options
62 LINE 1: COPY x from stdin (force_quote (a), force_quote *);
64 COPY x from stdin (force_not_null (a), force_not_null (b));
65 ERROR: conflicting or redundant options
66 LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
68 COPY x from stdin (force_null (a), force_null (b));
69 ERROR: conflicting or redundant options
70 LINE 1: COPY x from stdin (force_null (a), force_null (b));
72 COPY x from stdin (convert_selectively (a), convert_selectively (b));
73 ERROR: conflicting or redundant options
74 LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
76 COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
77 ERROR: conflicting or redundant options
78 LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
80 -- too many columns in column list: should fail
81 COPY x (a, b, c, d, e, d, c) from stdin;
82 ERROR: column "d" specified more than once
83 -- missing data: should fail
85 ERROR: invalid input syntax for type integer: ""
86 CONTEXT: COPY x, line 1, column a: ""
88 ERROR: missing data for column "e"
89 CONTEXT: COPY x, line 1: "2000 230 23 23"
91 ERROR: missing data for column "e"
92 CONTEXT: COPY x, line 1: "2001 231 \N \N"
93 -- extra data: should fail
95 ERROR: extra data after last expected column
96 CONTEXT: COPY x, line 1: "2002 232 40 50 60 70 80"
97 -- various COPY options: delimiters, oids, NULL string, encoding
98 COPY x (b, c, d, e) from stdin delimiter ',' null 'x';
99 COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
100 COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
101 COPY x TO stdout WHERE a = 1;
102 ERROR: WHERE clause not allowed with COPY TO
103 LINE 1: COPY x TO stdout WHERE a = 1;
105 COPY x from stdin WHERE a = 50004;
106 COPY x from stdin WHERE a > 60003;
107 COPY x from stdin WHERE f > 60003;
108 ERROR: column "f" does not exist
109 LINE 1: COPY x from stdin WHERE f > 60003;
111 COPY x from stdin WHERE a = max(x.b);
112 ERROR: aggregate functions are not allowed in COPY FROM WHERE conditions
113 LINE 1: COPY x from stdin WHERE a = max(x.b);
115 COPY x from stdin WHERE a IN (SELECT 1 FROM x);
116 ERROR: cannot use subquery in COPY FROM WHERE condition
117 LINE 1: COPY x from stdin WHERE a IN (SELECT 1 FROM x);
119 COPY x from stdin WHERE a IN (generate_series(1,5));
120 ERROR: set-returning functions are not allowed in COPY FROM WHERE conditions
121 LINE 1: COPY x from stdin WHERE a IN (generate_series(1,5));
123 COPY x from stdin WHERE a = row_number() over(b);
124 ERROR: window functions are not allowed in COPY FROM WHERE conditions
125 LINE 1: COPY x from stdin WHERE a = row_number() over(b);
127 -- check results of copy in
130 -------+----+------------+--------+----------------------
131 9999 | | \N | NN | before trigger fired
132 10000 | 21 | 31 | 41 | before trigger fired
133 10001 | 22 | 32 | 42 | before trigger fired
134 10002 | 23 | 33 | 43 | before trigger fired
135 10003 | 24 | 34 | 44 | before trigger fired
136 10004 | 25 | 35 | 45 | before trigger fired
137 10005 | 26 | 36 | 46 | before trigger fired
138 6 | | 45 | 80 | before trigger fired
139 7 | | x | \x | before trigger fired
140 8 | | , | \, | before trigger fired
141 3000 | | c | | before trigger fired
142 4000 | | C | | before trigger fired
143 4001 | 1 | empty | | before trigger fired
144 4002 | 2 | null | | before trigger fired
145 4003 | 3 | Backslash | \ | before trigger fired
146 4004 | 4 | BackslashX | \X | before trigger fired
147 4005 | 5 | N | N | before trigger fired
148 4006 | 6 | BackslashN | \N | before trigger fired
149 4007 | 7 | XX | XX | before trigger fired
150 4008 | 8 | Delimiter | : | before trigger fired
151 50004 | 25 | 35 | 45 | before trigger fired
152 60004 | 25 | 35 | 45 | before trigger fired
153 60005 | 26 | 36 | 46 | before trigger fired
154 1 | 1 | stuff | test_1 | after trigger fired
155 2 | 2 | stuff | test_2 | after trigger fired
156 3 | 3 | stuff | test_3 | after trigger fired
157 4 | 4 | stuff | test_4 | after trigger fired
158 5 | 5 | stuff | test_5 | after trigger fired
163 9999 \N \\N NN before trigger fired
164 10000 21 31 41 before trigger fired
165 10001 22 32 42 before trigger fired
166 10002 23 33 43 before trigger fired
167 10003 24 34 44 before trigger fired
168 10004 25 35 45 before trigger fired
169 10005 26 36 46 before trigger fired
170 6 \N 45 80 before trigger fired
171 7 \N x \\x before trigger fired
172 8 \N , \\, before trigger fired
173 3000 \N c \N before trigger fired
174 4000 \N C \N before trigger fired
175 4001 1 empty before trigger fired
176 4002 2 null \N before trigger fired
177 4003 3 Backslash \\ before trigger fired
178 4004 4 BackslashX \\X before trigger fired
179 4005 5 N N before trigger fired
180 4006 6 BackslashN \\N before trigger fired
181 4007 7 XX XX before trigger fired
182 4008 8 Delimiter : before trigger fired
183 50004 25 35 45 before trigger fired
184 60004 25 35 45 before trigger fired
185 60005 26 36 46 before trigger fired
186 1 1 stuff test_1 after trigger fired
187 2 2 stuff test_2 after trigger fired
188 3 3 stuff test_3 after trigger fired
189 4 4 stuff test_4 after trigger fired
190 5 5 stuff test_5 after trigger fired
191 COPY x (c, e) TO stdout;
192 \\N before trigger fired
193 31 before trigger fired
194 32 before trigger fired
195 33 before trigger fired
196 34 before trigger fired
197 35 before trigger fired
198 36 before trigger fired
199 45 before trigger fired
200 x before trigger fired
201 , before trigger fired
202 c before trigger fired
203 C before trigger fired
204 empty before trigger fired
205 null before trigger fired
206 Backslash before trigger fired
207 BackslashX before trigger fired
208 N before trigger fired
209 BackslashN before trigger fired
210 XX before trigger fired
211 Delimiter before trigger fired
212 35 before trigger fired
213 35 before trigger fired
214 36 before trigger fired
215 stuff after trigger fired
216 stuff after trigger fired
217 stuff after trigger fired
218 stuff after trigger fired
219 stuff after trigger fired
220 COPY x (b, e) TO stdout WITH NULL 'I''m null';
221 I'm null before trigger fired
222 21 before trigger fired
223 22 before trigger fired
224 23 before trigger fired
225 24 before trigger fired
226 25 before trigger fired
227 26 before trigger fired
228 I'm null before trigger fired
229 I'm null before trigger fired
230 I'm null before trigger fired
231 I'm null before trigger fired
232 I'm null before trigger fired
233 1 before trigger fired
234 2 before trigger fired
235 3 before trigger fired
236 4 before trigger fired
237 5 before trigger fired
238 6 before trigger fired
239 7 before trigger fired
240 8 before trigger fired
241 25 before trigger fired
242 25 before trigger fired
243 26 before trigger fired
244 1 after trigger fired
245 2 after trigger fired
246 3 after trigger fired
247 4 after trigger fired
248 5 after trigger fired
249 CREATE TEMP TABLE y (
253 INSERT INTO y VALUES ('Jackson, Sam', E'\\h');
254 INSERT INTO y VALUES ('It is "perfect".',E'\t');
255 INSERT INTO y VALUES ('', NULL);
256 COPY y TO stdout WITH CSV;
258 "It is ""perfect"".",
260 COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|';
264 COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\' ENCODING 'sql_ascii';
266 "It is \"perfect\"."," "
268 COPY y TO stdout WITH CSV FORCE QUOTE *;
270 "It is ""perfect""."," "
272 -- Repeat above tests with new 9.0 option syntax
273 COPY y TO stdout (FORMAT CSV);
275 "It is ""perfect"".",
277 COPY y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|');
281 COPY y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\');
283 "It is \"perfect\"."," "
285 COPY y TO stdout (FORMAT CSV, FORCE_QUOTE *);
287 "It is ""perfect""."," "
289 \copy y TO stdout (FORMAT CSV)
291 "It is ""perfect"".",
293 \copy y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|')
297 \copy y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\')
299 "It is \"perfect\"."," "
301 \copy y TO stdout (FORMAT CSV, FORCE_QUOTE *)
303 "It is ""perfect""."," "
305 --test that we read consecutive LFs properly
306 CREATE TEMP TABLE testnl (a int, b text, c int);
307 COPY testnl FROM stdin CSV;
308 -- test end of copy marker
309 CREATE TEMP TABLE testeoc (a text);
310 COPY testeoc FROM stdin CSV;
311 COPY testeoc TO stdout CSV;
316 -- test handling of nonstandard null marker that violates escaping rules
317 CREATE TEMP TABLE testnull(a int, b text);
318 INSERT INTO testnull VALUES (1, E'\\0'), (NULL, NULL);
319 COPY testnull TO stdout WITH NULL AS E'\\0';
322 COPY testnull FROM stdin WITH NULL AS E'\\0';
323 SELECT * FROM testnull;
333 CREATE TABLE vistest (LIKE testeoc);
334 COPY vistest FROM stdin CSV;
336 SELECT * FROM vistest;
345 COPY vistest FROM stdin CSV;
346 SELECT * FROM vistest;
355 COPY vistest FROM stdin CSV;
356 SELECT * FROM vistest;
364 SELECT * FROM vistest;
373 COPY vistest FROM stdin CSV FREEZE;
374 SELECT * FROM vistest;
383 COPY vistest FROM stdin CSV FREEZE;
384 SELECT * FROM vistest;
392 SELECT * FROM vistest;
401 COPY vistest FROM stdin CSV FREEZE;
402 SELECT * FROM vistest;
411 COPY vistest FROM stdin CSV FREEZE;
412 ERROR: cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction
416 COPY vistest FROM stdin CSV FREEZE;
417 ERROR: cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction
420 INSERT INTO vistest VALUES ('z');
423 ROLLBACK TO SAVEPOINT s1;
424 COPY vistest FROM stdin CSV FREEZE;
425 ERROR: cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction
427 CREATE FUNCTION truncate_in_subxact() RETURNS VOID AS
433 INSERT INTO vistest VALUES ('subxact failure');
437 INSERT INTO vistest VALUES ('z');
438 SELECT truncate_in_subxact();
440 ---------------------
444 COPY vistest FROM stdin CSV FREEZE;
445 SELECT * FROM vistest;
453 SELECT * FROM vistest;
460 -- Test FORCE_NOT_NULL and FORCE_NULL options
461 CREATE TEMP TABLE forcetest (
469 -- should succeed with no effect ("b" remains an empty string, "c" remains NULL)
471 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(b), FORCE_NULL(c));
473 SELECT b, c FROM forcetest WHERE a = 1;
479 -- should succeed, FORCE_NULL and FORCE_NOT_NULL can be both specified
481 COPY forcetest (a, b, c, d) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(c,d), FORCE_NULL(c,d));
483 SELECT c, d FROM forcetest WHERE a = 2;
489 -- should fail with not-null constraint violation
491 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b), FORCE_NOT_NULL(c));
492 ERROR: null value in column "b" of relation "forcetest" violates not-null constraint
493 DETAIL: Failing row contains (3, null, , null, null).
494 CONTEXT: COPY forcetest, line 1: "3,,"""
496 -- should fail with "not referenced by COPY" error
498 COPY forcetest (d, e) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(b));
499 ERROR: FORCE_NOT_NULL column "b" not referenced by COPY
501 -- should fail with "not referenced by COPY" error
503 COPY forcetest (d, e) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b));
504 ERROR: FORCE_NULL column "b" not referenced by COPY
507 -- test case with whole-row Var in a check constraint
508 create table check_con_tbl (f1 int);
509 create function check_con_function(check_con_tbl) returns bool as $$
511 raise notice 'input = %', row_to_json($1);
513 end $$ language plpgsql immutable;
514 alter table check_con_tbl add check (check_con_function(check_con_tbl.*));
516 Table "public.check_con_tbl"
517 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
518 --------+---------+-----------+----------+---------+---------+--------------+-------------
519 f1 | integer | | | | plain | |
521 "check_con_tbl_check" CHECK (check_con_function(check_con_tbl.*))
523 copy check_con_tbl from stdin;
524 NOTICE: input = {"f1":1}
525 NOTICE: input = {"f1":null}
526 copy check_con_tbl from stdin;
527 NOTICE: input = {"f1":0}
528 ERROR: new row for relation "check_con_tbl" violates check constraint "check_con_tbl_check"
529 DETAIL: Failing row contains (0).
530 CONTEXT: COPY check_con_tbl, line 1: "0"
531 select * from check_con_tbl;
538 -- test with RLS enabled.
539 CREATE ROLE regress_rls_copy_user;
540 CREATE ROLE regress_rls_copy_user_colperms;
541 CREATE TABLE rls_t1 (a int, b int, c int);
542 COPY rls_t1 (a, b, c) from stdin;
543 CREATE POLICY p1 ON rls_t1 FOR SELECT USING (a % 2 = 0);
544 ALTER TABLE rls_t1 ENABLE ROW LEVEL SECURITY;
545 ALTER TABLE rls_t1 FORCE ROW LEVEL SECURITY;
546 GRANT SELECT ON TABLE rls_t1 TO regress_rls_copy_user;
547 GRANT SELECT (a, b) ON TABLE rls_t1 TO regress_rls_copy_user_colperms;
549 COPY rls_t1 TO stdout;
554 COPY rls_t1 (a, b, c) TO stdout;
560 COPY rls_t1 (a) TO stdout;
565 COPY rls_t1 (a, b) TO stdout;
571 COPY rls_t1 (b, a) TO stdout;
576 SET SESSION AUTHORIZATION regress_rls_copy_user;
578 COPY rls_t1 TO stdout;
581 COPY rls_t1 (a, b, c) TO stdout;
585 COPY rls_t1 (a) TO stdout;
588 COPY rls_t1 (a, b) TO stdout;
592 COPY rls_t1 (b, a) TO stdout;
595 RESET SESSION AUTHORIZATION;
596 SET SESSION AUTHORIZATION regress_rls_copy_user_colperms;
597 -- attempt all columns (should fail)
598 COPY rls_t1 TO stdout;
599 ERROR: permission denied for table rls_t1
600 COPY rls_t1 (a, b, c) TO stdout;
601 ERROR: permission denied for table rls_t1
602 -- try to copy column with no privileges (should fail)
603 COPY rls_t1 (c) TO stdout;
604 ERROR: permission denied for table rls_t1
605 -- subset of columns (should succeed)
606 COPY rls_t1 (a) TO stdout;
609 COPY rls_t1 (a, b) TO stdout;
612 RESET SESSION AUTHORIZATION;
613 -- test with INSTEAD OF INSERT trigger on a view
614 CREATE TABLE instead_of_insert_tbl(id serial, name text);
615 CREATE VIEW instead_of_insert_tbl_view AS SELECT ''::text AS str;
616 COPY instead_of_insert_tbl_view FROM stdin; -- fail
617 ERROR: cannot copy to view "instead_of_insert_tbl_view"
618 HINT: To enable copying to a view, provide an INSTEAD OF INSERT trigger.
619 CREATE FUNCTION fun_instead_of_insert_tbl() RETURNS trigger AS $$
621 INSERT INTO instead_of_insert_tbl (name) VALUES (NEW.str);
625 CREATE TRIGGER trig_instead_of_insert_tbl_view
626 INSTEAD OF INSERT ON instead_of_insert_tbl_view
627 FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
628 COPY instead_of_insert_tbl_view FROM stdin;
629 SELECT * FROM instead_of_insert_tbl;
635 -- Test of COPY optimization with view using INSTEAD OF INSERT
636 -- trigger when relation is created in the same transaction as
637 -- when COPY is executed.
639 CREATE VIEW instead_of_insert_tbl_view_2 as select ''::text as str;
640 CREATE TRIGGER trig_instead_of_insert_tbl_view_2
641 INSTEAD OF INSERT ON instead_of_insert_tbl_view_2
642 FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
643 COPY instead_of_insert_tbl_view_2 FROM stdin;
644 SELECT * FROM instead_of_insert_tbl;
653 DROP TABLE forcetest;
655 DROP FUNCTION truncate_in_subxact();
657 DROP TABLE rls_t1 CASCADE;
658 DROP ROLE regress_rls_copy_user;
659 DROP ROLE regress_rls_copy_user_colperms;
660 DROP FUNCTION fn_x_before();
661 DROP FUNCTION fn_x_after();
662 DROP TABLE instead_of_insert_tbl;
663 DROP VIEW instead_of_insert_tbl_view;
664 DROP VIEW instead_of_insert_tbl_view_2;
665 DROP FUNCTION fun_instead_of_insert_tbl();