While reading about deprecating and removing various things in other
threads, I was wondering about how deprecated SELECT INTO is. There are
various source code comments about this, but the SELECT INTO reference
page only contains soft language like "recommended". I'm proposing the
attached patch to stick a more explicit deprecation notice right at the top.
I also found some gratuitous uses of SELECT INTO in various tests and
documentation (not ecpg or plpgsql of course). Here is a patch to
adjust those to CREATE TABLE AS.
I don't have a specific plan for removing top-level SELECT INTO
altogether, but there is a nontrivial amount of code for handling it, so
there would be some gain if it could be removed eventually.
From a3ae4248340317ac1580c257472e1361841bd4b2 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 2 Dec 2020 12:09:39 +0100
Subject: [PATCH 1/2] Remove gratuitous uses of deprecated SELECT INTO
CREATE TABLE AS has been preferred over SELECT INTO (outside of ecpg
and PL/pgSQL) for a long time. There were still a few uses of SELECT
INTO in tests and documentation, some old, some more recent. This
changes them to CREATE TABLE AS. Some occurrences in the tests remain
where they are specifically testing SELECT INTO parsing or similar.
---
contrib/sepgsql/expected/label.out | 2 +-
contrib/sepgsql/sql/label.sql | 2 +-
doc/src/sgml/hstore.sgml | 2 +-
src/bin/pg_basebackup/t/010_pg_basebackup.pl | 4 ++--
src/bin/pg_checksums/t/002_actions.pl | 2 +-
src/test/regress/expected/create_index.out | 2 +-
src/test/regress/expected/create_misc.out | 2 +-
src/test/regress/expected/random.out | 3 ++-
src/test/regress/expected/select_implicit.out | 6 ++++--
src/test/regress/expected/select_implicit_1.out | 6 ++++--
src/test/regress/expected/select_implicit_2.out | 6 ++++--
src/test/regress/sql/create_index.sql | 2 +-
src/test/regress/sql/create_misc.sql | 2 +-
src/test/regress/sql/random.sql | 3 ++-
src/test/regress/sql/select_implicit.sql | 6 ++++--
15 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/contrib/sepgsql/expected/label.out
b/contrib/sepgsql/expected/label.out
index 0300bc6fb4..b1b7db55f6 100644
--- a/contrib/sepgsql/expected/label.out
+++ b/contrib/sepgsql/expected/label.out
@@ -6,7 +6,7 @@
--
CREATE TABLE t1 (a int, b text);
INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
-SELECT * INTO t2 FROM t1 WHERE a % 2 = 0;
+CREATE TABLE t2 AS SELECT * FROM t1 WHERE a % 2 = 0;
CREATE FUNCTION f1 () RETURNS text
AS 'SELECT sepgsql_getcon()'
LANGUAGE sql;
diff --git a/contrib/sepgsql/sql/label.sql b/contrib/sepgsql/sql/label.sql
index d19c6edb4c..76e261bee8 100644
--- a/contrib/sepgsql/sql/label.sql
+++ b/contrib/sepgsql/sql/label.sql
@@ -7,7 +7,7 @@
--
CREATE TABLE t1 (a int, b text);
INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
-SELECT * INTO t2 FROM t1 WHERE a % 2 = 0;
+CREATE TABLE t2 AS SELECT * FROM t1 WHERE a % 2 = 0;
CREATE FUNCTION f1 () RETURNS text
AS 'SELECT sepgsql_getcon()'
diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml
index 14a36ade00..25904d9562 100644
--- a/doc/src/sgml/hstore.sgml
+++ b/doc/src/sgml/hstore.sgml
@@ -841,7 +841,7 @@ <title>Statistics</title>
<para>
Using a table:
<programlisting>
-SELECT (each(h)).key, (each(h)).value INTO stat FROM testhstore;
+CREATE TABLE stat AS SELECT (each(h)).key, (each(h)).value FROM testhstore;
</programlisting>
</para>
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index f674a7c94e..9eba7d8d7d 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -502,10 +502,10 @@
# create tables to corrupt and get their relfilenodes
my $file_corrupt1 = $node->safe_psql('postgres',
- q{SELECT a INTO corrupt1 FROM generate_series(1,10000) AS a; ALTER
TABLE corrupt1 SET (autovacuum_enabled=false); SELECT
pg_relation_filepath('corrupt1')}
+ q{CREATE TABLE corrupt1 AS SELECT a FROM generate_series(1,10000) AS a;
ALTER TABLE corrupt1 SET (autovacuum_enabled=false); SELECT
pg_relation_filepath('corrupt1')}
);
my $file_corrupt2 = $node->safe_psql('postgres',
- q{SELECT b INTO corrupt2 FROM generate_series(1,2) AS b; ALTER TABLE
corrupt2 SET (autovacuum_enabled=false); SELECT
pg_relation_filepath('corrupt2')}
+ q{CREATE TABLE corrupt2 AS SELECT b FROM generate_series(1,2) AS b;
ALTER TABLE corrupt2 SET (autovacuum_enabled=false); SELECT
pg_relation_filepath('corrupt2')}
);
# set page header and block sizes
diff --git a/src/bin/pg_checksums/t/002_actions.pl
b/src/bin/pg_checksums/t/002_actions.pl
index 4e4934532a..8a81f36a06 100644
--- a/src/bin/pg_checksums/t/002_actions.pl
+++ b/src/bin/pg_checksums/t/002_actions.pl
@@ -21,7 +21,7 @@ sub check_relation_corruption
$node->safe_psql(
'postgres',
- "SELECT a INTO $table FROM generate_series(1,10000) AS a;
+ "CREATE TABLE $table AS SELECT a FROM generate_series(1,10000)
AS a;
ALTER TABLE $table SET (autovacuum_enabled=false);");
$node->safe_psql('postgres',
diff --git a/src/test/regress/expected/create_index.out
b/src/test/regress/expected/create_index.out
index 18bb92b810..5fb8c48e95 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -1582,7 +1582,7 @@ DROP TABLE syscol_table;
--
-- Tests for IS NULL/IS NOT NULL with b-tree indexes
--
-SELECT unique1, unique2 INTO onek_with_null FROM onek;
+CREATE TABLE onek_with_null AS SELECT unique1, unique2 FROM onek;
INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL);
CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1);
SET enable_seqscan = OFF;
diff --git a/src/test/regress/expected/create_misc.out
b/src/test/regress/expected/create_misc.out
index cee35ed02f..41bc4d7750 100644
--- a/src/test/regress/expected/create_misc.out
+++ b/src/test/regress/expected/create_misc.out
@@ -5,7 +5,7 @@
-- (any resemblance to real life is purely coincidental)
--
INSERT INTO tenk2 SELECT * FROM tenk1;
-SELECT * INTO TABLE onek2 FROM onek;
+CREATE TABLE onek2 AS SELECT * FROM onek;
INSERT INTO fast_emp4000 SELECT * FROM slow_emp4000;
SELECT *
INTO TABLE Bprime
diff --git a/src/test/regress/expected/random.out
b/src/test/regress/expected/random.out
index 302c3d61c7..a919b28d8d 100644
--- a/src/test/regress/expected/random.out
+++ b/src/test/regress/expected/random.out
@@ -23,7 +23,8 @@ INTERSECT
(0 rows)
-- count roughly 1/10 of the tuples
-SELECT count(*) AS random INTO RANDOM_TBL
+CREATE TABLE RANDOM_TBL AS
+ SELECT count(*) AS random
FROM onek WHERE random() < 1.0/10;
-- select again, the count should be different
INSERT INTO RANDOM_TBL (random)
diff --git a/src/test/regress/expected/select_implicit.out
b/src/test/regress/expected/select_implicit.out
index 61b485fdaa..27c07de92c 100644
--- a/src/test/regress/expected/select_implicit.out
+++ b/src/test/regress/expected/select_implicit.out
@@ -202,7 +202,8 @@ SELECT count(*) FROM test_missing_target x,
test_missing_target y
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(*) INTO TABLE test_missing_target2
+CREATE TABLE test_missing_target2 AS
+SELECT count(*)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b ORDER BY x.b;
@@ -318,7 +319,8 @@ LINE 1: SELECT count(b) FROM test_missing_target x,
test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(x.b) INTO TABLE test_missing_target3
+CREATE TABLE test_missing_target3 AS
+SELECT count(x.b)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2 ORDER BY x.b/2;
diff --git a/src/test/regress/expected/select_implicit_1.out
b/src/test/regress/expected/select_implicit_1.out
index f277375ebf..d67521e8f8 100644
--- a/src/test/regress/expected/select_implicit_1.out
+++ b/src/test/regress/expected/select_implicit_1.out
@@ -202,7 +202,8 @@ SELECT count(*) FROM test_missing_target x,
test_missing_target y
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(*) INTO TABLE test_missing_target2
+CREATE TABLE test_missing_target2 AS
+SELECT count(*)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b ORDER BY x.b;
@@ -318,7 +319,8 @@ LINE 1: SELECT count(b) FROM test_missing_target x,
test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(x.b) INTO TABLE test_missing_target3
+CREATE TABLE test_missing_target3 AS
+SELECT count(x.b)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2 ORDER BY x.b/2;
diff --git a/src/test/regress/expected/select_implicit_2.out
b/src/test/regress/expected/select_implicit_2.out
index 91c3a24f92..7a353d0862 100644
--- a/src/test/regress/expected/select_implicit_2.out
+++ b/src/test/regress/expected/select_implicit_2.out
@@ -202,7 +202,8 @@ SELECT count(*) FROM test_missing_target x,
test_missing_target y
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(*) INTO TABLE test_missing_target2
+CREATE TABLE test_missing_target2 AS
+SELECT count(*)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b ORDER BY x.b;
@@ -318,7 +319,8 @@ LINE 1: SELECT count(b) FROM test_missing_target x,
test_missing_tar...
^
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(x.b) INTO TABLE test_missing_target3
+CREATE TABLE test_missing_target3 AS
+SELECT count(x.b)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2 ORDER BY x.b/2;
diff --git a/src/test/regress/sql/create_index.sql
b/src/test/regress/sql/create_index.sql
index 55326eb47b..331670962e 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -609,7 +609,7 @@ CREATE INDEX ON syscol_table (a) WHERE ctid >= '(1000,0)';
-- Tests for IS NULL/IS NOT NULL with b-tree indexes
--
-SELECT unique1, unique2 INTO onek_with_null FROM onek;
+CREATE TABLE onek_with_null AS SELECT unique1, unique2 FROM onek;
INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL);
CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1);
diff --git a/src/test/regress/sql/create_misc.sql
b/src/test/regress/sql/create_misc.sql
index d0b04a821f..c7d0d064c3 100644
--- a/src/test/regress/sql/create_misc.sql
+++ b/src/test/regress/sql/create_misc.sql
@@ -8,7 +8,7 @@
INSERT INTO tenk2 SELECT * FROM tenk1;
-SELECT * INTO TABLE onek2 FROM onek;
+CREATE TABLE onek2 AS SELECT * FROM onek;
INSERT INTO fast_emp4000 SELECT * FROM slow_emp4000;
diff --git a/src/test/regress/sql/random.sql b/src/test/regress/sql/random.sql
index ae6b70a157..8187b2c288 100644
--- a/src/test/regress/sql/random.sql
+++ b/src/test/regress/sql/random.sql
@@ -17,7 +17,8 @@
FROM onek ORDER BY random() LIMIT 1);
-- count roughly 1/10 of the tuples
-SELECT count(*) AS random INTO RANDOM_TBL
+CREATE TABLE RANDOM_TBL AS
+ SELECT count(*) AS random
FROM onek WHERE random() < 1.0/10;
-- select again, the count should be different
diff --git a/src/test/regress/sql/select_implicit.sql
b/src/test/regress/sql/select_implicit.sql
index d815504222..de3aef8d81 100644
--- a/src/test/regress/sql/select_implicit.sql
+++ b/src/test/regress/sql/select_implicit.sql
@@ -86,7 +86,8 @@ CREATE TABLE test_missing_target (a int, b int, c char(8), d
char);
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(*) INTO TABLE test_missing_target2
+CREATE TABLE test_missing_target2 AS
+SELECT count(*)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b ORDER BY x.b;
@@ -142,7 +143,8 @@ CREATE TABLE test_missing_target (a int, b int, c char(8),
d char);
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
-SELECT count(x.b) INTO TABLE test_missing_target3
+CREATE TABLE test_missing_target3 AS
+SELECT count(x.b)
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2 ORDER BY x.b/2;
--
2.29.2
From a7ddf18d2c89005ad6035cf1f40387ca7e949567 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 2 Dec 2020 12:47:03 +0100
Subject: [PATCH 2/2] doc: Add stronger deprecation language to SELECT INTO
reference page
Even though SELECT INTO (not ecpg, not PL/pgSQL) is widely recognized
among insiders to be deprecated, and there are some source code
comments about this, the SELECT INTO reference page only contains
vague language like "recommended". This change puts a deprecation
notice right at the top.
---
doc/src/sgml/ref/select_into.sgml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/doc/src/sgml/ref/select_into.sgml
b/doc/src/sgml/ref/select_into.sgml
index 7b327d9eee..b37ac345b0 100644
--- a/doc/src/sgml/ref/select_into.sgml
+++ b/doc/src/sgml/ref/select_into.sgml
@@ -42,6 +42,12 @@
<refsect1>
<title>Description</title>
+ <para>
+ This command is deprecated. Use <link
+ linkend="sql-createtableas"><command>CREATE TABLE AS</command></link>
+ instead.
+ </para>
+
<para>
<command>SELECT INTO</command> creates a new table and fills it
with data computed by a query. The data is not returned to the
--
2.29.2