Fix validation of COPY FORCE_NOT_NULL/FORCE_NULL for the all-column cases
[pgsql.git] / src / test / regress / sql / copy2.sql
blob45273557ce04000128bafba87a21f03bd249501b
1 CREATE TEMP TABLE x (
2         a serial,
3         b int,
4         c text not null default 'stuff',
5         d text,
6         e text
7 ) ;
9 CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS '
10   BEGIN
11                 NEW.e := ''before trigger fired''::text;
12                 return NEW;
13         END;
14 ' LANGUAGE plpgsql;
16 CREATE FUNCTION fn_x_after () RETURNS TRIGGER AS '
17   BEGIN
18                 UPDATE x set e=''after trigger fired'' where c=''stuff'';
19                 return NULL;
20         END;
21 ' LANGUAGE plpgsql;
23 CREATE TRIGGER trg_x_after AFTER INSERT ON x
24 FOR EACH ROW EXECUTE PROCEDURE fn_x_after();
26 CREATE TRIGGER trg_x_before BEFORE INSERT ON x
27 FOR EACH ROW EXECUTE PROCEDURE fn_x_before();
29 COPY x (a, b, c, d, e) from stdin;
30 9999    \N      \\N     \NN     \N
31 10000   21      31      41      51
34 COPY x (b, d) from stdin;
35 1       test_1
38 COPY x (b, d) from stdin;
39 2       test_2
40 3       test_3
41 4       test_4
42 5       test_5
45 COPY x (a, b, c, d, e) from stdin;
46 10001   22      32      42      52
47 10002   23      33      43      53
48 10003   24      34      44      54
49 10004   25      35      45      55
50 10005   26      36      46      56
53 -- non-existent column in column list: should fail
54 COPY x (xyz) from stdin;
56 -- redundant options
57 COPY x from stdin (format CSV, FORMAT CSV);
58 COPY x from stdin (freeze off, freeze on);
59 COPY x from stdin (delimiter ',', delimiter ',');
60 COPY x from stdin (null ' ', null ' ');
61 COPY x from stdin (header off, header on);
62 COPY x from stdin (quote ':', quote ':');
63 COPY x from stdin (escape ':', escape ':');
64 COPY x from stdin (force_quote (a), force_quote *);
65 COPY x from stdin (force_not_null (a), force_not_null (b));
66 COPY x from stdin (force_null (a), force_null (b));
67 COPY x from stdin (convert_selectively (a), convert_selectively (b));
68 COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
69 COPY x from stdin (on_error ignore, on_error ignore);
70 COPY x from stdin (log_verbosity default, log_verbosity verbose);
72 -- incorrect options
73 COPY x from stdin (format BINARY, delimiter ',');
74 COPY x from stdin (format BINARY, null 'x');
75 COPY x from stdin (format BINARY, on_error ignore);
76 COPY x from stdin (on_error unsupported);
77 COPY x from stdin (format TEXT, force_quote(a));
78 COPY x from stdin (format TEXT, force_quote *);
79 COPY x from stdin (format CSV, force_quote(a));
80 COPY x from stdin (format CSV, force_quote *);
81 COPY x from stdin (format TEXT, force_not_null(a));
82 COPY x from stdin (format TEXT, force_not_null *);
83 COPY x to stdout (format CSV, force_not_null(a));
84 COPY x to stdout (format CSV, force_not_null *);
85 COPY x from stdin (format TEXT, force_null(a));
86 COPY x from stdin (format TEXT, force_null *);
87 COPY x to stdout (format CSV, force_null(a));
88 COPY x to stdout (format CSV, force_null *);
89 COPY x to stdout (format BINARY, on_error unsupported);
90 COPY x from stdin (log_verbosity unsupported);
91 COPY x from stdin with (reject_limit 1);
92 COPY x from stdin with (on_error ignore, reject_limit 0);
94 -- too many columns in column list: should fail
95 COPY x (a, b, c, d, e, d, c) from stdin;
97 -- missing data: should fail
98 COPY x from stdin;
101 COPY x from stdin;
102 2000    230     23      23
104 COPY x from stdin;
105 2001    231     \N      \N
108 -- extra data: should fail
109 COPY x from stdin;
110 2002    232     40      50      60      70      80
113 -- various COPY options: delimiters, oids, NULL string, encoding
114 COPY x (b, c, d, e) from stdin delimiter ',' null 'x';
115 x,45,80,90
116 x,\x,\\x,\\\x
117 x,\,,\\\,,\\
120 COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
121 3000;;c;;
124 COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
125 4000:\X:C:\X:\X
126 4001:1:empty::
127 4002:2:null:\X:\X
128 4003:3:Backslash:\\:\\
129 4004:4:BackslashX:\\X:\\X
130 4005:5:N:\N:\N
131 4006:6:BackslashN:\\N:\\N
132 4007:7:XX:\XX:\XX
133 4008:8:Delimiter:\::\:
136 COPY x TO stdout WHERE a = 1;
137 COPY x from stdin WHERE a = 50004;
138 50003   24      34      44      54
139 50004   25      35      45      55
140 50005   26      36      46      56
143 COPY x from stdin WHERE a > 60003;
144 60001   22      32      42      52
145 60002   23      33      43      53
146 60003   24      34      44      54
147 60004   25      35      45      55
148 60005   26      36      46      56
151 COPY x from stdin WHERE f > 60003;
153 COPY x from stdin WHERE a = max(x.b);
155 COPY x from stdin WHERE a IN (SELECT 1 FROM x);
157 COPY x from stdin WHERE a IN (generate_series(1,5));
159 COPY x from stdin WHERE a = row_number() over(b);
162 -- check results of copy in
163 SELECT * FROM x;
165 -- check copy out
166 COPY x TO stdout;
167 COPY x (c, e) TO stdout;
168 COPY x (b, e) TO stdout WITH NULL 'I''m null';
170 CREATE TEMP TABLE y (
171         col1 text,
172         col2 text
175 INSERT INTO y VALUES ('Jackson, Sam', E'\\h');
176 INSERT INTO y VALUES ('It is "perfect".',E'\t');
177 INSERT INTO y VALUES ('', NULL);
179 COPY y TO stdout WITH CSV;
180 COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|';
181 COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\' ENCODING 'sql_ascii';
182 COPY y TO stdout WITH CSV FORCE QUOTE *;
184 -- Repeat above tests with new 9.0 option syntax
186 COPY y TO stdout (FORMAT CSV);
187 COPY y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|');
188 COPY y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\');
189 COPY y TO stdout (FORMAT CSV, FORCE_QUOTE *);
191 \copy y TO stdout (FORMAT CSV)
192 \copy y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|')
193 \copy y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\')
194 \copy y TO stdout (FORMAT CSV, FORCE_QUOTE *)
196 --test that we read consecutive LFs properly
198 CREATE TEMP TABLE testnl (a int, b text, c int);
200 COPY testnl FROM stdin CSV;
201 1,"a field with two LFs
203 inside",2
206 -- test end of copy marker
207 CREATE TEMP TABLE testeoc (a text);
209 COPY testeoc FROM stdin CSV;
212 c\.d
213 "\."
216 COPY testeoc TO stdout CSV;
218 -- test handling of nonstandard null marker that violates escaping rules
220 CREATE TEMP TABLE testnull(a int, b text);
221 INSERT INTO testnull VALUES (1, E'\\0'), (NULL, NULL);
223 COPY testnull TO stdout WITH NULL AS E'\\0';
225 COPY testnull FROM stdin WITH NULL AS E'\\0';
226 42      \\0
227 \0      \0
230 SELECT * FROM testnull;
232 BEGIN;
233 CREATE TABLE vistest (LIKE testeoc);
234 COPY vistest FROM stdin CSV;
238 COMMIT;
239 SELECT * FROM vistest;
240 BEGIN;
241 TRUNCATE vistest;
242 COPY vistest FROM stdin CSV;
246 SELECT * FROM vistest;
247 SAVEPOINT s1;
248 TRUNCATE vistest;
249 COPY vistest FROM stdin CSV;
253 SELECT * FROM vistest;
254 COMMIT;
255 SELECT * FROM vistest;
257 BEGIN;
258 TRUNCATE vistest;
259 COPY vistest FROM stdin CSV FREEZE;
263 SELECT * FROM vistest;
264 SAVEPOINT s1;
265 TRUNCATE vistest;
266 COPY vistest FROM stdin CSV FREEZE;
270 SELECT * FROM vistest;
271 COMMIT;
272 SELECT * FROM vistest;
274 BEGIN;
275 TRUNCATE vistest;
276 COPY vistest FROM stdin CSV FREEZE;
280 SELECT * FROM vistest;
281 COMMIT;
282 TRUNCATE vistest;
283 COPY vistest FROM stdin CSV FREEZE;
287 BEGIN;
288 TRUNCATE vistest;
289 SAVEPOINT s1;
290 COPY vistest FROM stdin CSV FREEZE;
294 COMMIT;
295 BEGIN;
296 INSERT INTO vistest VALUES ('z');
297 SAVEPOINT s1;
298 TRUNCATE vistest;
299 ROLLBACK TO SAVEPOINT s1;
300 COPY vistest FROM stdin CSV FREEZE;
304 COMMIT;
305 CREATE FUNCTION truncate_in_subxact() RETURNS VOID AS
307 BEGIN
308         TRUNCATE vistest;
309 EXCEPTION
310   WHEN OTHERS THEN
311         INSERT INTO vistest VALUES ('subxact failure');
312 END;
313 $$ language plpgsql;
314 BEGIN;
315 INSERT INTO vistest VALUES ('z');
316 SELECT truncate_in_subxact();
317 COPY vistest FROM stdin CSV FREEZE;
321 SELECT * FROM vistest;
322 COMMIT;
323 SELECT * FROM vistest;
324 -- Test FORCE_NOT_NULL and FORCE_NULL options
325 CREATE TEMP TABLE forcetest (
326     a INT NOT NULL,
327     b TEXT NOT NULL,
328     c TEXT,
329     d TEXT,
330     e TEXT
332 \pset null NULL
333 -- should succeed with no effect ("b" remains an empty string, "c" remains NULL)
334 BEGIN;
335 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(b), FORCE_NULL(c));
336 1,,""
338 COMMIT;
339 SELECT b, c FROM forcetest WHERE a = 1;
340 -- should succeed, FORCE_NULL and FORCE_NOT_NULL can be both specified
341 BEGIN;
342 COPY forcetest (a, b, c, d) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(c,d), FORCE_NULL(c,d));
343 2,'a',,""
345 COMMIT;
346 SELECT c, d FROM forcetest WHERE a = 2;
347 -- should fail with not-null constraint violation
348 BEGIN;
349 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b), FORCE_NOT_NULL(c));
350 3,,""
352 ROLLBACK;
353 -- should fail with "not referenced by COPY" error
354 BEGIN;
355 COPY forcetest (d, e) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL(b));
356 ROLLBACK;
357 -- should fail with "not referenced by COPY" error
358 BEGIN;
359 COPY forcetest (d, e) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b));
360 ROLLBACK;
361 -- should succeed with no effect ("b" remains an empty string, "c" remains NULL)
362 BEGIN;
363 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL *, FORCE_NULL *);
364 4,,""
366 COMMIT;
367 SELECT b, c FROM forcetest WHERE a = 4;
368 -- should succeed with effect ("b" remains an empty string)
369 BEGIN;
370 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL *);
371 5,,""
373 COMMIT;
374 SELECT b, c FROM forcetest WHERE a = 5;
375 -- should succeed with effect ("c" remains NULL)
376 BEGIN;
377 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL *);
378 6,"b",""
380 COMMIT;
381 SELECT b, c FROM forcetest WHERE a = 6;
382 -- should fail with "conflicting or redundant options" error
383 BEGIN;
384 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NOT_NULL *, FORCE_NOT_NULL(b));
385 ROLLBACK;
386 -- should fail with "conflicting or redundant options" error
387 BEGIN;
388 COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL *, FORCE_NULL(b));
389 ROLLBACK;
391 \pset null ''
393 -- test case with whole-row Var in a check constraint
394 create table check_con_tbl (f1 int);
395 create function check_con_function(check_con_tbl) returns bool as $$
396 begin
397   raise notice 'input = %', row_to_json($1);
398   return $1.f1 > 0;
399 end $$ language plpgsql immutable;
400 alter table check_con_tbl add check (check_con_function(check_con_tbl.*));
401 \d+ check_con_tbl
402 copy check_con_tbl from stdin;
406 copy check_con_tbl from stdin;
409 select * from check_con_tbl;
411 -- test with RLS enabled.
412 CREATE ROLE regress_rls_copy_user;
413 CREATE ROLE regress_rls_copy_user_colperms;
414 CREATE TABLE rls_t1 (a int, b int, c int);
416 COPY rls_t1 (a, b, c) from stdin;
417 1       4       1
418 2       3       2
419 3       2       3
420 4       1       4
423 CREATE POLICY p1 ON rls_t1 FOR SELECT USING (a % 2 = 0);
424 ALTER TABLE rls_t1 ENABLE ROW LEVEL SECURITY;
425 ALTER TABLE rls_t1 FORCE ROW LEVEL SECURITY;
427 GRANT SELECT ON TABLE rls_t1 TO regress_rls_copy_user;
428 GRANT SELECT (a, b) ON TABLE rls_t1 TO regress_rls_copy_user_colperms;
430 -- all columns
431 COPY rls_t1 TO stdout;
432 COPY rls_t1 (a, b, c) TO stdout;
434 -- subset of columns
435 COPY rls_t1 (a) TO stdout;
436 COPY rls_t1 (a, b) TO stdout;
438 -- column reordering
439 COPY rls_t1 (b, a) TO stdout;
441 SET SESSION AUTHORIZATION regress_rls_copy_user;
443 -- all columns
444 COPY rls_t1 TO stdout;
445 COPY rls_t1 (a, b, c) TO stdout;
447 -- subset of columns
448 COPY rls_t1 (a) TO stdout;
449 COPY rls_t1 (a, b) TO stdout;
451 -- column reordering
452 COPY rls_t1 (b, a) TO stdout;
454 RESET SESSION AUTHORIZATION;
456 SET SESSION AUTHORIZATION regress_rls_copy_user_colperms;
458 -- attempt all columns (should fail)
459 COPY rls_t1 TO stdout;
460 COPY rls_t1 (a, b, c) TO stdout;
462 -- try to copy column with no privileges (should fail)
463 COPY rls_t1 (c) TO stdout;
465 -- subset of columns (should succeed)
466 COPY rls_t1 (a) TO stdout;
467 COPY rls_t1 (a, b) TO stdout;
469 RESET SESSION AUTHORIZATION;
471 -- test with INSTEAD OF INSERT trigger on a view
472 CREATE TABLE instead_of_insert_tbl(id serial, name text);
473 CREATE VIEW instead_of_insert_tbl_view AS SELECT ''::text AS str;
475 COPY instead_of_insert_tbl_view FROM stdin; -- fail
476 test1
479 CREATE FUNCTION fun_instead_of_insert_tbl() RETURNS trigger AS $$
480 BEGIN
481   INSERT INTO instead_of_insert_tbl (name) VALUES (NEW.str);
482   RETURN NULL;
483 END;
484 $$ LANGUAGE plpgsql;
485 CREATE TRIGGER trig_instead_of_insert_tbl_view
486   INSTEAD OF INSERT ON instead_of_insert_tbl_view
487   FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
489 COPY instead_of_insert_tbl_view FROM stdin;
490 test1
493 SELECT * FROM instead_of_insert_tbl;
495 -- Test of COPY optimization with view using INSTEAD OF INSERT
496 -- trigger when relation is created in the same transaction as
497 -- when COPY is executed.
498 BEGIN;
499 CREATE VIEW instead_of_insert_tbl_view_2 as select ''::text as str;
500 CREATE TRIGGER trig_instead_of_insert_tbl_view_2
501   INSTEAD OF INSERT ON instead_of_insert_tbl_view_2
502   FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
504 COPY instead_of_insert_tbl_view_2 FROM stdin;
505 test1
508 SELECT * FROM instead_of_insert_tbl;
509 COMMIT;
511 -- tests for on_error option
512 CREATE TABLE check_ign_err (n int, m int[], k int);
513 COPY check_ign_err FROM STDIN WITH (on_error stop);
514 1       {1}     1
515 a       {2}     2
516 3       {3}     3333333333
517 4       {a, 4}  4
519 5       {5}     5
522 -- want context for notices
523 \set SHOW_CONTEXT always
525 COPY check_ign_err FROM STDIN WITH (on_error ignore, log_verbosity verbose);
526 1       {1}     1
527 a       {2}     2
528 3       {3}     3333333333
529 4       {a, 4}  4
531 5       {5}     5
532 6       a
533 7       {7}     a
534 8       {8}     8
537 -- tests for on_error option with log_verbosity and null constraint via domain
538 CREATE DOMAIN dcheck_ign_err2 varchar(15) NOT NULL;
539 CREATE TABLE check_ign_err2 (n int, m int[], k int, l dcheck_ign_err2);
540 COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity verbose);
541 1       {1}     1       'foo'
542 2       {2}     2       \N
544 COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity silent);
545 3       {3}     3       'bar'
546 4       {4}     4       \N
549 -- reset context choice
550 \set SHOW_CONTEXT errors
552 SELECT * FROM check_ign_err;
554 SELECT * FROM check_ign_err2;
556 -- test datatype error that can't be handled as soft: should fail
557 CREATE TABLE hard_err(foo widget);
558 COPY hard_err FROM STDIN WITH (on_error ignore);
562 -- test missing data: should fail
563 COPY check_ign_err FROM STDIN WITH (on_error ignore);
564 1       {1}
567 -- test extra data: should fail
568 COPY check_ign_err FROM STDIN WITH (on_error ignore);
569 1       {1}     3       abc
572 -- tests for reject_limit option
573 COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 3);
574 6       {6}     6
575 a       {7}     7
576 8       {8}     8888888888
577 9       {a, 9}  9
579 10      {10}    10
582 COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 4);
583 6       {6}     6
584 a       {7}     7
585 8       {8}     8888888888
586 9       {a, 9}  9
588 10      {10}    10
591 -- clean up
592 DROP TABLE forcetest;
593 DROP TABLE vistest;
594 DROP FUNCTION truncate_in_subxact();
595 DROP TABLE x, y;
596 DROP TABLE rls_t1 CASCADE;
597 DROP ROLE regress_rls_copy_user;
598 DROP ROLE regress_rls_copy_user_colperms;
599 DROP FUNCTION fn_x_before();
600 DROP FUNCTION fn_x_after();
601 DROP TABLE instead_of_insert_tbl;
602 DROP VIEW instead_of_insert_tbl_view;
603 DROP VIEW instead_of_insert_tbl_view_2;
604 DROP FUNCTION fun_instead_of_insert_tbl();
605 DROP TABLE check_ign_err;
606 DROP TABLE check_ign_err2;
607 DROP DOMAIN dcheck_ign_err2;
608 DROP TABLE hard_err;
611 -- COPY FROM ... DEFAULT
614 create temp table copy_default (
615         id integer primary key,
616         text_value text not null default 'test',
617         ts_value timestamp without time zone not null default '2022-07-05'
620 -- if DEFAULT is not specified, then the marker will be regular data
621 copy copy_default from stdin;
622 1       value   '2022-07-04'
623 2       \D      '2022-07-05'
626 select id, text_value, ts_value from copy_default;
628 truncate copy_default;
630 copy copy_default from stdin with (format csv);
631 1,value,2022-07-04
632 2,\D,2022-07-05
635 select id, text_value, ts_value from copy_default;
637 truncate copy_default;
639 -- DEFAULT cannot be used in binary mode
640 copy copy_default from stdin with (format binary, default '\D');
642 -- DEFAULT cannot be new line nor carriage return
643 copy copy_default from stdin with (default E'\n');
644 copy copy_default from stdin with (default E'\r');
646 -- DELIMITER cannot appear in DEFAULT spec
647 copy copy_default from stdin with (delimiter ';', default 'test;test');
649 -- CSV quote cannot appear in DEFAULT spec
650 copy copy_default from stdin with (format csv, quote '"', default 'test"test');
652 -- NULL and DEFAULT spec must be different
653 copy copy_default from stdin with (default '\N');
655 -- cannot use DEFAULT marker in column that has no DEFAULT value
656 copy copy_default from stdin with (default '\D');
657 \D      value   '2022-07-04'
658 2       \D      '2022-07-05'
661 copy copy_default from stdin with (format csv, default '\D');
662 \D,value,2022-07-04
663 2,\D,2022-07-05
666 -- The DEFAULT marker must be unquoted and unescaped or it's not recognized
667 copy copy_default from stdin with (default '\D');
668 1       \D      '2022-07-04'
669 2       \\D     '2022-07-04'
670 3       "\D"    '2022-07-04'
673 select id, text_value, ts_value from copy_default;
675 truncate copy_default;
677 copy copy_default from stdin with (format csv, default '\D');
678 1,\D,2022-07-04
679 2,\\D,2022-07-04
680 3,"\D",2022-07-04
683 select id, text_value, ts_value from copy_default;
685 truncate copy_default;
687 -- successful usage of DEFAULT option in COPY
688 copy copy_default from stdin with (default '\D');
689 1       value   '2022-07-04'
690 2       \D      '2022-07-03'
691 3       \D      \D
694 select id, text_value, ts_value from copy_default;
696 truncate copy_default;
698 copy copy_default from stdin with (format csv, default '\D');
699 1,value,2022-07-04
700 2,\D,2022-07-03
701 3,\D,\D
704 select id, text_value, ts_value from copy_default;
706 truncate copy_default;
708 -- DEFAULT cannot be used in COPY TO
709 copy (select 1 as test) TO stdout with (default '\D');