Add tests for COPY in PL/pgSQL
authorMichael Paquier <[email protected]>
Sat, 9 Nov 2019 05:50:20 +0000 (14:50 +0900)
committerMichael Paquier <[email protected]>
Sat, 9 Nov 2019 05:50:20 +0000 (14:50 +0900)
This stresses the error handling of COPY inside SPI which does not
support the operation using stdin or stdout, and these scenarios were
not tested up to now.

Author: Mark Dilger
Discussion: https://postgr.es/m/a6e9b130-7fd5-387b-4ec5-89bda24373ab@gmail.com

src/pl/plpgsql/src/Makefile
src/pl/plpgsql/src/data/copy1.data [new file with mode: 0644]
src/pl/plpgsql/src/expected/.gitignore [new file with mode: 0644]
src/pl/plpgsql/src/input/plpgsql_copy.source [new file with mode: 0644]
src/pl/plpgsql/src/output/plpgsql_copy.source [new file with mode: 0644]
src/pl/plpgsql/src/sql/.gitignore [new file with mode: 0644]

index 4d57bf5f1e5550c37a56918662613be317e34649..e0bcccf39e2ecddd084536cf0fac96b6c988f1fa 100644 (file)
@@ -32,8 +32,8 @@ DATA = plpgsql.control plpgsql--1.0.sql plpgsql--unpackaged--1.0.sql
 
 REGRESS_OPTS = --dbname=$(PL_TESTDB)
 
-REGRESS = plpgsql_call plpgsql_control plpgsql_domain plpgsql_record \
-       plpgsql_cache plpgsql_transaction plpgsql_trap \
+REGRESS = plpgsql_call plpgsql_control plpgsql_copy plpgsql_domain \
+       plpgsql_record plpgsql_cache plpgsql_transaction plpgsql_trap \
        plpgsql_trigger plpgsql_varprops
 
 # where to find gen_keywordlist.pl and subsidiary files
diff --git a/src/pl/plpgsql/src/data/copy1.data b/src/pl/plpgsql/src/data/copy1.data
new file mode 100644 (file)
index 0000000..5d8478f
--- /dev/null
@@ -0,0 +1,3 @@
+1      1.1
+2      2.2
+3      3.3
diff --git a/src/pl/plpgsql/src/expected/.gitignore b/src/pl/plpgsql/src/expected/.gitignore
new file mode 100644 (file)
index 0000000..13e5918
--- /dev/null
@@ -0,0 +1 @@
+/plpgsql_copy.out
diff --git a/src/pl/plpgsql/src/input/plpgsql_copy.source b/src/pl/plpgsql/src/input/plpgsql_copy.source
new file mode 100644 (file)
index 0000000..b7bcbb7
--- /dev/null
@@ -0,0 +1,62 @@
+CREATE TABLE copy1 (a int, b float);
+
+-- COPY TO/FROM not authorized from client.
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 TO stdout;
+END;
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM stdin;
+END;
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 TO stdout';
+END;
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM stdin';
+END;
+$$;
+
+-- Valid cases
+-- COPY FROM
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM '@abs_srcdir@/data/copy1.data';
+END;
+$$;
+SELECT * FROM copy1 ORDER BY 1;
+TRUNCATE copy1;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM ''@abs_srcdir@/data/copy1.data''';
+END;
+$$;
+SELECT * FROM copy1 ORDER BY 1;
+
+-- COPY TO
+-- Copy the data externally once, then process it back to the table.
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 TO '@abs_builddir@/results/copy1.data';
+END;
+$$;
+TRUNCATE copy1;
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM '@abs_builddir@/results/copy1.data';
+END;
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM ''@abs_builddir@/results/copy1.data''';
+END;
+$$;
+
+SELECT * FROM copy1 ORDER BY 1;
+
+DROP TABLE copy1;
diff --git a/src/pl/plpgsql/src/output/plpgsql_copy.source b/src/pl/plpgsql/src/output/plpgsql_copy.source
new file mode 100644 (file)
index 0000000..78c9a75
--- /dev/null
@@ -0,0 +1,89 @@
+CREATE TABLE copy1 (a int, b float);
+-- COPY TO/FROM not authorized from client.
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 TO stdout;
+END;
+$$;
+ERROR:  cannot COPY to/from client in PL/pgSQL
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at SQL statement
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM stdin;
+END;
+$$;
+ERROR:  cannot COPY to/from client in PL/pgSQL
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at SQL statement
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 TO stdout';
+END;
+$$;
+ERROR:  cannot COPY to/from client in PL/pgSQL
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at EXECUTE
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM stdin';
+END;
+$$;
+ERROR:  cannot COPY to/from client in PL/pgSQL
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at EXECUTE
+-- Valid cases
+-- COPY FROM
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM '@abs_builddir@/data/copy1.data';
+END;
+$$;
+SELECT * FROM copy1 ORDER BY 1;
+ a |  b  
+---+-----
+ 1 | 1.1
+ 2 | 2.2
+ 3 | 3.3
+(3 rows)
+
+TRUNCATE copy1;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM ''@abs_builddir@/data/copy1.data''';
+END;
+$$;
+SELECT * FROM copy1 ORDER BY 1;
+ a |  b  
+---+-----
+ 1 | 1.1
+ 2 | 2.2
+ 3 | 3.3
+(3 rows)
+
+-- COPY TO
+-- Copy the data externally once, then process it back to the table.
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 TO '@abs_builddir@/results/copy1.data';
+END;
+$$;
+TRUNCATE copy1;
+DO LANGUAGE plpgsql $$
+BEGIN
+  COPY copy1 FROM '@abs_builddir@/results/copy1.data';
+END;
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  EXECUTE 'COPY copy1 FROM ''@abs_builddir@/results/copy1.data''';
+END;
+$$;
+SELECT * FROM copy1 ORDER BY 1;
+ a |  b  
+---+-----
+ 1 | 1.1
+ 1 | 1.1
+ 2 | 2.2
+ 2 | 2.2
+ 3 | 3.3
+ 3 | 3.3
+(6 rows)
+
+DROP TABLE copy1;
diff --git a/src/pl/plpgsql/src/sql/.gitignore b/src/pl/plpgsql/src/sql/.gitignore
new file mode 100644 (file)
index 0000000..210bee1
--- /dev/null
@@ -0,0 +1 @@
+/plpgsql_copy.sql