From caccb974991b732e62a68c19f2caed556f6110af Mon Sep 17 00:00:00 2001 From: mb Date: Tue, 27 Jun 2023 11:35:45 +0200 Subject: [PATCH 1/6] Next snapshot release --- grammar-to-java/pom.xml | 2 +- parser-enums/pom.xml | 2 +- parser-test-gui/pom.xml | 2 +- parser/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grammar-to-java/pom.xml b/grammar-to-java/pom.xml index 2aca419..40ba5a8 100644 --- a/grammar-to-java/pom.xml +++ b/grammar-to-java/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.1 + 15.2-SNAPSHOT com.splendiddata.pg_sqlparser grammar-to-java diff --git a/parser-enums/pom.xml b/parser-enums/pom.xml index 0f4ba33..449af3d 100644 --- a/parser-enums/pom.xml +++ b/parser-enums/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.1 + 15.2-SNAPSHOT com.splendiddata.pg_sqlparser parser-enums diff --git a/parser-test-gui/pom.xml b/parser-test-gui/pom.xml index 83f3b6f..c5744c8 100644 --- a/parser-test-gui/pom.xml +++ b/parser-test-gui/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.1 + 15.2-SNAPSHOT parser-test-gui com.splendiddata.pg_sqlparser diff --git a/parser/pom.xml b/parser/pom.xml index 7e59882..23a699b 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.1 + 15.2-SNAPSHOT com.splendiddata.pg_sqlparser parser diff --git a/pom.xml b/pom.xml index 7a05a2c..280dd6a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.splendiddata pg_sqlparser - 15.1 + 15.2-SNAPSHOT pom pg_sqlparser Java implementation of the Postgres sql parser. This version of the sqlparser is generated from the Postgres version 15 parser. From 5c437fb796e900ab936597208af147cef51a8be3 Mon Sep 17 00:00:00 2001 From: mb Date: Tue, 22 Aug 2023 11:53:52 +0200 Subject: [PATCH 2/6] Adapted Postgres15.4 --- .../main/grammar/postgres/src/backend/parser/gram.y | 4 ++-- pom.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/parser/src/main/grammar/postgres/src/backend/parser/gram.y b/parser/src/main/grammar/postgres/src/backend/parser/gram.y index 0b9cd62..2ece5d7 100644 --- a/parser/src/main/grammar/postgres/src/backend/parser/gram.y +++ b/parser/src/main/grammar/postgres/src/backend/parser/gram.y @@ -18447,7 +18447,7 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) if (!pubobj->name && !pubobj->pubtable) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid table name at or near"), + errmsg("invalid table name"), parser_errposition(pubobj->location)); if (pubobj->name) @@ -18489,7 +18489,7 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid schema name at or near"), + errmsg("invalid schema name"), parser_errposition(pubobj->location)); } diff --git a/pom.xml b/pom.xml index 280dd6a..b5c2653 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ file:**/generated-sources/** 2.20.0 11.0.2 - 5.9.3 + 5.10.0 3.9.1 2.8 @@ -91,7 +91,7 @@ org.apache.maven maven-plugin-api - 3.9.3 + 3.9.4 org.apache.maven.plugin-tools @@ -107,13 +107,13 @@ org.apache.maven maven-core - 3.9.3 + 3.9.4 com.github.javaparser javaparser-core - 3.25.3 + 3.25.4 @@ -184,12 +184,12 @@ org.junit.platform junit-platform-runner test - 1.9.3 + 1.10.0 org.checkerframework checker-qual - 3.35.0 + 3.37.0 From 55483b47569668e58b19c820d025f1d448c144c3 Mon Sep 17 00:00:00 2001 From: mb Date: Tue, 4 Jun 2024 15:20:30 +0200 Subject: [PATCH 3/6] Updated some dependency versions --- .../postgres/src/backend/parser/gram.y | 2 +- .../postgres/src/backend/parser/scan.l | 2 +- pom.xml | 60 +++++++++---------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/parser/src/main/grammar/postgres/src/backend/parser/gram.y b/parser/src/main/grammar/postgres/src/backend/parser/gram.y index 2ece5d7..3564380 100644 --- a/parser/src/main/grammar/postgres/src/backend/parser/gram.y +++ b/parser/src/main/grammar/postgres/src/backend/parser/gram.y @@ -18565,4 +18565,4 @@ void parser_init(base_yy_extra_type *yyext) { yyext->parsetree = NIL; /* in case grammar forgets to set it */ -} +} \ No newline at end of file diff --git a/parser/src/main/scanner/postgres/src/backend/parser/scan.l b/parser/src/main/scanner/postgres/src/backend/parser/scan.l index 882e081..8c0f692 100644 --- a/parser/src/main/scanner/postgres/src/backend/parser/scan.l +++ b/parser/src/main/scanner/postgres/src/backend/parser/scan.l @@ -1435,4 +1435,4 @@ core_yyfree(void *ptr, core_yyscan_t yyscanner) { if (ptr) pfree(ptr); -} +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index b5c2653..3b8ee7c 100644 --- a/pom.xml +++ b/pom.xml @@ -38,9 +38,9 @@ ${java.version} UTF-8 file:**/generated-sources/** - 2.20.0 + 2.23.1 11.0.2 - 5.10.0 + 5.10.2 3.9.1 2.8 @@ -91,40 +91,40 @@ org.apache.maven maven-plugin-api - 3.9.4 + 3.9.7 org.apache.maven.plugin-tools maven-plugin-annotations - 3.9.0 + 3.13.1 provided org.apache.maven.plugin-tools maven-plugin-tools-api - 3.9.0 + 3.13.1 org.apache.maven maven-core - 3.9.4 + 3.9.7 com.github.javaparser javaparser-core - 3.25.4 + 3.26.0 jakarta.xml.bind jakarta.xml.bind-api - 4.0.0 + 4.0.2 org.glassfish.jaxb jaxb-runtime - 4.0.3 + 4.0.5 @@ -189,7 +189,7 @@ org.checkerframework checker-qual - 3.37.0 + 3.44.0 @@ -205,7 +205,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.13.0 ${java.version} @@ -221,27 +221,27 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.3.0 org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 de.jflex jflex-maven-plugin - 1.8.2 + 1.9.1 org.apache.maven.plugins maven-dependency-plugin - 3.4.0 + 3.6.1 org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.1 UTF-8 @@ -254,12 +254,12 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.12 org.apache.maven.plugins maven-plugin-plugin - 3.7.0 + 3.10.2 org.apache.maven.plugins @@ -269,22 +269,22 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.7.0 org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M7 + 3.2.5 org.apache.maven.plugins maven-clean-plugin - 3.2.0 + 3.3.2 org.apache.maven.plugins maven-deploy-plugin - 3.0.0 + 3.1.2 true @@ -292,17 +292,17 @@ org.apache.maven.plugins maven-install-plugin - 3.1.0 + 3.1.2 org.apache.maven.plugins maven-resources-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins maven-enforcer-plugin - 3.1.0 + 3.5.0 @@ -359,7 +359,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 attach-sources @@ -377,7 +377,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.1 + 3.5.0 @@ -390,7 +390,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.6.3 public false @@ -413,7 +413,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.0.0-M7 + 3.2.5 @@ -428,7 +428,7 @@ org.apache.maven.plugins maven-jxr-plugin - 3.3.0 + 3.4.0 org.jacoco From 7315f507f6a6805c92fba3379502aacc952b944c Mon Sep 17 00:00:00 2001 From: Martin Butter Date: Fri, 21 Nov 2025 17:07:31 +0100 Subject: [PATCH 4/6] Updated to Postgres version 15.15 --- grammar-to-java/pom.xml | 4 +- .../grammartojava/GrammarConverter.java | 4 +- .../grammartojava/JavaParserConverter.java | 4 +- .../grammartojava/JaxbIndexCreator.java | 4 +- .../sqlparser/grammartojava/LexConverter.java | 4 +- parser/pom.xml | 36 +-- .../postgres/src/backend/parser/gram.y | 28 +- .../sqlparser/structure/CreateStatsStmt.java | 4 +- .../sqlparser/structure/CreateStmt.java | 6 +- .../sqlparser/structure/DefineStmt.java | 37 ++- .../postgres/src/backend/parser/scan.l | 10 +- .../sqlparser/SqlFileRegressionTest.java | 150 ++++++--- .../resources/commands/create extension.sql | 6 +- .../test/resources/commands/create table.sql | 7 - .../test/regress/sql/advisory_lock.sql | 32 +- .../postgres/test/regress/sql/aggregates.sql | 56 +--- .../postgres/test/regress/sql/alter_table.sql | 245 +++++++++------ .../postgres/test/regress/sql/arrays.sql | 55 +++- .../postgres/test/regress/sql/brin_multi.sql | 106 +++++++ .../postgres/test/regress/sql/case.sql | 5 + .../test/regress/sql/collate.icu.utf8.sql | 84 ++++- .../postgres/test/regress/sql/conversion.sql | 26 +- .../postgres/test/regress/sql/copydml.sql | 4 + .../test/regress/sql/create_aggregate.sql | 18 +- .../postgres/test/regress/sql/create_am.sql | 18 ++ .../test/regress/sql/create_index.sql | 56 ++-- .../test/regress/sql/create_procedure.sql | 38 ++- .../test/regress/sql/create_schema.sql | 70 +++++ .../test/regress/sql/create_table.sql | 60 ++-- .../test/regress/sql/create_table_like.sql | 8 + .../postgres/test/regress/sql/create_view.sql | 101 +++--- .../postgres/test/regress/sql/database.sql | 23 ++ .../postgres/test/regress/sql/dbsize.sql | 4 + .../postgres/test/regress/sql/domain.sql | 26 +- .../test/regress/sql/event_trigger.sql | 71 ++++- .../postgres/test/regress/sql/expressions.sql | 2 +- .../test/regress/sql/fast_default.sql | 55 ++++ .../test/regress/sql/foreign_data.sql | 173 ++++++----- .../postgres/test/regress/sql/foreign_key.sql | 256 +++++++++++++-- .../postgres/test/regress/sql/generated.sql | 81 +++-- .../postgres/test/regress/sql/guc.sql | 18 -- .../postgres/test/regress/sql/horology.sql | 9 +- .../postgres/test/regress/sql/identity.sql | 47 ++- .../test/regress/sql/index_including.sql | 19 ++ .../postgres/test/regress/sql/indexing.sql | 111 +++++++ .../postgres/test/regress/sql/inherit.sql | 75 +++++ .../postgres/test/regress/sql/insert.sql | 83 ++++- .../test/regress/sql/insert_conflict.sql | 6 + .../postgres/test/regress/sql/int8.sql | 1 + .../postgres/test/regress/sql/interval.sql | 12 + .../postgres/test/regress/sql/join.sql | 68 ++-- .../postgres/test/regress/sql/join_hash.sql | 19 ++ .../postgres/test/regress/sql/jsonb.sql | 37 ++- .../test/regress/sql/jsonb_jsonpath.sql | 11 + .../postgres/test/regress/sql/limit.sql | 24 +- .../test/regress/sql/maintain_every.sql | 26 ++ .../postgres/test/regress/sql/matview.sql | 17 + .../postgres/test/regress/sql/memoize.sql | 48 ++- .../postgres/test/regress/sql/merge.sql | 292 ++++++++++++++++-- .../postgres/test/regress/sql/money.sql | 11 + .../postgres/test/regress/sql/namespace.sql | 34 +- .../postgres/test/regress/sql/numeric.sql | 28 +- .../postgres/test/regress/sql/numerology.sql | 27 +- .../postgres/test/regress/sql/opr_sanity.sql | 2 +- .../test/regress/sql/partition_join.sql | 48 +++ .../test/regress/sql/partition_prune.sql | 159 +++++++++- .../postgres/test/regress/sql/plpgsql.sql | 8 +- .../postgres/test/regress/sql/privileges.sql | 250 +++++++-------- .../postgres/test/regress/sql/publication.sql | 213 +++++++++---- .../postgres/test/regress/sql/rangefuncs.sql | 10 + .../test/regress/sql/replica_identity.sql | 20 ++ .../postgres/test/regress/sql/returning.sql | 24 ++ .../postgres/test/regress/sql/rowsecurity.sql | 251 +++++++++++++-- .../postgres/test/regress/sql/rowtypes.sql | 51 +++ .../postgres/test/regress/sql/rules.sql | 96 +++++- .../test/regress/sql/select_parallel.sql | 54 ++++ .../postgres/test/regress/sql/stats.sql | 58 +++- .../postgres/test/regress/sql/stats_ext.sql | 139 +++++++-- .../postgres/test/regress/sql/strings.sql | 26 +- .../test/regress/sql/subscription.sql | 17 +- .../postgres/test/regress/sql/subselect.sql | 31 +- .../postgres/test/regress/sql/temp.sql | 16 + .../postgres/test/regress/sql/timestamp.sql | 8 + .../postgres/test/regress/sql/timestamptz.sql | 16 +- .../postgres/test/regress/sql/timetz.sql | 20 ++ .../test/regress/sql/transactions.sql | 75 ++--- .../postgres/test/regress/sql/triggers.sql | 176 +++++++++-- .../postgres/test/regress/sql/tsdicts.sql | 30 ++ .../postgres/test/regress/sql/tsearch.sql | 31 +- .../test/regress/sql/updatable_views.sql | 45 +++ .../postgres/test/regress/sql/update.sql | 12 +- .../postgres/test/regress/sql/vacuum.sql | 29 ++ .../postgres/test/regress/sql/window.sql | 49 ++- .../postgres/test/regress/sql/with.sql | 137 +++++++- .../postgres/test/regress/sql/xml.sql | 12 +- pom.xml | 101 +++--- 96 files changed, 4073 insertions(+), 1141 deletions(-) create mode 100644 parser/src/test/resources/postgres/test/regress/sql/create_schema.sql create mode 100644 parser/src/test/resources/postgres/test/regress/sql/database.sql create mode 100644 parser/src/test/resources/postgres/test/regress/sql/maintain_every.sql diff --git a/grammar-to-java/pom.xml b/grammar-to-java/pom.xml index 40ba5a8..fb830d3 100644 --- a/grammar-to-java/pom.xml +++ b/grammar-to-java/pom.xml @@ -20,6 +20,7 @@ org.apache.maven maven-plugin-api + provided org.apache.maven.plugin-tools @@ -50,6 +51,7 @@ true + plugin @@ -68,7 +70,7 @@ https://www.gnu.org/licenses/gpl-3.0.en.html https://www.splendiddata.com - Copyright (c) Splendid Data Product Development B.V. 2013 - 2021 + Copyright (c) Splendid Data Product Development B.V. 2013 - 2025 diff --git a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/GrammarConverter.java b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/GrammarConverter.java index 7ea7c6c..2b6bd04 100644 --- a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/GrammarConverter.java +++ b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/GrammarConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 - 2022 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at Client's option) any later @@ -112,7 +112,7 @@ * @author Splendid Data Product Development B.V. * @since 0.0.1 */ -@Mojo(name = "convertGrammar", executionStrategy = "always", defaultPhase = LifecyclePhase.GENERATE_SOURCES) +@Mojo(name = "convertGrammar", defaultPhase = LifecyclePhase.GENERATE_SOURCES) @Execute(goal = "convertGrammar", phase = LifecyclePhase.GENERATE_SOURCES) public class GrammarConverter extends AbstractMojo implements FileVisitor { private Log log; diff --git a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JavaParserConverter.java b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JavaParserConverter.java index 3cf10f5..a72902f 100644 --- a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JavaParserConverter.java +++ b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JavaParserConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 - 2021 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at Client's option) any later @@ -60,7 +60,7 @@ * @author Splendid Data Product Development B.V. * @since 0.0.1 */ -@Mojo(name = "convertJava", executionStrategy = "always", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) +@Mojo(name = "convertJava", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) @Execute(goal = "convertJava", phase = LifecyclePhase.PROCESS_RESOURCES) public class JavaParserConverter extends AbstractMojo implements FileVisitor { private Log log; diff --git a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JaxbIndexCreator.java b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JaxbIndexCreator.java index a9fa3bc..876d4d3 100644 --- a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JaxbIndexCreator.java +++ b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/JaxbIndexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the * terms of the GNU General Public License as published by the Free Software @@ -58,7 +58,7 @@ * @author Splendid Data Product Development B.V. * @since 5.1 */ -@Mojo(name = "createJaxbIndex", executionStrategy = "always", defaultPhase = LifecyclePhase.COMPILE) +@Mojo(name = "createJaxbIndex",defaultPhase = LifecyclePhase.COMPILE) @Execute(goal = "createJaxbIndex", phase = LifecyclePhase.COMPILE) public class JaxbIndexCreator extends AbstractMojo implements FileVisitor { private Log log = getLog(); diff --git a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/LexConverter.java b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/LexConverter.java index 5f4b544..369e759 100644 --- a/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/LexConverter.java +++ b/grammar-to-java/src/main/java/com/splendiddata/sqlparser/grammartojava/LexConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the * terms of the GNU General Public License as published by the Free Software @@ -48,7 +48,7 @@ * @author Splendid Data Product Development B.V. * @since 0.0.1 */ -@Mojo(name = "convertLex", executionStrategy = "always", defaultPhase = LifecyclePhase.GENERATE_SOURCES) +@Mojo(name = "convertLex", defaultPhase = LifecyclePhase.GENERATE_SOURCES) @Execute(goal = "convertLex", phase = LifecyclePhase.GENERATE_SOURCES) public class LexConverter extends AbstractMojo implements FileVisitor { private Log log; diff --git a/parser/pom.xml b/parser/pom.xml index 23a699b..320acbe 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -18,54 +18,40 @@ com.splendiddata.pg_sqlparser parser-enums - ${project.version} + ${project.version} org.apache.logging.log4j log4j-api - + org.apache.logging.log4j log4j-core - - jakarta.xml.bind - jakarta.xml.bind-api - - - org.glassfish.jaxb - jaxb-runtime - - - org.checkerframework - checker-qual + jakarta.xml.bind + jakarta.xml.bind-api - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.platform - junit-platform-runner - test + org.glassfish.jaxb + jaxb-runtime + - org.junit.jupiter - junit-jupiter-api - test + org.checkerframework + checker-qual org.junit.jupiter - junit-jupiter-params + junit-jupiter test + ${project.basedir}/src/test/java org.apache.maven.plugins diff --git a/parser/src/main/grammar/postgres/src/backend/parser/gram.y b/parser/src/main/grammar/postgres/src/backend/parser/gram.y index 3564380..c77060c 100644 --- a/parser/src/main/grammar/postgres/src/backend/parser/gram.y +++ b/parser/src/main/grammar/postgres/src/backend/parser/gram.y @@ -2559,7 +2559,7 @@ alter_table_cmd: n->def = (Node *) c; c->contype = CONSTR_FOREIGN; /* others not supported, yet */ c->conname = $3; - processCASbits($4, @4, "ALTER CONSTRAINT statement", + processCASbits($4, @4, "FOREIGN KEY", &c->deferrable, &c->initdeferred, NULL, NULL, yyscanner); @@ -4738,6 +4738,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("increment", (Node *) $3, @1); } + | LOGGED + { + $$ = makeDefElem("logged", NULL, @1); + } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); @@ -4760,7 +4764,6 @@ SeqOptElem: AS SimpleTypename } | SEQUENCE NAME_P any_name { - /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly @@ -4775,6 +4778,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("restart", (Node *) $3, @1); } + | UNLOGGED + { + $$ = makeDefElem("unlogged", NULL, @1); + } ; opt_by: BY @@ -13813,7 +13820,7 @@ xmltable_column_el: parser_errposition(defel->location))); fc->colexpr = defel->arg; } - else if (strcmp(defel->defname, "is_not_null") == 0) + else if (strcmp(defel->defname, "__pg__is_not_null") == 0) { if (nullability_seen) ereport(ERROR, @@ -13856,13 +13863,20 @@ xmltable_column_option_list: xmltable_column_option_el: IDENT b_expr - { $$ = makeDefElem($1, $2, @1); } + { + if (strcmp($1, "__pg__is_not_null") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option name \"%s\" cannot be used in XMLTABLE", $1), + parser_errposition(@1))); + $$ = makeDefElem($1, $2, @1); + } | DEFAULT b_expr { $$ = makeDefElem("default", $2, @1); } | NOT NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); } ; xml_namespace_list: @@ -18565,4 +18579,4 @@ void parser_init(base_yy_extra_type *yyext) { yyext->parsetree = NIL; /* in case grammar forgets to set it */ -} \ No newline at end of file +} diff --git a/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStatsStmt.java b/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStatsStmt.java index f08a007..e17ce7f 100644 --- a/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStatsStmt.java +++ b/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStatsStmt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the * terms of the GNU General Public License as published by the Free Software @@ -146,7 +146,7 @@ public String toString() { } if (relations != null) { String separator = " from "; - for (RangeVar relation : relations) { + for (Node relation : relations) { result.append(separator).append(relation); separator = ", "; } diff --git a/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStmt.java b/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStmt.java index cd838eb..d93e62f 100644 --- a/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStmt.java +++ b/parser/src/main/java/com/splendiddata/sqlparser/structure/CreateStmt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the * terms of the GNU General Public License as published by the Free Software @@ -256,9 +256,9 @@ public String toStringStartingWithTable() { if (options.size() == 1 && "oids".equals(options.get(0).defname.toLowerCase())) { Value val = (Value) options.get(0).arg; if (val == null || val.val.ival == 0) { - result.append(" without oids"); + result.append(" with (oids = false)"); } else { - result.append(" with oids"); + result.append(" with (oids = true)"); } } else { result.append(" with ("); diff --git a/parser/src/main/java/com/splendiddata/sqlparser/structure/DefineStmt.java b/parser/src/main/java/com/splendiddata/sqlparser/structure/DefineStmt.java index d0e0d41..2d4ad02 100644 --- a/parser/src/main/java/com/splendiddata/sqlparser/structure/DefineStmt.java +++ b/parser/src/main/java/com/splendiddata/sqlparser/structure/DefineStmt.java @@ -1,32 +1,29 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * - * This program is free software: You may redistribute and/or modify under the - * terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at Client's option) any - * later version. + * This program is free software: You may redistribute and/or modify under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at Client's option) any later + * version. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, Client should obtain one via www.gnu.org/licenses/. + * You should have received a copy of the GNU General Public License along with this program. If not, Client should + * obtain one via www.gnu.org/licenses/. */ package com.splendiddata.sqlparser.structure; +import com.splendiddata.sqlparser.ParserUtil; +import com.splendiddata.sqlparser.enums.NodeTag; +import com.splendiddata.sqlparser.enums.ObjectType; + import jakarta.xml.bind.annotation.XmlAnyElement; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlElementWrapper; import jakarta.xml.bind.annotation.XmlRootElement; -import com.splendiddata.sqlparser.ParserUtil; -import com.splendiddata.sqlparser.enums.NodeTag; -import com.splendiddata.sqlparser.enums.ObjectType; - /** * Copied from /postgresql-12beta2/src/include/nodes/parsenodes.h *

@@ -107,7 +104,7 @@ public DefineStmt(DefineStmt original) { this.definition = original.definition.clone(); } this.if_not_exists = original.if_not_exists; - this.replace=original.replace; + this.replace = original.replace; } @Override @@ -223,6 +220,14 @@ public String toString() { break; } break; + case "lc_collate": + if (def.arg instanceof Value) { + // uc_EN is case sensitive, so take the literal string + result.append(" = '").append(((Value) def.arg).val.str).append('\''); + } else { + result.append(" = ").append(def.arg); + } + break; default: if (def.arg != null) { result.append(" = "); diff --git a/parser/src/main/scanner/postgres/src/backend/parser/scan.l b/parser/src/main/scanner/postgres/src/backend/parser/scan.l index 8c0f692..1638ae8 100644 --- a/parser/src/main/scanner/postgres/src/backend/parser/scan.l +++ b/parser/src/main/scanner/postgres/src/backend/parser/scan.l @@ -398,12 +398,12 @@ decimalfail {digit}+\.\. real ({integer}|{decimal})[Ee][-+]?{digit}+ realfail ({integer}|{decimal})[Ee][-+] -integer_junk {integer}{ident_start} -decimal_junk {decimal}{ident_start} -real_junk {real}{ident_start} +integer_junk {integer}{identifier} +decimal_junk {decimal}{identifier} +real_junk {real}{identifier} param \${integer} -param_junk \${integer}{ident_start} +param_junk \${integer}{identifier} other . @@ -1435,4 +1435,4 @@ core_yyfree(void *ptr, core_yyscan_t yyscanner) { if (ptr) pfree(ptr); -} \ No newline at end of file +} diff --git a/parser/src/test/java/com/splendiddata/sqlparser/SqlFileRegressionTest.java b/parser/src/test/java/com/splendiddata/sqlparser/SqlFileRegressionTest.java index 1f0135f..784bf6b 100644 --- a/parser/src/test/java/com/splendiddata/sqlparser/SqlFileRegressionTest.java +++ b/parser/src/test/java/com/splendiddata/sqlparser/SqlFileRegressionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at Client's option) any later @@ -21,7 +21,10 @@ import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; +import java.io.UncheckedIOException; import java.lang.reflect.Field; +import java.nio.charset.MalformedInputException; +import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; @@ -31,6 +34,8 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Pattern; import java.util.stream.Stream; import org.apache.logging.log4j.LogManager; @@ -39,6 +44,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import com.splendiddata.sqlparser.enums.Severity; import com.splendiddata.sqlparser.structure.Node; import com.splendiddata.sqlparser.structure.Value; @@ -54,27 +60,106 @@ public class SqlFileRegressionTest { private static final Logger log = LogManager.getLogger(SqlFileRegressionTest.class); + private static final class CopyStmtFilter implements Predicate { + + /** + * Lines that start with \copy + */ + private static final Pattern COPY_STMT_PATTERN = Pattern.compile("(?i)^\\\\COPY"); + + /** + * True for lines between \copy and \. + */ + private boolean inCopyStatement = false; + + /** + * @see java.util.function.Predicate#test(java.lang.Object) + * + * @param line + * The line to check + * @return false for lines between \copy and \., true for all other lines + */ + @Override + public boolean test(String line) { + if (inCopyStatement) { + if (line.startsWith("\\.")) { + inCopyStatement = false; + } + return false; + } + inCopyStatement = COPY_STMT_PATTERN.matcher(line).matches(); + return true; + } + + void reset() { + inCopyStatement = false; + } + }; + + private static final CopyStmtFilter COPY_STMT_FILTER = new CopyStmtFilter(); + private List parserErrors = new ArrayList<>(); + private static Path projectDirectory; + private static Path inputTestResourcesPath; + private static Path outputTestResourcesPath; /** * Returns all sql files that are to be tested + *

+ * The files are preprocessed and copied to the target/test/resources directory. Preprocessing consists of: + *

    + *
  • All lines that are starting with a backslash (\) or a colon (:) are commented out + *
  • '\;' is replaced by just a semi colon (;) + *
  • Everywhere the literal '\gset' is replaced by '; -- ' + *
  • The colon (:) character is removed everywhere a single colon precedes an identifier or a text literal + *
  • Data for PSQL \COPY statements is filtered out + *
* * @return Stream with all files to be tested */ - @SuppressWarnings("unused") private static Stream getSqlTestFiles() { List paths = new ArrayList<>(); FileVisitor fileVisitor = new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (attrs.isRegularFile() && !file.getFileName().toString().startsWith(".")) { - paths.add(file); + Path relativePath = inputTestResourcesPath.relativize(file); + Path preprocessedFile = Paths.get(outputTestResourcesPath.toString(), relativePath.toString()) + .toAbsolutePath(); + log.debug(() -> "Preprocessing " + relativePath + " to " + preprocessedFile); + try { + Files.createDirectories(preprocessedFile.getParent()); + try (PrintWriter pw = new PrintWriter( + Files.newBufferedWriter(preprocessedFile, StandardCharsets.UTF_8)); + BufferedReader br = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { + COPY_STMT_FILTER.reset(); + br.lines().filter(line -> COPY_STMT_FILTER.test(line)) + .map(line -> line.replaceAll("(?i)\\\\crosstabview", "; -- \\crosstabview") + .replaceAll("(?i)\\\\gset", "; -- \\gset") + .replaceAll("(?i)\\\\gexec", "; -- \\gexec").replace("\\;", ";") + .replaceAll("([^:\\d]):(['\\w^\\d])", "$1$2").replaceAll("^\\\\", "-- \\\\") + .replaceAll("^:", "-- :")) + .forEach(line -> pw.println(line)); + } + paths.add(preprocessedFile); + } catch (MalformedInputException e) { + // Probably the collate.windows.win1252.sql file, which is not UTF-8 encoded + try { + log.info(e.getMessage() + " - just copying " + file); + Files.copy(file, preprocessedFile); + paths.add(preprocessedFile); + } catch (IOException e1) { + log.error(e, e); + } + } catch (UncheckedIOException | IOException e) { + log.warn(e, e); + } } return FileVisitResult.CONTINUE; } }; - Path projectDirectory = Paths.get("."); + projectDirectory = Paths.get("."); try { projectDirectory = projectDirectory.toAbsolutePath().getParent(); if (!projectDirectory.toAbsolutePath().endsWith("parser")) { @@ -85,11 +170,13 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { */ projectDirectory = Paths.get(projectDirectory.toAbsolutePath().toString(), "parser"); } - Files.walkFileTree(Paths.get(projectDirectory.toString(), "src/test/resources/commands"), fileVisitor); - Files.walkFileTree(Paths.get(projectDirectory.toString(), "src/test/resources/postgres/test/regress/sql"), - fileVisitor); + inputTestResourcesPath = Paths.get(projectDirectory.toString(), "src/test/resources"); + outputTestResourcesPath = Paths.get(projectDirectory.toString(), "target/test/resources"); + + Files.walkFileTree(Paths.get(inputTestResourcesPath.toString(), "commands"), fileVisitor); + Files.walkFileTree(Paths.get(inputTestResourcesPath.toString(), "postgres/test/regress/sql"), fileVisitor); } catch (Exception e) { - log.error("getSqlTestFiles()->failed, basde directory = " + projectDirectory.toAbsolutePath(), e); + log.error("getSqlTestFiles()->failed, base directory = " + projectDirectory.toAbsolutePath(), e); } return paths.stream().sorted(); @@ -114,9 +201,13 @@ void testSqlFile(Path file) throws IOException { log.trace(str.toString()); } - try (Reader reader = new SqlTextReader(new FileReader(file.toFile()))) { + try (Reader reader = Files.newBufferedReader(file)) { SqlParser parser = new SqlParser(reader, error -> parserErrors.add(error)); Assertions.assertTrue(parser.parse(), "Parser error in: " + fileName + "\n" + parserErrors); + Assertions.assertTrue( + parserErrors.isEmpty() + || parserErrors.stream().noneMatch(err -> Severity.ERROR.equals(err.getSeverity())), + "parser.parse() returned true, but parser errors exist:\n" + parserErrors); Assertions.assertNotNull(parser.getResult(), "Expected non-null result: " + fileName); for (Node originallyParsedStatement : parser.getResult()) { log.debug("parsed sql = " + originallyParsedStatement); @@ -205,45 +296,4 @@ private static void verifyNodeTagIsFilledIn(Node node) { } } } - - private static final class SqlTextReader extends BufferedReader { - /** - * Constructor - * - * @param in - */ - SqlTextReader(Reader in) { - super(in); - } - - /** - * @see java.io.BufferedReader#read(char[], int, int) - * - * @param cbuf - * @param off - * @param len - * @return - * @throws IOException - */ - @Override - public int read(char[] cbuf, int off, int len) throws IOException { - int result = super.read(cbuf, off, len); - for (int i = 0; i < result; i++) { - if (cbuf[off + i] == '\n' && i < result - 3) { - if (cbuf[off + i + 1] == '\\') { - cbuf[off + i + 1] = '-'; - cbuf[off + i + 2] = '-'; - } - } else if (cbuf[off + i] == ':' && i < result - 1 && cbuf[off + i + 1] == '\'' && i > 0 - && (cbuf[off + i - 1] == ' ' || cbuf[off + i - 1] == '(')) { - /* - * Remove the colon from :'some_filename' constructs - */ - cbuf[off + i] = ' '; - } - } - return result; - } - - } } diff --git a/parser/src/test/resources/commands/create extension.sql b/parser/src/test/resources/commands/create extension.sql index 0c79610..0b7ebba 100644 --- a/parser/src/test/resources/commands/create extension.sql +++ b/parser/src/test/resources/commands/create extension.sql @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2025 * * This program is free software: You may redistribute and/or modify under the * terms of the GNU General Public License as published by the Free Software @@ -21,6 +21,4 @@ create extension if not exists extension_name with schema schema version "1.0.5" create extension ext_name_casc cascade; create extension ext_name_casc with cascade; -create extension ext_name_casc with schema schema_name cascade; - -create extension ext_from_old_version with version v2 from v1; \ No newline at end of file +create extension ext_name_casc with schema schema_name cascade; \ No newline at end of file diff --git a/parser/src/test/resources/commands/create table.sql b/parser/src/test/resources/commands/create table.sql index f42056a..2ea962f 100644 --- a/parser/src/test/resources/commands/create table.sql +++ b/parser/src/test/resources/commands/create table.sql @@ -26,13 +26,6 @@ create global temp table if not exists schema.table with (a = 'a', b, c = 44) on commit preserve rows tablespace tablespace; - -create unlogged table schema.table - ( col_1 schema.type default 'x'::schema.type unique references schema.another_table match full on delete cascade on update cascade deferrable initially deferred - , col_2 text not null constraint bladibla check (value like '%xyz%') no inherit references some_table(some_column) match partial - , constraint constr_1 primary key (col_1, col_2) with (a = 'a', b) using index tablespace ts - , exclude using my_index_method ((col_1 || col_2) with schema.==, col3 with &) with (a = 'b', c) where (col_2 > 'abc') - ); create global temp table if not exists schema.table ( col_1 schma.type collate coll primary key check (value >= 'a' and value <= z) diff --git a/parser/src/test/resources/postgres/test/regress/sql/advisory_lock.sql b/parser/src/test/resources/postgres/test/regress/sql/advisory_lock.sql index 57c47c0..8513ab8 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/advisory_lock.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/advisory_lock.sql @@ -2,6 +2,8 @@ -- ADVISORY LOCKS -- +SELECT oid AS datoid FROM pg_database WHERE datname = current_database() \gset + BEGIN; SELECT @@ -9,14 +11,14 @@ SELECT pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; -- pg_advisory_unlock_all() shouldn't release xact locks SELECT pg_advisory_unlock_all(); -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; -- can't unlock xact locks @@ -28,7 +30,7 @@ SELECT -- automatically release xact locks at commit COMMIT; -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; BEGIN; @@ -39,7 +41,7 @@ SELECT pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; SELECT @@ -49,7 +51,7 @@ SELECT ROLLBACK; SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; @@ -60,7 +62,7 @@ SELECT pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1), pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2); -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; BEGIN; @@ -71,7 +73,7 @@ SELECT pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; SELECT @@ -81,14 +83,14 @@ SELECT ROLLBACK; SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; -- releasing all session locks SELECT pg_advisory_unlock_all(); -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; BEGIN; @@ -102,12 +104,12 @@ SELECT pg_advisory_xact_lock_shared(2, 2), pg_advisory_xact_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; COMMIT; -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; -- grabbing session locks multiple times @@ -118,7 +120,7 @@ SELECT pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; SELECT @@ -127,7 +129,7 @@ SELECT pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1), pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2); -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; -- .. and releasing them all at once @@ -138,9 +140,9 @@ SELECT pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2); SELECT locktype, classid, objid, objsubid, mode, granted - FROM pg_locks WHERE locktype = 'advisory' + FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid ORDER BY classid, objid, objsubid; SELECT pg_advisory_unlock_all(); -SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; +SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid; diff --git a/parser/src/test/resources/postgres/test/regress/sql/aggregates.sql b/parser/src/test/resources/postgres/test/regress/sql/aggregates.sql index daebda5..332b0e7 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/aggregates.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/aggregates.sql @@ -440,9 +440,22 @@ select distinct min(f1), max(f1) from minmaxtest; drop table minmaxtest cascade; +-- DISTINCT can also trigger wrong answers with hash aggregation (bug #18465) +begin; +set local enable_sort = off; +explain (costs off) + select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) + from int4_tbl t0; +select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) +from int4_tbl t0; +rollback; + -- check for correct detection of nested-aggregate errors select max(min(unique1)) from tenk1; select (select max(min(unique1)) from int8_tbl) from tenk1; +select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) + from tenk1 a1(col1))) +from tenk1 a2(col2); -- -- Test removal of redundant GROUP BY columns @@ -512,49 +525,6 @@ select t1.f1 from t1 left join t2 using (f1) group by f1; drop table t1, t2; --- --- Test planner's selection of pathkeys for ORDER BY aggregates --- - --- Ensure we order by four. This suits the most aggregate functions. -explain (costs off) -select sum(two order by two),max(four order by four), min(four order by four) -from tenk1; - --- Ensure we order by two. It's a tie between ordering by two and four but --- we tiebreak on the aggregate's position. -explain (costs off) -select - sum(two order by two), max(four order by four), - min(four order by four), max(two order by two) -from tenk1; - --- Similar to above, but tiebreak on ordering by four -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two) -from tenk1; - --- Ensure this one orders by ten since there are 3 aggregates that require ten --- vs two that suit two and four. -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two), - sum(ten order by ten), min(ten order by ten), max(ten order by ten) -from tenk1; - --- Try a case involving a GROUP BY clause where the GROUP BY column is also --- part of an aggregate's ORDER BY clause. We want a sort order that works --- for the GROUP BY along with the first and the last aggregate. -explain (costs off) -select - sum(unique1 order by ten, two), sum(unique1 order by four), - sum(unique1 order by two, four) -from tenk1 -group by ten; - -- -- Test combinations of DISTINCT and/or ORDER BY -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/alter_table.sql b/parser/src/test/resources/postgres/test/regress/sql/alter_table.sql index 8456563..418d5fa 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/alter_table.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/alter_table.sql @@ -4,6 +4,7 @@ * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: */ + -- -- ALTER_TABLE -- @@ -154,7 +155,7 @@ ALTER INDEX attmp_idx ALTER COLUMN 1 SET STATISTICS 1000; ALTER INDEX attmp_idx ALTER COLUMN 2 SET STATISTICS 1000; --- Deactivated for SplendidDataTest: \d+ attmp_idx +\d+ attmp_idx ALTER INDEX attmp_idx ALTER COLUMN 3 SET STATISTICS 1000; @@ -304,23 +305,23 @@ ALTER TABLE onek DROP CONSTRAINT onek_unique1_constraint_foo; -- renaming constraints vs. inheritance CREATE TABLE constraint_rename_test (a int CONSTRAINT con1 CHECK (a > 0), b int, c int); --- Deactivated for SplendidDataTest: \d constraint_rename_test +\d constraint_rename_test CREATE TABLE constraint_rename_test2 (a int CONSTRAINT con1 CHECK (a > 0), d int) INHERITS (constraint_rename_test); --- Deactivated for SplendidDataTest: \d constraint_rename_test2 +\d constraint_rename_test2 ALTER TABLE constraint_rename_test2 RENAME CONSTRAINT con1 TO con1foo; -- fail ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- fail ALTER TABLE constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- ok --- Deactivated for SplendidDataTest: \d constraint_rename_test --- Deactivated for SplendidDataTest: \d constraint_rename_test2 +\d constraint_rename_test +\d constraint_rename_test2 -- Deactivated for SplendidDataTest: ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0) NO INHERIT; ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con2 TO con2foo; -- ok ALTER TABLE constraint_rename_test RENAME CONSTRAINT con2foo TO con2bar; -- ok --- Deactivated for SplendidDataTest: \d constraint_rename_test --- Deactivated for SplendidDataTest: \d constraint_rename_test2 +\d constraint_rename_test +\d constraint_rename_test2 ALTER TABLE constraint_rename_test ADD CONSTRAINT con3 PRIMARY KEY (a); ALTER TABLE constraint_rename_test RENAME CONSTRAINT con3 TO con3foo; -- ok --- Deactivated for SplendidDataTest: \d constraint_rename_test --- Deactivated for SplendidDataTest: \d constraint_rename_test2 +\d constraint_rename_test +\d constraint_rename_test2 DROP TABLE constraint_rename_test2; DROP TABLE constraint_rename_test; ALTER TABLE IF EXISTS constraint_not_exist RENAME CONSTRAINT con3 TO con3foo; -- ok @@ -336,7 +337,7 @@ ALTER TABLE constraint_rename_cache RENAME CONSTRAINT constraint_rename_cache_pkey TO constraint_rename_pkey_new; CREATE TABLE like_constraint_rename_cache (LIKE constraint_rename_cache INCLUDING ALL); --- Deactivated for SplendidDataTest: \d like_constraint_rename_cache +\d like_constraint_rename_cache DROP TABLE constraint_rename_cache; DROP TABLE like_constraint_rename_cache; @@ -453,7 +454,7 @@ DROP TABLE attmp2; set constraint_exclusion TO 'partition'; create table nv_parent (d date, check (false) no inherit not valid); -- not valid constraint added at creation time should automatically become valid --- Deactivated for SplendidDataTest: \d nv_parent +\d nv_parent create table nv_child_2010 () inherits (nv_parent); create table nv_child_2011 () inherits (nv_parent); @@ -469,7 +470,7 @@ explain (costs off) select * from nv_parent where d between '2009-08-01'::date a -- add an inherited NOT VALID constraint alter table nv_parent add check (d between '2001-01-01'::date and '2099-12-31'::date) not valid; --- Deactivated for SplendidDataTest: \d nv_child_2009 +\d nv_child_2009 -- we leave nv_parent and children around to help test pg_dump logic -- Foreign key adding test with mixed types @@ -1145,17 +1146,17 @@ copy attest(a) to stdout; copy attest("........pg.dropped.1........") to stdout; copy attest from stdin; -- Deactivated for SplendidDataTest: 10 11 12 --- Deactivated for SplendidDataTest: \. +\. select * from attest; copy attest from stdin; -- Deactivated for SplendidDataTest: 21 22 --- Deactivated for SplendidDataTest: \. +\. select * from attest; copy attest(a) from stdin; copy attest("........pg.dropped.1........") from stdin; copy attest(b,c) from stdin; -- Deactivated for SplendidDataTest: 31 32 --- Deactivated for SplendidDataTest: \. +\. select * from attest; drop table attest; @@ -1390,14 +1391,14 @@ alter table anothertab create index on anothertab(f2,f3); create unique index on anothertab(f4); --- Deactivated for SplendidDataTest: \d anothertab +\d anothertab alter table anothertab alter column f1 type bigint; alter table anothertab alter column f2 type bigint, alter column f3 type bigint, alter column f4 type bigint; alter table anothertab alter column f5 type bigint; --- Deactivated for SplendidDataTest: \d anothertab +\d anothertab drop table anothertab; @@ -1450,13 +1451,13 @@ create table at_part_2 (b text, a int); insert into at_part_2 values ('1.234', 1024); create index on at_partitioned (b); create index on at_partitioned (a); --- Deactivated for SplendidDataTest: \d at_part_1 --- Deactivated for SplendidDataTest: \d at_part_2 +\d at_part_1 +\d at_part_2 alter table at_partitioned attach partition at_part_2 for values from (1000) to (2000); --- Deactivated for SplendidDataTest: \d at_part_2 +\d at_part_2 alter table at_partitioned alter column b type numeric using b::numeric; --- Deactivated for SplendidDataTest: \d at_part_1 --- Deactivated for SplendidDataTest: \d at_part_2 +\d at_part_1 +\d at_part_2 drop table at_partitioned; -- Alter column type when no table rewrite is required @@ -1533,36 +1534,36 @@ alter table recur1 add column f2 int; alter table recur1 alter column f2 type recur2; -- fails -- SET STORAGE may need to add a TOAST table --- Deactivated for SplendidDataTest: create table test_storage (a text, c text storage plain); +create table test_storage (a text); +select reltoastrelid <> 0 as has_toast_table + from pg_class where oid = 'test_storage'::regclass; alter table test_storage alter a set storage plain; -alter table test_storage add b int default 0; -- rewrite table to remove its TOAST table +-- rewrite table to remove its TOAST table; need a non-constant column default +alter table test_storage add b int default random()::int; +select reltoastrelid <> 0 as has_toast_table + from pg_class where oid = 'test_storage'::regclass; alter table test_storage alter a set storage extended; -- re-add TOAST table - select reltoastrelid <> 0 as has_toast_table -from pg_class -where oid = 'test_storage'::regclass; - --- check STORAGE correctness --- Deactivated for SplendidDataTest: create table test_storage_failed (a text, b int storage extended); + from pg_class where oid = 'test_storage'::regclass; -- test that SET STORAGE propagates to index correctly create index test_storage_idx on test_storage (b, a); alter table test_storage alter column a set storage external; --- Deactivated for SplendidDataTest: \d+ test_storage --- Deactivated for SplendidDataTest: \d+ test_storage_idx +\d+ test_storage +\d+ test_storage_idx -- ALTER COLUMN TYPE with a check constraint and a child table (bug #13779) CREATE TABLE test_inh_check (a float check (a > 10.2), b float); CREATE TABLE test_inh_check_child() INHERITS(test_inh_check); --- Deactivated for SplendidDataTest: \d test_inh_check --- Deactivated for SplendidDataTest: \d test_inh_check_child +\d test_inh_check +\d test_inh_check_child select relname, conname, coninhcount, conislocal, connoinherit from pg_constraint c, pg_class r where relname like 'test_inh_check%' and c.conrelid = r.oid order by 1, 2; ALTER TABLE test_inh_check ALTER COLUMN a TYPE numeric; --- Deactivated for SplendidDataTest: \d test_inh_check --- Deactivated for SplendidDataTest: \d test_inh_check_child +\d test_inh_check +\d test_inh_check_child select relname, conname, coninhcount, conislocal, connoinherit from pg_constraint c, pg_class r where relname like 'test_inh_check%' and c.conrelid = r.oid @@ -1572,15 +1573,15 @@ ALTER TABLE test_inh_check ADD CONSTRAINT bnoinherit CHECK (b > 100) NO INHERIT; ALTER TABLE test_inh_check_child ADD CONSTRAINT blocal CHECK (b < 1000); ALTER TABLE test_inh_check_child ADD CONSTRAINT bmerged CHECK (b > 1); ALTER TABLE test_inh_check ADD CONSTRAINT bmerged CHECK (b > 1); --- Deactivated for SplendidDataTest: \d test_inh_check --- Deactivated for SplendidDataTest: \d test_inh_check_child +\d test_inh_check +\d test_inh_check_child select relname, conname, coninhcount, conislocal, connoinherit from pg_constraint c, pg_class r where relname like 'test_inh_check%' and c.conrelid = r.oid order by 1, 2; ALTER TABLE test_inh_check ALTER COLUMN b TYPE numeric; --- Deactivated for SplendidDataTest: \d test_inh_check --- Deactivated for SplendidDataTest: \d test_inh_check_child +\d test_inh_check +\d test_inh_check_child select relname, conname, coninhcount, conislocal, connoinherit from pg_constraint c, pg_class r where relname like 'test_inh_check%' and c.conrelid = r.oid @@ -1615,7 +1616,7 @@ BEGIN; ALTER TABLE check_fk_presence_2 DROP CONSTRAINT check_fk_presence_2_id_fkey; ANALYZE check_fk_presence_2; ROLLBACK; --- Deactivated for SplendidDataTest: \d check_fk_presence_2 +\d check_fk_presence_2 DROP TABLE check_fk_presence_1, check_fk_presence_2; -- check column addition within a view (bug #14876) @@ -1623,14 +1624,14 @@ create table at_base_table(id int, stuff text); insert into at_base_table values (23, 'skidoo'); create view at_view_1 as select * from at_base_table bt; create view at_view_2 as select *, to_json(v1) as j from at_view_1 v1; --- Deactivated for SplendidDataTest: \d+ at_view_1 --- Deactivated for SplendidDataTest: \d+ at_view_2 +\d+ at_view_1 +\d+ at_view_2 explain (verbose, costs off) select * from at_view_2; select * from at_view_2; create or replace view at_view_1 as select *, 2+2 as more from at_base_table bt; --- Deactivated for SplendidDataTest: \d+ at_view_1 --- Deactivated for SplendidDataTest: \d+ at_view_2 +\d+ at_view_1 +\d+ at_view_2 explain (verbose, costs off) select * from at_view_2; select * from at_view_2; @@ -1638,7 +1639,25 @@ drop view at_view_2; drop view at_view_1; drop table at_base_table; --- check adding a column not iself requiring a rewrite, together with +-- related case (bug #17811) +begin; +create temp table t1 as select * from int8_tbl; +create temp view v1 as select 1::int8 as q1; +create temp view v2 as select * from v1; +create or replace temp view v1 with (security_barrier = true) + as select * from t1; + +create temp table log (q1 int8, q2 int8); +create rule v1_upd_rule as on update to v1 + do also insert into log values (new.*); + +update v2 set q1 = q1 + 1 where q1 = 123; + +select * from t1; +select * from log; +rollback; + +-- check adding a column not itself requiring a rewrite, together with -- a column requiring a default (bug #16038) -- ensure that rewrites aren't silently optimized away, removing the @@ -1933,34 +1952,34 @@ drop schema alter2 cascade; -- CREATE TYPE test_type AS (a int); --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE nosuchtype ADD ATTRIBUTE b text; -- fails ALTER TYPE test_type ADD ATTRIBUTE b text; --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE test_type ADD ATTRIBUTE b text; -- fails ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE varchar; --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE integer; --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE test_type DROP ATTRIBUTE b; --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE test_type DROP ATTRIBUTE c; -- fails ALTER TYPE test_type DROP ATTRIBUTE IF EXISTS c; ALTER TYPE test_type DROP ATTRIBUTE a, ADD ATTRIBUTE d boolean; --- Deactivated for SplendidDataTest: \d test_type +\d test_type ALTER TYPE test_type RENAME ATTRIBUTE a TO aa; ALTER TYPE test_type RENAME ATTRIBUTE d TO dd; --- Deactivated for SplendidDataTest: \d test_type +\d test_type DROP TYPE test_type; @@ -1968,40 +1987,49 @@ CREATE TYPE test_type1 AS (a int, b text); CREATE TABLE test_tbl1 (x int, y test_type1); ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails +DROP TABLE test_tbl1; +CREATE TABLE test_tbl1 (x int, y text); +CREATE INDEX test_tbl1_idx ON test_tbl1((row(x,y)::test_type1)); +ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails + +DROP TABLE test_tbl1; +DROP TYPE test_type1; + CREATE TYPE test_type2 AS (a int, b text); CREATE TABLE test_tbl2 OF test_type2; CREATE TABLE test_tbl2_subclass () INHERITS (test_tbl2); --- Deactivated for SplendidDataTest: \d test_type2 --- Deactivated for SplendidDataTest: \d test_tbl2 +\d test_type2 +\d test_tbl2 ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails ALTER TYPE test_type2 ADD ATTRIBUTE c text CASCADE; --- Deactivated for SplendidDataTest: \d test_type2 --- Deactivated for SplendidDataTest: \d test_tbl2 +\d test_type2 +\d test_tbl2 ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar CASCADE; --- Deactivated for SplendidDataTest: \d test_type2 --- Deactivated for SplendidDataTest: \d test_tbl2 +\d test_type2 +\d test_tbl2 ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails ALTER TYPE test_type2 DROP ATTRIBUTE b CASCADE; --- Deactivated for SplendidDataTest: \d test_type2 --- Deactivated for SplendidDataTest: \d test_tbl2 +\d test_type2 +\d test_tbl2 ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa; -- fails ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE; --- Deactivated for SplendidDataTest: \d test_type2 --- Deactivated for SplendidDataTest: \d test_tbl2 --- Deactivated for SplendidDataTest: \d test_tbl2_subclass +\d test_type2 +\d test_tbl2 +\d test_tbl2_subclass -DROP TABLE test_tbl2_subclass; +DROP TABLE test_tbl2_subclass, test_tbl2; +DROP TYPE test_type2; CREATE TYPE test_typex AS (a int, b text); CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0)); ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails ALTER TYPE test_typex DROP ATTRIBUTE a CASCADE; --- Deactivated for SplendidDataTest: \d test_tblx +\d test_tblx DROP TABLE test_tblx; DROP TYPE test_typex; @@ -2043,7 +2071,7 @@ ALTER TABLE tt7 OF tt_t0; CREATE TYPE tt_t1 AS (x int, y numeric(8,2)); ALTER TABLE tt7 OF tt_t1; -- reassign an already-typed table ALTER TABLE tt7 NOT OF; --- Deactivated for SplendidDataTest: \d tt7 +\d tt7 -- make sure we can drop a constraint on the parent but it remains on the child CREATE TABLE test_drop_constr_parent (c text CHECK (c IS NOT NULL)); @@ -2073,7 +2101,7 @@ ALTER TABLE IF EXISTS tt8 ALTER COLUMN f SET DEFAULT 0; ALTER TABLE IF EXISTS tt8 RENAME COLUMN f TO f1; ALTER TABLE IF EXISTS tt8 SET SCHEMA alter2; --- Deactivated for SplendidDataTest: \d alter2.tt8 +\d alter2.tt8 DROP TABLE alter2.tt8; DROP SCHEMA alter2; @@ -2093,7 +2121,7 @@ ALTER TABLE tt9 ADD CONSTRAINT foo UNIQUE(c); -- fail, dup name ALTER TABLE tt9 ADD CONSTRAINT tt9_c_key CHECK(c > 5); -- fail, dup name ALTER TABLE tt9 ADD CONSTRAINT tt9_c_key2 CHECK(c > 6); ALTER TABLE tt9 ADD UNIQUE(c); -- picks nonconflicting name --- Deactivated for SplendidDataTest: \d tt9 +\d tt9 DROP TABLE tt9; @@ -2155,13 +2183,15 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F -- filenode function call can return NULL for a relation dropped concurrently -- with the call's surrounding query, so ignore a NULL mapped_oid for -- relations that no longer exist after all calls finish. +-- Temporary relations are ignored, as not supported by pg_filenode_relation(). CREATE TEMP TABLE filenode_mapping AS SELECT oid, mapped_oid, reltablespace, relfilenode, relname FROM pg_class, pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid -WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid; - +WHERE relkind IN ('r', 'i', 'S', 't', 'm') + AND relpersistence != 't' + AND mapped_oid IS DISTINCT FROM oid; SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL; @@ -2243,48 +2273,48 @@ DROP TABLE logged1; -- test ADD COLUMN IF NOT EXISTS CREATE TABLE test_add_column(c1 integer); --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN c2 integer; --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN c2 integer; -- fail because c2 already exists ALTER TABLE ONLY test_add_column ADD COLUMN c2 integer; -- fail because c2 already exists --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c2 integer; -- skipping because c2 already exists ALTER TABLE ONLY test_add_column ADD COLUMN IF NOT EXISTS c2 integer; -- skipping because c2 already exists --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN c2 integer, -- fail because c2 already exists ADD COLUMN c3 integer primary key; --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c2 integer, -- skipping because c2 already exists ADD COLUMN c3 integer primary key; --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c2 integer, -- skipping because c2 already exists ADD COLUMN IF NOT EXISTS c3 integer primary key; -- skipping because c3 already exists --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c2 integer, -- skipping because c2 already exists ADD COLUMN IF NOT EXISTS c3 integer, -- skipping because c3 already exists ADD COLUMN c4 integer REFERENCES test_add_column; --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c4 integer REFERENCES test_add_column; --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c5 SERIAL CHECK (c5 > 8); --- Deactivated for SplendidDataTest: \d test_add_column +\d test_add_column ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c5 SERIAL CHECK (c5 > 10); --- Deactivated for SplendidDataTest: \d test_add_column* +\d test_add_column* DROP TABLE test_add_column; --- Deactivated for SplendidDataTest: \d test_add_column* +\d test_add_column* -- assorted cases with multiple ALTER TABLE steps CREATE TABLE ataddindex(f1 INT); @@ -2293,7 +2323,7 @@ CREATE UNIQUE INDEX ataddindexi0 ON ataddindex(f1); ALTER TABLE ataddindex ADD PRIMARY KEY USING INDEX ataddindexi0, ALTER f1 TYPE BIGINT; --- Deactivated for SplendidDataTest: \d ataddindex +\d ataddindex DROP TABLE ataddindex; CREATE TABLE ataddindex(f1 VARCHAR(10)); @@ -2301,21 +2331,21 @@ INSERT INTO ataddindex(f1) VALUES ('foo'), ('a'); ALTER TABLE ataddindex ALTER f1 SET DATA TYPE TEXT, ADD EXCLUDE ((f1 LIKE 'a') WITH =); --- Deactivated for SplendidDataTest: \d ataddindex +\d ataddindex DROP TABLE ataddindex; CREATE TABLE ataddindex(id int, ref_id int); ALTER TABLE ataddindex ADD PRIMARY KEY (id), ADD FOREIGN KEY (ref_id) REFERENCES ataddindex; --- Deactivated for SplendidDataTest: \d ataddindex +\d ataddindex DROP TABLE ataddindex; CREATE TABLE ataddindex(id int, ref_id int); ALTER TABLE ataddindex ADD UNIQUE (id), ADD FOREIGN KEY (ref_id) REFERENCES ataddindex (id); --- Deactivated for SplendidDataTest: \d ataddindex +\d ataddindex DROP TABLE ataddindex; -- unsupported constraint types for partitioned tables @@ -2389,6 +2419,13 @@ CREATE TABLE parent (LIKE list_parted); CREATE TABLE child () INHERITS (parent); ALTER TABLE list_parted ATTACH PARTITION child FOR VALUES IN (1); ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1); +DROP TABLE child; +-- now it should work, with a little tweak +ALTER TABLE parent ADD CONSTRAINT check_a CHECK (a > 0); +ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1); +-- test insert/update, per bug #18550 +INSERT INTO parent VALUES (1); +UPDATE parent SET a = 2 WHERE a = 1; DROP TABLE parent CASCADE; -- check any TEMP-ness @@ -2747,15 +2784,24 @@ ALTER TABLE range_parted2 DETACH PARTITION part_rpd CONCURRENTLY; DROP TABLE part_rpd; -- works fine ALTER TABLE range_parted2 DETACH PARTITION part_rp CONCURRENTLY; --- Deactivated for SplendidDataTest: \d+ range_parted2 +\d+ range_parted2 -- constraint should be created --- Deactivated for SplendidDataTest: \d part_rp +\d part_rp CREATE TABLE part_rp100 PARTITION OF range_parted2 (CHECK (a>=123 AND a<133 AND a IS NOT NULL)) FOR VALUES FROM (100) to (200); ALTER TABLE range_parted2 DETACH PARTITION part_rp100 CONCURRENTLY; -- redundant constraint should not be created --- Deactivated for SplendidDataTest: \d part_rp100 +\d part_rp100 DROP TABLE range_parted2; +-- Test that hash partitions continue to work after they're concurrently +-- detached (bugs #18371, #19070) +CREATE TABLE hash_parted2 (a int) PARTITION BY HASH(a); +CREATE TABLE part_hp PARTITION OF hash_parted2 FOR VALUES WITH (MODULUS 2, REMAINDER 0); +ALTER TABLE hash_parted2 DETACH PARTITION part_hp CONCURRENTLY; +DROP TABLE hash_parted2; +INSERT INTO part_hp VALUES (1); +DROP TABLE part_hp; + -- Check ALTER TABLE commands for partitioned tables and partitions -- cannot add/drop column to/from *only* the parent @@ -2986,6 +3032,23 @@ drop table attbl, atref; /* End test case for bug #17409 */ +/* Test case for bug #18970 */ + +create table attbl(a int); +create table atref(b attbl check ((b).a is not null)); +alter table attbl alter column a type numeric; -- someday this should work +alter table atref drop constraint atref_b_check; + +create statistics atref_stat on ((b).a is not null) from atref; +alter table attbl alter column a type numeric; -- someday this should work +drop statistics atref_stat; + +create index atref_idx on atref (((b).a)); +alter table attbl alter column a type numeric; -- someday this should work +drop table attbl, atref; + +/* End test case for bug #18970 */ + -- Test that ALTER TABLE rewrite preserves a clustered index -- for normal indexes and indexes on constraints. create table alttype_cluster (a int); @@ -3038,7 +3101,7 @@ set client_min_messages = 'ERROR'; create publication pub1 for table alter1.t1, tables in schema alter2; reset client_min_messages; alter table alter1.t1 set schema alter2; --- Deactivated for SplendidDataTest: \d+ alter2.t1 +\d+ alter2.t1 drop publication pub1; drop schema alter1 cascade; drop schema alter2 cascade; diff --git a/parser/src/test/resources/postgres/test/regress/sql/arrays.sql b/parser/src/test/resources/postgres/test/regress/sql/arrays.sql index 7e527c6..dd15d61 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/arrays.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/arrays.sql @@ -1,17 +1,9 @@ -/* - * This file has been altered by SplendidData. - * It is only used for syntax checking, not for the testing of a commandline paser. - * So input for the copy statements is removed. - * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: - */ - - -- -- ARRAYS -- -- directory paths are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv abs_srcdir PG_ABS_SRCDIR +\getenv abs_srcdir PG_ABS_SRCDIR CREATE TABLE arrtest ( a int2[], @@ -29,7 +21,7 @@ CREATE TABLE array_op_test ( t text[] ); --- Deactivated for SplendidDataTest: \set filename :abs_srcdir '/data/array.data' +\set filename :abs_srcdir '/data/array.data' COPY array_op_test FROM :'filename'; ANALYZE array_op_test; @@ -440,6 +432,27 @@ insert into arr_pk_tbl(pk, f1[1:2]) values (1, '{6,7,8}') on conflict (pk) reset enable_seqscan; reset enable_bitmapscan; +-- test subscript overflow detection + +-- The normal error message includes a platform-dependent limit, +-- so suppress it to avoid needing multiple expected-files. +\set VERBOSITY sqlstate + +insert into arr_pk_tbl values(10, '[-2147483648:-2147483647]={1,2}'); +update arr_pk_tbl set f1[2147483647] = 42 where pk = 10; +update arr_pk_tbl set f1[2147483646:2147483647] = array[4,2] where pk = 10; +insert into arr_pk_tbl(pk, f1[0:2147483647]) values (2, '{}'); +insert into arr_pk_tbl(pk, f1[-2147483648:2147483647]) values (2, '{}'); + +-- also exercise the expanded-array case +do $$ declare a int[]; +begin + a := '[-2147483648:-2147483647]={1,2}'::int[]; + a[2147483647] := 42; +end $$; + +\set VERBOSITY default + -- test [not] (like|ilike) (any|all) (...) select 'foo' like any (array['%a', '%o']); -- t select 'foo' like any (array['%a', '%b']); -- f @@ -663,6 +676,28 @@ select array_replace(array['AB',NULL,'CDE'],NULL,'12'); select array(select array[i,i/2] from generate_series(1,5) i); select array(select array['Hello', i::text] from generate_series(9,11) i); +-- int2vector and oidvector should be treated as scalar types for this purpose +select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5))); +select array(select '11 22 33'::int2vector from generate_series(1,5)); +select unnest(array(select '11 22 33'::int2vector from generate_series(1,5))); +select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5))); +select array(select '11 22 33'::oidvector from generate_series(1,5)); +select unnest(array(select '11 22 33'::oidvector from generate_series(1,5))); + +-- array[] should do the same +select pg_typeof(array['11 22 33'::int2vector]); +select array['11 22 33'::int2vector]; +select pg_typeof(unnest(array['11 22 33'::int2vector])); +select unnest(array['11 22 33'::int2vector]); +select pg_typeof(unnest('11 22 33'::int2vector)); +select unnest('11 22 33'::int2vector); +select pg_typeof(array['11 22 33'::oidvector]); +select array['11 22 33'::oidvector]; +select pg_typeof(unnest(array['11 22 33'::oidvector])); +select unnest(array['11 22 33'::oidvector]); +select pg_typeof(unnest('11 22 33'::oidvector)); +select unnest('11 22 33'::oidvector); + -- Insert/update on a column that is array of composite create temp table t1 (f1 int8_tbl[]); diff --git a/parser/src/test/resources/postgres/test/regress/sql/brin_multi.sql b/parser/src/test/resources/postgres/test/regress/sql/brin_multi.sql index 2189b6c..1667081 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/brin_multi.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/brin_multi.sql @@ -357,6 +357,13 @@ insert into public.brintest_multi (float8col) values (real 'nan'); UPDATE brintest_multi SET int8col = int8col * int4col; +-- Test handling of inet netmasks with inet_minmax_multi_ops +CREATE TABLE brin_test_inet (a inet); +CREATE INDEX ON brin_test_inet USING brin (a inet_minmax_multi_ops); +INSERT INTO brin_test_inet VALUES ('127.0.0.1/0'); +INSERT INTO brin_test_inet VALUES ('0.0.0.0/12'); +DROP TABLE brin_test_inet; + -- Tests for brin_summarize_new_values SELECT brin_summarize_new_values('brintest_multi'); -- error, not an index SELECT brin_summarize_new_values('tenk1_unique1'); -- error, not a BRIN index @@ -414,3 +421,102 @@ VACUUM ANALYZE brin_test_multi; EXPLAIN (COSTS OFF) SELECT * FROM brin_test_multi WHERE a = 1; -- Ensure brin index is not used when values are not correlated EXPLAIN (COSTS OFF) SELECT * FROM brin_test_multi WHERE b = 1; + +-- test overflows during CREATE INDEX with extreme timestamp values +CREATE TABLE brin_timestamp_test(a TIMESTAMPTZ); + +SET datestyle TO iso; + +-- values close to timetamp minimum +INSERT INTO brin_timestamp_test +SELECT '4713-01-01 00:00:01 BC'::timestamptz + (i || ' seconds')::interval + FROM generate_series(1,30) s(i); + +-- values close to timetamp maximum +INSERT INTO brin_timestamp_test +SELECT '294276-12-01 00:00:01'::timestamptz + (i || ' seconds')::interval + FROM generate_series(1,30) s(i); + +CREATE INDEX ON brin_timestamp_test USING brin (a timestamptz_minmax_multi_ops) WITH (pages_per_range=1); +DROP TABLE brin_timestamp_test; + +-- test overflows during CREATE INDEX with extreme date values +CREATE TABLE brin_date_test(a DATE); + +-- insert values close to date minimum +INSERT INTO brin_date_test SELECT '4713-01-01 BC'::date + i FROM generate_series(1, 30) s(i); + +-- insert values close to date minimum +INSERT INTO brin_date_test SELECT '5874897-12-01'::date + i FROM generate_series(1, 30) s(i); + +CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_per_range=1); + +SET enable_seqscan = off; + +-- make sure the ranges were built correctly and 2023-01-01 eliminates all +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; + +DROP TABLE brin_date_test; +RESET enable_seqscan; + +-- test handling of infinite timestamp values +CREATE TABLE brin_timestamp_test(a TIMESTAMP); + +INSERT INTO brin_timestamp_test VALUES ('-infinity'), ('infinity'); +INSERT INTO brin_timestamp_test +SELECT i FROM generate_series('2000-01-01'::timestamp, '2000-02-09'::timestamp, '1 day'::interval) s(i); + +CREATE INDEX ON brin_timestamp_test USING brin (a timestamp_minmax_multi_ops) WITH (pages_per_range=1); + +SET enable_seqscan = off; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_timestamp_test WHERE a = '2023-01-01'::timestamp; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_timestamp_test WHERE a = '1900-01-01'::timestamp; + +DROP TABLE brin_timestamp_test; +RESET enable_seqscan; + +-- test handling of infinite date values +CREATE TABLE brin_date_test(a DATE); + +INSERT INTO brin_date_test VALUES ('-infinity'), ('infinity'); +INSERT INTO brin_date_test SELECT '2000-01-01'::date + i FROM generate_series(1, 40) s(i); + +CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_per_range=1); + +SET enable_seqscan = off; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_date_test WHERE a = '1900-01-01'::date; + +DROP TABLE brin_date_test; +RESET enable_seqscan; +RESET datestyle; + +-- test handling of overflow for interval values +CREATE TABLE brin_interval_test(a INTERVAL); + +INSERT INTO brin_interval_test SELECT (i || ' years')::interval FROM generate_series(-178000000, -177999980) s(i); + +INSERT INTO brin_interval_test SELECT (i || ' years')::interval FROM generate_series( 177999980, 178000000) s(i); + +CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH (pages_per_range=1); + +SET enable_seqscan = off; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval; + +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +SELECT * FROM brin_interval_test WHERE a = '30 years'::interval; + +DROP TABLE brin_interval_test; +RESET enable_seqscan; +RESET datestyle; diff --git a/parser/src/test/resources/postgres/test/regress/sql/case.sql b/parser/src/test/resources/postgres/test/regress/sql/case.sql index 83fe43b..388d4c6 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/case.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/case.sql @@ -242,6 +242,11 @@ SELECT CASE make_ad(1,2) WHEN array[1,2]::arrdomain THEN 'right' END; +-- While we're here, also test handling of a NULLIF arg that is a read/write +-- object (bug #18722) + +SELECT NULLIF(make_ad(1,2), array[2,3]::arrdomain); + ROLLBACK; -- Test interaction of CASE with ArrayCoerceExpr (bug #15471) diff --git a/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql b/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql index 9b21c0b..d39dd70 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql @@ -5,18 +5,17 @@ */ - /* * This test is for ICU collations. */ /* skip test if not UTF8 server encoding or no ICU collations installed */ --- Deactivated for SplendidDataTest: SELECT getdatabaseencoding() <> 'UTF8' OR --- Deactivated for SplendidDataTest: (SELECT count(*) FROM pg_collation WHERE collprovider = 'i') = 0 --- Deactivated for SplendidDataTest: AS skip_test \gset --- Deactivated for SplendidDataTest: \if :skip_test --- Deactivated for SplendidDataTest: \quit --- Deactivated for SplendidDataTest: \endif +SELECT getdatabaseencoding() <> 'UTF8' OR + (SELECT count(*) FROM pg_collation WHERE collprovider = 'i') = 0 + AS skip_test \gset +\if :skip_test +\quit +\endif SET client_encoding TO UTF8; @@ -29,7 +28,7 @@ CREATE TABLE collate_test1 ( b text COLLATE "en-x-icu" NOT NULL ); --- Deactivated for SplendidDataTest: \d collate_test1 +\d collate_test1 CREATE TABLE collate_test_fail ( a int, @@ -50,7 +49,7 @@ CREATE TABLE collate_test_like ( LIKE collate_test1 ); --- Deactivated for SplendidDataTest: \d collate_test_like +\d collate_test_like CREATE TABLE collate_test2 ( a int, @@ -378,7 +377,7 @@ BEGIN quote_literal(current_setting('lc_collate')) || ');'; END $$; --- Deactivated for SplendidDataTest: CREATE COLLATION test3 (provider = icu, lc_collate = 'en_US.utf8'); -- fail, need lc_ctype +CREATE COLLATION test3 (provider = icu, lc_collate = 'en_US.utf8'); -- fail, needs "locale" CREATE COLLATION testx (provider = icu, locale = 'nonsense'); /* never fails with ICU */ DROP COLLATION testx; CREATE COLLATION test4 FROM nonsense; @@ -416,7 +415,7 @@ DROP ROLE regress_test_role; ALTER COLLATION "en-x-icu" REFRESH VERSION; -- also test for database while we are here --- Deactivated for SplendidDataTest: SELECT current_database() AS datname \gset +SELECT current_database() AS datname \gset -- Deactivated for SplendidDataTest: ALTER DATABASE :"datname" REFRESH COLLATION VERSION; @@ -434,8 +433,8 @@ CREATE INDEX collate_dep_test4i ON collate_dep_test4t (b COLLATE test0); DROP COLLATION test0 RESTRICT; -- fail DROP COLLATION test0 CASCADE; --- Deactivated for SplendidDataTest: \d collate_dep_test1 --- Deactivated for SplendidDataTest: \d collate_dep_test2 +\d collate_dep_test1 +\d collate_dep_test2 DROP TABLE collate_dep_test1, collate_dep_test4t; DROP TYPE collate_dep_test2; @@ -757,6 +756,65 @@ INSERT INTO test33 VALUES (2, 'DEF'); -- they end up in the same partition (but it's platform-dependent which one) SELECT (SELECT count(*) FROM test33_0) <> (SELECT count(*) FROM test33_1); +-- +-- Bug #18568 +-- +-- Partitionwise aggregate (full or partial) should not be used when a +-- partition key's collation doesn't match that of the GROUP BY column it is +-- matched with. +SET max_parallel_workers_per_gather TO 0; +SET enable_incremental_sort TO off; + +CREATE TABLE pagg_tab3 (a text, c text collate case_insensitive) PARTITION BY LIST(c collate "C"); +CREATE TABLE pagg_tab3_p1 PARTITION OF pagg_tab3 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab3_p2 PARTITION OF pagg_tab3 FOR VALUES IN ('B', 'A'); +INSERT INTO pagg_tab3 SELECT i % 4 + 1, substr('abAB', (i % 4) + 1 , 1) FROM generate_series(0, 19) i; +ANALYZE pagg_tab3; + +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + +-- No "full" partitionwise aggregation allowed, though "partial" is allowed. +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + +-- OK to use full partitionwise aggregate after changing the GROUP BY column's +-- collation to be the same as that of the partition key. +EXPLAIN (COSTS OFF) +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; + +-- Partitionwise join should not be allowed too when the collation used by the +-- join keys doesn't match the partition key collation. +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +SET enable_partitionwise_join TO true; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +-- OK when the join clause uses the same collation as the partition key. +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + +DROP TABLE pagg_tab3; + +RESET enable_partitionwise_aggregate; +RESET max_parallel_workers_per_gather; +RESET enable_incremental_sort; -- cleanup RESET search_path; diff --git a/parser/src/test/resources/postgres/test/regress/sql/conversion.sql b/parser/src/test/resources/postgres/test/regress/sql/conversion.sql index e4dde3f..a80d623 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/conversion.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/conversion.sql @@ -1,20 +1,17 @@ -/* - * This file has been altered by SplendidData. - * It is only used for syntax checking, not for the testing of a commandline paser. - * So input for the copy statements is removed. - * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: - */ - - -- -- create user defined conversion -- -- directory paths and dlsuffix are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv libdir PG_LIBDIR --- Deactivated for SplendidDataTest: \getenv dlsuffix PG_DLSUFFIX +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX --- Deactivated for SplendidDataTest: \set regresslib :libdir '/regress' :dlsuffix +\set regresslib :libdir '/regress' :dlsuffix + +CREATE FUNCTION test_enc_setup() RETURNS void + AS :'regresslib', 'test_enc_setup' + LANGUAGE C STRICT; +SELECT FROM test_enc_setup(); CREATE FUNCTION test_enc_conversion(bytea, name, name, bool, validlen OUT int, result OUT bytea) AS :'regresslib', 'test_enc_conversion' @@ -303,11 +300,14 @@ insert into gb18030_inputs values ('\x666f6f84309c38', 'valid, translates to UTF-8 by mapping function'), ('\x666f6f84309c', 'incomplete char '), ('\x666f6f84309c0a', 'incomplete char, followed by newline '), + ('\x666f6f84', 'incomplete char at end'), ('\x666f6f84309c3800', 'invalid, NUL byte'), ('\x666f6f84309c0038', 'invalid, NUL byte'); --- Test GB18030 verification -select description, inbytes, (test_conv(inbytes, 'gb18030', 'gb18030')).* from gb18030_inputs; +-- Test GB18030 verification. Round-trip through text so the backing of the +-- bytea values is palloc, not shared_buffers. This lets Valgrind detect +-- reads past the end. +select description, inbytes, (test_conv(inbytes::text::bytea, 'gb18030', 'gb18030')).* from gb18030_inputs; -- Test conversions from GB18030 select description, inbytes, (test_conv(inbytes, 'gb18030', 'utf8')).* from gb18030_inputs; diff --git a/parser/src/test/resources/postgres/test/regress/sql/copydml.sql b/parser/src/test/resources/postgres/test/regress/sql/copydml.sql index 4578342..b7eeb0e 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/copydml.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/copydml.sql @@ -66,6 +66,10 @@ create rule qqq as on delete to copydml_test where old.t <> 'f' do instead inser copy (delete from copydml_test) to stdout; drop rule qqq on copydml_test; +create rule qqq as on insert to copydml_test do instead notify copydml_test; +copy (insert into copydml_test default values) to stdout; +drop rule qqq on copydml_test; + -- triggers create function qqq_trig() returns trigger as $$ begin diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_aggregate.sql b/parser/src/test/resources/postgres/test/regress/sql/create_aggregate.sql index f40d6fe..fcd06b2 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_aggregate.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_aggregate.sql @@ -129,18 +129,18 @@ create aggregate my_percentile_disc(float8 ORDER BY anyelement) ( finalfunc_modify = read_write ); -create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") ( - stype = internal, - sfunc = ordered_set_transition_multi, - finalfunc = rank_final, - finalfunc_extra = true, - hypothetical -); +-- Deactivated for SplendidDataTest: create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") ( +-- Deactivated for SplendidDataTest: stype = internal, +-- Deactivated for SplendidDataTest: sfunc = ordered_set_transition_multi, +-- Deactivated for SplendidDataTest: finalfunc = rank_final, +-- Deactivated for SplendidDataTest: finalfunc_extra = true, +-- Deactivated for SplendidDataTest: hypothetical +-- Deactivated for SplendidDataTest: ); alter aggregate my_percentile_disc(float8 ORDER BY anyelement) rename to test_percentile_disc; -alter aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") - rename to test_rank; +-- Deactivated for SplendidDataTest: alter aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") +-- Deactivated for SplendidDataTest: rename to test_rank; -- Deactivated for SplendidDataTest: \da test_* diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_am.sql b/parser/src/test/resources/postgres/test/regress/sql/create_am.sql index 82cf25f..c27c917 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_am.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_am.sql @@ -174,6 +174,24 @@ CREATE TABLE heaptable USING heap AS SELECT a, repeat(a::text, 100) FROM generate_series(1,9) AS a; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass; +-- Switching to heap2 adds new dependency entry to the AM. +ALTER TABLE heaptable SET ACCESS METHOD heap2; +SELECT pg_describe_object(classid, objid, objsubid) as obj, + pg_describe_object(refclassid, refobjid, refobjsubid) as objref, + deptype + FROM pg_depend + WHERE classid = 'pg_class'::regclass AND + objid = 'heaptable'::regclass + ORDER BY 1, 2; +-- Switching to heap should not have a dependency entry to the AM. +ALTER TABLE heaptable SET ACCESS METHOD heap; +SELECT pg_describe_object(classid, objid, objsubid) as obj, + pg_describe_object(refclassid, refobjid, refobjsubid) as objref, + deptype + FROM pg_depend + WHERE classid = 'pg_class'::regclass AND + objid = 'heaptable'::regclass + ORDER BY 1, 2; ALTER TABLE heaptable SET ACCESS METHOD heap2; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass; diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_index.sql b/parser/src/test/resources/postgres/test/regress/sql/create_index.sql index 57d37d5..2a5a13f 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_index.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_index.sql @@ -13,7 +13,7 @@ -- -- directory paths are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv abs_srcdir PG_ABS_SRCDIR +\getenv abs_srcdir PG_ABS_SRCDIR -- -- BTREE @@ -79,7 +79,7 @@ CREATE TABLE fast_emp4000 ( home_base box ); --- Deactivated for SplendidDataTest: \set filename :abs_srcdir '/data/rect.data' +\set filename :abs_srcdir '/data/rect.data' -- Deactivated for SplendidDataTest: COPY slow_emp4000 FROM :'filename'; INSERT INTO fast_emp4000 SELECT * FROM slow_emp4000; @@ -277,7 +277,7 @@ CREATE TABLE array_index_op_test ( t text[] ); --- Deactivated for SplendidDataTest: \set filename :abs_srcdir '/data/array.data' +\set filename :abs_srcdir '/data/array.data' -- Deactivated for SplendidDataTest: COPY array_index_op_test FROM :'filename'; ANALYZE array_index_op_test; @@ -363,7 +363,7 @@ DROP TABLE array_gin_test; -- CREATE INDEX gin_relopts_test ON array_index_op_test USING gin (i) WITH (FASTUPDATE=on, GIN_PENDING_LIST_LIMIT=128); --- Deactivated for SplendidDataTest: \d+ gin_relopts_test +\d+ gin_relopts_test -- -- HASH @@ -413,9 +413,9 @@ DELETE FROM unique_tbl WHERE t = 'seven'; CREATE UNIQUE INDEX unique_idx4 ON unique_tbl (i) NULLS NOT DISTINCT; -- ok now --- Deactivated for SplendidDataTest: \d unique_tbl --- Deactivated for SplendidDataTest: \d unique_idx3 --- Deactivated for SplendidDataTest: \d unique_idx4 +\d unique_tbl +\d unique_idx3 +\d unique_idx4 SELECT pg_get_indexdef('unique_idx3'::regclass); SELECT pg_get_indexdef('unique_idx4'::regclass); @@ -437,8 +437,8 @@ INSERT INTO func_index_heap VALUES('ABCD', 'EF'); INSERT INTO func_index_heap VALUES('QWERTY'); -- while we're here, see that the metadata looks sane --- Deactivated for SplendidDataTest: \d func_index_heap --- Deactivated for SplendidDataTest: \d func_index_index +\d func_index_heap +\d func_index_index -- @@ -457,8 +457,8 @@ INSERT INTO func_index_heap VALUES('ABCD', 'EF'); INSERT INTO func_index_heap VALUES('QWERTY'); -- while we're here, see that the metadata looks sane --- Deactivated for SplendidDataTest: \d func_index_heap --- Deactivated for SplendidDataTest: \d func_index_index +\d func_index_heap +\d func_index_index -- this should fail because of unsafe column type (anonymous record) create index on func_index_heap ((f1 || f2), (row(f1, f2))); @@ -534,9 +534,9 @@ VACUUM FULL concur_heap; REINDEX TABLE concur_heap; DELETE FROM concur_heap WHERE f1 = 'b'; VACUUM FULL concur_heap; --- Deactivated for SplendidDataTest: \d concur_heap +\d concur_heap REINDEX TABLE concur_heap; --- Deactivated for SplendidDataTest: \d concur_heap +\d concur_heap -- Temporary tables with concurrent builds and on-commit actions -- CONCURRENTLY used with CREATE INDEX and DROP INDEX is ignored. @@ -582,7 +582,7 @@ DROP INDEX CONCURRENTLY "concur_index5"; DROP INDEX CONCURRENTLY "concur_index1"; DROP INDEX CONCURRENTLY "concur_heap_expr_idx"; --- Deactivated for SplendidDataTest: \d concur_heap +\d concur_heap DROP TABLE concur_heap; @@ -599,16 +599,16 @@ INSERT INTO cwi_test VALUES(1, 2), (3, 4), (5, 6); CREATE UNIQUE INDEX cwi_uniq_idx ON cwi_test(a , b); ALTER TABLE cwi_test ADD primary key USING INDEX cwi_uniq_idx; --- Deactivated for SplendidDataTest: \d cwi_test --- Deactivated for SplendidDataTest: \d cwi_uniq_idx +\d cwi_test +\d cwi_uniq_idx CREATE UNIQUE INDEX cwi_uniq2_idx ON cwi_test(b , a); ALTER TABLE cwi_test DROP CONSTRAINT cwi_uniq_idx, ADD CONSTRAINT cwi_replaced_pkey PRIMARY KEY USING INDEX cwi_uniq2_idx; --- Deactivated for SplendidDataTest: \d cwi_test --- Deactivated for SplendidDataTest: \d cwi_replaced_pkey +\d cwi_test +\d cwi_replaced_pkey DROP INDEX cwi_replaced_pkey; -- Should fail; a constraint depends on it @@ -632,7 +632,7 @@ DROP TABLE cwi_test; CREATE TABLE syscol_table (a INT); -- System columns cannot be indexed -CREATE INDEX ON syscolcol_table (ctid); +CREATE INDEX ON syscol_table (ctid); -- nor used in expressions CREATE INDEX ON syscol_table ((ctid >= '(1000,0)')); @@ -820,9 +820,9 @@ explain (costs off) -- REINDEX (VERBOSE) -- CREATE TABLE reindex_verbose(id integer primary key); --- Deactivated for SplendidDataTest: \set VERBOSITY terse \\ -- suppress machine-dependent details +\set VERBOSITY terse \\ -- suppress machine-dependent details REINDEX (VERBOSE) TABLE reindex_verbose; --- Deactivated for SplendidDataTest: \set VERBOSITY default +\set VERBOSITY default DROP TABLE reindex_verbose; -- @@ -919,7 +919,7 @@ CREATE INDEX concur_appclass_ind on concur_appclass_tab CREATE INDEX concur_appclass_ind_2 on concur_appclass_tab USING gist (k tsvector_ops (siglen='300'), j tsvector_ops); REINDEX TABLE CONCURRENTLY concur_appclass_tab; --- Deactivated for SplendidDataTest: \d concur_appclass_tab +\d concur_appclass_tab DROP TABLE concur_appclass_tab; -- Partitions @@ -1081,15 +1081,11 @@ REINDEX INDEX CONCURRENTLY pg_class_oid_index; -- no catalog index REINDEX TABLE CONCURRENTLY pg_toast.pg_toast_1260; -- no catalog toast table REINDEX INDEX CONCURRENTLY pg_toast.pg_toast_1260_index; -- no catalog toast index REINDEX SYSTEM CONCURRENTLY postgres; -- not allowed for SYSTEM -REINDEX (CONCURRENTLY) SYSTEM postgres; -- ditto --- Deactivated for SplendidDataTest: REINDEX (CONCURRENTLY) SYSTEM; -- ditto -- Warns about catalog relations REINDEX SCHEMA CONCURRENTLY pg_catalog; --- Not the current database -REINDEX DATABASE not_current_database; -- Check the relation status, there should not be invalid indexes --- Deactivated for SplendidDataTest: \d concur_reindex_tab +\d concur_reindex_tab DROP MATERIALIZED VIEW concur_reindex_matview; DROP TABLE concur_reindex_tab, concur_reindex_tab2, concur_reindex_tab3; @@ -1101,16 +1097,16 @@ CREATE UNIQUE INDEX CONCURRENTLY concur_reindex_ind5 ON concur_reindex_tab4 (c1) -- Reindexing concurrently this index fails with the same failure. -- The extra index created is itself invalid, and can be dropped. REINDEX INDEX CONCURRENTLY concur_reindex_ind5; --- Deactivated for SplendidDataTest: \d concur_reindex_tab4 +\d concur_reindex_tab4 DROP INDEX concur_reindex_ind5_ccnew; -- This makes the previous failure go away, so the index can become valid. DELETE FROM concur_reindex_tab4 WHERE c1 = 1; -- The invalid index is not processed when running REINDEX TABLE. REINDEX TABLE CONCURRENTLY concur_reindex_tab4; --- Deactivated for SplendidDataTest: \d concur_reindex_tab4 +\d concur_reindex_tab4 -- But it is fixed with REINDEX INDEX. REINDEX INDEX CONCURRENTLY concur_reindex_ind5; --- Deactivated for SplendidDataTest: \d concur_reindex_tab4 +\d concur_reindex_tab4 DROP TABLE concur_reindex_tab4; -- Check handling of indexes with expressions and predicates. The diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_procedure.sql b/parser/src/test/resources/postgres/test/regress/sql/create_procedure.sql index 75cc0fc..9735d17 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_procedure.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_procedure.sql @@ -90,7 +90,16 @@ AS $$ CALL ptest4a(a, b); -- error, not supported $$; -DROP PROCEDURE ptest4a; +-- we used to get confused by a single output argument that is composite +CREATE PROCEDURE ptest4c(INOUT comp int8_tbl) +LANGUAGE SQL +AS $$ +SELECT ROW(1, 2); +$$; + +CALL ptest4c(NULL); + +DROP PROCEDURE ptest4a, ptest4c; -- named and default parameters @@ -122,6 +131,33 @@ $$; CALL ptest6(1, 2); +CREATE PROCEDURE ptest6a(inout a anyelement, out b anyelement) +LANGUAGE SQL +AS $$ +SELECT $1, $1; +$$; + +CALL ptest6a(1, null); +CALL ptest6a(1.1, null); + +CREATE PROCEDURE ptest6b(a anyelement, out b anyelement, out c anyarray) +LANGUAGE SQL +AS $$ +SELECT $1, array[$1]; +$$; + +CALL ptest6b(1, null, null); +CALL ptest6b(1.1, null, null); + +CREATE PROCEDURE ptest6c(inout a anyelement, inout b anyelement) +LANGUAGE SQL +AS $$ +SELECT $1, 1; +$$; + +CALL ptest6c(1, null); +CALL ptest6c(1.1, null); -- fails before v13 + -- collation assignment diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_schema.sql b/parser/src/test/resources/postgres/test/regress/sql/create_schema.sql new file mode 100644 index 0000000..1b70642 --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/create_schema.sql @@ -0,0 +1,70 @@ +-- +-- CREATE_SCHEMA +-- + +-- Schema creation with elements. + +CREATE ROLE regress_create_schema_role SUPERUSER; + +-- Cases where schema creation fails as objects are qualified with a schema +-- that does not match with what's expected. +-- This checks all the object types that include schema qualifications. +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE SEQUENCE schema_not_existing.seq; +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE TABLE schema_not_existing.tab (id int); +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE VIEW schema_not_existing.view AS SELECT 1; +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE INDEX ON schema_not_existing.tab (id); +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab + EXECUTE FUNCTION schema_trig.no_func(); +-- Again, with a role specification and no schema names. +SET ROLE regress_create_schema_role; +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE SEQUENCE schema_not_existing.seq; +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE TABLE schema_not_existing.tab (id int); +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE VIEW schema_not_existing.view AS SELECT 1; +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE INDEX ON schema_not_existing.tab (id); +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab + EXECUTE FUNCTION schema_trig.no_func(); +-- Again, with a schema name and a role specification. +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE SEQUENCE schema_not_existing.seq; +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE TABLE schema_not_existing.tab (id int); +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE VIEW schema_not_existing.view AS SELECT 1; +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE INDEX ON schema_not_existing.tab (id); +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab + EXECUTE FUNCTION schema_trig.no_func(); +RESET ROLE; + +-- Cases where the schema creation succeeds. +-- The schema created matches the role name. +CREATE SCHEMA AUTHORIZATION regress_create_schema_role + CREATE TABLE regress_create_schema_role.tab (id int); +\d regress_create_schema_role.tab +DROP SCHEMA regress_create_schema_role CASCADE; +-- Again, with a different role specification and no schema names. +SET ROLE regress_create_schema_role; +CREATE SCHEMA AUTHORIZATION CURRENT_ROLE + CREATE TABLE regress_create_schema_role.tab (id int); +\d regress_create_schema_role.tab +DROP SCHEMA regress_create_schema_role CASCADE; +-- Again, with a schema name and a role specification. +CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE + CREATE TABLE regress_schema_1.tab (id int); +\d regress_schema_1.tab +DROP SCHEMA regress_schema_1 CASCADE; +RESET ROLE; + +-- Clean up +DROP ROLE regress_create_schema_role; diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_table.sql b/parser/src/test/resources/postgres/test/regress/sql/create_table.sql index b39b2c3..759c8db 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_table.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_table.sql @@ -54,11 +54,11 @@ DEALLOCATE select1; -- create an extra wide table to test for issues related to that -- (temporarily hide query, to avoid the long CREATE TABLE stmt) --- Deactivated for SplendidDataTest: \set ECHO none +\set ECHO none SELECT 'CREATE TABLE extra_wide_table(firstc text, '|| array_to_string(array_agg('c'||i||' bool'),',')||', lastc text);' -FROM generate_series(1, 1100) g(i); --- Deactivated for SplendidDataTest: \gexec --- Deactivated for SplendidDataTest: \set ECHO all +FROM generate_series(1, 1100) g(i) +\gexec +\set ECHO all INSERT INTO extra_wide_table(firstc, lastc) VALUES('first col', 'last col'); SELECT firstc, lastc FROM extra_wide_table; @@ -68,8 +68,16 @@ SELECT firstc, lastc FROM extra_wide_table; -- Deactivated for SplendidDataTest: CREATE TABLE withoid() WITH (oids = true); -- but explicitly not adding oids is still supported --- Deactivated for SplendidDataTest: CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid; --- Deactivated for SplendidDataTest: CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid; +CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid; +CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid; + +-- temporary tables are ignored by pg_filenode_relation(). +CREATE TEMP TABLE relation_filenode_check(c1 int); +SELECT relpersistence, + pg_filenode_relation (reltablespace, pg_relation_filenode(oid)) + FROM pg_class + WHERE relname = 'relation_filenode_check'; +DROP TABLE relation_filenode_check; -- check restriction with default expressions -- invalid use of column reference in default expressions @@ -227,12 +235,12 @@ CREATE TABLE partitioned2 ( CREATE TABLE fail () INHERITS (partitioned2); -- Partition key in describe output --- Deactivated for SplendidDataTest: \d partitioned --- Deactivated for SplendidDataTest: \d partitioned2 +\d partitioned +\d+ partitioned2 INSERT INTO partitioned2 VALUES (1, 'hello'); CREATE TABLE part2_1 PARTITION OF partitioned2 FOR VALUES FROM (-1, 'aaaaa') TO (100, 'ccccc'); --- Deactivated for SplendidDataTest: \d+ part2_1 +\d+ part2_1 DROP TABLE partitioned, partitioned2; @@ -256,7 +264,7 @@ create table partitioned2 partition of partitioned for values in ('(2,4)'); explain (costs off) select * from partitioned where partitioned = '(1,2)'::partitioned; --- Deactivated for SplendidDataTest: \d+ partitioned1 +\d+ partitioned1 drop table partitioned; -- check that dependencies of partition columns are handled correctly @@ -305,7 +313,7 @@ CREATE TABLE part_p1 PARTITION OF list_parted FOR VALUES IN ('1'); CREATE TABLE part_p2 PARTITION OF list_parted FOR VALUES IN (2); CREATE TABLE part_p3 PARTITION OF list_parted FOR VALUES IN ((2+1)); CREATE TABLE part_null PARTITION OF list_parted FOR VALUES IN (null); --- Deactivated for SplendidDataTest: \d+ list_parted +\d+ list_parted -- forbidden expressions for partition bound with list partitioned table -- Deactivated for SplendidDataTest: CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename); @@ -569,7 +577,7 @@ create table parted_notnull_inh_test (a int default 1, b int not null default 0) create table parted_notnull_inh_test1 partition of parted_notnull_inh_test (a not null, b default 1) for values in (1); insert into parted_notnull_inh_test (b) values (null); -- note that while b's default is overridden, a's default is preserved --- Deactivated for SplendidDataTest: \d parted_notnull_inh_test1 +\d parted_notnull_inh_test1 drop table parted_notnull_inh_test; -- check that collations are assigned in partition bound expressions @@ -607,32 +615,32 @@ create table test_part_coll_cast2 partition of test_part_coll_posix for values f drop table test_part_coll_posix; -- Partition bound in describe output --- Deactivated for SplendidDataTest: \d+ part_b +\d+ part_b -- Both partition bound and partition key in describe output --- Deactivated for SplendidDataTest: \d+ part_c +\d+ part_c -- a level-2 partition's constraint will include the parent's expressions --- Deactivated for SplendidDataTest: \d+ part_c_1_10 +\d+ part_c_1_10 -- Show partition count in the parent's describe output -- Tempted to include \d+ output listing partitions with bound info but -- output could vary depending on the order in which partition oids are -- returned. --- Deactivated for SplendidDataTest: \d parted --- Deactivated for SplendidDataTest: \d hash_parted +\d parted +\d hash_parted -- check that we get the expected partition constraints CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c); CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE); --- Deactivated for SplendidDataTest: \d+ unbounded_range_part +\d+ unbounded_range_part DROP TABLE unbounded_range_part; CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE); --- Deactivated for SplendidDataTest: \d+ range_parted4_1 +\d+ range_parted4_1 CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE); --- Deactivated for SplendidDataTest: \d+ range_parted4_2 +\d+ range_parted4_2 CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE); --- Deactivated for SplendidDataTest: \d+ range_parted4_3 +\d+ range_parted4_3 DROP TABLE range_parted4; -- user-defined operator class in partition key @@ -658,20 +666,20 @@ CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a); COMMENT ON TABLE parted_col_comment IS 'Am partitioned table'; COMMENT ON COLUMN parted_col_comment.a IS 'Partition key'; SELECT obj_description('parted_col_comment'::regclass); --- Deactivated for SplendidDataTest: \d+ parted_col_comment +\d+ parted_col_comment DROP TABLE parted_col_comment; -- list partitioning on array type column CREATE TABLE arrlp (a int[]) PARTITION BY LIST (a); CREATE TABLE arrlp12 PARTITION OF arrlp FOR VALUES IN ('{1}', '{2}'); --- Deactivated for SplendidDataTest: \d+ arrlp12 +\d+ arrlp12 DROP TABLE arrlp; -- partition on boolean column create table boolspart (a bool) partition by list (a); create table boolspart_t partition of boolspart for values in (true); create table boolspart_f partition of boolspart for values in (false); --- Deactivated for SplendidDataTest: \d+ boolspart +\d+ boolspart drop table boolspart; -- partitions mixing temporary and permanent relations @@ -739,6 +747,6 @@ create index part_column_drop_d_pred on part_column_drop(d) where d = 2; create index part_column_drop_d_expr on part_column_drop((d = 2)); create table part_column_drop_1_10 partition of part_column_drop for values from (1) to (10); --- Deactivated for SplendidDataTest: \d part_column_drop --- Deactivated for SplendidDataTest: \d part_column_drop_1_10 +\d part_column_drop +\d part_column_drop_1_10 drop table part_column_drop; diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql b/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql index 4929d37..04008a0 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql @@ -95,8 +95,16 @@ CREATE TABLE test_like_5c (LIKE test_like_4 INCLUDING ALL) INHERITS (test_like_5, test_like_5x); \d test_like_5c +-- Test updating of column numbers in statistics expressions (bug #18468) +CREATE TABLE test_like_6 (a int, c text, b text); +CREATE STATISTICS ext_stat ON (a || b) FROM test_like_6; +ALTER TABLE test_like_6 DROP COLUMN c; +CREATE TABLE test_like_6c (LIKE test_like_6 INCLUDING ALL); +\d+ test_like_6c + DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d; DROP TABLE test_like_5, test_like_5x, test_like_5c; +DROP TABLE test_like_6, test_like_6c; CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */ INSERT INTO inhg VALUES (5, 10); diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_view.sql b/parser/src/test/resources/postgres/test/regress/sql/create_view.sql index ab3bb67..113b3bb 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_view.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_view.sql @@ -13,11 +13,11 @@ -- -- directory paths and dlsuffix are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv abs_srcdir PG_ABS_SRCDIR --- Deactivated for SplendidDataTest: \getenv libdir PG_LIBDIR --- Deactivated for SplendidDataTest: \getenv dlsuffix PG_DLSUFFIX +\getenv abs_srcdir PG_ABS_SRCDIR +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX --- Deactivated for SplendidDataTest: \set regresslib :libdir '/regress' :dlsuffix +\set regresslib :libdir '/regress' :dlsuffix CREATE FUNCTION interpt_pp(path, path) RETURNS point @@ -30,7 +30,7 @@ CREATE TABLE real_city ( outline path ); --- Deactivated for SplendidDataTest: \set filename :abs_srcdir '/data/real_city.data' +\set filename :abs_srcdir '/data/real_city.data' COPY real_city FROM :'filename'; ANALYZE real_city; @@ -303,7 +303,7 @@ SELECT relname, relkind, reloptions FROM pg_class CREATE VIEW unspecified_types AS SELECT 42 as i, 42.5 as num, 'foo' as u, 'foo'::unknown as u2, null as n; --- Deactivated for SplendidDataTest: \d+ unspecified_types +\d+ unspecified_types SELECT * FROM unspecified_types; -- This test checks that proper typmods are assigned in a multi-row VALUES @@ -314,7 +314,7 @@ CREATE VIEW tt1 AS ('abc'::varchar(3), '0123456789', 42, 'abcd'::varchar(4)), ('0123456789', 'abc'::varchar(3), 42.12, 'abc'::varchar(4)) ) vv(a,b,c,d); --- Deactivated for SplendidDataTest: \d+ tt1 +\d+ tt1 SELECT * FROM tt1; SELECT a::varchar(3) FROM tt1; DROP VIEW tt1; @@ -338,48 +338,48 @@ CREATE VIEW aliased_view_4 AS select * from temp_view_test.tt1 where exists (select 1 from tt1 where temp_view_test.tt1.y1 = tt1.f1); --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 ALTER TABLE tx1 RENAME TO a1; --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 ALTER TABLE tt1 RENAME TO a2; --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 ALTER TABLE a1 RENAME TO tt1; --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 ALTER TABLE a2 RENAME TO tx1; ALTER TABLE tx1 SET SCHEMA temp_view_test; --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 ALTER TABLE temp_view_test.tt1 RENAME TO tmp1; ALTER TABLE temp_view_test.tmp1 SET SCHEMA testviewschm2; ALTER TABLE tmp1 RENAME TO tx1; --- Deactivated for SplendidDataTest: \d+ aliased_view_1 --- Deactivated for SplendidDataTest: \d+ aliased_view_2 --- Deactivated for SplendidDataTest: \d+ aliased_view_3 --- Deactivated for SplendidDataTest: \d+ aliased_view_4 +\d+ aliased_view_1 +\d+ aliased_view_2 +\d+ aliased_view_3 +\d+ aliased_view_4 -- Test aliasing of joins @@ -388,7 +388,7 @@ select * from (select * from (tbl1 cross join tbl2) same) ss, (tbl3 cross join tbl4) same; --- Deactivated for SplendidDataTest: \d+ view_of_joins +\d+ view_of_joins create table tbl1a (a int, c int); create view view_of_joins_2a as select * from tbl1 join tbl1a using (a); @@ -673,7 +673,7 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl)); create table tt15v_log(o tt15v, n tt15v, incr bool); create rule updlog as on update to tt15v do also insert into tt15v_log values(old, new, row(old,old) < row(new,new)); --- Deactivated for SplendidDataTest: \d+ tt15v +\d+ tt15v -- check unique-ification of overlength names @@ -711,6 +711,7 @@ select pg_get_viewdef('tt20v', true); create view tt201v as select + ('2022-12-01'::date + '1 day'::interval) at time zone 'UTC' as atz, extract(day from now()) as extr, (now(), '1 day'::interval) overlaps (current_timestamp(2), '1 day'::interval) as o, @@ -729,8 +730,7 @@ select trim(trailing ' foo ') as rt, trim(E'\\000'::bytea from E'\\000Tom\\000'::bytea) as btb, trim(leading E'\\000'::bytea from E'\\000Tom\\000'::bytea) as ltb, - trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea) as rtb, - SYSTEM_USER as su; + trim(trailing E'\\000'::bytea from E'\\000Tom\\000'::bytea) as rtb; select pg_get_viewdef('tt201v', true); -- corner cases with empty join conditions @@ -789,6 +789,37 @@ select x + y + z as c1, from (values(1,2,3)) v(x,y,z); select pg_get_viewdef('tt26v', true); + +-- Test that changing the relkind of a relcache entry doesn't cause +-- trouble. Prior instances of where it did: +-- CALDaNm2yXz+zOtv7y5zBd5WKT8O0Ld3YxikuU3dcyCvxF7gypA@mail.gmail.com +-- CALDaNm3oZA-8Wbps2Jd1g5_Gjrr-x3YWrJPek-mF5Asrrvz2Dg@mail.gmail.com +CREATE TABLE tt26(c int); + +BEGIN; +CREATE TABLE tt27(c int); +SAVEPOINT q; +CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26; +SELECT * FROM tt27; +ROLLBACK TO q; +CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26; +ROLLBACK; + +BEGIN; +CREATE TABLE tt28(c int); +CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26; +CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26; +ROLLBACK; + +-- test restriction on non-system view expansion. +create table tt27v_tbl (a int); +create view tt27v as select a from tt27v_tbl; +set restrict_nonsystem_relation_kind to 'view'; +select a from tt27v where a > 0; -- Error +insert into tt27v values (1); -- Error +select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view. +reset restrict_nonsystem_relation_kind; + -- clean up all the random objects we made above DROP SCHEMA temp_view_test CASCADE; DROP SCHEMA testviewschm2 CASCADE; diff --git a/parser/src/test/resources/postgres/test/regress/sql/database.sql b/parser/src/test/resources/postgres/test/regress/sql/database.sql new file mode 100644 index 0000000..edd6212 --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/database.sql @@ -0,0 +1,23 @@ +CREATE DATABASE regression_tbd + ENCODING utf8 LC_COLLATE "C" LC_CTYPE "C" TEMPLATE template0; +ALTER DATABASE regression_tbd RENAME TO regression_utf8; +ALTER DATABASE regression_utf8 RESET TABLESPACE; +ALTER DATABASE regression_utf8 CONNECTION_LIMIT 123; + +-- Test PgDatabaseToastTable. Doing this with GRANT would be slow. +BEGIN; +UPDATE pg_database +SET datacl = array_fill(makeaclitem(10, 10, 'USAGE', false), ARRAY[5e5::int]) +WHERE datname = 'regression_utf8'; +-- load catcache entry, if nothing else does +ALTER DATABASE regression_utf8 RESET TABLESPACE; +ROLLBACK; + +CREATE ROLE regress_datdba_before; +CREATE ROLE regress_datdba_after; +ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; +REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; + +DROP DATABASE regression_utf8; +DROP ROLE regress_datdba_before; +DROP ROLE regress_datdba_after; diff --git a/parser/src/test/resources/postgres/test/regress/sql/dbsize.sql b/parser/src/test/resources/postgres/test/regress/sql/dbsize.sql index 7df8652..2a4f9c4 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/dbsize.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/dbsize.sql @@ -27,6 +27,10 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM (11258449312612351::numeric), (11258449312612352::numeric), (11528652096115048447::numeric), (11528652096115048448::numeric)) x(size); +-- Ensure we get the expected results when passing the extremities of bigint +SELECT pg_size_pretty('-9223372036854775808'::bigint), + pg_size_pretty('9223372036854775807'::bigint); + -- pg_size_bytes() tests SELECT size, pg_size_bytes(size) FROM (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '), diff --git a/parser/src/test/resources/postgres/test/regress/sql/domain.sql b/parser/src/test/resources/postgres/test/regress/sql/domain.sql index 38572f2..cfc6d61 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/domain.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/domain.sql @@ -55,11 +55,11 @@ INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate -- Test copy COPY basictest (testvarchar) FROM stdin; -- fail -- Deactivated for SplendidDataTest: notsoshorttext --- Deactivated for SplendidDataTest: \. +\. COPY basictest (testvarchar) FROM stdin; -- Deactivated for SplendidDataTest: short --- Deactivated for SplendidDataTest: \. +\. select * from basictest; @@ -100,12 +100,12 @@ select array_dims(testint4arr), array_dims(testchar4arr) from domarrtest; COPY domarrtest FROM stdin; -- Deactivated for SplendidDataTest: {3,4} {q,w,e} --- Deactivated for SplendidDataTest: \N \N --- Deactivated for SplendidDataTest: \. +\N \N +\. COPY domarrtest FROM stdin; -- fail -- Deactivated for SplendidDataTest: {3,4} {qwerty,w,e} --- Deactivated for SplendidDataTest: \. +\. select * from domarrtest; @@ -161,7 +161,7 @@ explain (verbose, costs off) update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; create rule silly as on delete to dcomptable do instead update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; --- Deactivated for SplendidDataTest: \d+ dcomptable +\d+ dcomptable create function makedcomp(r float8, i float8) returns dcomptype as 'select row(r, i)' language sql; @@ -236,7 +236,7 @@ explain (verbose, costs off) create rule silly as on delete to dcomptable do instead update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1 where d1[1].i > 0; --- Deactivated for SplendidDataTest: \d+ dcomptable +\d+ dcomptable drop table dcomptable; drop type comptype cascade; @@ -297,6 +297,10 @@ table dcomptable; update dcomptable set f1[1].cf1 = -1; -- fail update dcomptable set f1[1].cf1 = 1; table dcomptable; +-- if there's no constraints, a different code path is taken: +alter domain dcomptype drop constraint dcomptype_check; +update dcomptable set f1[1].cf1 = -1; -- now ok +table dcomptable; drop table dcomptable; drop type comptype cascade; @@ -327,18 +331,18 @@ INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good -- Test copy COPY nulltest FROM stdin; --fail -- Deactivated for SplendidDataTest: a b \N d d --- Deactivated for SplendidDataTest: \. +\. COPY nulltest FROM stdin; --fail -- Deactivated for SplendidDataTest: a b c d \N --- Deactivated for SplendidDataTest: \. +\. -- Last row is bad COPY nulltest FROM stdin; -- Deactivated for SplendidDataTest: a b c \N c -- Deactivated for SplendidDataTest: a b c \N d -- Deactivated for SplendidDataTest: a b c \N a --- Deactivated for SplendidDataTest: \. +\. select * from nulltest; @@ -386,7 +390,7 @@ insert into defaulttest default values; -- Test defaults with copy COPY defaulttest(col5) FROM stdin; -- Deactivated for SplendidDataTest: 42 --- Deactivated for SplendidDataTest: \. +\. select * from defaulttest; diff --git a/parser/src/test/resources/postgres/test/regress/sql/event_trigger.sql b/parser/src/test/resources/postgres/test/regress/sql/event_trigger.sql index 5c6cae6..8291fb6 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/event_trigger.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/event_trigger.sql @@ -211,9 +211,15 @@ INSERT INTO undroppable_objs VALUES ('table', 'audit_tbls.schema_two_table_three'); CREATE TABLE dropped_objects ( - type text, - schema text, - object text + object_type text, + schema_name text, + object_name text, + object_identity text, + address_names text[], + address_args text[], + is_temporary bool, + original bool, + normal bool ); -- This tests errors raised within event triggers; the one in audit_tbls @@ -254,8 +260,12 @@ BEGIN END IF; INSERT INTO dropped_objects - (type, schema, object) VALUES - (obj.object_type, obj.schema_name, obj.object_identity); + (object_type, schema_name, object_name, + object_identity, address_names, address_args, + is_temporary, original, normal) VALUES + (obj.object_type, obj.schema_name, obj.object_name, + obj.object_identity, obj.address_names, obj.address_args, + obj.is_temporary, obj.original, obj.normal); END LOOP; END $$; @@ -272,10 +282,12 @@ DROP SCHEMA schema_one, schema_two CASCADE; DELETE FROM undroppable_objs WHERE object_identity = 'schema_one.table_three'; DROP SCHEMA schema_one, schema_two CASCADE; -SELECT * FROM dropped_objects WHERE schema IS NULL OR schema <> 'pg_toast'; +-- exclude TOAST objects because they have unstable names +SELECT * FROM dropped_objects + WHERE schema_name IS NULL OR schema_name <> 'pg_toast'; DROP OWNED BY regress_evt_user; -SELECT * FROM dropped_objects WHERE type = 'schema'; +SELECT * FROM dropped_objects WHERE object_type = 'schema'; DROP ROLE regress_evt_user; @@ -294,9 +306,10 @@ BEGIN IF NOT r.normal AND NOT r.original THEN CONTINUE; END IF; - RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% name=% args=%', + RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% schema=% name=% addr=% args=%', r.original, r.normal, r.is_temporary, r.object_type, - r.object_identity, r.address_names, r.address_args; + r.object_identity, r.schema_name, r.object_name, + r.address_names, r.address_args; END LOOP; END; $$; CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop @@ -346,6 +359,46 @@ DROP INDEX evttrig.one_idx; DROP SCHEMA evttrig CASCADE; DROP TABLE a_temp_tbl; +-- check unfiltered results, too +CREATE OR REPLACE FUNCTION event_trigger_report_dropped() + RETURNS event_trigger + LANGUAGE plpgsql +AS $$ +DECLARE r record; +BEGIN + FOR r IN SELECT * from pg_event_trigger_dropped_objects() + LOOP + RAISE NOTICE 'DROP: orig=% normal=% istemp=% type=% identity=% schema=% name=% addr=% args=%', + r.original, r.normal, r.is_temporary, r.object_type, + r.object_identity, r.schema_name, r.object_name, + r.address_names, r.address_args; + END LOOP; +END; $$; + +CREATE FUNCTION event_trigger_dummy_trigger() + RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + RETURN new; +END; $$; + +CREATE TABLE evtrg_nontemp_table (f1 int primary key, f2 int default 42); +CREATE TRIGGER evtrg_nontemp_trig + BEFORE INSERT ON evtrg_nontemp_table + EXECUTE FUNCTION event_trigger_dummy_trigger(); +CREATE POLICY evtrg_nontemp_pol ON evtrg_nontemp_table USING (f2 > 0); +DROP TABLE evtrg_nontemp_table; + +CREATE TEMP TABLE a_temp_tbl (f1 int primary key, f2 int default 42); +CREATE TRIGGER a_temp_trig + BEFORE INSERT ON a_temp_tbl + EXECUTE FUNCTION event_trigger_dummy_trigger(); +CREATE POLICY a_temp_pol ON a_temp_tbl USING (f2 > 0); +DROP TABLE a_temp_tbl; + +DROP FUNCTION event_trigger_dummy_trigger(); + -- CREATE OPERATOR CLASS without FAMILY clause should report -- both CREATE OPERATOR FAMILY and CREATE OPERATOR CLASS CREATE OPERATOR CLASS evttrigopclass FOR TYPE int USING btree AS STORAGE int; diff --git a/parser/src/test/resources/postgres/test/regress/sql/expressions.sql b/parser/src/test/resources/postgres/test/regress/sql/expressions.sql index 0e163cc..aebd08f 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/expressions.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/expressions.sql @@ -24,7 +24,7 @@ SELECT length(current_timestamp::text) >= length(current_timestamp(0)::text); -- localtimestamp SELECT now()::timestamp::text = localtimestamp::text; --- current_role/user/user is tested in rolnames.sql +-- current_role/user/user is tested in rolenames.sql -- current database / catalog SELECT current_catalog = current_database(); diff --git a/parser/src/test/resources/postgres/test/regress/sql/fast_default.sql b/parser/src/test/resources/postgres/test/regress/sql/fast_default.sql index 16a3b7c..1b37b61 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/fast_default.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/fast_default.sql @@ -237,6 +237,50 @@ SELECT comp(); DROP TABLE T; +-- Test domains with default value for table rewrite. +CREATE DOMAIN domain1 AS int DEFAULT 11; -- constant +CREATE DOMAIN domain2 AS int DEFAULT 10 + (random() * 10)::int; -- volatile +CREATE DOMAIN domain3 AS text DEFAULT foo(4); -- stable +CREATE DOMAIN domain4 AS text[] + DEFAULT ('{"This", "is", "' || foo(4) || '","the", "real", "world"}')::TEXT[]; + +CREATE TABLE t2 (a domain1); +INSERT INTO t2 VALUES (1),(2); + +-- no table rewrite +ALTER TABLE t2 ADD COLUMN b domain1 default 3; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN c domain3 default left(random()::text,3); + +-- no table rewrite +ALTER TABLE t2 ADD COLUMN d domain4; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN e domain2; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +SELECT a, b, length(c) = 3 as c_ok, d, e >= 10 as e_ok FROM t2; + +DROP TABLE t2; +DROP DOMAIN domain1; +DROP DOMAIN domain2; +DROP DOMAIN domain3; +DROP DOMAIN domain4; DROP FUNCTION foo(INT); -- Fall back to full rewrite for volatile expressions @@ -256,7 +300,18 @@ ALTER TABLE T ADD COLUMN c2 TIMESTAMP DEFAULT clock_timestamp(); SELECT comp(); +-- check that we notice insertion of a volatile default argument +CREATE FUNCTION foolme(timestamptz DEFAULT clock_timestamp()) + RETURNS timestamptz + IMMUTABLE AS 'select $1' LANGUAGE sql; +ALTER TABLE T ADD COLUMN c3 timestamptz DEFAULT foolme(); + +SELECT attname, atthasmissing, attmissingval FROM pg_attribute + WHERE attrelid = 't'::regclass AND attnum > 0 + ORDER BY attnum; + DROP TABLE T; +DROP FUNCTION foolme(timestamptz); -- Simple querie CREATE TABLE T (pk INT NOT NULL PRIMARY KEY); diff --git a/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql b/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql index eeaadfd..e1a5ae9 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql @@ -11,10 +11,10 @@ -- -- directory paths and dlsuffix are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv libdir PG_LIBDIR --- Deactivated for SplendidDataTest: \getenv dlsuffix PG_DLSUFFIX +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX --- Deactivated for SplendidDataTest: \set regresslib :libdir '/regress' :dlsuffix +\set regresslib :libdir '/regress' :dlsuffix CREATE FUNCTION test_fdw_handler() RETURNS fdw_handler @@ -51,24 +51,24 @@ SELECT * FROM pg_user_mapping; -- CREATE FOREIGN DATA WRAPPER CREATE FOREIGN DATA WRAPPER foo VALIDATOR bar; -- ERROR CREATE FOREIGN DATA WRAPPER foo; --- Deactivated for SplendidDataTest: \dew +\dew CREATE FOREIGN DATA WRAPPER foo; -- duplicate DROP FOREIGN DATA WRAPPER foo; CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1'); --- Deactivated for SplendidDataTest: \dew+ +\dew+ DROP FOREIGN DATA WRAPPER foo; CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', testing '2'); -- ERROR CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2'); --- Deactivated for SplendidDataTest: \dew+ +\dew+ DROP FOREIGN DATA WRAPPER foo; SET ROLE regress_test_role; CREATE FOREIGN DATA WRAPPER foo; -- ERROR RESET ROLE; CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator; --- Deactivated for SplendidDataTest: \dew+ +\dew+ -- HANDLER related checks CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;'; @@ -83,26 +83,26 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (nonexistent 'fdw'); -- ERROR -- Deactivated for SplendidDataTest: ALTER FOREIGN DATA WRAPPER foo; -- ERROR ALTER FOREIGN DATA WRAPPER foo VALIDATOR bar; -- ERROR ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR; --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2'); ALTER FOREIGN DATA WRAPPER foo OPTIONS (SET c '4'); -- ERROR ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP c); -- ERROR ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x); --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4'); --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '2'); ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4'); -- ERROR --- Deactivated for SplendidDataTest: \dew+ +\dew+ SET ROLE regress_test_role; ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5'); -- ERROR SET ROLE regress_test_role_super; ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5'); --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role; -- ERROR ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role_super; @@ -110,10 +110,10 @@ ALTER ROLE regress_test_role_super NOSUPERUSER; SET ROLE regress_test_role_super; ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD e '6'); -- ERROR RESET ROLE; --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo RENAME TO foo1; --- Deactivated for SplendidDataTest: \dew+ +\dew+ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo; -- HANDLER related checks @@ -125,14 +125,14 @@ DROP FUNCTION invalid_fdw_handler(); -- DROP FOREIGN DATA WRAPPER DROP FOREIGN DATA WRAPPER nonexistent; -- ERROR DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent; --- Deactivated for SplendidDataTest: \dew+ +\dew+ DROP ROLE regress_test_role_super; -- ERROR SET ROLE regress_test_role_super; DROP FOREIGN DATA WRAPPER foo; RESET ROLE; DROP ROLE regress_test_role_super; --- Deactivated for SplendidDataTest: \dew+ +\dew+ CREATE FOREIGN DATA WRAPPER foo; CREATE SERVER s1 FOREIGN DATA WRAPPER foo; @@ -140,17 +140,17 @@ COMMENT ON SERVER s1 IS 'foreign server'; CREATE USER MAPPING FOR current_user SERVER s1; CREATE USER MAPPING FOR current_user SERVER s1; -- ERROR CREATE USER MAPPING IF NOT EXISTS FOR current_user SERVER s1; -- NOTICE --- Deactivated for SplendidDataTest: \dew+ --- Deactivated for SplendidDataTest: \des+ --- Deactivated for SplendidDataTest: \deu+ +\dew+ +\des+ +\deu+ DROP FOREIGN DATA WRAPPER foo; -- ERROR SET ROLE regress_test_role; DROP FOREIGN DATA WRAPPER foo CASCADE; -- ERROR RESET ROLE; DROP FOREIGN DATA WRAPPER foo CASCADE; --- Deactivated for SplendidDataTest: \dew+ --- Deactivated for SplendidDataTest: \des+ --- Deactivated for SplendidDataTest: \deu+ +\dew+ +\des+ +\deu+ -- exercise CREATE SERVER CREATE SERVER s1 FOREIGN DATA WRAPPER foo; -- ERROR @@ -166,7 +166,7 @@ CREATE SERVER s6 VERSION '16.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbna CREATE SERVER s7 TYPE 'oracle' VERSION '17.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b'); CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (foo '1'); -- ERROR CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db'); --- Deactivated for SplendidDataTest: \des+ +\des+ SET ROLE regress_test_role; CREATE SERVER t1 FOREIGN DATA WRAPPER foo; -- ERROR: no usage on FDW RESET ROLE; @@ -174,7 +174,7 @@ GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role; SET ROLE regress_test_role; CREATE SERVER t1 FOREIGN DATA WRAPPER foo; RESET ROLE; --- Deactivated for SplendidDataTest: \des+ +\des+ REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM regress_test_role; GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_indirect; @@ -184,7 +184,7 @@ RESET ROLE; GRANT regress_test_indirect TO regress_test_role; SET ROLE regress_test_role; CREATE SERVER t2 FOREIGN DATA WRAPPER foo; --- Deactivated for SplendidDataTest: \des+ +\des+ RESET ROLE; REVOKE regress_test_indirect FROM regress_test_role; @@ -196,7 +196,7 @@ ALTER SERVER s2 VERSION '1.1'; ALTER SERVER s3 OPTIONS ("tns name" 'orcl', port '1521'); GRANT USAGE ON FOREIGN SERVER s1 TO regress_test_role; GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role2 WITH GRANT OPTION; --- Deactivated for SplendidDataTest: \des+ +\des+ SET ROLE regress_test_role; ALTER SERVER s1 VERSION '1.1'; -- ERROR ALTER SERVER s1 OWNER TO regress_test_role; -- ERROR @@ -221,32 +221,32 @@ SET ROLE regress_test_role; ALTER SERVER s1 OWNER TO regress_test_indirect; RESET ROLE; DROP ROLE regress_test_indirect; -- ERROR --- Deactivated for SplendidDataTest: \des+ +\des+ ALTER SERVER s8 RENAME to s8new; --- Deactivated for SplendidDataTest: \des+ +\des+ ALTER SERVER s8new RENAME to s8; -- DROP SERVER DROP SERVER nonexistent; -- ERROR DROP SERVER IF EXISTS nonexistent; --- Deactivated for SplendidDataTest: \des +\des SET ROLE regress_test_role; DROP SERVER s2; -- ERROR DROP SERVER s1; RESET ROLE; --- Deactivated for SplendidDataTest: \des +\des ALTER SERVER s2 OWNER TO regress_test_role; SET ROLE regress_test_role; DROP SERVER s2; RESET ROLE; --- Deactivated for SplendidDataTest: \des +\des CREATE USER MAPPING FOR current_user SERVER s3; --- Deactivated for SplendidDataTest: \deu +\deu DROP SERVER s3; -- ERROR DROP SERVER s3 CASCADE; --- Deactivated for SplendidDataTest: \des --- Deactivated for SplendidDataTest: \deu +\des +\deu -- CREATE USER MAPPING CREATE USER MAPPING FOR regress_test_missing_role SERVER s1; -- ERROR @@ -270,7 +270,7 @@ SET ROLE regress_test_role; CREATE USER MAPPING FOR current_user SERVER t1 OPTIONS (username 'bob', password 'boo'); CREATE USER MAPPING FOR public SERVER t1; RESET ROLE; --- Deactivated for SplendidDataTest: \deu +\deu -- ALTER USER MAPPING ALTER USER MAPPING FOR regress_test_missing_role SERVER s4 OPTIONS (gotcha 'true'); -- ERROR @@ -283,7 +283,7 @@ ALTER USER MAPPING FOR current_user SERVER s5 OPTIONS (ADD modified '1'); ALTER USER MAPPING FOR public SERVER s4 OPTIONS (ADD modified '1'); -- ERROR ALTER USER MAPPING FOR public SERVER t1 OPTIONS (ADD modified '1'); RESET ROLE; --- Deactivated for SplendidDataTest: \deu+ +\deu+ -- DROP USER MAPPING DROP USER MAPPING FOR regress_test_missing_role SERVER s4; -- ERROR @@ -297,7 +297,7 @@ SET ROLE regress_test_role; DROP USER MAPPING FOR public SERVER s8; -- ERROR RESET ROLE; DROP SERVER s7; --- Deactivated for SplendidDataTest: \deu +\deu -- CREATE FOREIGN TABLE CREATE SCHEMA foreign_schema; @@ -330,8 +330,8 @@ CREATE FOREIGN TABLE ft1 ( ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); COMMENT ON FOREIGN TABLE ft1 IS 'ft1'; COMMENT ON COLUMN ft1.c1 IS 'ft1.c1'; --- Deactivated for SplendidDataTest: \d+ ft1 --- Deactivated for SplendidDataTest: \det+ +\d+ ft1 +\det+ CREATE INDEX id_ft1_c2 ON ft1 (c2); -- ERROR SELECT * FROM ft1; -- ERROR EXPLAIN SELECT * FROM ft1; -- ERROR @@ -411,7 +411,7 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET STATISTICS 10000; ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET (n_distinct = 100); ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STATISTICS -1; ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN; --- Deactivated for SplendidDataTest: \d+ ft1 +\d+ ft1 -- can't change the column type if it's used elsewhere CREATE TABLE use_ft1_column_type (x ft1); ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET DATA TYPE integer; -- ERROR @@ -427,11 +427,13 @@ ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@'); ALTER FOREIGN TABLE ft1 DROP COLUMN no_column; -- ERROR ALTER FOREIGN TABLE ft1 DROP COLUMN IF EXISTS no_column; ALTER FOREIGN TABLE ft1 DROP COLUMN c9; +ALTER FOREIGN TABLE ft1 ADD COLUMN c11 serial; ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema; ALTER FOREIGN TABLE ft1 SET TABLESPACE ts; -- ERROR +ALTER SEQUENCE foreign_schema.ft1_c11_seq SET SCHEMA public; -- ERROR ALTER FOREIGN TABLE foreign_schema.ft1 RENAME c1 TO foreign_column_1; ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1; --- Deactivated for SplendidDataTest: \d foreign_schema.foreign_table_1 +\d foreign_schema.foreign_table_1 -- alter noexisting table ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c4 integer; @@ -578,13 +580,13 @@ CREATE SERVER s10 FOREIGN DATA WRAPPER foo; CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret'); CREATE USER MAPPING FOR regress_unprivileged_role SERVER s10 OPTIONS (user 'secret'); -- owner of server can see some option fields --- Deactivated for SplendidDataTest: \deu+ +\deu+ RESET ROLE; -- superuser can see all option fields --- Deactivated for SplendidDataTest: \deu+ +\deu+ -- unprivileged user cannot see any option field SET ROLE regress_unprivileged_role; --- Deactivated for SplendidDataTest: \deu+ +\deu+ RESET ROLE; DROP SERVER s10 CASCADE; @@ -646,19 +648,19 @@ CREATE TABLE fd_pt1 ( ); CREATE FOREIGN TABLE ft2 () INHERITS (fd_pt1) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 DROP FOREIGN TABLE ft2; --- Deactivated for SplendidDataTest: \d+ fd_pt1 +\d+ fd_pt1 CREATE FOREIGN TABLE ft2 ( c1 integer NOT NULL, c2 text, c3 date ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ ft2 ALTER FOREIGN TABLE ft2 INHERIT fd_pt1; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 CREATE TABLE ct3() INHERITS(ft2); CREATE FOREIGN TABLE ft3 ( c1 integer NOT NULL, @@ -666,9 +668,9 @@ CREATE FOREIGN TABLE ft3 ( c3 date ) INHERITS(ft2) SERVER s0; --- Deactivated for SplendidDataTest: \d+ ft2 --- Deactivated for SplendidDataTest: \d+ ct3 --- Deactivated for SplendidDataTest: \d+ ft3 +\d+ ft2 +\d+ ct3 +\d+ ft3 -- add attributes recursively ALTER TABLE fd_pt1 ADD COLUMN c4 integer; @@ -676,10 +678,10 @@ ALTER TABLE fd_pt1 ADD COLUMN c5 integer DEFAULT 0; ALTER TABLE fd_pt1 ADD COLUMN c6 integer; ALTER TABLE fd_pt1 ADD COLUMN c7 integer NOT NULL; ALTER TABLE fd_pt1 ADD COLUMN c8 integer; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 --- Deactivated for SplendidDataTest: \d+ ct3 --- Deactivated for SplendidDataTest: \d+ ft3 +\d+ fd_pt1 +\d+ ft2 +\d+ ct3 +\d+ ft3 -- alter attributes recursively ALTER TABLE fd_pt1 ALTER COLUMN c4 SET DEFAULT 0; @@ -693,8 +695,8 @@ ALTER TABLE fd_pt1 ALTER COLUMN c1 SET STATISTICS 10000; ALTER TABLE fd_pt1 ALTER COLUMN c1 SET (n_distinct = 100); ALTER TABLE fd_pt1 ALTER COLUMN c8 SET STATISTICS -1; ALTER TABLE fd_pt1 ALTER COLUMN c8 SET STORAGE EXTERNAL; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 -- drop attributes recursively ALTER TABLE fd_pt1 DROP COLUMN c4; @@ -702,8 +704,8 @@ ALTER TABLE fd_pt1 DROP COLUMN c5; ALTER TABLE fd_pt1 DROP COLUMN c6; ALTER TABLE fd_pt1 DROP COLUMN c7; ALTER TABLE fd_pt1 DROP COLUMN c8; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 -- add constraints recursively ALTER TABLE fd_pt1 ADD CONSTRAINT fd_pt1chk1 CHECK (c1 > 0) NO INHERIT; @@ -714,8 +716,8 @@ SELECT relname, conname, contype, conislocal, coninhcount, connoinherit WHERE pc.relname = 'fd_pt1' ORDER BY 1,2; -- child does not inherit NO INHERIT constraints --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 DROP FOREIGN TABLE ft2; -- ERROR DROP FOREIGN TABLE ft2 CASCADE; CREATE FOREIGN TABLE ft2 ( @@ -728,8 +730,8 @@ ALTER FOREIGN TABLE ft2 INHERIT fd_pt1; -- ERROR ALTER FOREIGN TABLE ft2 ADD CONSTRAINT fd_pt1chk2 CHECK (c2 <> ''); ALTER FOREIGN TABLE ft2 INHERIT fd_pt1; -- child does not inherit NO INHERIT constraints --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 -- drop constraints recursively ALTER TABLE fd_pt1 DROP CONSTRAINT fd_pt1chk1 CASCADE; @@ -738,12 +740,12 @@ ALTER TABLE fd_pt1 DROP CONSTRAINT fd_pt1chk2 CASCADE; -- NOT VALID case INSERT INTO fd_pt1 VALUES (1, 'fd_pt1'::text, '1994-01-01'::date); ALTER TABLE fd_pt1 ADD CONSTRAINT fd_pt1chk3 CHECK (c2 <> '') NOT VALID; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 -- VALIDATE CONSTRAINT need do nothing on foreign tables ALTER TABLE fd_pt1 VALIDATE CONSTRAINT fd_pt1chk3; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 -- changes name of an attribute recursively ALTER TABLE fd_pt1 RENAME COLUMN c1 TO f1; @@ -751,8 +753,8 @@ ALTER TABLE fd_pt1 RENAME COLUMN c2 TO f2; ALTER TABLE fd_pt1 RENAME COLUMN c3 TO f3; -- changes name of a constraint recursively ALTER TABLE fd_pt1 RENAME CONSTRAINT fd_pt1chk3 TO f2_check; --- Deactivated for SplendidDataTest: \d+ fd_pt1 --- Deactivated for SplendidDataTest: \d+ ft2 +\d+ fd_pt1 +\d+ ft2 DROP TABLE fd_pt1 CASCADE; @@ -781,8 +783,8 @@ CREATE TABLE fd_pt2 ( ) PARTITION BY LIST (c1); CREATE FOREIGN TABLE fd_pt2_1 PARTITION OF fd_pt2 FOR VALUES IN (1) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); --- Deactivated for SplendidDataTest: \d+ fd_pt2 --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2 +\d+ fd_pt2_1 -- partition cannot have additional columns DROP FOREIGN TABLE fd_pt2_1; @@ -792,21 +794,21 @@ CREATE FOREIGN TABLE fd_pt2_1 ( c3 date, c4 char ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2_1 ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); -- ERROR DROP FOREIGN TABLE fd_pt2_1; --- Deactivated for SplendidDataTest: \d+ fd_pt2 +\d+ fd_pt2 CREATE FOREIGN TABLE fd_pt2_1 ( c1 integer NOT NULL, c2 text, c3 date ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2_1 -- no attach partition validation occurs for foreign tables ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); --- Deactivated for SplendidDataTest: \d+ fd_pt2 --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2 +\d+ fd_pt2_1 -- cannot add column to a partition ALTER TABLE fd_pt2_1 ADD c4 char; @@ -814,8 +816,8 @@ ALTER TABLE fd_pt2_1 ADD c4 char; -- ok to have a partition's own constraints though ALTER TABLE fd_pt2_1 ALTER c3 SET NOT NULL; ALTER TABLE fd_pt2_1 ADD CONSTRAINT p21chk CHECK (c2 <> ''); --- Deactivated for SplendidDataTest: \d+ fd_pt2 --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2 +\d+ fd_pt2_1 -- cannot drop inherited NOT NULL constraint from a partition ALTER TABLE fd_pt2_1 ALTER c1 DROP NOT NULL; @@ -823,19 +825,20 @@ ALTER TABLE fd_pt2_1 ALTER c1 DROP NOT NULL; -- partition must have parent's constraints ALTER TABLE fd_pt2 DETACH PARTITION fd_pt2_1; ALTER TABLE fd_pt2 ALTER c2 SET NOT NULL; --- Deactivated for SplendidDataTest: \d+ fd_pt2 --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2 +\d+ fd_pt2_1 ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); -- ERROR ALTER FOREIGN TABLE fd_pt2_1 ALTER c2 SET NOT NULL; ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); ALTER TABLE fd_pt2 DETACH PARTITION fd_pt2_1; ALTER TABLE fd_pt2 ADD CONSTRAINT fd_pt2chk1 CHECK (c1 > 0); --- Deactivated for SplendidDataTest: \d+ fd_pt2 --- Deactivated for SplendidDataTest: \d+ fd_pt2_1 +\d+ fd_pt2 +\d+ fd_pt2_1 ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); -- ERROR ALTER FOREIGN TABLE fd_pt2_1 ADD CONSTRAINT fd_pt2chk1 CHECK (c1 > 0); ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); + DROP FOREIGN TABLE fd_pt2_1; DROP TABLE fd_pt2; @@ -864,7 +867,7 @@ DROP ROLE regress_unprivileged_role; DROP ROLE regress_test_role2; DROP FOREIGN DATA WRAPPER postgresql CASCADE; DROP FOREIGN DATA WRAPPER dummy CASCADE; --- Deactivated for SplendidDataTest: \c +\c DROP ROLE regress_foreign_data_user; -- At this point we should have no wrappers, no servers, and no mappings. diff --git a/parser/src/test/resources/postgres/test/regress/sql/foreign_key.sql b/parser/src/test/resources/postgres/test/regress/sql/foreign_key.sql index cdd146b..b8fcc94 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/foreign_key.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/foreign_key.sql @@ -475,13 +475,14 @@ DROP TABLE PKTABLE; CREATE TABLE PKTABLE (tid int, id int, PRIMARY KEY (tid, id)); CREATE TABLE FKTABLE (tid int, id int, foo int, FOREIGN KEY (tid, id) REFERENCES PKTABLE ON DELETE SET NULL (bar)); CREATE TABLE FKTABLE (tid int, id int, foo int, FOREIGN KEY (tid, id) REFERENCES PKTABLE ON DELETE SET NULL (foo)); -CREATE TABLE FKTABLE (tid int, id int, foo int, FOREIGN KEY (tid, foo) REFERENCES PKTABLE ON UPDATE SET NULL (foo)); +-- Deactivated for SplendidDataTest: CREATE TABLE FKTABLE (tid int, id int, foo int, FOREIGN KEY (tid, foo) REFERENCES PKTABLE ON UPDATE SET NULL (foo)); CREATE TABLE FKTABLE ( tid int, id int, fk_id_del_set_null int, fk_id_del_set_default int DEFAULT 0, FOREIGN KEY (tid, fk_id_del_set_null) REFERENCES PKTABLE ON DELETE SET NULL (fk_id_del_set_null), - FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default) + -- this tests handling of duplicate entries in SET DEFAULT column list + FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default, fk_id_del_set_default) ); SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = 'fktable'::regclass::oid ORDER BY oid; @@ -498,12 +499,13 @@ SELECT * FROM FKTABLE ORDER BY id; DROP TABLE FKTABLE; DROP TABLE PKTABLE; -CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +-- Test some invalid FK definitions +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY, someoid oid); CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE); CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2)); +CREATE TABLE FKTABLE_FAIL3 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (tableoid) REFERENCES PKTABLE(someoid)); +CREATE TABLE FKTABLE_FAIL4 ( ftest1 oid, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(tableoid)); -DROP TABLE FKTABLE_FAIL1; -DROP TABLE FKTABLE_FAIL2; DROP TABLE PKTABLE; -- Test for referencing column number smaller than referenced constraint @@ -977,8 +979,10 @@ COMMIT; -- try additional syntax ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE; --- illegal option +-- illegal options -- Deactivated for SplendidDataTest: ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; -- test order of firing of FK triggers when several RI-induced changes need to -- be made to the same row. This was broken by subtransaction-related @@ -1242,7 +1246,7 @@ UPDATE fk_notpartitioned_pk SET b = 502 WHERE a = 500; UPDATE fk_notpartitioned_pk SET b = 1502 WHERE a = 1500; UPDATE fk_notpartitioned_pk SET b = 2504 WHERE a = 2500; -- check psql behavior --- Deactivated for SplendidDataTest: \d fk_notpartitioned_pk +\d fk_notpartitioned_pk ALTER TABLE fk_partitioned_fk DROP CONSTRAINT fk_partitioned_fk_a_b_fkey; -- done. DROP TABLE fk_notpartitioned_pk, fk_partitioned_fk; @@ -1367,7 +1371,7 @@ ALTER TABLE fk_partitioned_fk DETACH PARTITION fk_partitioned_fk_2; BEGIN; DROP TABLE fk_partitioned_fk; -- constraint should still be there --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_2; +\d fk_partitioned_fk_2; ROLLBACK; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); DROP TABLE fk_partitioned_fk_2; @@ -1376,7 +1380,7 @@ CREATE TABLE fk_partitioned_fk_2 (b int, c text, a int, ALTER TABLE fk_partitioned_fk_2 DROP COLUMN c; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); -- should have only one constraint --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_2 +\d fk_partitioned_fk_2 DROP TABLE fk_partitioned_fk_2; CREATE TABLE fk_partitioned_fk_4 (a int, b int, FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE) PARTITION BY RANGE (b, a); @@ -1387,10 +1391,10 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_4 FOR VALUES IN ALTER TABLE fk_partitioned_fk DETACH PARTITION fk_partitioned_fk_4; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_4 FOR VALUES IN (3500,3502); -- should only have one constraint --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_4 --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_4_1 +\d fk_partitioned_fk_4 +\d fk_partitioned_fk_4_1 -- this one has an FK with mismatched properties --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_4_2 +\d fk_partitioned_fk_4_2 CREATE TABLE fk_partitioned_fk_5 (a int, b int, FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE, @@ -1403,12 +1407,12 @@ ALTER TABLE fk_partitioned_fk DETACH PARTITION fk_partitioned_fk_5; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_5 FOR VALUES IN (4500); -- this one has two constraints, similar but not quite the one in the parent, -- so it gets a new one --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_5 +\d fk_partitioned_fk_5 -- verify that it works to reattaching a child with multiple candidate -- constraints ALTER TABLE fk_partitioned_fk_5 DETACH PARTITION fk_partitioned_fk_5_1; ALTER TABLE fk_partitioned_fk_5 ATTACH PARTITION fk_partitioned_fk_5_1 FOR VALUES FROM (0) TO (10); --- Deactivated for SplendidDataTest: \d fk_partitioned_fk_5_1 +\d fk_partitioned_fk_5_1 -- verify that attaching a table checks that the existing data satisfies the -- constraint @@ -1424,6 +1428,23 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 -- leave these tables around intentionally +-- Verify that attaching a table that's referenced by an existing FK +-- in the parent throws an error +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; + +-- This case is similar to above, but the referenced relation is one level +-- lower in the hierarchy. This one fails in a different way as the above, +-- because we don't bother to protect against this case explicitly. If the +-- current error stops happening, we'll need to add a better protection. +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY) PARTITION BY list (a); +CREATE TABLE fk_partitioned_pk_61 PARTITION OF fk_partitioned_pk_6 FOR VALUES IN (1); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_61) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; + -- test the case when the referenced table is owned by a different user create role regress_other_partitioned_fk_owner; grant references on fk_notpartitioned_pk to regress_other_partitioned_fk_owner; @@ -1449,6 +1470,84 @@ reset role; revoke all on fk_notpartitioned_pk from regress_other_partitioned_fk_owner; drop role regress_other_partitioned_fk_owner; +-- +-- Test self-referencing foreign key with partition. +-- This should create only one fk constraint per partition +-- +CREATE TABLE parted_self_fk ( + id bigint NOT NULL PRIMARY KEY, + id_abc bigint, + FOREIGN KEY (id_abc) REFERENCES parted_self_fk(id) +) +PARTITION BY RANGE (id); +CREATE TABLE part1_self_fk ( + id bigint NOT NULL PRIMARY KEY, + id_abc bigint +); +ALTER TABLE parted_self_fk ATTACH PARTITION part1_self_fk FOR VALUES FROM (0) TO (10); +CREATE TABLE part2_self_fk PARTITION OF parted_self_fk FOR VALUES FROM (10) TO (20); +CREATE TABLE part3_self_fk ( -- a partitioned partition + id bigint NOT NULL PRIMARY KEY, + id_abc bigint +) PARTITION BY RANGE (id); +CREATE TABLE part32_self_fk PARTITION OF part3_self_fk FOR VALUES FROM (20) TO (30); +ALTER TABLE parted_self_fk ATTACH PARTITION part3_self_fk FOR VALUES FROM (20) TO (40); +CREATE TABLE part33_self_fk ( + id bigint NOT NULL PRIMARY KEY, + id_abc bigint +); +ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); + +-- verify that this constraint works +INSERT INTO parted_self_fk VALUES (1, NULL), (2, NULL), (3, NULL); +INSERT INTO parted_self_fk VALUES (10, 1), (11, 2), (12, 3) RETURNING tableoid::regclass; + +INSERT INTO parted_self_fk VALUES (4, 5); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 1 RETURNING *; -- error: reference remains + +SELECT cr.relname, co.conname, co.convalidated, + p.conname AS conparent, p.convalidated, cf.relname AS foreignrel +FROM pg_constraint co +JOIN pg_class cr ON cr.oid = co.conrelid +LEFT JOIN pg_class cf ON cf.oid = co.confrelid +LEFT JOIN pg_constraint p ON p.oid = co.conparentid +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; + +-- detach and re-attach multiple times just to ensure everything is kosher +ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; + +INSERT INTO part2_self_fk VALUES (16, 9); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 2 RETURNING *; -- error: reference remains + +ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); + +INSERT INTO parted_self_fk VALUES (16, 9); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 3 RETURNING *; -- error: reference remains + +ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; +ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); + +ALTER TABLE parted_self_fk DETACH PARTITION part3_self_fk; +ALTER TABLE parted_self_fk ATTACH PARTITION part3_self_fk FOR VALUES FROM (30) TO (40); + +ALTER TABLE part3_self_fk DETACH PARTITION part33_self_fk; +ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); + +SELECT cr.relname, co.conname, co.convalidated, + p.conname AS conparent, p.convalidated, cf.relname AS foreignrel +FROM pg_constraint co +JOIN pg_class cr ON cr.oid = co.conrelid +LEFT JOIN pg_class cf ON cf.oid = co.confrelid +LEFT JOIN pg_constraint p ON p.oid = co.conparentid +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; + +-- Leave this table around, for pg_upgrade/pg_dump tests + + -- Test creating a constraint at the parent that already exists in partitions. -- There should be no duplicated constraints, and attempts to drop the -- constraint in partitions should raise appropriate errors. @@ -1463,23 +1562,23 @@ create schema fkpart0 create table fk_part_23_2 partition of fk_part_23 for values in (2); alter table fkpart0.fk_part add foreign key (a) references fkpart0.pkey; --- Deactivated for SplendidDataTest: \d fkpart0.fk_part_1 \\ -- should have only one FK +\d fkpart0.fk_part_1 \\ -- should have only one FK alter table fkpart0.fk_part_1 drop constraint fk_part_1_a_fkey; --- Deactivated for SplendidDataTest: \d fkpart0.fk_part_23 \\ -- should have only one FK --- Deactivated for SplendidDataTest: \d fkpart0.fk_part_23_2 \\ -- should have only one FK +\d fkpart0.fk_part_23 \\ -- should have only one FK +\d fkpart0.fk_part_23_2 \\ -- should have only one FK alter table fkpart0.fk_part_23 drop constraint fk_part_23_a_fkey; alter table fkpart0.fk_part_23_2 drop constraint fk_part_23_a_fkey; create table fkpart0.fk_part_4 partition of fkpart0.fk_part for values in (4); --- Deactivated for SplendidDataTest: \d fkpart0.fk_part_4 +\d fkpart0.fk_part_4 alter table fkpart0.fk_part_4 drop constraint fk_part_a_fkey; create table fkpart0.fk_part_56 partition of fkpart0.fk_part for values in (5,6) partition by list (a); create table fkpart0.fk_part_56_5 partition of fkpart0.fk_part_56 for values in (5); --- Deactivated for SplendidDataTest: \d fkpart0.fk_part_56 +\d fkpart0.fk_part_56 alter table fkpart0.fk_part_56 drop constraint fk_part_a_fkey; alter table fkpart0.fk_part_56_5 drop constraint fk_part_a_fkey; @@ -1607,6 +1706,14 @@ DELETE FROM pk WHERE a = 4002; UPDATE pk SET a = 4502 WHERE a = 4500; DELETE FROM pk WHERE a = 4502; +-- Also, detaching a partition that has the FK itself should work +-- https://postgr.es/m/CAAJ_b97GuPh6wQPbxQS-Zpy16Oh+0aMv-w64QcGrLhCOZZ6p+g@mail.gmail.com +CREATE TABLE ffk (a int, b int REFERENCES pk) PARTITION BY list (a); +CREATE TABLE ffk1 PARTITION OF ffk FOR VALUES IN (1); +ALTER TABLE ffk1 ADD FOREIGN KEY (a) REFERENCES pk; +ALTER TABLE ffk DETACH PARTITION ffk1; +DROP TABLE ffk, ffk1; + CREATE SCHEMA fkpart4; SET search_path TO fkpart4; -- dropping/detaching PARTITIONs is prevented if that would break @@ -1750,7 +1857,7 @@ DELETE FROM pt; DELETE FROM ref; ABORT; DROP TABLE pt, ref; --- Multi-level partitioning at referenced end +-- Multi-level partitioning at at referenced end CREATE TABLE pt(f1 int, f2 int, f3 int, PRIMARY KEY(f1,f2)) PARTITION BY LIST(f1); CREATE TABLE pt1_2 PARTITION OF pt FOR VALUES IN (1, 2) PARTITION BY LIST (f1); @@ -2021,3 +2128,112 @@ UPDATE fkpart11.pk SET a = 3 WHERE a = 4; UPDATE fkpart11.pk SET a = 1 WHERE a = 2; DROP SCHEMA fkpart11 CASCADE; + +-- When a table is attached as partition to a partitioned table that has +-- a foreign key to another partitioned table, it acquires a clone of the +-- FK. Upon detach, this clone is not removed, but instead becomes an +-- independent FK. If it then attaches to the partitioned table again, +-- the FK from the parent "takes over" ownership of the independent FK rather +-- than creating a separate one. +CREATE SCHEMA fkpart12 + CREATE TABLE fk_p ( id int, jd int, PRIMARY KEY(id, jd)) PARTITION BY list (id) + CREATE TABLE fk_p_1 PARTITION OF fk_p FOR VALUES IN (1) PARTITION BY list (jd) + CREATE TABLE fk_p_1_1 PARTITION OF fk_p_1 FOR VALUES IN (1) + CREATE TABLE fk_p_1_2 (x int, y int, jd int NOT NULL, id int NOT NULL) + CREATE TABLE fk_p_2 PARTITION OF fk_p FOR VALUES IN (2) PARTITION BY list (jd) + CREATE TABLE fk_p_2_1 PARTITION OF fk_p_2 FOR VALUES IN (1) + CREATE TABLE fk_p_2_2 PARTITION OF fk_p_2 FOR VALUES IN (2) + CREATE TABLE fk_r_1 ( p_jd int NOT NULL, x int, id int PRIMARY KEY, p_id int NOT NULL) + CREATE TABLE fk_r_2 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL) PARTITION BY list (id) + CREATE TABLE fk_r_2_1 PARTITION OF fk_r_2 FOR VALUES IN (2, 1) + CREATE TABLE fk_r ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL, + FOREIGN KEY (p_id, p_jd) REFERENCES fk_p (id, jd) + ) PARTITION BY list (id); +SET search_path TO fkpart12; + +ALTER TABLE fk_p_1_2 DROP COLUMN x, DROP COLUMN y; +ALTER TABLE fk_p_1 ATTACH PARTITION fk_p_1_2 FOR VALUES IN (2); +ALTER TABLE fk_r_1 DROP COLUMN x; + +INSERT INTO fk_p VALUES (1, 1); + +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); + +\d fk_r_2 + +INSERT INTO fk_r VALUES (1, 1, 1); +INSERT INTO fk_r VALUES (2, 2, 1); + +ALTER TABLE fk_r DETACH PARTITION fk_r_1; +ALTER TABLE fk_r DETACH PARTITION fk_r_2; + +\d fk_r_2 + +INSERT INTO fk_r_1 (id, p_id, p_jd) VALUES (2, 1, 2); -- should fail +DELETE FROM fk_p; -- should fail + +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); + +\d fk_r_2 + +DELETE FROM fk_p; -- should fail + +-- these should all fail +ALTER TABLE fk_r_1 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; +ALTER TABLE fk_r DROP CONSTRAINT fk_r_p_id_p_jd_fkey1; +ALTER TABLE fk_r_2 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; + +SET client_min_messages TO warning; +DROP SCHEMA fkpart12 CASCADE; +RESET client_min_messages; +RESET search_path; + +-- Exercise the column mapping code with foreign keys. In this test we'll +-- create a partitioned table which has a partition with a dropped column and +-- check to ensure that an UPDATE cascades the changes correctly to the +-- partitioned table. +CREATE SCHEMA fkpart13; +SET search_path TO fkpart13; + +CREATE TABLE fkpart13_t1 (a int PRIMARY KEY); + +CREATE TABLE fkpart13_t2 ( + part_id int PRIMARY KEY, + column_to_drop int, + FOREIGN KEY (part_id) REFERENCES fkpart13_t1 ON UPDATE CASCADE ON DELETE CASCADE +) PARTITION BY LIST (part_id); + +CREATE TABLE fkpart13_t2_p1 PARTITION OF fkpart13_t2 FOR VALUES IN (1); + +-- drop the column +ALTER TABLE fkpart13_t2 DROP COLUMN column_to_drop; + +-- create a new partition without the dropped column +CREATE TABLE fkpart13_t2_p2 PARTITION OF fkpart13_t2 FOR VALUES IN (2); + +CREATE TABLE fkpart13_t3 ( + a int NOT NULL, + FOREIGN KEY (a) + REFERENCES fkpart13_t2 + ON UPDATE CASCADE ON DELETE CASCADE +); + +INSERT INTO fkpart13_t1 (a) VALUES (1); +INSERT INTO fkpart13_t2 (part_id) VALUES (1); +INSERT INTO fkpart13_t3 (a) VALUES (1); + +-- Test a cascading update works correctly with with the dropped column +UPDATE fkpart13_t1 SET a = 2 WHERE a = 1; +SELECT tableoid::regclass,* FROM fkpart13_t2; +SELECT tableoid::regclass,* FROM fkpart13_t3; + +-- Exercise code in ExecGetTriggerResultRel() as there's been previous issues +-- with ResultRelInfos being returned with the incorrect ri_RootResultRelInfo +WITH cte AS ( + UPDATE fkpart13_t2_p1 SET part_id = part_id +) UPDATE fkpart13_t1 SET a = 2 WHERE a = 1; + +DROP SCHEMA fkpart13 CASCADE; +RESET search_path; diff --git a/parser/src/test/resources/postgres/test/regress/sql/generated.sql b/parser/src/test/resources/postgres/test/regress/sql/generated.sql index 372a50f..442c8ac 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/generated.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/generated.sql @@ -17,7 +17,7 @@ SELECT table_name, column_name, column_default, is_nullable, is_generated, gener SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage ORDER BY 1, 2, 3; --- Deactivated for SplendidDataTest: \d gtest1 +\d gtest1 -- duplicate generated CREATE TABLE gtest_err_1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED GENERATED ALWAYS AS (a * 3) STORED); @@ -34,6 +34,9 @@ CREATE TABLE gtest_err_3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) S -- generation expression must be immutable CREATE TABLE gtest_err_4 (a int PRIMARY KEY, b double precision GENERATED ALWAYS AS (random()) STORED); +-- ... but be sure that the immutability test is accurate +CREATE TABLE gtest2 (a int, b text GENERATED ALWAYS AS (a || ' sec') STORED); +DROP TABLE gtest2; -- cannot have default/identity and generated CREATE TABLE gtest_err_5a (a int PRIMARY KEY, b int DEFAULT 5 GENERATED ALWAYS AS (a * 2) STORED); @@ -89,6 +92,21 @@ SELECT * FROM gtest1 ORDER BY a; DELETE FROM gtest1 WHERE b = 2; SELECT * FROM gtest1 ORDER BY a; +-- test MERGE +CREATE TABLE gtestm ( + id int PRIMARY KEY, + f1 int, + f2 int, + f3 int GENERATED ALWAYS AS (f1 * 2) STORED, + f4 int GENERATED ALWAYS AS (f2 * 2) STORED +); +INSERT INTO gtestm VALUES (1, 5, 100); +MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id + WHEN MATCHED THEN UPDATE SET f1 = v.f1 + WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200); +SELECT * FROM gtestm ORDER BY id; +DROP TABLE gtestm; + -- views CREATE VIEW gtest1v AS SELECT * FROM gtest1; SELECT * FROM gtest1v; @@ -113,14 +131,14 @@ WITH foo AS (SELECT * FROM gtest1) SELECT * FROM foo; -- inheritance CREATE TABLE gtest1_1 () INHERITS (gtest1); SELECT * FROM gtest1_1; --- Deactivated for SplendidDataTest: \d gtest1_1 +\d gtest1_1 INSERT INTO gtest1_1 VALUES (4); SELECT * FROM gtest1_1; SELECT * FROM gtest1; CREATE TABLE gtest_normal (a int, b int); CREATE TABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) STORED) INHERITS (gtest_normal); --- Deactivated for SplendidDataTest: \d gtest_normal_child +\d gtest_normal_child INSERT INTO gtest_normal (a) VALUES (1); INSERT INTO gtest_normal_child (a) VALUES (2); SELECT * FROM gtest_normal; @@ -157,6 +175,15 @@ CREATE TABLE gtesty (x int, b int DEFAULT 55); CREATE TABLE gtest1_2 () INHERITS (gtest0, gtesty); -- error DROP TABLE gtesty; +-- test correct handling of GENERATED column that's only in child +CREATE TABLE gtestp (f1 int); +CREATE TABLE gtestc (f2 int GENERATED ALWAYS AS (f1+1) STORED) INHERITS(gtestp); +INSERT INTO gtestc values(42); +TABLE gtestc; +UPDATE gtestp SET f1 = f1 * 10; +TABLE gtestc; +DROP TABLE gtestp CASCADE; + -- test stored update CREATE TABLE gtest3 (a int, b int GENERATED ALWAYS AS (a * 3) STORED); INSERT INTO gtest3 (a) VALUES (1), (2), (3), (NULL); @@ -181,10 +208,14 @@ COPY gtest1 (a, b) TO stdout; COPY gtest1 FROM stdin; -- Deactivated for SplendidDataTest: 3 -- Deactivated for SplendidDataTest: 4 --- Deactivated for SplendidDataTest: \. +\. COPY gtest1 (a, b) FROM stdin; +COPY gtest1 FROM stdin WHERE b <> 10; + +COPY gtest1 FROM stdin WHERE gtest1 IS NULL; + SELECT * FROM gtest1 ORDER BY a; TRUNCATE gtest3; @@ -197,7 +228,7 @@ COPY gtest3 (a, b) TO stdout; COPY gtest3 FROM stdin; -- Deactivated for SplendidDataTest: 3 -- Deactivated for SplendidDataTest: 4 --- Deactivated for SplendidDataTest: \. +\. COPY gtest3 (a, b) FROM stdin; @@ -242,7 +273,7 @@ CREATE TABLE gtest10 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2 ALTER TABLE gtest10 DROP COLUMN b; -- fails ALTER TABLE gtest10 DROP COLUMN b CASCADE; -- drops c too --- Deactivated for SplendidDataTest: \d gtest10 +\d gtest10 CREATE TABLE gtest10a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED); ALTER TABLE gtest10a DROP COLUMN b; @@ -316,7 +347,7 @@ CREATE TABLE gtest22c (a int, b int GENERATED ALWAYS AS (a * 2) STORED); CREATE INDEX gtest22c_b_idx ON gtest22c (b); CREATE INDEX gtest22c_expr_idx ON gtest22c ((b * 3)); CREATE INDEX gtest22c_pred_idx ON gtest22c (a) WHERE b > 0; --- Deactivated for SplendidDataTest: \d gtest22c +\d gtest22c INSERT INTO gtest22c VALUES (1), (2), (3); SET enable_seqscan TO off; @@ -338,7 +369,7 @@ CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x) ON DELETE SET NULL); -- error CREATE TABLE gtest23b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x)); --- Deactivated for SplendidDataTest: \d gtest23b +\d gtest23b INSERT INTO gtest23b VALUES (1); -- ok INSERT INTO gtest23b VALUES (5); -- error @@ -359,6 +390,11 @@ CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * INSERT INTO gtest24 (a) VALUES (4); -- ok INSERT INTO gtest24 (a) VALUES (6); -- error +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) STORED); +INSERT INTO gtest24nn (a) VALUES (4); -- ok +INSERT INTO gtest24nn (a) VALUES (NULL); -- error + -- typed tables (currently not supported) CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); CREATE TABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) STORED); @@ -374,14 +410,21 @@ DROP TABLE gtest_parent; -- partitioned table CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE (f1); CREATE TABLE gtest_child PARTITION OF gtest_parent FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 1); SELECT * FROM gtest_parent; SELECT * FROM gtest_child; +UPDATE gtest_parent SET f1 = f1 + 60, f2 = f2 + 1; +SELECT * FROM gtest_parent; +SELECT * FROM gtest_child3; DROP TABLE gtest_parent; -- generated columns in partition key (not allowed) CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE (f3); +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((f3)); CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((f3 * 3)); +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((gtest_parent)); +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((gtest_parent is not null)); -- ALTER TABLE ... ADD COLUMN CREATE TABLE gtest25 (a int PRIMARY KEY); @@ -396,7 +439,7 @@ ALTER TABLE gtest25 ADD COLUMN d int DEFAULT 101; ALTER TABLE gtest25 ALTER COLUMN d SET DATA TYPE float8, ADD COLUMN y float8 GENERATED ALWAYS AS (d * 4) STORED; SELECT * FROM gtest25 ORDER BY a; --- Deactivated for SplendidDataTest: \d gtest25 +\d gtest25 -- ALTER TABLE ... ALTER COLUMN CREATE TABLE gtest27 ( @@ -407,7 +450,7 @@ CREATE TABLE gtest27 ( INSERT INTO gtest27 (a, b) VALUES (3, 7), (4, 11); ALTER TABLE gtest27 ALTER COLUMN a TYPE text; -- error ALTER TABLE gtest27 ALTER COLUMN x TYPE numeric; --- Deactivated for SplendidDataTest: \d gtest27 +\d gtest27 SELECT * FROM gtest27; ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0; -- error ALTER TABLE gtest27 ALTER COLUMN x DROP DEFAULT; -- error @@ -417,12 +460,12 @@ ALTER TABLE gtest27 ALTER COLUMN a TYPE bigint, ALTER COLUMN b TYPE bigint, ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) STORED; --- Deactivated for SplendidDataTest: \d gtest27 +\d gtest27 -- Ideally you could just do this, but not today (and should x change type?): ALTER TABLE gtest27 ALTER COLUMN a TYPE float8, ALTER COLUMN b TYPE float8; -- error --- Deactivated for SplendidDataTest: \d gtest27 +\d gtest27 SELECT * FROM gtest27; -- ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION @@ -437,11 +480,11 @@ ALTER TABLE gtest29 ALTER COLUMN b DROP EXPRESSION; INSERT INTO gtest29 (a) VALUES (5); INSERT INTO gtest29 (a, b) VALUES (6, 66); SELECT * FROM gtest29; --- Deactivated for SplendidDataTest: \d gtest29 +\d gtest29 -- check that dependencies between columns have also been removed ALTER TABLE gtest29 DROP COLUMN a; -- should not drop b --- Deactivated for SplendidDataTest: \d gtest29 +\d gtest29 -- with inheritance CREATE TABLE gtest30 ( @@ -450,8 +493,8 @@ CREATE TABLE gtest30 ( ); CREATE TABLE gtest30_1 () INHERITS (gtest30); ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION; --- Deactivated for SplendidDataTest: \d gtest30 --- Deactivated for SplendidDataTest: \d gtest30_1 +\d gtest30 +\d gtest30_1 DROP TABLE gtest30 CASCADE; CREATE TABLE gtest30 ( a int, @@ -459,8 +502,8 @@ CREATE TABLE gtest30 ( ); CREATE TABLE gtest30_1 () INHERITS (gtest30); ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error --- Deactivated for SplendidDataTest: \d gtest30 --- Deactivated for SplendidDataTest: \d gtest30_1 +\d gtest30 +\d gtest30_1 ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error -- triggers @@ -588,4 +631,4 @@ ALTER TABLE gtest28a DROP COLUMN a; CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); --- Deactivated for SplendidDataTest: \d gtest28* +\d gtest28* diff --git a/parser/src/test/resources/postgres/test/regress/sql/guc.sql b/parser/src/test/resources/postgres/test/regress/sql/guc.sql index 8c56f76..b87824a 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/guc.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/guc.sql @@ -333,9 +333,7 @@ SELECT pg_settings_get_flags(NULL); SELECT pg_settings_get_flags('does_not_exist'); CREATE TABLE tab_settings_flags AS SELECT name, category, 'EXPLAIN' = ANY(flags) AS explain, - 'NO_RESET' = ANY(flags) AS no_reset, 'NO_RESET_ALL' = ANY(flags) AS no_reset_all, - 'NO_SHOW_ALL' = ANY(flags) AS no_show_all, 'NOT_IN_SAMPLE' = ANY(flags) AS not_in_sample, 'RUNTIME_COMPUTED' = ANY(flags) AS runtime_computed FROM pg_show_all_settings() AS psas, @@ -358,20 +356,4 @@ SELECT name FROM tab_settings_flags SELECT name FROM tab_settings_flags WHERE category = 'Preset Options' AND NOT not_in_sample ORDER BY 1; --- NO_SHOW_ALL implies NO_RESET_ALL, and vice-versa. -SELECT name FROM tab_settings_flags - WHERE no_show_all AND NOT no_reset_all - ORDER BY 1; --- Exceptions are transaction_*. -SELECT name FROM tab_settings_flags - WHERE NOT no_show_all AND no_reset_all - ORDER BY 1; --- NO_SHOW_ALL implies NOT_IN_SAMPLE. -SELECT name FROM tab_settings_flags - WHERE no_show_all AND NOT not_in_sample - ORDER BY 1; --- NO_RESET implies NO_RESET_ALL. -SELECT name FROM tab_settings_flags - WHERE no_reset AND NOT no_reset_all - ORDER BY 1; DROP TABLE tab_settings_flags; diff --git a/parser/src/test/resources/postgres/test/regress/sql/horology.sql b/parser/src/test/resources/postgres/test/regress/sql/horology.sql index 2724a2b..e2e151d 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/horology.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/horology.sql @@ -1,9 +1,9 @@ -- -- HOROLOGY -- -SET DateStyle = 'Postgres, MDY'; -SHOW TimeZone; -- Many of these tests depend on the prevailing setting +SHOW TimeZone; -- Many of these tests depend on the prevailing settings +SHOW DateStyle; -- -- Test various input formats @@ -86,6 +86,8 @@ SELECT timestamp without time zone '1999-12-01' + interval '1 month - 1 second' SELECT timestamp without time zone 'Jan 1, 4713 BC' + interval '106000000 days' AS "Feb 23, 285506"; SELECT timestamp without time zone 'Jan 1, 4713 BC' + interval '107000000 days' AS "Jan 20, 288244"; SELECT timestamp without time zone 'Jan 1, 4713 BC' + interval '109203489 days' AS "Dec 31, 294276"; +SELECT timestamp without time zone '2000-01-01' - interval '2483590 days' AS "out of range"; +SELECT timestamp without time zone '294276-12-31 23:59:59' + interval '9223372036854775807 microseconds' AS "out of range"; SELECT timestamp without time zone '12/31/294276' - timestamp without time zone '12/23/1999' AS "106751991 Days"; -- Shorthand values @@ -117,6 +119,8 @@ SELECT timestamp with time zone '1996-03-01' - interval '1 second' AS "Feb 29"; SELECT timestamp with time zone '1999-03-01' - interval '1 second' AS "Feb 28"; SELECT timestamp with time zone '2000-03-01' - interval '1 second' AS "Feb 29"; SELECT timestamp with time zone '1999-12-01' + interval '1 month - 1 second' AS "Dec 31"; +SELECT timestamp with time zone '2000-01-01' - interval '2483590 days' AS "out of range"; +SELECT timestamp with time zone '294276-12-31 23:59:59 UTC' + interval '9223372036854775807 microseconds' AS "out of range"; SELECT (timestamp with time zone 'today' = (timestamp with time zone 'yesterday' + interval '1 day')) as "True"; SELECT (timestamp with time zone 'today' = (timestamp with time zone 'tomorrow' - interval '1 day')) as "True"; @@ -476,6 +480,7 @@ SELECT i, to_timestamp('2018-11-02 12:34:56.1234', 'YYYY-MM-DD HH24:MI:SS.FF' || SELECT i, to_timestamp('2018-11-02 12:34:56.12345', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; +SELECT i, to_timestamp('20181102123456123456', 'YYYYMMDDHH24MISSFF' || i) FROM generate_series(1, 6) i; SELECT to_date('1 4 1902', 'Q MM YYYY'); -- Q is ignored SELECT to_date('3 4 21 01', 'W MM CC YY'); diff --git a/parser/src/test/resources/postgres/test/regress/sql/identity.sql b/parser/src/test/resources/postgres/test/regress/sql/identity.sql index 673736a..beeb592 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/identity.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/identity.sql @@ -23,7 +23,7 @@ SELECT sequence_name FROM information_schema.sequences WHERE sequence_name LIKE SELECT pg_get_serial_sequence('itest1', 'a'); --- Deactivated for SplendidDataTest: \d itest1_a_seq +\d itest1_a_seq CREATE TABLE itest4 (a int, b text); ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- error, requires NOT NULL @@ -142,12 +142,12 @@ CREATE TABLE itest9 (a int GENERATED ALWAYS AS IDENTITY, b text, c bigint); COPY itest9 FROM stdin; -- Deactivated for SplendidDataTest: 100 foo 200 -- Deactivated for SplendidDataTest: 101 bar 201 --- Deactivated for SplendidDataTest: \. +\. COPY itest9 (b, c) FROM stdin; -- Deactivated for SplendidDataTest: foo2 202 -- Deactivated for SplendidDataTest: bar2 203 --- Deactivated for SplendidDataTest: \. +\. SELECT * FROM itest9 ORDER BY c; @@ -219,15 +219,33 @@ ALTER TABLE itest5 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; ALTER TABLE itest3 ALTER COLUMN a TYPE int; SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regclass; --- Deactivated for SplendidDataTest: \d itest3 +\d itest3 ALTER TABLE itest3 ALTER COLUMN a TYPE text; -- error +-- check that unlogged propagates to sequence +CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text); +ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; +ALTER TABLE itest17 ADD COLUMN c int GENERATED ALWAYS AS IDENTITY; +\d itest17 +\d itest17_a_seq +\d itest17_c_seq +CREATE TABLE itest18 (a int NOT NULL, b text); +ALTER TABLE itest18 SET UNLOGGED, ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; +\d itest18 +\d itest18_a_seq +ALTER TABLE itest18 SET LOGGED; +\d itest18 +\d itest18_a_seq +ALTER TABLE itest18 SET UNLOGGED; +\d itest18 +\d itest18_a_seq + -- kinda silly to change property in the same command, but it should work ALTER TABLE itest3 ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY, ALTER COLUMN c SET GENERATED ALWAYS; --- Deactivated for SplendidDataTest: \d itest3 +\d itest3 -- ALTER COLUMN ... SET @@ -325,11 +343,11 @@ ALTER TABLE itest8 ALTER COLUMN f22 ADD GENERATED ALWAYS AS IDENTITY; TABLE itest8; --- Deactivated for SplendidDataTest: \d+ itest8 --- Deactivated for SplendidDataTest: \d itest8_f2_seq --- Deactivated for SplendidDataTest: \d itest8_f3_seq --- Deactivated for SplendidDataTest: \d itest8_f4_seq --- Deactivated for SplendidDataTest: \d itest8_f5_seq +\d+ itest8 +\d itest8_f2_seq +\d itest8_f3_seq +\d itest8_f4_seq +\d itest8_f5_seq DROP TABLE itest8; @@ -410,3 +428,12 @@ SELECT * FROM itest15; SELECT * FROM itest16; DROP TABLE itest15; DROP TABLE itest16; + +-- For testing of pg_dump and pg_upgrade, leave behind some identity +-- sequences whose logged-ness doesn't match their owning table's. +CREATE TABLE identity_dump_logged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_logged_a_seq SET UNLOGGED; +CREATE UNLOGGED TABLE identity_dump_unlogged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_unlogged_a_seq SET LOGGED; +SELECT relname, relpersistence FROM pg_class + WHERE relname ~ '^identity_dump_' ORDER BY 1; diff --git a/parser/src/test/resources/postgres/test/regress/sql/index_including.sql b/parser/src/test/resources/postgres/test/regress/sql/index_including.sql index 44b3400..ad9cbdd 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/index_including.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/index_including.sql @@ -217,3 +217,22 @@ ALTER TABLE tbl ALTER c1 TYPE bigint; ALTER TABLE tbl ALTER c3 TYPE bigint; \d tbl DROP TABLE tbl; + +/* + * 10. Test coverage for names stored as cstrings in indexes + */ +CREATE TABLE nametbl (c1 int, c2 name, c3 float); +CREATE INDEX nametbl_c1_c2_idx ON nametbl (c2, c1) INCLUDE (c3); +INSERT INTO nametbl VALUES(1, 'two', 3.0); +VACUUM nametbl; +SET enable_seqscan = 0; + +-- Ensure we get an index only scan plan +EXPLAIN (COSTS OFF) SELECT c2, c1, c3 FROM nametbl WHERE c2 = 'two' AND c1 = 1; + +-- Validate the results look sane +SELECT c2, c1, c3 FROM nametbl WHERE c2 = 'two' AND c1 = 1; + +RESET enable_seqscan; + +DROP TABLE nametbl; \ No newline at end of file diff --git a/parser/src/test/resources/postgres/test/regress/sql/indexing.sql b/parser/src/test/resources/postgres/test/regress/sql/indexing.sql index 429120e..a48a317 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/indexing.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/indexing.sql @@ -668,6 +668,26 @@ insert into idxpart values (857142, 'six'); select tableoid::regclass, * from idxpart order by a; drop table idxpart; +-- Test some other non-btree index types +create table idxpart (a int, b text, c int[]) partition by range (a); +create table idxpart1 partition of idxpart for values from (0) to (100000); +set enable_seqscan to off; + +create index idxpart_brin on idxpart using brin(b); +explain (costs off) select * from idxpart where b = 'abcd'; +drop index idxpart_brin; + +create index idxpart_spgist on idxpart using spgist(b); +explain (costs off) select * from idxpart where b = 'abcd'; +drop index idxpart_spgist; + +create index idxpart_gin on idxpart using gin(c); +explain (costs off) select * from idxpart where c @> array[42]; +drop index idxpart_gin; + +reset enable_seqscan; +drop table idxpart; + -- intentionally leave some objects around create table idxpart (a int) partition by range (a); create table idxpart1 partition of idxpart for values from (0) to (100); @@ -760,3 +780,94 @@ alter table parted_index_col_drop drop column c; \d parted_index_col_drop2 \d parted_index_col_drop11 drop table parted_index_col_drop; + +-- Check that invalid indexes are not selected when attaching a partition. +create table parted_inval_tab (a int) partition by range (a); +create index parted_inval_idx on parted_inval_tab (a); +create table parted_inval_tab_1 (a int) partition by range (a); +create table parted_inval_tab_1_1 partition of parted_inval_tab_1 + for values from (0) to (10); +create table parted_inval_tab_1_2 partition of parted_inval_tab_1 + for values from (10) to (20); +-- this creates an invalid index. +create index parted_inval_ixd_1 on only parted_inval_tab_1 (a); +-- this creates new indexes for all the partitions of parted_inval_tab_1, +-- discarding the invalid index created previously as what is chosen. +alter table parted_inval_tab attach partition parted_inval_tab_1 + for values from (1) to (100); +select indexrelid::regclass, indisvalid, + indrelid::regclass, inhparent::regclass + from pg_index idx left join + pg_inherits inh on (idx.indexrelid = inh.inhrelid) + where indexrelid::regclass::text like 'parted_inval%' + order by indexrelid::regclass::text collate "C"; +drop table parted_inval_tab; + +-- Check setup of indisvalid across a complex partition tree on index +-- creation. If one index in a partition index is invalid, so should its +-- partitioned index. +create table parted_isvalid_tab (a int, b int) partition by range (a); +create table parted_isvalid_tab_1 partition of parted_isvalid_tab + for values from (1) to (10) partition by range (a); +create table parted_isvalid_tab_2 partition of parted_isvalid_tab + for values from (10) to (20) partition by range (a); +create table parted_isvalid_tab_11 partition of parted_isvalid_tab_1 + for values from (1) to (5); +create table parted_isvalid_tab_12 partition of parted_isvalid_tab_1 + for values from (5) to (10); +-- create an invalid index on one of the partitions. +insert into parted_isvalid_tab_11 values (1, 0); +create index concurrently parted_isvalid_idx_11 on parted_isvalid_tab_11 ((a/b)); +-- The previous invalid index is selected, invalidating all the indexes up to +-- the top-most parent. +create index parted_isvalid_idx on parted_isvalid_tab ((a/b)); +select indexrelid::regclass, indisvalid, + indrelid::regclass, inhparent::regclass + from pg_index idx left join + pg_inherits inh on (idx.indexrelid = inh.inhrelid) + where indexrelid::regclass::text like 'parted_isvalid%' + order by indexrelid::regclass::text collate "C"; +drop table parted_isvalid_tab; + +-- Check state of replica indexes when attaching a partition. +begin; +create table parted_replica_tab (id int not null) partition by range (id); +create table parted_replica_tab_1 partition of parted_replica_tab + for values from (1) to (10) partition by range (id); +create table parted_replica_tab_11 partition of parted_replica_tab_1 + for values from (1) to (5); +create unique index parted_replica_idx + on only parted_replica_tab using btree (id); +create unique index parted_replica_idx_1 + on only parted_replica_tab_1 using btree (id); +-- This triggers an update of pg_index.indisreplident for parted_replica_idx. +alter table only parted_replica_tab_1 replica identity + using index parted_replica_idx_1; +create unique index parted_replica_idx_11 on parted_replica_tab_11 USING btree (id); +select indexrelid::regclass, indisvalid, indisreplident, + indrelid::regclass, inhparent::regclass + from pg_index idx left join + pg_inherits inh on (idx.indexrelid = inh.inhrelid) + where indexrelid::regclass::text like 'parted_replica%' + order by indexrelid::regclass::text collate "C"; +-- parted_replica_idx is not valid yet here, because parted_replica_idx_1 +-- is not valid. +alter index parted_replica_idx ATTACH PARTITION parted_replica_idx_1; +select indexrelid::regclass, indisvalid, indisreplident, + indrelid::regclass, inhparent::regclass + from pg_index idx left join + pg_inherits inh on (idx.indexrelid = inh.inhrelid) + where indexrelid::regclass::text like 'parted_replica%' + order by indexrelid::regclass::text collate "C"; +-- parted_replica_idx becomes valid here. +alter index parted_replica_idx_1 ATTACH PARTITION parted_replica_idx_11; +alter table only parted_replica_tab_1 replica identity + using index parted_replica_idx_1; +commit; +select indexrelid::regclass, indisvalid, indisreplident, + indrelid::regclass, inhparent::regclass + from pg_index idx left join + pg_inherits inh on (idx.indexrelid = inh.inhrelid) + where indexrelid::regclass::text like 'parted_replica%' + order by indexrelid::regclass::text collate "C"; +drop table parted_replica_tab; diff --git a/parser/src/test/resources/postgres/test/regress/sql/inherit.sql b/parser/src/test/resources/postgres/test/regress/sql/inherit.sql index 195aedb..50e7b9c 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/inherit.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/inherit.sql @@ -97,6 +97,25 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid; CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); INSERT INTO z VALUES (NULL, 'text'); -- should fail +-- Check inherited UPDATE with first child excluded +create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit); +create table some_tab_child () inherits(some_tab); +insert into some_tab_child select i, i+1, 0 from generate_series(1,1000) i; +create index on some_tab_child(f1, f2); +-- while at it, also check that statement-level triggers fire +create function some_tab_stmt_trig_func() returns trigger as +$$begin raise notice 'updating some_tab'; return NULL; end;$$ +language plpgsql; +create trigger some_tab_stmt_trig + before update on some_tab execute function some_tab_stmt_trig_func(); + +explain (costs off) +update some_tab set f3 = 11 where f1 = 12 and f2 = 13; +update some_tab set f3 = 11 where f1 = 12 and f2 = 13; + +drop table some_tab cascade; +drop function some_tab_stmt_trig_func(); + -- Check inherited UPDATE with all children excluded create table some_tab (a int, b int); create table some_tab_child () inherits (some_tab); @@ -353,6 +372,16 @@ ALTER TABLE inhts RENAME d TO dd; DROP TABLE inhts; +-- Test for adding a column to a parent table with complex inheritance +CREATE TABLE inhta (); +CREATE TABLE inhtb () INHERITS (inhta); +CREATE TABLE inhtc () INHERITS (inhtb); +CREATE TABLE inhtd () INHERITS (inhta, inhtb, inhtc); +ALTER TABLE inhta ADD COLUMN i int, ADD COLUMN j bigint DEFAULT 1; +\d+ inhta +\d+ inhtd +DROP TABLE inhta, inhtb, inhtc, inhtd; + -- Test for renaming in diamond inheritance CREATE TABLE inht2 (x int) INHERITS (inht1); CREATE TABLE inht3 (y int) INHERITS (inht1); @@ -534,6 +563,14 @@ select min(1-id) from matest0; reset enable_seqscan; reset enable_parallel_append; +explain (verbose, costs off) -- bug #18652 +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; + drop table matest0 cascade; -- @@ -629,6 +666,44 @@ reset enable_seqscan; reset enable_indexscan; reset enable_bitmapscan; +-- +-- Check handling of MULTIEXPR SubPlans in inherited updates +-- +create table inhpar(f1 int, f2 name); +create table inhcld(f2 name, f1 int); +alter table inhcld inherit inhpar; +insert into inhpar select x, x::text from generate_series(1,5) x; +insert into inhcld select x::text, x from generate_series(6,10) x; + +explain (verbose, costs off) +update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); +update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); +select * from inhpar; + +drop table inhpar cascade; + +-- +-- And the same for partitioned cases +-- +create table inhpar(f1 int primary key, f2 name) partition by range (f1); +create table inhcld1(f2 name, f1 int primary key); +create table inhcld2(f1 int primary key, f2 name); +alter table inhpar attach partition inhcld1 for values from (1) to (5); +alter table inhpar attach partition inhcld2 for values from (5) to (100); +insert into inhpar select x, x::text from generate_series(1,10) x; + +explain (verbose, costs off) +update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); +update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); +select * from inhpar; + +-- Also check ON CONFLICT +insert into inhpar as i values (3), (7) on conflict (f1) + do update set (f1, f2) = (select i.f1, i.f2 || '+'); +select * from inhpar order by f1; -- tuple order might be unstable here + +drop table inhpar cascade; + -- -- Check handling of a constant-null CHECK constraint -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/insert.sql b/parser/src/test/resources/postgres/test/regress/sql/insert.sql index d1133e8..58174fb 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/insert.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/insert.sql @@ -110,11 +110,88 @@ create rule irule2 as on insert to inserttest2 do also create rule irule3 as on insert to inserttest2 do also insert into inserttest (f4[1].if1, f4[1].if2[2]) select new.f1, new.f2; --- Deactivated for SplendidDataTest: \d+ inserttest2 +\d+ inserttest2 drop table inserttest2; drop table inserttest; -drop type insert_test_type; + +-- Make the same tests with domains over the array and composite fields + +create domain insert_pos_ints as int[] check (value[1] > 0); + +create domain insert_test_domain as insert_test_type + check ((value).if2[1] is not null); + +create table inserttesta (f1 int, f2 insert_pos_ints); +create table inserttestb (f3 insert_test_domain, f4 insert_test_domain[]); + +insert into inserttesta (f2[1], f2[2]) values (1,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (5,6); +insert into inserttesta (f2[1], f2[2]) select 7,8; +insert into inserttesta (f2[1], f2[2]) values (1,default); -- not supported +insert into inserttesta (f2[1], f2[2]) values (0,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (0,6); +insert into inserttesta (f2[1], f2[2]) select 0,8; + +insert into inserttestb (f3.if1, f3.if2) values (1,array['foo']); +insert into inserttestb (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{baz,quux}'; +insert into inserttestb (f3.if1, f3.if2) values (1,default); -- not supported +insert into inserttestb (f3.if1, f3.if2) values (1,array[null]); +insert into inserttestb (f3.if1, f3.if2) values (1,'{null}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{null,quux}'; + +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'); +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux'); +insert into inserttestb (f3.if2[1], f3.if2[2]) select 'bear', 'beer'; + +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'), (row(2,'{y}'), 'baz', 'quux'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) select row(1,'{x}')::insert_test_domain, 'bear', 'beer'; + +select * from inserttesta; +select * from inserttestb; + +-- also check reverse-listing +create table inserttest2 (f1 bigint, f2 text); +create rule irule1 as on insert to inserttest2 do also + insert into inserttestb (f3.if2[1], f3.if2[2]) + values (new.f1,new.f2); +create rule irule2 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + values (1,'fool'),(new.f1,new.f2); +create rule irule3 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + select new.f1, new.f2; +\d+ inserttest2 + +drop table inserttest2; +drop table inserttesta; +drop table inserttestb; +drop domain insert_pos_ints; +drop domain insert_test_domain; + +-- Verify that multiple inserts to subfields of a domain-over-container +-- check the domain constraints only on the finished value + +create domain insert_nnarray as int[] + check (value[1] is not null and value[2] is not null); + +create domain insert_test_domain as insert_test_type + check ((value).if1 is not null and (value).if2 is not null); + +create table inserttesta (f1 insert_nnarray); +insert into inserttesta (f1[1]) values (1); -- fail +insert into inserttesta (f1[1], f1[2]) values (1, 2); + +create table inserttestb (f1 insert_test_domain); +insert into inserttestb (f1.if1) values (1); -- fail +insert into inserttestb (f1.if1, f1.if2) values (1, '{foo}'); + +drop table inserttesta; +drop table inserttestb; +drop domain insert_nnarray; +drop type insert_test_type cascade; -- direct partition inserts should check partition bound constraint create table range_parted ( @@ -560,7 +637,7 @@ insert into donothingbrtrig_test values (1, 'foo'), (2, 'bar'); copy donothingbrtrig_test from stdout; -- Deactivated for SplendidDataTest: 1 baz -- Deactivated for SplendidDataTest: 2 qux --- Deactivated for SplendidDataTest: \. +\. select tableoid::regclass, * from donothingbrtrig_test; -- cleanup diff --git a/parser/src/test/resources/postgres/test/regress/sql/insert_conflict.sql b/parser/src/test/resources/postgres/test/regress/sql/insert_conflict.sql index 23d5778..144c347 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/insert_conflict.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/insert_conflict.sql @@ -3,6 +3,9 @@ -- create table insertconflicttest(key int4, fruit text); +-- These things should work through a view, as well +create view insertconflictview as select * from insertconflicttest; + -- -- Test unique index inference with operator class specifications and -- named collations @@ -20,6 +23,7 @@ explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on con explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on conflict (key, fruit) do nothing; explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on conflict (fruit, key, fruit, key) do nothing; explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on conflict (lower(fruit), key, lower(fruit), key) do nothing; +explain (costs off) insert into insertconflictview values(0, 'Crowberry') on conflict (lower(fruit), key, lower(fruit), key) do nothing; explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on conflict (key, fruit) do update set fruit = excluded.fruit where exists (select 1 from insertconflicttest ii where ii.key = excluded.key); -- Neither collation nor operator class specifications are required -- @@ -215,6 +219,7 @@ create unique index partial_key_index on insertconflicttest(key) where fruit lik -- Succeeds insert into insertconflicttest values (23, 'Blackberry') on conflict (key) where fruit like '%berry' do update set fruit = excluded.fruit; insert into insertconflicttest as t values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and t.fruit = 'inconsequential' do nothing; +insert into insertconflictview as t values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and t.fruit = 'inconsequential' do nothing; -- fails insert into insertconflicttest values (23, 'Blackberry') on conflict (key) do update set fruit = excluded.fruit; @@ -247,6 +252,7 @@ explain (costs off) insert into insertconflicttest as i values (23, 'Avocado') o drop index plain; -- Cleanup +drop view insertconflictview; drop table insertconflicttest; diff --git a/parser/src/test/resources/postgres/test/regress/sql/int8.sql b/parser/src/test/resources/postgres/test/regress/sql/int8.sql index 38b7719..8a3d537 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/int8.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/int8.sql @@ -126,6 +126,7 @@ select '9223372036854775808'::int8; select -('-9223372036854775807'::int8); select -('-9223372036854775808'::int8); +select 0::int8 - '-9223372036854775808'::int8; select '9223372036854775800'::int8 + '9223372036854775800'::int8; select '-9223372036854775800'::int8 + '-9223372036854775800'::int8; diff --git a/parser/src/test/resources/postgres/test/regress/sql/interval.sql b/parser/src/test/resources/postgres/test/regress/sql/interval.sql index af11166..56043b2 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/interval.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/interval.sql @@ -138,6 +138,14 @@ SET IntervalStyle to postgres_verbose; SELECT * FROM INTERVAL_TBL; +-- multiplication and division overflow test cases +SELECT '3000000 months'::interval * 1000; +SELECT '3000000 months'::interval / 0.001; +SELECT '3000000 days'::interval * 1000; +SELECT '3000000 days'::interval / 0.001; +SELECT '1 month 2146410 days'::interval * 1000.5002; +SELECT '4611686018427387904 usec'::interval / 0.1; + -- test avg(interval), which is somewhat fragile since people have been -- known to change the allowed input syntax for type interval without -- updating pg_aggregate.agginitval @@ -286,6 +294,9 @@ SELECT interval '-23 hours 45 min 12.34 sec', interval '-1 year 2 months 1 day 23 hours 45 min 12.34 sec', interval '-1 year 2 months 1 day 23 hours 45 min +12.34 sec'; +-- edge case for sign-matching rules +SELECT interval ''; -- error + -- test outputting iso8601 intervals SET IntervalStyle to iso_8601; select interval '0' AS "zero", @@ -327,6 +338,7 @@ select interval 'P1.0Y0M3DT4H5M6S'; select interval 'P1.1Y0M3DT4H5M6S'; select interval 'P1.Y0M3DT4H5M6S'; select interval 'P.1Y0M3DT4H5M6S'; +select interval 'P10.5e4Y'; -- not per spec, but we've historically taken it select interval 'P.Y0M3DT4H5M6S'; -- error -- test a couple rounding cases that changed since 8.3 w/ HAVE_INT64_TIMESTAMP. diff --git a/parser/src/test/resources/postgres/test/regress/sql/join.sql b/parser/src/test/resources/postgres/test/regress/sql/join.sql index 27e7e74..11a8570 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/join.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/join.sql @@ -472,24 +472,6 @@ select count(*) from (select * from tenk1 y order by y.unique2) y on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; -set enable_hashjoin = 0; -set enable_nestloop = 0; -set enable_hashagg = 0; - --- --- Check that we use the pathkeys from a prefix of the group by / order by --- clause for the join pathkeys when that prefix covers all join quals. We --- expect this to lead to an incremental sort for the group by / order by. --- -explain (costs off) -select x.thousand, x.twothousand, count(*) -from tenk1 x inner join tenk1 y on x.thousand = y.thousand -group by x.thousand, x.twothousand -order by x.thousand desc, x.twothousand; - -reset enable_hashagg; -reset enable_nestloop; -reset enable_hashjoin; -- -- Clean up @@ -1131,6 +1113,16 @@ select * from select a as b) as t3 where b; +-- Test PHV in a semijoin qual, which confused useless-RTE removal (bug #17700) +explain (verbose, costs off) +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + -- -- test inlining of immutable functions -- @@ -1986,6 +1978,18 @@ select * from ) on c.q2 = ss2.q1, lateral (select ss2.y offset 0) ss3; +-- another case requiring nested PlaceHolderVars +explain (verbose, costs off) +select * from + (select 0 as val0) as ss0 + left join (select 1 as val) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + +select * from + (select 0 as val0) as ss0 + left join (select 1 as val) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + -- case that breaks the old ph_may_need optimization explain (verbose, costs off) select c.*,a.*,ss1.q1,ss2.q1,ss3.* from @@ -2025,6 +2029,25 @@ select * from (select q1.v) ) as q2; +-- check for generation of join EC conditions at wrong level (bug #18429) +explain (costs off) +select * from ( + select arrayd.ad, coalesce(c.hundred, 0) as h + from unnest(array[1]) as arrayd(ad) + left join lateral ( + select hundred from tenk1 where unique2 = arrayd.ad + ) c on true +) c2 +where c2.h * c2.ad = c2.h * (c2.ad + 1); +select * from ( + select arrayd.ad, coalesce(c.hundred, 0) as h + from unnest(array[1]) as arrayd(ad) + left join lateral ( + select hundred from tenk1 where unique2 = arrayd.ad + ) c on true +) c2 +where c2.h * c2.ad = c2.h * (c2.ad + 1); + -- check the number of columns specified SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d); @@ -2271,6 +2294,15 @@ explain (verbose, costs off) select * from j1 left join j2 on j1.id1 = j2.id1 where j1.id2 = 1; +create unique index j1_id2_idx on j1(id2) where id2 is not null; + +-- ensure we don't use a partial unique index as unique proofs +explain (verbose, costs off) +select * from j1 +inner join j2 on j1.id2 = j2.id2; + +drop index j1_id2_idx; + -- validate logic in merge joins which skips mark and restore. -- it should only do this if all quals which were used to detect the unique -- are present as join quals, and not plain quals. diff --git a/parser/src/test/resources/postgres/test/regress/sql/join_hash.sql b/parser/src/test/resources/postgres/test/regress/sql/join_hash.sql index 77dbc18..e1707cd 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/join_hash.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/join_hash.sql @@ -556,3 +556,22 @@ WHERE AND hjtest_1.a <> hjtest_2.b; ROLLBACK; + +-- Verify that we behave sanely when the inner hash keys contain parameters +-- (that is, outer or lateral references). This situation has to defeat +-- re-use of the inner hash table across rescans. +begin; +set local enable_hashjoin = on; + +explain (costs off) +select i8.q2, ss.* from +int8_tbl i8, +lateral (select t1.fivethous, i4.f1 from tenk1 t1 join int4_tbl i4 + on t1.fivethous = i4.f1+i8.q2 order by 1,2) ss; + +select i8.q2, ss.* from +int8_tbl i8, +lateral (select t1.fivethous, i4.f1 from tenk1 t1 join int4_tbl i4 + on t1.fivethous = i4.f1+i8.q2 order by 1,2) ss; + +rollback; diff --git a/parser/src/test/resources/postgres/test/regress/sql/jsonb.sql b/parser/src/test/resources/postgres/test/regress/sql/jsonb.sql index 08dc5df..66d731a 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/jsonb.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/jsonb.sql @@ -1,19 +1,11 @@ -/* - * This file has been altered by SplendidData. - * It is only used for syntax checking, not for the testing of a commandline paser. - * So input for the copy statements is removed. - * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: - */ - - -- directory paths are passed to us in environment variables --- Deactivated for SplendidDataTest:\getenv abs_srcdir PG_ABS_SRCDIR +\getenv abs_srcdir PG_ABS_SRCDIR CREATE TABLE testjsonb ( j jsonb ); --- Deactivated for SplendidDataTest:\set filename :abs_srcdir '/data/jsonb.data' +\set filename :abs_srcdir '/data/jsonb.data' COPY testjsonb FROM :'filename'; -- Strings. @@ -415,6 +407,9 @@ SELECT jsonb_object_agg(name, type) FROM foo; INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT jsonb_object_agg(name, type) FROM foo; +-- edge case for parser +SELECT jsonb_object_agg(DISTINCT 'a', 'abc'); + -- jsonb_object -- empty object, one dimension @@ -1195,7 +1190,7 @@ select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, NULL}', '"new_value"'); -- jsonb_set_lax --- Deactivated for SplendidDataTest: \pset null NULL +\pset null NULL -- pass though non nulls to jsonb_set select jsonb_set_lax('{"a":1,"b":2}','{b}','5') ; @@ -1212,7 +1207,7 @@ select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'retu select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'delete_key') as delete_key; select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'use_json_null') as use_json_null; --- Deactivated for SplendidDataTest: \pset null '' +\pset null '' -- jsonb_insert select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"'); @@ -1423,6 +1418,24 @@ insert into test_jsonb_subscript values (1, 'null'); update test_jsonb_subscript set test_json[0] = '1'; update test_jsonb_subscript set test_json[0][0] = '1'; +-- try some things with short-header and toasted subscript values + +drop table test_jsonb_subscript; +create temp table test_jsonb_subscript ( + id text, + test_json jsonb +); + +insert into test_jsonb_subscript values('foo', '{"foo": "bar"}'); +insert into test_jsonb_subscript + select s, ('{"' || s || '": "bar"}')::jsonb from repeat('xyzzy', 500) s; +select length(id), test_json[id] from test_jsonb_subscript; +update test_jsonb_subscript set test_json[id] = '"baz"'; +select length(id), test_json[id] from test_jsonb_subscript; +\x +table test_jsonb_subscript; +\x + -- jsonb to tsvector select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::jsonb); diff --git a/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql b/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql index 60f73cb..e0ce509 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql @@ -414,6 +414,9 @@ select jsonb_path_query('"2017-03-10 12:34:56+3:10"', '$.datetime().type()'); select jsonb_path_query('"2017-03-10 12:34:56+3:10"', '$.datetime()'); select jsonb_path_query('"2017-03-10T12:34:56+3:10"', '$.datetime()'); select jsonb_path_query('"2017-03-10t12:34:56+3:10"', '$.datetime()'); +select jsonb_path_query('"2017-03-10 12:34:56.789+3:10"', '$.datetime()'); +select jsonb_path_query('"2017-03-10T12:34:56.789+3:10"', '$.datetime()'); +select jsonb_path_query('"2017-03-10t12:34:56.789+3:10"', '$.datetime()'); select jsonb_path_query('"12:34:56"', '$.datetime().type()'); select jsonb_path_query('"12:34:56"', '$.datetime()'); select jsonb_path_query('"12:34:56+3"', '$.datetime().type()'); @@ -532,6 +535,8 @@ set time zone default; SELECT jsonb_path_query('[{"a": 1}, {"a": 2}]', '$[*]'); SELECT jsonb_path_query('[{"a": 1}, {"a": 2}]', '$[*] ? (@.a > 10)'); +SELECT jsonb_path_query('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_query('[{"a": 1}]', 'false'); SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}, {}]', 'strict $[*].a'); SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}]', '$[*].a'); @@ -547,12 +552,16 @@ SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ == 1)'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ > 10)'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*].a ? (@ > $min && @ < $max)', vars => '{"min": 1, "max": 4}'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*].a ? (@ > $min && @ < $max)', vars => '{"min": 3, "max": 4}'); +SELECT jsonb_path_query_first('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_query_first('[{"a": 1}]', 'false'); SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)'; SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*] ? (@.a > 2)'; SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ > 1)'); SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 1, "max": 4}'); SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 3, "max": 4}'); +SELECT jsonb_path_exists('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_exists('[{"a": 1}]', 'false'); SELECT jsonb_path_match('true', '$', silent => false); SELECT jsonb_path_match('false', '$', silent => false); @@ -569,6 +578,8 @@ SELECT jsonb_path_match('[true, true]', '$[*]', silent => false); SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 1'; SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 2'; SELECT jsonb_path_match('[{"a": 1}, {"a": 2}]', '$[*].a > 1'); +SELECT jsonb_path_match('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_match('[{"a": 1}]', 'false'); -- test string comparison (Unicode codepoint collation) WITH str(j, num) AS diff --git a/parser/src/test/resources/postgres/test/regress/sql/limit.sql b/parser/src/test/resources/postgres/test/regress/sql/limit.sql index 6f0cda9..c8fdad9 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/limit.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/limit.sql @@ -1,3 +1,10 @@ +/* + * This file has been altered by SplendidData. + * It is only used for happy flow syntax checking, so erroneous statements are commented out here. + * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: + */ + + -- -- LIMIT -- Check the LIMIT/OFFSET feature of SELECT @@ -174,14 +181,14 @@ SELECT thousand ORDER BY thousand FETCH FIRST 2 ROW ONLY; -- SKIP LOCKED and WITH TIES are incompatible -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; +-- Deactivated for SplendidDataTest: SELECT thousand +-- Deactivated for SplendidDataTest: FROM onek WHERE thousand < 5 +-- Deactivated for SplendidDataTest: ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; -- should fail -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 50 - FETCH FIRST 2 ROW WITH TIES; +-- Deactivated for SplendidDataTest: SELECT ''::text AS two, unique1, unique2, stringu1 +-- Deactivated for SplendidDataTest: FROM onek WHERE unique1 > 50 +-- Deactivated for SplendidDataTest: FETCH FIRST 2 ROW WITH TIES; -- test ruleutils CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 @@ -196,6 +203,9 @@ CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; \d+ limit_thousand_v_3 CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS ONLY; + ORDER BY thousand FETCH FIRST (5::bigint) ROWS WITH TIES; \d+ limit_thousand_v_4 +CREATE VIEW limit_thousand_v_5 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS ONLY; +\d+ limit_thousand_v_5 -- leave these views diff --git a/parser/src/test/resources/postgres/test/regress/sql/maintain_every.sql b/parser/src/test/resources/postgres/test/regress/sql/maintain_every.sql new file mode 100644 index 0000000..263e972 --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/maintain_every.sql @@ -0,0 +1,26 @@ +-- Test maintenance commands that visit every eligible relation. Run as a +-- non-superuser, to skip other users' tables. + +CREATE ROLE regress_maintain; +SET ROLE regress_maintain; + +-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f +-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an +-- empty index. +CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts" +CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS; +CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent); +CREATE INDEX ON past_inh_db_parent ((1)); +ANALYZE past_inh_db_parent; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; +DROP TABLE past_inh_db_child; +SET client_min_messages = error; -- hide WARNINGs for other users' tables +ANALYZE; +RESET client_min_messages; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; +DROP TABLE past_inh_db_parent, past_inh_db_other; + +RESET ROLE; +DROP ROLE regress_maintain; diff --git a/parser/src/test/resources/postgres/test/regress/sql/matview.sql b/parser/src/test/resources/postgres/test/regress/sql/matview.sql index 68b9ccf..543e0a6 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/matview.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/matview.sql @@ -231,6 +231,23 @@ REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo; DROP OWNED BY regress_user_mvtest CASCADE; DROP ROLE regress_user_mvtest; +-- Concurrent refresh requires a unique index on the materialized +-- view. Test what happens if it's dropped during the refresh. +CREATE OR REPLACE FUNCTION mvtest_drop_the_index() + RETURNS bool AS $$ +BEGIN + EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx'; + RETURN true; +END; +$$ LANGUAGE plpgsql; + +CREATE MATERIALIZED VIEW drop_idx_matview AS + SELECT 1 as i WHERE mvtest_drop_the_index(); + +CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i); +REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview; +DROP MATERIALIZED VIEW drop_idx_matview; -- clean up + -- make sure that create WITH NO DATA works via SPI BEGIN; CREATE FUNCTION mvtest_func() diff --git a/parser/src/test/resources/postgres/test/regress/sql/memoize.sql b/parser/src/test/resources/postgres/test/regress/sql/memoize.sql index 0979bcd..7b02a82 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/memoize.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/memoize.sql @@ -47,18 +47,41 @@ WHERE t2.unique1 < 1000; -- Try with LATERAL joins SELECT explain_memoize(' SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1, -LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2 +LATERAL (SELECT t2.unique1 FROM tenk1 t2 + WHERE t1.twenty = t2.unique1 OFFSET 0) t2 WHERE t1.unique1 < 1000;', false); -- And check we get the expected results. SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1, -LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2 +LATERAL (SELECT t2.unique1 FROM tenk1 t2 + WHERE t1.twenty = t2.unique1 OFFSET 0) t2 WHERE t1.unique1 < 1000; +SET enable_mergejoin TO off; + +-- Test for varlena datatype with expr evaluation +CREATE TABLE expr_key (x numeric, t text); +INSERT INTO expr_key (x, t) +SELECT d1::numeric, d1::text FROM ( + SELECT round((d / pi())::numeric, 7) AS d1 FROM generate_series(1, 20) AS d +) t; + +-- duplicate rows so we get some cache hits +INSERT INTO expr_key SELECT * FROM expr_key; + +CREATE INDEX expr_key_idx_x_t ON expr_key (x, t); +VACUUM ANALYZE expr_key; + +-- Ensure we get we get a cache miss and hit for each of the 20 distinct values +SELECT explain_memoize(' +SELECT * FROM expr_key t1 INNER JOIN expr_key t2 +ON t1.x = t2.t::numeric AND t1.t::numeric = t2.x;', false); + +DROP TABLE expr_key; + -- Reduce work_mem and hash_mem_multiplier so that we see some cache evictions SET work_mem TO '64kB'; SET hash_mem_multiplier TO 1.0; -SET enable_mergejoin TO off; -- Ensure we get some evictions. We're unable to validate the hits and misses -- here as the number of entries that fit in the cache at once will vary -- between different machines. @@ -104,6 +127,25 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false); DROP TABLE strtest; +-- Ensure memoize works with partitionwise join +SET enable_partitionwise_join TO on; + +CREATE TABLE prt (a int) PARTITION BY RANGE(a); +CREATE TABLE prt_p1 PARTITION OF prt FOR VALUES FROM (0) TO (10); +CREATE TABLE prt_p2 PARTITION OF prt FOR VALUES FROM (10) TO (20); +INSERT INTO prt VALUES (0), (0), (0), (0); +INSERT INTO prt VALUES (10), (10), (10), (10); +CREATE INDEX iprt_p1_a ON prt_p1 (a); +CREATE INDEX iprt_p2_a ON prt_p2 (a); +ANALYZE prt; + +SELECT explain_memoize(' +SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false); + +DROP TABLE prt; + +RESET enable_partitionwise_join; + -- Exercise Memoize code that flushes the cache when a parameter changes which -- is not part of the cache key. diff --git a/parser/src/test/resources/postgres/test/regress/sql/merge.sql b/parser/src/test/resources/postgres/test/regress/sql/merge.sql index 12dc334..b4fc164 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/merge.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/merge.sql @@ -12,6 +12,8 @@ CREATE USER regress_merge_privs; CREATE USER regress_merge_no_privs; +CREATE USER regress_merge_none; + DROP TABLE IF EXISTS target; DROP TABLE IF EXISTS source; CREATE TABLE target (tid integer, balance integer) @@ -126,6 +128,14 @@ DROP MATERIALIZED VIEW mv; -- permissions +SET SESSION AUTHORIZATION regress_merge_none; +MERGE INTO target +USING (SELECT 1) AS s +ON true +WHEN MATCHED THEN + DO NOTHING; + +SET SESSION AUTHORIZATION regress_merge_privs; MERGE INTO target USING source2 ON target.tid = source2.sid @@ -446,7 +456,7 @@ USING source AS s ON t.tid = s.sid WHEN MATCHED THEN /* Terminal WHEN clause for MATCHED */ DELETE -WHEN MATCHED AND s.delta > 0 THEN +WHEN MATCHED THEN UPDATE SET balance = t.balance - s.delta; ROLLBACK; @@ -572,24 +582,6 @@ WHEN MATCHED AND t.tableoid >= 0 THEN UPDATE SET balance = t.balance + s.balance; SELECT * FROM wq_target; --- test preventing WHEN conditions from writing to the database -create or replace function merge_when_and_write() returns boolean -language plpgsql as -$$ -BEGIN - INSERT INTO target VALUES (100, 100); - RETURN TRUE; -END; -$$; - -BEGIN; -MERGE INTO wq_target t -USING wq_source s ON t.tid = s.sid -WHEN MATCHED AND (merge_when_and_write()) THEN - UPDATE SET balance = t.balance + s.balance; -ROLLBACK; -drop function merge_when_and_write(); - DROP TABLE wq_target, wq_source; -- test triggers @@ -662,12 +654,25 @@ $$; SELECT * FROM target full outer join source on (sid = tid); create trigger merge_skip BEFORE INSERT OR UPDATE or DELETE ON target FOR EACH ROW EXECUTE FUNCTION skip_merge_op(); +DO $$ +DECLARE + result integer; +BEGIN MERGE INTO target t USING source AS s ON t.tid = s.sid WHEN MATCHED AND s.sid = 3 THEN UPDATE SET balance = t.balance + s.delta WHEN MATCHED THEN DELETE WHEN NOT MATCHED THEN INSERT VALUES (sid, delta); +IF FOUND THEN + RAISE NOTICE 'Found'; +ELSE + RAISE NOTICE 'Not found'; +END IF; +GET DIAGNOSTICS result := ROW_COUNT; +RAISE NOTICE 'ROW_COUNT = %', result; +END; +$$; SELECT * FROM target FULL OUTER JOIN source ON (sid = tid); DROP TRIGGER merge_skip ON target; DROP FUNCTION skip_merge_op(); @@ -951,6 +956,23 @@ WHEN MATCHED AND t.a < 10 THEN DROP TABLE ex_msource, ex_mtarget; DROP FUNCTION explain_merge(text); +-- EXPLAIN SubPlans and InitPlans +CREATE TABLE src (a int, b int, c int, d int); +CREATE TABLE tgt (a int, b int, c int, d int); +CREATE TABLE ref (ab int, cd int); + +EXPLAIN (verbose, costs off) +MERGE INTO tgt t +USING (SELECT *, (SELECT count(*) FROM ref r + WHERE r.ab = s.a + s.b + AND r.cd = s.c - s.d) cnt + FROM src s) s +ON t.a = s.a AND t.b < s.cnt +WHEN MATCHED AND t.c > s.cnt THEN + UPDATE SET (b, c) = (SELECT s.b, s.cnt); + +DROP TABLE src, tgt, ref; + -- Subqueries BEGIN; MERGE INTO sq_target t @@ -1025,6 +1047,10 @@ ROLLBACK; -- try updating the partition key column BEGIN; +CREATE FUNCTION merge_func() RETURNS integer LANGUAGE plpgsql AS $$ +DECLARE + result integer; +BEGIN MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid @@ -1032,9 +1058,29 @@ MERGE INTO pa_target t UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' WHEN NOT MATCHED THEN INSERT VALUES (sid, delta, 'inserted by merge'); +IF FOUND THEN + GET DIAGNOSTICS result := ROW_COUNT; +END IF; +RETURN result; +END; +$$; +SELECT merge_func(); SELECT * FROM pa_target ORDER BY tid; ROLLBACK; +-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions +BEGIN; +TRUNCATE pa_target; +MERGE INTO pa_target t + USING (VALUES (10, 100)) AS s(sid, delta) + ON t.tid = s.sid + WHEN NOT MATCHED THEN + INSERT VALUES (1, 10, 'inserted by merge') + WHEN MATCHED THEN + DO NOTHING; +SELECT * FROM pa_target ORDER BY tid, val; +ROLLBACK; + DROP TABLE pa_target CASCADE; -- The target table is partitioned in the same way, but this time by attaching @@ -1062,6 +1108,10 @@ INSERT INTO pa_target SELECT id, id * 100, 'initial' FROM generate_series(1,14,2 -- try simple MERGE BEGIN; +DO $$ +DECLARE + result integer; +BEGIN MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid @@ -1069,6 +1119,10 @@ MERGE INTO pa_target t UPDATE SET balance = balance + delta, val = val || ' updated by merge' WHEN NOT MATCHED THEN INSERT VALUES (sid, delta, 'inserted by merge'); +GET DIAGNOSTICS result := ROW_COUNT; +RAISE NOTICE 'ROW_COUNT = %', result; +END; +$$; SELECT * FROM pa_target ORDER BY tid; ROLLBACK; @@ -1087,6 +1141,10 @@ ROLLBACK; -- try updating the partition key column BEGIN; +DO $$ +DECLARE + result integer; +BEGIN MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid @@ -1094,9 +1152,73 @@ MERGE INTO pa_target t UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' WHEN NOT MATCHED THEN INSERT VALUES (sid, delta, 'inserted by merge'); +GET DIAGNOSTICS result := ROW_COUNT; +RAISE NOTICE 'ROW_COUNT = %', result; +END; +$$; SELECT * FROM pa_target ORDER BY tid; ROLLBACK; +-- as above, but blocked by BEFORE DELETE ROW trigger +BEGIN; +CREATE FUNCTION trig_fn() RETURNS trigger LANGUAGE plpgsql AS + $$ BEGIN RETURN NULL; END; $$; +CREATE TRIGGER del_trig BEFORE DELETE ON pa_target + FOR EACH ROW EXECUTE PROCEDURE trig_fn(); +DO $$ +DECLARE + result integer; +BEGIN +MERGE INTO pa_target t + USING pa_source s + ON t.tid = s.sid + WHEN MATCHED THEN + UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' + WHEN NOT MATCHED THEN + INSERT VALUES (sid, delta, 'inserted by merge'); +GET DIAGNOSTICS result := ROW_COUNT; +RAISE NOTICE 'ROW_COUNT = %', result; +END; +$$; +SELECT * FROM pa_target ORDER BY tid; +ROLLBACK; + +-- as above, but blocked by BEFORE INSERT ROW trigger +BEGIN; +CREATE FUNCTION trig_fn() RETURNS trigger LANGUAGE plpgsql AS + $$ BEGIN RETURN NULL; END; $$; +CREATE TRIGGER ins_trig BEFORE INSERT ON pa_target + FOR EACH ROW EXECUTE PROCEDURE trig_fn(); +DO $$ +DECLARE + result integer; +BEGIN +MERGE INTO pa_target t + USING pa_source s + ON t.tid = s.sid + WHEN MATCHED THEN + UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' + WHEN NOT MATCHED THEN + INSERT VALUES (sid, delta, 'inserted by merge'); +GET DIAGNOSTICS result := ROW_COUNT; +RAISE NOTICE 'ROW_COUNT = %', result; +END; +$$; +SELECT * FROM pa_target ORDER BY tid; +ROLLBACK; + +-- test RLS enforcement +BEGIN; +ALTER TABLE pa_target ENABLE ROW LEVEL SECURITY; +ALTER TABLE pa_target FORCE ROW LEVEL SECURITY; +CREATE POLICY pa_target_pol ON pa_target USING (tid != 0); +MERGE INTO pa_target t + USING pa_source s + ON t.tid = s.sid AND t.tid IN (1,2,3,4) + WHEN MATCHED THEN + UPDATE SET tid = tid - 1; +ROLLBACK; + DROP TABLE pa_source; DROP TABLE pa_target CASCADE; @@ -1142,6 +1264,38 @@ ROLLBACK; DROP TABLE pa_source; DROP TABLE pa_target CASCADE; +-- Partitioned table with primary key + +CREATE TABLE pa_target (tid integer PRIMARY KEY) PARTITION BY LIST (tid); +CREATE TABLE pa_targetp PARTITION OF pa_target DEFAULT; +CREATE TABLE pa_source (sid integer); + +INSERT INTO pa_source VALUES (1), (2); + +EXPLAIN (VERBOSE, COSTS OFF) +MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid + WHEN NOT MATCHED THEN INSERT VALUES (s.sid); + +MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid + WHEN NOT MATCHED THEN INSERT VALUES (s.sid); + +TABLE pa_target; + +-- Partition-less partitioned table +-- (the bug we are checking for appeared only if table had partitions before) + +DROP TABLE pa_targetp; + +EXPLAIN (VERBOSE, COSTS OFF) +MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid + WHEN NOT MATCHED THEN INSERT VALUES (s.sid); + +MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid + WHEN NOT MATCHED THEN INSERT VALUES (s.sid); + +DROP TABLE pa_source; +DROP TABLE pa_target CASCADE; + -- some complex joins on the source side CREATE TABLE cj_target (tid integer, balance float, val text) @@ -1195,6 +1349,16 @@ WHEN MATCHED THEN SELECT * FROM cj_target; +-- try it with an outer join and PlaceHolderVar +MERGE INTO cj_target t +USING (SELECT *, 'join input'::text AS phv FROM cj_source1) fj + FULL JOIN cj_source2 fj2 ON fj.scat = fj2.sid2 * 10 +ON t.tid = fj.scat +WHEN NOT MATCHED THEN + INSERT (tid, balance, val) VALUES (fj.scat, fj.delta, fj.phv); + +SELECT * FROM cj_target; + ALTER TABLE cj_source1 RENAME COLUMN sid1 TO sid; ALTER TABLE cj_source2 RENAME COLUMN sid2 TO sid; @@ -1257,6 +1421,7 @@ CREATE TABLE measurement_y2007m01 ( ) WITH (autovacuum_enabled=off); ALTER TABLE measurement_y2007m01 DROP COLUMN filler; ALTER TABLE measurement_y2007m01 INHERIT measurement; +INSERT INTO measurement VALUES (0, '2005-07-21', 5, 15); CREATE OR REPLACE FUNCTION measurement_insert_trigger() RETURNS TRIGGER AS $$ @@ -1290,6 +1455,7 @@ INSERT INTO measurement VALUES (1, '2007-01-17', 10, 10); SELECT tableoid::regclass, * FROM measurement ORDER BY city_id, logdate; CREATE TABLE new_measurement (LIKE measurement) WITH (autovacuum_enabled=off); +INSERT INTO new_measurement VALUES (0, '2005-07-21', 25, 20); INSERT INTO new_measurement VALUES (1, '2006-03-01', 20, 10); INSERT INTO new_measurement VALUES (1, '2006-02-16', 50, 10); INSERT INTO new_measurement VALUES (2, '2006-02-10', 20, 20); @@ -1298,6 +1464,21 @@ INSERT INTO new_measurement VALUES (1, '2007-01-17', NULL, NULL); INSERT INTO new_measurement VALUES (1, '2007-01-15', 5, NULL); INSERT INTO new_measurement VALUES (1, '2007-01-16', 10, 10); +BEGIN; +MERGE INTO ONLY measurement m + USING new_measurement nm ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN MATCHED AND nm.peaktemp IS NULL THEN DELETE +WHEN MATCHED THEN UPDATE + SET peaktemp = greatest(m.peaktemp, nm.peaktemp), + unitsales = m.unitsales + coalesce(nm.unitsales, 0) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id, logdate, peaktemp, unitsales); + +SELECT tableoid::regclass, * FROM measurement ORDER BY city_id, logdate, peaktemp; +ROLLBACK; + MERGE into measurement m USING new_measurement nm ON (m.city_id = nm.city_id and m.logdate=nm.logdate) @@ -1310,14 +1491,87 @@ WHEN NOT MATCHED THEN INSERT VALUES (city_id, logdate, peaktemp, unitsales); SELECT tableoid::regclass, * FROM measurement ORDER BY city_id, logdate; + +BEGIN; +MERGE INTO new_measurement nm + USING ONLY measurement m ON + (nm.city_id = m.city_id and nm.logdate=m.logdate) +WHEN MATCHED THEN DELETE; + +SELECT * FROM new_measurement ORDER BY city_id, logdate; +ROLLBACK; + +MERGE INTO new_measurement nm + USING measurement m ON + (nm.city_id = m.city_id and nm.logdate=m.logdate) +WHEN MATCHED THEN DELETE; + +SELECT * FROM new_measurement ORDER BY city_id, logdate; + +-- MERGE into inheritance root table +DROP TRIGGER insert_measurement_trigger ON measurement; +ALTER TABLE measurement ADD CONSTRAINT mcheck CHECK (city_id = 0) NO INHERIT; + +EXPLAIN (COSTS OFF) +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); + +BEGIN; +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; +ROLLBACK; + +ALTER TABLE measurement ENABLE ROW LEVEL SECURITY; +ALTER TABLE measurement FORCE ROW LEVEL SECURITY; +CREATE POLICY measurement_p ON measurement USING (peaktemp IS NOT NULL); + +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, NULL, 100); -- should fail + +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); -- ok +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; + DROP TABLE measurement, new_measurement CASCADE; DROP FUNCTION measurement_insert_trigger(); -- prepare RESET SESSION AUTHORIZATION; + +-- try a system catalog +MERGE INTO pg_class c +USING (SELECT 'pg_depend'::regclass AS oid) AS j +ON j.oid = c.oid +WHEN MATCHED THEN + UPDATE SET reltuples = reltuples + 1; + +MERGE INTO pg_class c +USING pg_namespace n +ON n.oid = c.relnamespace +WHEN MATCHED AND c.oid = 'pg_depend'::regclass THEN + UPDATE SET reltuples = reltuples - 1; + DROP TABLE target, target2; DROP TABLE source, source2; DROP FUNCTION merge_trigfunc(); DROP USER regress_merge_privs; DROP USER regress_merge_no_privs; +DROP USER regress_merge_none; diff --git a/parser/src/test/resources/postgres/test/regress/sql/money.sql b/parser/src/test/resources/postgres/test/regress/sql/money.sql index 5e74628..1eb471d 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/money.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/money.sql @@ -129,3 +129,14 @@ SELECT '12345678901234567'::money::numeric; SELECT '-12345678901234567'::money::numeric; SELECT '92233720368547758.07'::money::numeric; SELECT '-92233720368547758.08'::money::numeric; + +-- overflow checks +SELECT '92233720368547758.07'::money + '0.01'::money; +SELECT '-92233720368547758.08'::money - '0.01'::money; +SELECT '92233720368547758.07'::money * 2::float8; +SELECT '-1'::money / 1.175494e-38::float4; +SELECT '92233720368547758.07'::money * 2::int4; +SELECT '1'::money / 0::int2; +SELECT '42'::money * 'inf'::float8; +SELECT '42'::money * '-inf'::float8; +SELECT '42'::money * 'nan'::float4; diff --git a/parser/src/test/resources/postgres/test/regress/sql/namespace.sql b/parser/src/test/resources/postgres/test/regress/sql/namespace.sql index 6b12c96..d071c02 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/namespace.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/namespace.sql @@ -2,6 +2,10 @@ -- Regression tests for schemas (namespaces) -- +-- set the whitespace-only search_path to test that the +-- GUC list syntax is preserved during a schema creation +SELECT pg_catalog.set_config('search_path', ' ', false); + CREATE SCHEMA test_ns_schema_1 CREATE UNIQUE INDEX abc_a_idx ON abc (a) @@ -13,6 +17,26 @@ CREATE SCHEMA test_ns_schema_1 b int UNIQUE ); +-- verify that the correct search_path restored on abort +SET search_path to public; +BEGIN; +SET search_path to public, test_ns_schema_1; +CREATE SCHEMA test_ns_schema_2 + CREATE VIEW abc_view AS SELECT c FROM abc; +COMMIT; +SHOW search_path; + +-- verify that the correct search_path preserved +-- after creating the schema and on commit +BEGIN; +SET search_path to public, test_ns_schema_1; +CREATE SCHEMA test_ns_schema_2 + CREATE VIEW abc_view AS SELECT a FROM abc; +SHOW search_path; +COMMIT; +SHOW search_path; +DROP SCHEMA test_ns_schema_2 CASCADE; + -- verify that the objects were created SELECT COUNT(*) FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'test_ns_schema_1'); @@ -31,11 +55,11 @@ SELECT COUNT(*) FROM pg_class WHERE relnamespace = -- test IF NOT EXISTS cases CREATE SCHEMA test_ns_schema_renamed; -- fail, already exists CREATE SCHEMA IF NOT EXISTS test_ns_schema_renamed; -- ok with notice -CREATE SCHEMA IF NOT EXISTS test_ns_schema_renamed -- fail, disallowed - CREATE TABLE abc ( - a serial, - b int UNIQUE - ); +-- Deactivated for SplendidDataTest: CREATE SCHEMA IF NOT EXISTS test_ns_schema_renamed -- fail, disallowed +-- Deactivated for SplendidDataTest: CREATE TABLE abc ( +-- Deactivated for SplendidDataTest: a serial, +-- Deactivated for SplendidDataTest: b int UNIQUE +-- Deactivated for SplendidDataTest: ); DROP SCHEMA test_ns_schema_renamed CASCADE; diff --git a/parser/src/test/resources/postgres/test/regress/sql/numeric.sql b/parser/src/test/resources/postgres/test/regress/sql/numeric.sql index 3ae6dab..5e4728a 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/numeric.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/numeric.sql @@ -842,6 +842,31 @@ SELECT i as pow, round((2.5 * 10 ^ i)::numeric, -i) FROM generate_series(-5,5) AS t(i); +-- Check limits of rounding before the decimal point +SELECT round(4.4e131071, -131071) = 4e131071; +SELECT round(4.5e131071, -131071) = 5e131071; +SELECT round(4.5e131071, -131072); -- loses all digits +SELECT round(5.5e131071, -131072); -- rounds up and overflows +SELECT round(5.5e131071, -131073); -- loses all digits +SELECT round(5.5e131071, -1000000); -- loses all digits + +-- Check limits of rounding after the decimal point +SELECT round(5e-16383, 1000000) = 5e-16383; +SELECT round(5e-16383, 16383) = 5e-16383; +SELECT round(5e-16383, 16382) = 1e-16382; +SELECT round(5e-16383, 16381) = 0; + +-- Check limits of trunc() before the decimal point +SELECT trunc(9.9e131071, -131071) = 9e131071; +SELECT trunc(9.9e131071, -131072); -- loses all digits +SELECT trunc(9.9e131071, -131073); -- loses all digits +SELECT trunc(9.9e131071, -1000000); -- loses all digits + +-- Check limits of trunc() after the decimal point +SELECT trunc(5e-16383, 1000000) = 5e-16383; +SELECT trunc(5e-16383, 16383) = 5e-16383; +SELECT trunc(5e-16383, 16382) = 0; + -- Testing for width_bucket(). For convenience, we test both the -- numeric and float8 versions of the function in this file. @@ -988,6 +1013,7 @@ FROM v; SELECT to_char('100'::numeric, 'FM999.9'); SELECT to_char('100'::numeric, 'FM999.'); SELECT to_char('100'::numeric, 'FM999'); +SELECT to_char('12345678901'::float8, 'FM9999999999D9999900000000000000000'); -- Check parsing of literal text in a format string SELECT to_char('100'::numeric, 'foo999'); @@ -1073,7 +1099,7 @@ CREATE TABLE num_typemod_test ( thousandths numeric(3, 3), millionths numeric(3, 6) ); --- Deactivated for SplendidDataTest: \d num_typemod_test +\d num_typemod_test -- rounding of valid inputs INSERT INTO num_typemod_test VALUES (123456, 123, 0.123, 0.000123, 0.000000123); diff --git a/parser/src/test/resources/postgres/test/regress/sql/numerology.sql b/parser/src/test/resources/postgres/test/regress/sql/numerology.sql index be7d6df..761b292 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/numerology.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/numerology.sql @@ -1,3 +1,10 @@ +/* + * This file has been altered by SplendidData. + * It is only used for happy flow syntax checking, so erroneous statements are commented out here. + * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: + */ + + -- -- NUMEROLOGY -- Test various combinations of numeric types and functions. @@ -7,16 +14,16 @@ -- Trailing junk in numeric literals -- -SELECT 123abc; -SELECT 0x0o; -SELECT 1_2_3; -SELECT 0.a; -SELECT 0.0a; -SELECT .0a; -SELECT 0.0e1a; -SELECT 0.0e; -SELECT 0.0e+a; -PREPARE p1 AS SELECT $1a; +-- Deactivated for SplendidDataTest: SELECT 123abc; +-- Deactivated for SplendidDataTest: SELECT 0x0o; +-- Deactivated for SplendidDataTest: SELECT 1_2_3; +-- Deactivated for SplendidDataTest: SELECT 0.a; +-- Deactivated for SplendidDataTest: SELECT 0.0a; +-- Deactivated for SplendidDataTest: SELECT .0a; +-- Deactivated for SplendidDataTest: SELECT 0.0e1a; +-- Deactivated for SplendidDataTest: SELECT 0.0e; +-- Deactivated for SplendidDataTest: SELECT 0.0e+a; +-- Deactivated for SplendidDataTest: PREPARE p1 AS SELECT $1a; -- -- Test implicit type conversions diff --git a/parser/src/test/resources/postgres/test/regress/sql/opr_sanity.sql b/parser/src/test/resources/postgres/test/regress/sql/opr_sanity.sql index 2b29285..0f039f2 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/opr_sanity.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/opr_sanity.sql @@ -1195,7 +1195,7 @@ WHERE p1.oid = a1.amhandler AND a1.amtype = 'i' AND SELECT a1.oid, a1.amname, p1.oid, p1.proname FROM pg_am AS a1, pg_proc AS p1 -WHERE p1.oid = a1.amhandler AND a1.amtype = 's' AND +WHERE p1.oid = a1.amhandler AND a1.amtype = 't' AND (p1.prorettype != 'table_am_handler'::regtype OR p1.proretset OR p1.pronargs != 1 diff --git a/parser/src/test/resources/postgres/test/regress/sql/partition_join.sql b/parser/src/test/resources/postgres/test/regress/sql/partition_join.sql index 67f5063..04d7adb 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/partition_join.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/partition_join.sql @@ -91,6 +91,33 @@ SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFT JOIN LATERAL (SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss ON t1.c = ss.t2c WHERE (t1.b + coalesce(ss.t2b, 0)) = 0 ORDER BY t1.a; +SET max_parallel_workers_per_gather = 0; +-- If there are lateral references to the other relation in sample scan, +-- we cannot generate a partitionwise join. +EXPLAIN (COSTS OFF) +SELECT * FROM prt1 t1 JOIN LATERAL + (SELECT * FROM prt1 t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s + ON t1.a = s.a; + +-- If there are lateral references to the other relation in scan's restriction +-- clauses, we cannot generate a partitionwise join. +EXPLAIN (COSTS OFF) +SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s + ON t1.a = s.b WHERE s.t1b = s.a; +SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s + ON t1.a = s.b WHERE s.t1b = s.a; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s + ON t1.a = s.b WHERE s.t1b = s.b; +SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s + ON t1.a = s.b WHERE s.t1b = s.b; +RESET max_parallel_workers_per_gather; + -- bug with inadequate sort key representation SET enable_partitionwise_aggregate TO true; SET enable_hashjoin TO false; @@ -378,6 +405,27 @@ SELECT * FROM prt1_l t1 LEFT JOIN LATERAL (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss ON t1.a = ss.t2a AND t1.c = ss.t2c WHERE t1.b = 0 ORDER BY t1.a; +SET max_parallel_workers_per_gather = 0; +-- If there are lateral references to the other relation in sample scan, +-- we cannot generate a partitionwise join. +EXPLAIN (COSTS OFF) +SELECT * FROM prt1_l t1 JOIN LATERAL + (SELECT * FROM prt1_l t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s + ON t1.a = s.a AND t1.b = s.b AND t1.c = s.c; + +-- If there are lateral references to the other relation in scan's restriction +-- clauses, we cannot generate a partitionwise join. +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM prt1_l t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s + ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c + WHERE s.t1b = s.a; +SELECT COUNT(*) FROM prt1_l t1 LEFT JOIN LATERAL + (SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s + ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c + WHERE s.t1b = s.a; +RESET max_parallel_workers_per_gather; + -- join with one side empty EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c; diff --git a/parser/src/test/resources/postgres/test/regress/sql/partition_prune.sql b/parser/src/test/resources/postgres/test/regress/sql/partition_prune.sql index d70bd86..34a8e40 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/partition_prune.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/partition_prune.sql @@ -158,6 +158,7 @@ create table boolpart (a bool) partition by list (a); create table boolpart_default partition of boolpart default; create table boolpart_t partition of boolpart for values in ('true'); create table boolpart_f partition of boolpart for values in ('false'); +insert into boolpart values (true), (false), (null); explain (costs off) select * from boolpart where a in (true, false); explain (costs off) select * from boolpart where a = false; @@ -168,15 +169,80 @@ explain (costs off) select * from boolpart where a is not true and a is not fals explain (costs off) select * from boolpart where a is unknown; explain (costs off) select * from boolpart where a is not unknown; +select * from boolpart where a in (true, false); +select * from boolpart where a = false; +select * from boolpart where not a = false; +select * from boolpart where a is true or a is not true; +select * from boolpart where a is not true; +select * from boolpart where a is not true and a is not false; +select * from boolpart where a is unknown; +select * from boolpart where a is not unknown; + +-- try some other permutations with a NULL partition instead of a DEFAULT +delete from boolpart where a is null; +create table boolpart_null partition of boolpart for values in (null); +insert into boolpart values(null); + +explain (costs off) select * from boolpart where a is not true; +explain (costs off) select * from boolpart where a is not true and a is not false; +explain (costs off) select * from boolpart where a is not false; + +select * from boolpart where a is not true; +select * from boolpart where a is not true and a is not false; +select * from boolpart where a is not false; + +-- inverse boolean partitioning - a seemingly unlikely design, but we've got +-- code for it, so we'd better test it. +create table iboolpart (a bool) partition by list ((not a)); +create table iboolpart_default partition of iboolpart default; +create table iboolpart_f partition of iboolpart for values in ('true'); +create table iboolpart_t partition of iboolpart for values in ('false'); +insert into iboolpart values (true), (false), (null); + +explain (costs off) select * from iboolpart where a in (true, false); +explain (costs off) select * from iboolpart where a = false; +explain (costs off) select * from iboolpart where not a = false; +explain (costs off) select * from iboolpart where a is true or a is not true; +explain (costs off) select * from iboolpart where a is not true; +explain (costs off) select * from iboolpart where a is not true and a is not false; +explain (costs off) select * from iboolpart where a is unknown; +explain (costs off) select * from iboolpart where a is not unknown; + +select * from iboolpart where a in (true, false); +select * from iboolpart where a = false; +select * from iboolpart where not a = false; +select * from iboolpart where a is true or a is not true; +select * from iboolpart where a is not true; +select * from iboolpart where a is not true and a is not false; +select * from iboolpart where a is unknown; +select * from iboolpart where a is not unknown; + +-- Try some other permutations with a NULL partition instead of a DEFAULT +delete from iboolpart where a is null; +create table iboolpart_null partition of iboolpart for values in (null); +insert into iboolpart values(null); + +-- Pruning shouldn't take place for these. Just check the result is correct +select * from iboolpart where a is not true; +select * from iboolpart where a is not true and a is not false; +select * from iboolpart where a is not false; + create table boolrangep (a bool, b bool, c int) partition by range (a,b,c); create table boolrangep_tf partition of boolrangep for values from ('true', 'false', 0) to ('true', 'false', 100); create table boolrangep_ft partition of boolrangep for values from ('false', 'true', 0) to ('false', 'true', 100); create table boolrangep_ff1 partition of boolrangep for values from ('false', 'false', 0) to ('false', 'false', 50); create table boolrangep_ff2 partition of boolrangep for values from ('false', 'false', 50) to ('false', 'false', 100); +create table boolrangep_null partition of boolrangep default; -- try a more complex case that's been known to trip up pruning in the past explain (costs off) select * from boolrangep where not a and not b and c = 25; +-- ensure we prune boolrangep_tf +explain (costs off) select * from boolrangep where a is not true and not b and c = 25; + +-- ensure we prune everything apart from boolrangep_tf and boolrangep_null +explain (costs off) select * from boolrangep where a is not false and not b and c = 25; + -- test scalar-to-array operators create table coercepart (a varchar) partition by list (a); create table coercepart_ab partition of coercepart for values in ('ab'); @@ -294,7 +360,22 @@ create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values fr -- all partitions but rparted_by_int2_maxvalue pruned explain (costs off) select * from rparted_by_int2 where a > 100000000000000; -drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2; +drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, iboolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2; + +-- check that AlternativeSubPlan within a pruning expression gets cleaned up + +create table asptab (id int primary key) partition by range (id); +create table asptab0 partition of asptab for values from (0) to (1); +create table asptab1 partition of asptab for values from (1) to (2); + +explain (costs off) +select * from + (select exists (select 1 from int4_tbl tinner where f1 = touter.f1) as b + from int4_tbl touter) ss, + asptab +where asptab.id > ss.b::int; + +drop table asptab; -- -- Test Partition pruning for HASH partitioning @@ -348,8 +429,6 @@ drop table hp2; explain (costs off) select * from hp where a = 1 and b = 'abcde' and (c = 2 or c = 3); -drop table hp; - -- -- Test runtime partition pruning -- @@ -400,6 +479,25 @@ select a from ab where b between $1 and $2 and a < (select 3); explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); +-- +-- Test runtime pruning with hash partitioned tables +-- + +-- recreate partitions dropped above +create table hp1 partition of hp for values with (modulus 4, remainder 1); +create table hp2 partition of hp for values with (modulus 4, remainder 2); +create table hp3 partition of hp for values with (modulus 4, remainder 3); + +-- Ensure we correctly prune unneeded partitions when there is an IS NULL qual +prepare hp_q1 (text) as +select * from hp where a is null and b = $1; + +explain (costs off) execute hp_q1('xxx'); + +deallocate hp_q1; + +drop table hp; + -- Test a backwards Append scan create table list_part (a int) partition by list (a); create table list_part1 partition of list_part for values in (1); @@ -1146,16 +1244,57 @@ explain (costs off) select * from rp_prefix_test3 where a >= 1 and b >= 1 and b -- that the caller arranges clauses in that prefix in the required order) explain (costs off) select * from rp_prefix_test3 where a >= 1 and b >= 1 and b = 2 and c = 2 and d >= 0; -create table hp_prefix_test (a int, b int, c int, d int) partition by hash (a part_test_int4_ops, b part_test_int4_ops, c part_test_int4_ops, d part_test_int4_ops); -create table hp_prefix_test_p1 partition of hp_prefix_test for values with (modulus 2, remainder 0); -create table hp_prefix_test_p2 partition of hp_prefix_test for values with (modulus 2, remainder 1); - --- Test that get_steps_using_prefix() handles non-NULL step_nullkeys -explain (costs off) select * from hp_prefix_test where a = 1 and b is null and c = 1 and d = 1; - drop table rp_prefix_test1; drop table rp_prefix_test2; drop table rp_prefix_test3; + +-- +-- Test that get_steps_using_prefix() handles IS NULL clauses correctly +-- +create table hp_prefix_test (a int, b int, c int, d int) + partition by hash (a part_test_int4_ops, b part_test_int4_ops, c part_test_int4_ops, d part_test_int4_ops); + +-- create 8 partitions +select 'create table hp_prefix_test_p' || x::text || ' partition of hp_prefix_test for values with (modulus 8, remainder ' || x::text || ');' +from generate_Series(0,7) x; +\gexec + +-- insert 16 rows, one row for each test to perform. +insert into hp_prefix_test +select + case a when 0 then null else 1 end, + case b when 0 then null else 2 end, + case c when 0 then null else 3 end, + case d when 0 then null else 4 end +from + generate_series(0,1) a, + generate_series(0,1) b, + generate_Series(0,1) c, + generate_Series(0,1) d; + +-- Ensure partition pruning works correctly for each combination of IS NULL +-- and equality quals. This may seem a little excessive, but there have been +-- a number of bugs in this area over the years. We make use of row only +-- output to reduce the size of the expected results. +\t on +select + 'explain (costs off) select tableoid::regclass,* from hp_prefix_test where ' || + string_agg(c.colname || case when g.s & (1 << c.colpos) = 0 then ' is null' else ' = ' || (colpos+1)::text end, ' and ' order by c.colpos) +from (values('a',0),('b',1),('c',2),('d',3)) c(colname, colpos), generate_Series(0,15) g(s) +group by g.s +order by g.s; +\gexec + +-- And ensure we get exactly 1 row from each. Again, all 16 possible combinations. +select + 'select tableoid::regclass,* from hp_prefix_test where ' || + string_agg(c.colname || case when g.s & (1 << c.colpos) = 0 then ' is null' else ' = ' || (colpos+1)::text end, ' and ' order by c.colpos) +from (values('a',0),('b',1),('c',2),('d',3)) c(colname, colpos), generate_Series(0,15) g(s) +group by g.s +order by g.s; +\gexec +\t off + drop table hp_prefix_test; -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/plpgsql.sql b/parser/src/test/resources/postgres/test/regress/sql/plpgsql.sql index 352a2a1..65928ef 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/plpgsql.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/plpgsql.sql @@ -2056,11 +2056,9 @@ begin end $$ language plpgsql; select namedparmcursor_test7(); --- check that line comments work correctly within the argument list (there --- is some special handling of this case in the code: the newline after the --- comment must be preserved when the argument-evaluating query is --- constructed, otherwise the comment effectively comments out the next --- argument, too) +-- check that line comments work correctly within the argument list +-- (this used to require a special hack in the code; it no longer does, +-- but let's keep the test anyway) create function namedparmcursor_test8() returns int4 as $$ declare c1 cursor (p1 int, p2 int) for diff --git a/parser/src/test/resources/postgres/test/regress/sql/privileges.sql b/parser/src/test/resources/postgres/test/regress/sql/privileges.sql index 68a0c79..9d24dad 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/privileges.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/privileges.sql @@ -45,63 +45,9 @@ CREATE USER regress_priv_user9; CREATE USER regress_priv_user10; CREATE ROLE regress_priv_role; --- circular ADMIN OPTION grants should be disallowed -GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; -GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION GRANTED BY regress_priv_user2; -GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION GRANTED BY regress_priv_user3; - --- need CASCADE to revoke grant or admin option if dependent grants exist -REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2; -- fail -REVOKE regress_priv_user1 FROM regress_priv_user2; -- fail -SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole; -BEGIN; -REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2 CASCADE; -SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole; -ROLLBACK; -REVOKE regress_priv_user1 FROM regress_priv_user2 CASCADE; -SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole; - --- inferred grantor must be a role with ADMIN OPTION -GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; -GRANT regress_priv_user2 TO regress_priv_user3; -SET ROLE regress_priv_user3; -GRANT regress_priv_user1 TO regress_priv_user4; -SELECT grantor::regrole FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole and member = 'regress_priv_user4'::regrole; -RESET ROLE; -REVOKE regress_priv_user2 FROM regress_priv_user3; -REVOKE regress_priv_user1 FROM regress_priv_user2 CASCADE; - --- test GRANTED BY with DROP OWNED and REASSIGN OWNED -GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; -GRANT regress_priv_user1 TO regress_priv_user3 GRANTED BY regress_priv_user2; -DROP ROLE regress_priv_user2; -- fail, dependency -REASSIGN OWNED BY regress_priv_user2 TO regress_priv_user4; -DROP ROLE regress_priv_user2; -- still fail, REASSIGN OWNED doesn't help -DROP OWNED BY regress_priv_user2; -DROP ROLE regress_priv_user2; -- ok now, DROP OWNED does the job - --- test that removing granted role or grantee role removes dependency -GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION; -GRANT regress_priv_user1 TO regress_priv_user4 GRANTED BY regress_priv_user3; -DROP ROLE regress_priv_user3; -- should fail, dependency -DROP ROLE regress_priv_user4; -- ok -DROP ROLE regress_priv_user3; -- ok now -GRANT regress_priv_user1 TO regress_priv_user5 WITH ADMIN OPTION; -GRANT regress_priv_user1 TO regress_priv_user6 GRANTED BY regress_priv_user5; -DROP ROLE regress_priv_user5; -- should fail, dependency -DROP ROLE regress_priv_user1, regress_priv_user5; -- ok, despite order - --- recreate the roles we just dropped -CREATE USER regress_priv_user1; -CREATE USER regress_priv_user2; -CREATE USER regress_priv_user3; -CREATE USER regress_priv_user4; -CREATE USER regress_priv_user5; - GRANT pg_read_all_data TO regress_priv_user6; GRANT pg_write_all_data TO regress_priv_user7; GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION; -GRANT regress_priv_user9 TO regress_priv_user8; SET SESSION AUTHORIZATION regress_priv_user8; GRANT pg_read_all_settings TO regress_priv_user9 WITH ADMIN OPTION; @@ -110,12 +56,11 @@ SET SESSION AUTHORIZATION regress_priv_user9; GRANT pg_read_all_settings TO regress_priv_user10; SET SESSION AUTHORIZATION regress_priv_user8; -REVOKE pg_read_all_settings FROM regress_priv_user10 GRANTED BY regress_priv_user9; +REVOKE pg_read_all_settings FROM regress_priv_user10; REVOKE ADMIN OPTION FOR pg_read_all_settings FROM regress_priv_user9; REVOKE pg_read_all_settings FROM regress_priv_user9; RESET SESSION AUTHORIZATION; -REVOKE regress_priv_user9 FROM regress_priv_user8; REVOKE ADMIN OPTION FOR pg_read_all_settings FROM regress_priv_user8; SET SESSION AUTHORIZATION regress_priv_user8; @@ -123,6 +68,39 @@ SET ROLE pg_read_all_settings; RESET ROLE; RESET SESSION AUTHORIZATION; + +-- test interaction of SET SESSION AUTHORIZATION and SET ROLE, +-- as well as propagation of these settings to parallel workers +GRANT regress_priv_user9 TO regress_priv_user8; + +SET SESSION AUTHORIZATION regress_priv_user8; +SET ROLE regress_priv_user9; +SET force_parallel_mode = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET force_parallel_mode = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + +BEGIN; +SET SESSION AUTHORIZATION regress_priv_user10; +SET force_parallel_mode = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET force_parallel_mode = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; +ROLLBACK; +SET force_parallel_mode = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET force_parallel_mode = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + +RESET SESSION AUTHORIZATION; +-- session_user at this point is installation-dependent +SET force_parallel_mode = 0; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; +SET force_parallel_mode = 1; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; + +RESET force_parallel_mode; + REVOKE pg_read_all_settings FROM regress_priv_user8; DROP USER regress_priv_user10; @@ -130,19 +108,12 @@ DROP USER regress_priv_user9; DROP USER regress_priv_user8; CREATE GROUP regress_priv_group1; -CREATE GROUP regress_priv_group2 WITH ADMIN regress_priv_user1 USER regress_priv_user2; +CREATE GROUP regress_priv_group2 WITH USER regress_priv_user1, regress_priv_user2; ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4; -GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1; -SET SESSION AUTHORIZATION regress_priv_user1; -ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- duplicate ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; -ALTER USER regress_priv_user2 PASSWORD 'verysecret'; -- not permitted -RESET SESSION AUTHORIZATION; -ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; -REVOKE ADMIN OPTION FOR regress_priv_group2 FROM regress_priv_user1; GRANT regress_priv_group2 TO regress_priv_user4 WITH ADMIN OPTION; -- prepare non-leakproof function for later @@ -153,10 +124,9 @@ ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1; -- test owner privileges -GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regress_priv_role; -- error, doesn't have ADMIN OPTION GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE; REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error -REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY regress_priv_user2; -- warning, noop +REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY regress_priv_user2; -- error REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_USER; REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE; DROP ROLE regress_priv_role; @@ -288,8 +258,6 @@ CREATE VIEW atest12v AS SELECT * FROM atest12 WHERE b <<< 5; CREATE VIEW atest12sbv WITH (security_barrier=true) AS SELECT * FROM atest12 WHERE b <<< 5; -GRANT SELECT ON atest12v TO PUBLIC; -GRANT SELECT ON atest12sbv TO PUBLIC; -- This plan should use nestloop, knowing that few rows will be selected. EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b; @@ -311,8 +279,16 @@ CREATE FUNCTION leak2(integer,integer) RETURNS boolean CREATE OPERATOR >>> (procedure = leak2, leftarg = integer, rightarg = integer, restrict = scalargtsel); --- This should not show any "leak" notices before failing. +-- These should not show any "leak" notices before failing. EXPLAIN (COSTS OFF) SELECT * FROM atest12 WHERE a >>> 0; +EXPLAIN (COSTS OFF) SELECT * FROM atest12v WHERE a >>> 0; +EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv WHERE a >>> 0; + +-- Now regress_priv_user1 grants access to regress_priv_user2 via the views. +SET SESSION AUTHORIZATION regress_priv_user1; +GRANT SELECT ON atest12v TO PUBLIC; +GRANT SELECT ON atest12sbv TO PUBLIC; +SET SESSION AUTHORIZATION regress_priv_user2; -- These plans should continue to use a nestloop, since they execute with the -- privileges of the view owner. @@ -359,18 +335,7 @@ BEGIN; RESET SESSION AUTHORIZATION; ALTER ROLE regress_priv_user1 NOINHERIT; SET SESSION AUTHORIZATION regress_priv_user1; -SAVEPOINT s1; -DELETE FROM atest3; -- ok because grant-level option is unchanged -ROLLBACK TO s1; -RESET SESSION AUTHORIZATION; --- Deactivated for SplendidDataTest: GRANT regress_priv_group2 TO regress_priv_user1 WITH INHERIT FALSE; -SET SESSION AUTHORIZATION regress_priv_user1; -DELETE FROM atest3; -- fail -ROLLBACK TO s1; -RESET SESSION AUTHORIZATION; --- Deactivated for SplendidDataTest: REVOKE INHERIT OPTION FOR regress_priv_group2 FROM regress_priv_user1; -SET SESSION AUTHORIZATION regress_priv_user1; -DELETE FROM atest3; -- also fail +DELETE FROM atest3; ROLLBACK; -- views @@ -790,7 +755,7 @@ END; -- privileges on functions, languages -- switch to superuser --- Deactivated for SplendidDataTest: \c - +\c - REVOKE ALL PRIVILEGES ON LANGUAGE sql FROM PUBLIC; GRANT USAGE ON LANGUAGE sql TO regress_priv_user1; -- ok @@ -843,7 +808,7 @@ DROP FUNCTION priv_testfunc1(int); -- fail DROP AGGREGATE priv_testagg1(int); -- fail DROP PROCEDURE priv_testproc1(int); -- fail --- Deactivated for SplendidDataTest: \c - +\c - DROP FUNCTION priv_testfunc1(int); -- ok -- restore to sanity @@ -861,7 +826,7 @@ ROLLBACK; -- privileges on types -- switch to superuser --- Deactivated for SplendidDataTest: \c - +\c - CREATE TYPE priv_testtype1 AS (a int, b text); REVOKE USAGE ON TYPE priv_testtype1 FROM PUBLIC; @@ -946,7 +911,7 @@ CREATE TABLE test11b AS (SELECT 1::priv_testdomain1 AS a); REVOKE ALL ON TYPE priv_testtype1 FROM PUBLIC; --- Deactivated for SplendidDataTest: \c - +\c - DROP AGGREGATE priv_testagg1b(priv_testdomain1); DROP DOMAIN priv_testdomain2b; DROP OPERATOR !! (NONE, priv_testdomain1); @@ -983,7 +948,7 @@ select has_table_privilege(-999999,'pg_authid','update'); select has_table_privilege(1,'select'); -- superuser --- Deactivated for SplendidDataTest: \c - +\c - select has_table_privilege(current_user,'pg_authid','select'); select has_table_privilege(current_user,'pg_authid','insert'); @@ -1122,7 +1087,7 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP -- security-restricted operations --- Deactivated for SplendidDataTest: \c - +\c - CREATE ROLE regress_sro_user; -- Check that index expressions and predicates are run as the table's owner @@ -1180,7 +1145,7 @@ CREATE FUNCTION mv_action() RETURNS bool LANGUAGE sql AS -- REFRESH of this MV will queue a GRANT at end of transaction CREATE MATERIALIZED VIEW sro_mv AS SELECT mv_action() WITH NO DATA; REFRESH MATERIALIZED VIEW sro_mv; --- Deactivated for SplendidDataTest: \c - +\c - REFRESH MATERIALIZED VIEW sro_mv; SET SESSION AUTHORIZATION regress_sro_user; @@ -1194,7 +1159,7 @@ CREATE CONSTRAINT TRIGGER t AFTER INSERT ON sro_trojan_table CREATE OR REPLACE FUNCTION mv_action() RETURNS bool LANGUAGE sql AS 'INSERT INTO sro_trojan_table DEFAULT VALUES; SELECT true'; REFRESH MATERIALIZED VIEW sro_mv; --- Deactivated for SplendidDataTest: \c - +\c - REFRESH MATERIALIZED VIEW sro_mv; BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT; @@ -1211,7 +1176,7 @@ EXCEPTION WHEN OTHERS THEN END$$; CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c; CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0; --- Deactivated for SplendidDataTest: \c - +\c - REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv; REFRESH MATERIALIZED VIEW sro_index_mv; @@ -1243,7 +1208,7 @@ REVOKE regress_priv_group2 FROM regress_priv_user5; -- has_sequence_privilege tests --- Deactivated for SplendidDataTest: \c - +\c - CREATE SEQUENCE x_seq; @@ -1258,7 +1223,7 @@ SET SESSION AUTHORIZATION regress_priv_user2; SELECT has_sequence_privilege('x_seq', 'USAGE'); -- largeobject privilege tests --- Deactivated for SplendidDataTest: \c - +\c - SET SESSION AUTHORIZATION regress_priv_user1; SELECT lo_create(1001); @@ -1277,7 +1242,7 @@ GRANT SELECT, INSERT ON LARGE OBJECT 1001 TO PUBLIC; -- to be failed GRANT SELECT, UPDATE ON LARGE OBJECT 1001 TO nosuchuser; -- to be failed GRANT SELECT, UPDATE ON LARGE OBJECT 999 TO PUBLIC; -- to be failed --- Deactivated for SplendidDataTest: \c - +\c - SET SESSION AUTHORIZATION regress_priv_user2; SELECT lo_create(2001); @@ -1304,7 +1269,7 @@ GRANT ALL ON LARGE OBJECT 2001 TO regress_priv_user3; SELECT lo_unlink(1001); -- to be denied SELECT lo_unlink(2002); --- Deactivated for SplendidDataTest: \c - +\c - -- confirm ACL setting SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; @@ -1318,7 +1283,7 @@ SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); -- compatibility mode in largeobject permission --- Deactivated for SplendidDataTest: \c - +\c - SET lo_compat_privileges = false; -- default setting SET SESSION AUTHORIZATION regress_priv_user4; @@ -1331,7 +1296,7 @@ SELECT lo_export(1001, '/dev/null'); -- to be denied SELECT lo_import('/dev/null'); -- to be denied SELECT lo_import('/dev/null', 2003); -- to be denied --- Deactivated for SplendidDataTest: \c - +\c - SET lo_compat_privileges = true; -- compatibility mode SET SESSION AUTHORIZATION regress_priv_user4; @@ -1342,12 +1307,27 @@ SELECT lo_unlink(1002); SELECT lo_export(1001, '/dev/null'); -- to be denied -- don't allow unpriv users to access pg_largeobject contents --- Deactivated for SplendidDataTest: \c - +\c - SELECT * FROM pg_largeobject LIMIT 0; SET SESSION AUTHORIZATION regress_priv_user1; SELECT * FROM pg_largeobject LIMIT 0; -- to be denied +-- pg_signal_backend can't signal superusers +RESET SESSION AUTHORIZATION; +BEGIN; +CREATE OR REPLACE FUNCTION terminate_nothrow(pid int) RETURNS bool + LANGUAGE plpgsql SECURITY DEFINER SET client_min_messages = error AS $$ +BEGIN + RETURN pg_terminate_backend($1); +EXCEPTION WHEN OTHERS THEN + RETURN false; +END$$; +ALTER FUNCTION terminate_nothrow OWNER TO pg_signal_backend; +SELECT backend_type FROM pg_stat_activity +WHERE CASE WHEN COALESCE(usesysid, 10) = 10 THEN terminate_nothrow(pid) END; +ROLLBACK; + -- test pg_database_owner RESET SESSION AUTHORIZATION; GRANT pg_database_owner TO regress_priv_user1; @@ -1380,7 +1360,7 @@ INSERT INTO datdba_only DEFAULT VALUES; ROLLBACK; -- test default ACLs --- Deactivated for SplendidDataTest: \c - +\c - CREATE SCHEMA testns; GRANT ALL ON SCHEMA testns TO regress_priv_user1; @@ -1421,13 +1401,13 @@ ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error --- Test makeaclitem() -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT', TRUE); -- single privilege -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT, INSERT, UPDATE , DELETE ', FALSE); -- multiple privileges -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT, fake_privilege', FALSE); -- error +-- Test quoting and dequoting of user names in ACLs +CREATE ROLE "regress_""quoted"; +SELECT makeaclitem('regress_"quoted'::regrole, 'regress_"quoted'::regrole, + 'SELECT', TRUE); +SELECT '"regress_""quoted"=r*/"regress_""quoted"'::aclitem; +SELECT '""=r*/""'::aclitem; -- used to be misparsed as """" +DROP ROLE "regress_""quoted"; -- -- Testing blanket default grants is very hazardous since it might change @@ -1547,7 +1527,7 @@ SELECT d.* -- check that entries went away -- Grant on all objects of given type in a schema --- Deactivated for SplendidDataTest: \c - +\c - CREATE SCHEMA testns; CREATE TABLE testns.t1 (f1 int); @@ -1593,7 +1573,7 @@ DROP SCHEMA testns CASCADE; -- Change owner of the schema & and rename of new schema owner --- Deactivated for SplendidDataTest: \c - +\c - CREATE ROLE regress_schemauser1 superuser login; CREATE ROLE regress_schemauser2 superuser login; @@ -1611,14 +1591,14 @@ set session role regress_schemauser_renamed; DROP SCHEMA testns CASCADE; -- clean up --- Deactivated for SplendidDataTest: \c - +\c - DROP ROLE regress_schemauser1; DROP ROLE regress_schemauser_renamed; -- test that dependent privileges are revoked (or not) properly --- Deactivated for SplendidDataTest: \c - +\c - set session role regress_priv_user1; create table dep_priv_test (a int); @@ -1630,20 +1610,20 @@ set session role regress_priv_user3; grant select on dep_priv_test to regress_priv_user4 with grant option; set session role regress_priv_user4; grant select on dep_priv_test to regress_priv_user5; --- Deactivated for SplendidDataTest: \dp dep_priv_test +\dp dep_priv_test set session role regress_priv_user2; revoke select on dep_priv_test from regress_priv_user4 cascade; --- Deactivated for SplendidDataTest: \dp dep_priv_test +\dp dep_priv_test set session role regress_priv_user3; revoke select on dep_priv_test from regress_priv_user4 cascade; --- Deactivated for SplendidDataTest: \dp dep_priv_test +\dp dep_priv_test set session role regress_priv_user1; drop table dep_priv_test; -- clean up --- Deactivated for SplendidDataTest: \c +\c drop sequence x_seq; @@ -1689,6 +1669,13 @@ DROP USER regress_priv_user7; DROP USER regress_priv_user8; -- does not exist +-- leave some default ACLs for pg_upgrade's dump-restore test input. +ALTER DEFAULT PRIVILEGES FOR ROLE pg_signal_backend + REVOKE USAGE ON TYPES FROM pg_signal_backend; +ALTER DEFAULT PRIVILEGES FOR ROLE pg_read_all_settings + REVOKE USAGE ON TYPES FROM pg_read_all_settings; + + -- permissions with LOCK TABLE CREATE USER regress_locktable_user; CREATE TABLE lock_table (a int); @@ -1705,7 +1692,7 @@ COMMIT; BEGIN; LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail ROLLBACK; --- Deactivated for SplendidDataTest: \c +\c REVOKE SELECT ON lock_table FROM regress_locktable_user; -- LOCK TABLE and INSERT permission @@ -1720,7 +1707,7 @@ ROLLBACK; BEGIN; LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail ROLLBACK; --- Deactivated for SplendidDataTest: \c +\c REVOKE INSERT ON lock_table FROM regress_locktable_user; -- LOCK TABLE and UPDATE permission @@ -1735,7 +1722,7 @@ ROLLBACK; BEGIN; LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT; --- Deactivated for SplendidDataTest: \c +\c REVOKE UPDATE ON lock_table FROM regress_locktable_user; -- LOCK TABLE and DELETE permission @@ -1750,7 +1737,7 @@ ROLLBACK; BEGIN; LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT; --- Deactivated for SplendidDataTest: \c +\c REVOKE DELETE ON lock_table FROM regress_locktable_user; -- LOCK TABLE and TRUNCATE permission @@ -1765,7 +1752,7 @@ ROLLBACK; BEGIN; LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT; --- Deactivated for SplendidDataTest: \c +\c REVOKE TRUNCATE ON lock_table FROM regress_locktable_user; -- clean up @@ -1776,7 +1763,7 @@ DROP USER regress_locktable_user; -- pg_backend_memory_contexts. -- switch to superuser --- Deactivated for SplendidDataTest: \c - +\c - CREATE ROLE regress_readallstats; @@ -1796,28 +1783,3 @@ RESET ROLE; -- clean up DROP ROLE regress_readallstats; - --- test role grantor machinery -CREATE ROLE regress_group; -CREATE ROLE regress_group_direct_manager; -CREATE ROLE regress_group_indirect_manager; -CREATE ROLE regress_group_member; - --- Deactivated for SplendidDataTest: GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE; -GRANT regress_group_direct_manager TO regress_group_indirect_manager; - -SET SESSION AUTHORIZATION regress_group_direct_manager; -GRANT regress_group TO regress_group_member; -SELECT member::regrole::text, CASE WHEN grantor = 10 THEN 'BOOTSTRAP SUPERUSER' ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDER BY 1, 2; -REVOKE regress_group FROM regress_group_member; - -SET SESSION AUTHORIZATION regress_group_indirect_manager; -GRANT regress_group TO regress_group_member; -SELECT member::regrole::text, CASE WHEN grantor = 10 THEN 'BOOTSTRAP SUPERUSER' ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDER BY 1, 2; -REVOKE regress_group FROM regress_group_member; - -RESET SESSION AUTHORIZATION; -DROP ROLE regress_group; -DROP ROLE regress_group_direct_manager; -DROP ROLE regress_group_indirect_manager; -DROP ROLE regress_group_member; diff --git a/parser/src/test/resources/postgres/test/regress/sql/publication.sql b/parser/src/test/resources/postgres/test/regress/sql/publication.sql index d4cb2be..1082136 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/publication.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/publication.sql @@ -33,11 +33,11 @@ CREATE PUBLICATION testpub_xxx WITH (foo); CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum'); CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0'); --- Deactivated for SplendidDataTest: \dRp +\dRp ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete'); --- Deactivated for SplendidDataTest: \dRp +\dRp --- adding tables CREATE SCHEMA pub_test; @@ -71,13 +71,13 @@ CREATE PUBLICATION testpub_fortable FOR TABLE testpub_tbl1; RESET client_min_messages; -- should be able to add schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test; --- Deactivated for SplendidDataTest: \dRp+ testpub_fortable +\dRp+ testpub_fortable -- should be able to drop schema from 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test; --- Deactivated for SplendidDataTest: \dRp+ testpub_fortable +\dRp+ testpub_fortable -- should be able to set schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test; --- Deactivated for SplendidDataTest: \dRp+ testpub_fortable +\dRp+ testpub_fortable SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test; @@ -85,26 +85,30 @@ CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test; -- schema CREATE PUBLICATION testpub_for_tbl_schema FOR TABLES IN SCHEMA pub_test, TABLE pub_test.testpub_nopk; RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub_for_tbl_schema +\dRp+ testpub_for_tbl_schema + +-- weird parser corner case +-- Deactivated for SplendidDataTest: CREATE PUBLICATION testpub_parsertst FOR TABLE pub_test.testpub_nopk, CURRENT_SCHEMA; +-- Deactivated for SplendidDataTest: CREATE PUBLICATION testpub_parsertst FOR TABLES IN SCHEMA foo, test.foo; -- should be able to add a table of the same schema to the schema publication ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk; --- Deactivated for SplendidDataTest: \dRp+ testpub_forschema +\dRp+ testpub_forschema -- should be able to drop the table ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk; --- Deactivated for SplendidDataTest: \dRp+ testpub_forschema +\dRp+ testpub_forschema -- fail - can't drop a table from the schema publication which isn't in the -- publication ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk; -- should be able to set table to schema publication ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk; --- Deactivated for SplendidDataTest: \dRp+ testpub_forschema +\dRp+ testpub_forschema SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_foralltables'; --- Deactivated for SplendidDataTest: \d+ testpub_tbl2 --- Deactivated for SplendidDataTest: \dRp+ testpub_foralltables +\d+ testpub_tbl2 +\dRp+ testpub_foralltables DROP TABLE testpub_tbl2; DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema; @@ -115,8 +119,8 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub3 FOR TABLE testpub_tbl3; CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl3; RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub3 --- Deactivated for SplendidDataTest: \dRp+ testpub4 +\dRp+ testpub3 +\dRp+ testpub4 DROP TABLE testpub_tbl3, testpub_tbl3a; DROP PUBLICATION testpub3, testpub4; @@ -135,7 +139,7 @@ ALTER TABLE testpub_parted ATTACH PARTITION testpub_parted2 FOR VALUES IN (2); UPDATE testpub_parted1 SET a = 1; -- only parent is listed as being in publication, not the partition ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted; --- Deactivated for SplendidDataTest: \dRp+ testpub_forparted +\dRp+ testpub_forparted -- works despite missing REPLICA IDENTITY, because no actual update happened UPDATE testpub_parted SET a = 1 WHERE false; -- should now fail, because parent's publication replicates updates @@ -144,7 +148,7 @@ ALTER TABLE testpub_parted DETACH PARTITION testpub_parted1; -- works again, because parent's publication is no longer considered UPDATE testpub_parted1 SET a = 1; ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true); --- Deactivated for SplendidDataTest: \dRp+ testpub_forparted +\dRp+ testpub_forparted -- still fail, because parent's publication replicates updates UPDATE testpub_parted2 SET a = 2; ALTER PUBLICATION testpub_forparted DROP TABLE testpub_parted; @@ -168,34 +172,34 @@ SET client_min_messages = 'ERROR'; -- validation of referenced columns is less strict than for delete/update. CREATE PUBLICATION testpub5 FOR TABLE testpub_rf_tbl1, testpub_rf_tbl2 WHERE (c <> 'test' AND d < 5) WITH (publish = 'insert'); RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub5 --- Deactivated for SplendidDataTest: \d testpub_rf_tbl3 +\dRp+ testpub5 +\d testpub_rf_tbl3 ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 2000); --- Deactivated for SplendidDataTest: \dRp+ testpub5 --- Deactivated for SplendidDataTest: \d testpub_rf_tbl3 +\dRp+ testpub5 +\d testpub_rf_tbl3 ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2; --- Deactivated for SplendidDataTest: \dRp+ testpub5 +\dRp+ testpub5 -- remove testpub_rf_tbl1 and add testpub_rf_tbl3 again (another WHERE expression) ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500); --- Deactivated for SplendidDataTest: \dRp+ testpub5 --- Deactivated for SplendidDataTest: \d testpub_rf_tbl3 +\dRp+ testpub5 +\d testpub_rf_tbl3 -- test \d (now it displays filter information) SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_rf_yes FOR TABLE testpub_rf_tbl1 WHERE (a > 1) WITH (publish = 'insert'); CREATE PUBLICATION testpub_rf_no FOR TABLE testpub_rf_tbl1; RESET client_min_messages; --- Deactivated for SplendidDataTest: \d testpub_rf_tbl1 +\d testpub_rf_tbl1 DROP PUBLICATION testpub_rf_yes, testpub_rf_no; -- some more syntax tests to exercise other parser pathways SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax1 FOR TABLE testpub_rf_tbl1, ONLY testpub_rf_tbl3 WHERE (e < 999) WITH (publish = 'insert'); RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub_syntax1 +\dRp+ testpub_syntax1 DROP PUBLICATION testpub_syntax1; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax2 FOR TABLE testpub_rf_tbl1, testpub_rf_schema1.testpub_rf_tbl5 WHERE (h < 999) WITH (publish = 'insert'); RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub_syntax2 +\dRp+ testpub_syntax2 DROP PUBLICATION testpub_syntax2; -- fail - schemas don't allow WHERE clause SET client_min_messages = 'ERROR'; @@ -262,7 +266,7 @@ CREATE PUBLICATION testpub6 FOR TABLES IN SCHEMA testpub_rf_schema2; -- should be able to set publication with schema and table of the same schema ALTER PUBLICATION testpub6 SET TABLES IN SCHEMA testpub_rf_schema2, TABLE testpub_rf_schema2.testpub_rf_tbl6 WHERE (i < 99); RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub6 +\dRp+ testpub6 DROP TABLE testpub_rf_tbl1; DROP TABLE testpub_rf_tbl2; @@ -446,7 +450,7 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_table_ins WITH (publish = 'insert, truncate'); RESET client_min_messages; ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a); -- ok --- Deactivated for SplendidDataTest: \dRp+ testpub_table_ins +\dRp+ testpub_table_ins -- tests with REPLICA IDENTITY FULL CREATE TABLE testpub_tbl6 (a int, b text, c text); @@ -462,13 +466,13 @@ UPDATE testpub_tbl6 SET a = 1; -- make sure changing the column list is propagated to the catalog CREATE TABLE testpub_tbl7 (a int primary key, b text, c text); ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl7 (a, b); --- Deactivated for SplendidDataTest: \d+ testpub_tbl7 +\d+ testpub_tbl7 -- ok: the column list is the same, we should skip this table (or at least not fail) ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl7 (a, b); --- Deactivated for SplendidDataTest: \d+ testpub_tbl7 +\d+ testpub_tbl7 -- ok: the column list changes, make sure the catalog gets updated ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl7 (a, c); --- Deactivated for SplendidDataTest: \d+ testpub_tbl7 +\d+ testpub_tbl7 -- column list for partitioned tables has to cover replica identities for -- all child relations @@ -578,8 +582,8 @@ RESET client_min_messages; CREATE TABLE testpub_tbl_both_filters (a int, b int, c int, PRIMARY KEY (a,c)); ALTER TABLE testpub_tbl_both_filters REPLICA IDENTITY USING INDEX testpub_tbl_both_filters_pkey; ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c) WHERE (c != 1); --- Deactivated for SplendidDataTest: \dRp+ testpub_both_filters --- Deactivated for SplendidDataTest: \d+ testpub_tbl_both_filters +\dRp+ testpub_both_filters +\d+ testpub_tbl_both_filters DROP TABLE testpub_tbl_both_filters; DROP PUBLICATION testpub_both_filters; @@ -746,7 +750,7 @@ ALTER PUBLICATION testpub_fortbl ADD TABLE testpub_tbl1; -- fail - already added CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1; --- Deactivated for SplendidDataTest: \dRp+ testpub_fortbl +\dRp+ testpub_fortbl -- fail - view ALTER PUBLICATION testpub_default ADD TABLE testpub_view; @@ -757,15 +761,15 @@ ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk; ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; --- Deactivated for SplendidDataTest: \d+ pub_test.testpub_nopk --- Deactivated for SplendidDataTest: \d+ testpub_tbl1 --- Deactivated for SplendidDataTest: \dRp+ testpub_default +\d+ pub_test.testpub_nopk +\d+ testpub_tbl1 +\dRp+ testpub_default ALTER PUBLICATION testpub_default DROP TABLE testpub_tbl1, pub_test.testpub_nopk; -- fail - nonexistent ALTER PUBLICATION testpub_default DROP TABLE pub_test.testpub_nopk; --- Deactivated for SplendidDataTest: \d+ testpub_tbl1 +\d+ testpub_tbl1 -- verify relation cache invalidation when a primary key is added using -- an existing index @@ -825,7 +829,7 @@ REVOKE CREATE ON DATABASE regression FROM regress_publication_user2; DROP TABLE testpub_parted; DROP TABLE testpub_tbl1; --- Deactivated for SplendidDataTest: \dRp+ testpub_default +\dRp+ testpub_default -- fail - must be owner of publication SET ROLE regress_publication_user_dummy; @@ -834,14 +838,14 @@ RESET ROLE; ALTER PUBLICATION testpub_default RENAME TO testpub_foo; --- Deactivated for SplendidDataTest: \dRp testpub_foo +\dRp testpub_foo -- rename back to keep the rest simple ALTER PUBLICATION testpub_foo RENAME TO testpub_default; ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2; --- Deactivated for SplendidDataTest: \dRp testpub_default +\dRp testpub_default -- adding schemas and tables CREATE SCHEMA pub_test1; @@ -856,10 +860,10 @@ CREATE TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"(id int); -- suppress warning that depends on wal_level SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2, pub_test3; --- Deactivated for SplendidDataTest: \dRp+ testpub2_forschema +\dRp+ testpub2_forschema -- check create publication on CURRENT_SCHEMA CREATE PUBLICATION testpub3_forschema FOR TABLES IN SCHEMA CURRENT_SCHEMA; @@ -870,11 +874,11 @@ CREATE PUBLICATION testpub_fortable FOR TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"; RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub3_forschema --- Deactivated for SplendidDataTest: \dRp+ testpub4_forschema --- Deactivated for SplendidDataTest: \dRp+ testpub5_forschema --- Deactivated for SplendidDataTest: \dRp+ testpub6_forschema --- Deactivated for SplendidDataTest: \dRp+ testpub_fortable +\dRp+ testpub3_forschema +\dRp+ testpub4_forschema +\dRp+ testpub5_forschema +\dRp+ testpub6_forschema +\dRp+ testpub_fortable -- check create publication on CURRENT_SCHEMA where search_path is not set SET SEARCH_PATH=''; @@ -899,55 +903,55 @@ CREATE PUBLICATION testpub1_forschema1 FOR TABLES IN SCHEMA testpub_view; -- dropping the schema should reflect the change in publication DROP SCHEMA pub_test3; --- Deactivated for SplendidDataTest: \dRp+ testpub2_forschema +\dRp+ testpub2_forschema -- renaming the schema should reflect the change in publication ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed; --- Deactivated for SplendidDataTest: \dRp+ testpub2_forschema +\dRp+ testpub2_forschema ALTER SCHEMA pub_test1_renamed RENAME to pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub2_forschema +\dRp+ testpub2_forschema -- alter publication add schema --- Deactivated for SplendidDataTest: ALTER PUBLICATION testpub1_forschema ADD ALL TABLES IN SCHEMA pub_test2; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +-- Deactivated for SplendidDataTest: ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2; +\dRp+ testpub1_forschema -- add non existent schema ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA non_existent_schema; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- add a schema which is already added to the publication ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- alter publication drop schema ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- drop schema that is not present in the publication ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- drop a schema that does not exist in the system ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA non_existent_schema; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- drop all schemas ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- alter publication set multiple schema ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- alter publication set non-existent schema ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA non_existent_schema; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- alter publication set it duplicate schemas should set the schemas after -- removing the duplicate schemas ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub1_forschema +\dRp+ testpub1_forschema -- Verify that it fails to add a schema with a column specification -- Deactivated for SplendidDataTest: ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA foo (a, b); @@ -1014,9 +1018,9 @@ UPDATE pub_testpart1.child_parent2 set a = 1; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub3_forschema; RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub3_forschema +\dRp+ testpub3_forschema ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1; --- Deactivated for SplendidDataTest: \dRp+ testpub3_forschema +\dRp+ testpub3_forschema -- create publication including both 'FOR TABLE' and 'FOR TABLES IN SCHEMA' SET client_min_messages = 'ERROR'; @@ -1024,8 +1028,8 @@ CREATE PUBLICATION testpub_forschema_fortable FOR TABLES IN SCHEMA pub_test1, TA CREATE PUBLICATION testpub_fortable_forschema FOR TABLE pub_test2.tbl1, TABLES IN SCHEMA pub_test1; RESET client_min_messages; --- Deactivated for SplendidDataTest: \dRp+ testpub_forschema_fortable --- Deactivated for SplendidDataTest: \dRp+ testpub_fortable_forschema +\dRp+ testpub_forschema_fortable +\dRp+ testpub_fortable_forschema -- fail specifying table without any of 'FOR TABLES IN SCHEMA' or --'FOR TABLE' or 'FOR ALL TABLES' @@ -1101,6 +1105,85 @@ DROP TABLE sch1.tbl1; DROP SCHEMA sch1 cascade; DROP SCHEMA sch2 cascade; +-- Test that the INSERT ON CONFLICT command correctly checks REPLICA IDENTITY +-- when the target table is published. +CREATE TABLE testpub_insert_onconfl_no_ri (a int unique, b int); +CREATE TABLE testpub_insert_onconfl_parted (a int unique, b int) PARTITION by RANGE (a); +CREATE TABLE testpub_insert_onconfl_part_no_ri PARTITION OF testpub_insert_onconfl_parted FOR VALUES FROM (1) TO (10); + +SET client_min_messages = 'ERROR'; +CREATE PUBLICATION pub1 FOR ALL TABLES; +RESET client_min_messages; + +-- fail - missing REPLICA IDENTITY +INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2; + +-- ok - no updates +INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT DO NOTHING; + +-- fail - missing REPLICA IDENTITY in partition testpub_insert_onconfl_no_ri +INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2; + +-- ok - no updates +INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT DO NOTHING; + +DROP PUBLICATION pub1; +DROP TABLE testpub_insert_onconfl_no_ri; +DROP TABLE testpub_insert_onconfl_parted; + +-- Test that the MERGE command correctly checks REPLICA IDENTITY when the +-- target table is published. +CREATE TABLE testpub_merge_no_ri (a int, b int); +CREATE TABLE testpub_merge_pk (a int primary key, b int); + +SET client_min_messages = 'ERROR'; +CREATE PUBLICATION pub1 FOR ALL TABLES; +RESET client_min_messages; + +-- fail - missing REPLICA IDENTITY +MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 + WHEN MATCHED THEN UPDATE SET b = s.b; + +-- fail - missing REPLICA IDENTITY +MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 + WHEN MATCHED THEN DELETE; + +-- ok - insert and do nothing are not restricted +MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 + WHEN MATCHED THEN DO NOTHING + WHEN NOT MATCHED THEN INSERT (a, b) VALUES (0, 0); + +-- ok - REPLICA IDENTITY is DEFAULT and table has a PK +MERGE INTO testpub_merge_pk USING testpub_merge_no_ri s ON s.a >= 1 + WHEN MATCHED AND s.a > 0 THEN UPDATE SET b = s.b + WHEN MATCHED THEN DELETE; + +DROP PUBLICATION pub1; +DROP TABLE testpub_merge_no_ri; +DROP TABLE testpub_merge_pk; + RESET SESSION AUTHORIZATION; DROP ROLE regress_publication_user, regress_publication_user2; DROP ROLE regress_publication_user_dummy; + +-- stage objects for pg_dump tests +CREATE SCHEMA pubme CREATE TABLE t0 (c int, d int) CREATE TABLE t1 (c int); +CREATE SCHEMA pubme2 CREATE TABLE t0 (c int, d int); +SET client_min_messages = 'ERROR'; +CREATE PUBLICATION dump_pub_qual_1ct FOR + TABLE ONLY pubme.t0 (c, d) WHERE (c > 0); +CREATE PUBLICATION dump_pub_qual_2ct FOR + TABLE ONLY pubme.t0 (c) WHERE (c > 0), + TABLE ONLY pubme.t1 (c); +CREATE PUBLICATION dump_pub_nsp_1ct FOR + TABLES IN SCHEMA pubme; +CREATE PUBLICATION dump_pub_nsp_2ct FOR + TABLES IN SCHEMA pubme, + TABLES IN SCHEMA pubme2; +CREATE PUBLICATION dump_pub_all FOR + TABLE ONLY pubme.t0, + TABLE ONLY pubme.t1 WHERE (c < 0), + TABLES IN SCHEMA pubme, + TABLES IN SCHEMA pubme2 + WITH (publish_via_partition_root = true); +RESET client_min_messages; diff --git a/parser/src/test/resources/postgres/test/regress/sql/rangefuncs.sql b/parser/src/test/resources/postgres/test/regress/sql/rangefuncs.sql index 63351e1..3c47c98 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/rangefuncs.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/rangefuncs.sql @@ -815,3 +815,13 @@ select * from from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb]) as unnested_modules(module)) as ss, jsonb_to_recordset(ss.lecture) as j (id text); + +-- check detection of mismatching record types with a const-folded expression + +with a(b) as (values (row(1,2,3))) +select * from a, coalesce(b) as c(d int, e int); -- fail +with a(b) as (values (row(1,2,3))) +select * from a, coalesce(b) as c(d int, e int, f int, g int); -- fail +with a(b) as (values (row(1,2,3))) +select * from a, coalesce(b) as c(d int, e int, f float); -- fail +select * from int8_tbl, coalesce(row(1)) as (a int, b int); -- fail diff --git a/parser/src/test/resources/postgres/test/regress/sql/replica_identity.sql b/parser/src/test/resources/postgres/test/regress/sql/replica_identity.sql index 33da829..14620b7 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/replica_identity.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/replica_identity.sql @@ -98,7 +98,27 @@ ALTER TABLE test_replica_identity3 ALTER COLUMN id TYPE bigint; -- used as replica identity. ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL; +-- +-- Test that replica identity can be set on an index that's not yet valid. +-- (This matches the way pg_dump will try to dump a partitioned table.) +-- +CREATE TABLE test_replica_identity4(id integer NOT NULL) PARTITION BY LIST (id); +CREATE TABLE test_replica_identity4_1(id integer NOT NULL); +ALTER TABLE ONLY test_replica_identity4 + ATTACH PARTITION test_replica_identity4_1 FOR VALUES IN (1); +ALTER TABLE ONLY test_replica_identity4 + ADD CONSTRAINT test_replica_identity4_pkey PRIMARY KEY (id); +ALTER TABLE ONLY test_replica_identity4 + REPLICA IDENTITY USING INDEX test_replica_identity4_pkey; +ALTER TABLE ONLY test_replica_identity4_1 + ADD CONSTRAINT test_replica_identity4_1_pkey PRIMARY KEY (id); +\d+ test_replica_identity4 +ALTER INDEX test_replica_identity4_pkey + ATTACH PARTITION test_replica_identity4_1_pkey; +\d+ test_replica_identity4 + DROP TABLE test_replica_identity; DROP TABLE test_replica_identity2; DROP TABLE test_replica_identity3; +DROP TABLE test_replica_identity4; DROP TABLE test_replica_identity_othertable; diff --git a/parser/src/test/resources/postgres/test/regress/sql/returning.sql b/parser/src/test/resources/postgres/test/regress/sql/returning.sql index a460f82..8a2a2a5 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/returning.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/returning.sql @@ -132,6 +132,30 @@ DELETE FROM foo WHERE f2 = 'zit' RETURNING *; SELECT * FROM foo; SELECT * FROM voo; +-- Check use of a whole-row variable for an un-flattenable view +CREATE TEMP VIEW foo_v AS SELECT * FROM foo OFFSET 0; +UPDATE foo SET f2 = foo_v.f2 FROM foo_v WHERE foo_v.f1 = foo.f1 + RETURNING foo_v; +SELECT * FROM foo; + +-- Check use of a whole-row variable for an inlined set-returning function +CREATE FUNCTION foo_f() RETURNS SETOF foo AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; +SELECT * FROM foo; +DROP FUNCTION foo_f(); + +-- As above, but SRF is defined to return a composite type +CREATE TYPE foo_t AS (f1 int, f2 text, f3 int, f4 int8); +CREATE FUNCTION foo_f() RETURNS SETOF foo_t AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; +SELECT * FROM foo; +DROP FUNCTION foo_f(); +DROP TYPE foo_t; + -- Try a join case CREATE TEMP TABLE joinme (f2j text, other int); diff --git a/parser/src/test/resources/postgres/test/regress/sql/rowsecurity.sql b/parser/src/test/resources/postgres/test/regress/sql/rowsecurity.sql index 8b17624..e7e1607 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/rowsecurity.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/rowsecurity.sql @@ -98,23 +98,23 @@ INSERT INTO document VALUES ALTER TABLE document ENABLE ROW LEVEL SECURITY; -- user's security level must be higher than or equal to document's -CREATE POLICY p1 ON document AS PERMISSIVE - USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); +-- Deactivated for SplendidDataTest: CREATE POLICY p1 ON document AS PERMISSIVE +-- Deactivated for SplendidDataTest: USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); -- try to create a policy of bogus type -CREATE POLICY p1 ON document AS UGLY - USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); +-- Deactivated for SplendidDataTest: CREATE POLICY p1 ON document AS UGLY +-- Deactivated for SplendidDataTest: USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); -- but Dave isn't allowed to anything at cid 50 or above -- this is to make sure that we sort the policies by name first -- when applying WITH CHECK, a later INSERT by Dave should fail due -- to p1r first -CREATE POLICY p2r ON document AS RESTRICTIVE TO regress_rls_dave - USING (cid <> 44 AND cid < 50); +-- Deactivated for SplendidDataTest: CREATE POLICY p2r ON document AS RESTRICTIVE TO regress_rls_dave +-- Deactivated for SplendidDataTest: USING (cid <> 44 AND cid < 50); -- and Dave isn't allowed to see manga documents -CREATE POLICY p1r ON document AS RESTRICTIVE TO regress_rls_dave - USING (cid <> 44); +-- Deactivated for SplendidDataTest: CREATE POLICY p1r ON document AS RESTRICTIVE TO regress_rls_dave +-- Deactivated for SplendidDataTest: USING (cid <> 44); \dp \d document @@ -357,12 +357,12 @@ ALTER TABLE part_document ENABLE ROW LEVEL SECURITY; -- Create policy on parent -- user's security level must be higher than or equal to document's -CREATE POLICY pp1 ON part_document AS PERMISSIVE - USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); +-- Deactivated for SplendidDataTest: CREATE POLICY pp1 ON part_document AS PERMISSIVE +-- Deactivated for SplendidDataTest: USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user)); -- Dave is only allowed to see cid < 55 -CREATE POLICY pp1r ON part_document AS RESTRICTIVE TO regress_rls_dave - USING (cid < 55); +-- Deactivated for SplendidDataTest: CREATE POLICY pp1r ON part_document AS RESTRICTIVE TO regress_rls_dave +-- Deactivated for SplendidDataTest: USING (cid < 55); \d+ part_document SELECT * FROM pg_policies WHERE schemaname = 'regress_rls_schema' AND tablename like '%part_document%' ORDER BY policyname; @@ -401,8 +401,8 @@ SELECT * FROM part_document_satire WHERE f_leak(dtitle) ORDER BY did; -- Turn on RLS and create policy on child to show RLS is checked before constraints SET SESSION AUTHORIZATION regress_rls_alice; ALTER TABLE part_document_satire ENABLE ROW LEVEL SECURITY; -CREATE POLICY pp3 ON part_document_satire AS RESTRICTIVE - USING (cid < 55); +-- Deactivated for SplendidDataTest: CREATE POLICY pp3 ON part_document_satire AS RESTRICTIVE +-- Deactivated for SplendidDataTest: USING (cid < 55); -- This should fail with RLS violation now. SET SESSION AUTHORIZATION regress_rls_dave; INSERT INTO part_document_satire VALUES (101, 55, 1, 'regress_rls_dave', 'testing RLS with partitions'); -- fail @@ -462,8 +462,8 @@ SELECT * FROM part_document_satire ORDER by did; -- Check behavior with a policy that uses a SubPlan not an InitPlan. SET SESSION AUTHORIZATION regress_rls_alice; SET row_security TO ON; -CREATE POLICY pp3 ON part_document AS RESTRICTIVE - USING ((SELECT dlevel <= seclv FROM uaccount WHERE pguser = current_user)); +-- Deactivated for SplendidDataTest: CREATE POLICY pp3 ON part_document AS RESTRICTIVE +-- Deactivated for SplendidDataTest: USING ((SELECT dlevel <= seclv FROM uaccount WHERE pguser = current_user)); SET SESSION AUTHORIZATION regress_rls_carol; INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_carol', 'testing pp3'); -- fail @@ -830,10 +830,10 @@ ALTER TABLE document ADD COLUMN dnotes text DEFAULT ''; CREATE POLICY p1 ON document FOR SELECT USING (true); -- one may insert documents only authored by them CREATE POLICY p2 ON document FOR INSERT WITH CHECK (dauthor = current_user); --- one may only update documents in 'novel' category +-- one may only update documents in 'novel' category and new dlevel must be > 0 CREATE POLICY p3 ON document FOR UPDATE USING (cid = (SELECT cid from category WHERE cname = 'novel')) - WITH CHECK (dauthor = current_user); + WITH CHECK (dlevel > 0); -- one may only delete documents in 'manga' category CREATE POLICY p4 ON document FOR DELETE USING (cid = (SELECT cid from category WHERE cname = 'manga')); @@ -842,12 +842,12 @@ SELECT * FROM document; SET SESSION AUTHORIZATION regress_rls_bob; --- Fails, since update violates WITH CHECK qual on dauthor +-- Fails, since update violates WITH CHECK qual on dlevel MERGE INTO document d USING (SELECT 1 as sdid) s ON did = s.sdid WHEN MATCHED THEN - UPDATE SET dnotes = dnotes || ' notes added by merge1 ', dauthor = 'regress_rls_alice'; + UPDATE SET dnotes = dnotes || ' notes added by merge1 ', dlevel = 0; -- Should be OK since USING and WITH CHECK quals pass MERGE INTO document d @@ -856,12 +856,12 @@ ON did = s.sdid WHEN MATCHED THEN UPDATE SET dnotes = dnotes || ' notes added by merge2 '; --- Even when dauthor is updated explicitly, but to the existing value +-- Even when dlevel is updated explicitly, but to the existing value MERGE INTO document d USING (SELECT 1 as sdid) s ON did = s.sdid WHEN MATCHED THEN - UPDATE SET dnotes = dnotes || ' notes added by merge3 ', dauthor = 'regress_rls_bob'; + UPDATE SET dnotes = dnotes || ' notes added by merge3 ', dlevel = 1; -- There is a MATCH for did = 3, but UPDATE's USING qual does not allow -- updating an item in category 'science fiction' @@ -901,6 +901,15 @@ WHEN MATCHED AND dnotes <> '' THEN WHEN MATCHED THEN DELETE; +-- OK if DELETE is replaced with DO NOTHING +MERGE INTO document d +USING (SELECT 4 as sdid) s +ON did = s.sdid +WHEN MATCHED AND dnotes <> '' THEN + UPDATE SET dnotes = dnotes || ' notes added by merge ' +WHEN MATCHED THEN + DO NOTHING; + SELECT * FROM document WHERE did = 4; -- Switch to regress_rls_carol role and try the DELETE again. It should succeed @@ -950,24 +959,49 @@ WHEN NOT MATCHED THEN INSERT VALUES (12, 11, 1, 'regress_rls_bob', 'another novel'); -- drop and create a new SELECT policy which prevents us from reading --- any document except with category 'magna' +-- any document except with category 'novel' RESET SESSION AUTHORIZATION; DROP POLICY p1 ON document; CREATE POLICY p1 ON document FOR SELECT - USING (cid = (SELECT cid from category WHERE cname = 'manga')); + USING (cid = (SELECT cid from category WHERE cname = 'novel')); SET SESSION AUTHORIZATION regress_rls_bob; -- MERGE can no longer see the matching row and hence attempts the -- NOT MATCHED action, which results in unique key violation MERGE INTO document d -USING (SELECT 1 as sdid) s +USING (SELECT 7 as sdid) s ON did = s.sdid WHEN MATCHED THEN UPDATE SET dnotes = dnotes || ' notes added by merge5 ' WHEN NOT MATCHED THEN INSERT VALUES (12, 11, 1, 'regress_rls_bob', 'another novel'); +-- UPDATE action fails if new row is not visible +MERGE INTO document d +USING (SELECT 1 as sdid) s +ON did = s.sdid +WHEN MATCHED THEN + UPDATE SET dnotes = dnotes || ' notes added by merge6 ', + cid = (SELECT cid from category WHERE cname = 'technology'); + +-- but OK if new row is visible +MERGE INTO document d +USING (SELECT 1 as sdid) s +ON did = s.sdid +WHEN MATCHED THEN + UPDATE SET dnotes = dnotes || ' notes added by merge7 ', + cid = (SELECT cid from category WHERE cname = 'novel'); + +-- OK to insert a new row that is not visible +MERGE INTO document d +USING (SELECT 13 as sdid) s +ON did = s.sdid +WHEN MATCHED THEN + UPDATE SET dnotes = dnotes || ' notes added by merge8 ' +WHEN NOT MATCHED THEN + INSERT VALUES (13, 44, 1, 'regress_rls_bob', 'new manga'); + RESET SESSION AUTHORIZATION; -- drop the restrictive SELECT policy so that we can look at the -- final state of the table @@ -1086,7 +1120,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM rls_view; SET SESSION AUTHORIZATION regress_rls_alice; CREATE TABLE z1_blacklist (a int); INSERT INTO z1_blacklist VALUES (3), (4); -CREATE POLICY p3 ON z1 AS RESTRICTIVE USING (a NOT IN (SELECT a FROM z1_blacklist)); +-- Deactivated for SplendidDataTest: CREATE POLICY p3 ON z1 AS RESTRICTIVE USING (a NOT IN (SELECT a FROM z1_blacklist)); -- Query as role that is not owner of table but is owner of view without permissions. SET SESSION AUTHORIZATION regress_rls_bob; @@ -1169,7 +1203,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM rls_view; -- Policy requiring access to another table. SET SESSION AUTHORIZATION regress_rls_alice; -CREATE POLICY p3 ON z1 AS RESTRICTIVE USING (a NOT IN (SELECT a FROM z1_blacklist)); +-- Deactivated for SplendidDataTest: CREATE POLICY p3 ON z1 AS RESTRICTIVE USING (a NOT IN (SELECT a FROM z1_blacklist)); -- Query as role that is not owner of table but is owner of view without permissions. SET SESSION AUTHORIZATION regress_rls_bob; @@ -1552,6 +1586,40 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied SET row_security TO ON; COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied +-- Check behavior with a child table. +RESET SESSION AUTHORIZATION; +SET row_security TO ON; +CREATE TABLE copy_rel_to_child () INHERITS (copy_rel_to); +INSERT INTO copy_rel_to_child VALUES (1, 'one'), (2, 'two'); + +-- Check COPY TO as Superuser/owner. +RESET SESSION AUTHORIZATION; +SET row_security TO OFF; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; +SET row_security TO ON; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; + +-- Check COPY TO as user with permissions. +SET SESSION AUTHORIZATION regress_rls_bob; +SET row_security TO OFF; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS +SET row_security TO ON; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok + +-- Check COPY TO as user with permissions and BYPASSRLS +SET SESSION AUTHORIZATION regress_rls_exempt_user; +SET row_security TO OFF; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok +SET row_security TO ON; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok + +-- Check COPY TO as user without permissions. SET row_security TO OFF; +SET SESSION AUTHORIZATION regress_rls_carol; +SET row_security TO OFF; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied +SET row_security TO ON; +COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied + -- Check COPY FROM as Superuser/owner. RESET SESSION AUTHORIZATION; SET row_security TO OFF; @@ -2087,7 +2155,7 @@ DROP VIEW rls_view; DROP TABLE rls_tbl; DROP TABLE ref_tbl; --- Leaky operator test +-- Leaky operator tests CREATE TABLE rls_tbl (a int); INSERT INTO rls_tbl SELECT x/10 FROM generate_series(1, 100) x; ANALYZE rls_tbl; @@ -2102,9 +2170,58 @@ CREATE FUNCTION op_leak(int, int) RETURNS bool CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); SELECT * FROM rls_tbl WHERE a <<< 1000; +RESET SESSION AUTHORIZATION; + +CREATE TABLE rls_child_tbl () INHERITS (rls_tbl); +INSERT INTO rls_child_tbl SELECT x/10 FROM generate_series(1, 100) x; +ANALYZE rls_child_tbl; + +CREATE TABLE rls_ptbl (a int) PARTITION BY RANGE (a); +CREATE TABLE rls_part PARTITION OF rls_ptbl FOR VALUES FROM (-100) TO (100); +INSERT INTO rls_ptbl SELECT x/10 FROM generate_series(1, 100) x; +ANALYZE rls_ptbl, rls_part; + +ALTER TABLE rls_ptbl ENABLE ROW LEVEL SECURITY; +ALTER TABLE rls_part ENABLE ROW LEVEL SECURITY; +GRANT SELECT ON rls_ptbl TO regress_rls_alice; +GRANT SELECT ON rls_part TO regress_rls_alice; +CREATE POLICY p1 ON rls_tbl USING (a < 0); +CREATE POLICY p2 ON rls_ptbl USING (a < 0); +CREATE POLICY p3 ON rls_part USING (a < 0); + +SET SESSION AUTHORIZATION regress_rls_alice; +SELECT * FROM rls_tbl WHERE a <<< 1000; +SELECT * FROM rls_child_tbl WHERE a <<< 1000; +SELECT * FROM rls_ptbl WHERE a <<< 1000; +SELECT * FROM rls_part WHERE a <<< 1000; +SELECT * FROM (SELECT * FROM rls_tbl UNION ALL + SELECT * FROM rls_tbl) t WHERE a <<< 1000; +SELECT * FROM (SELECT * FROM rls_child_tbl UNION ALL + SELECT * FROM rls_child_tbl) t WHERE a <<< 1000; +RESET SESSION AUTHORIZATION; + +REVOKE SELECT ON rls_tbl FROM regress_rls_alice; +CREATE VIEW rls_tbl_view AS SELECT * FROM rls_tbl; + +ALTER TABLE rls_child_tbl ENABLE ROW LEVEL SECURITY; +GRANT SELECT ON rls_child_tbl TO regress_rls_alice; +CREATE POLICY p4 ON rls_child_tbl USING (a < 0); + +SET SESSION AUTHORIZATION regress_rls_alice; +SELECT * FROM rls_tbl WHERE a <<< 1000; +SELECT * FROM rls_tbl_view WHERE a <<< 1000; +SELECT * FROM rls_child_tbl WHERE a <<< 1000; +SELECT * FROM (SELECT * FROM rls_tbl UNION ALL + SELECT * FROM rls_tbl) t WHERE a <<< 1000; +SELECT * FROM (SELECT * FROM rls_child_tbl UNION ALL + SELECT * FROM rls_child_tbl) t WHERE a <<< 1000; DROP OPERATOR <<< (int, int); DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; +DROP TABLE rls_part; +DROP TABLE rls_ptbl; +DROP TABLE rls_child_tbl; +DROP VIEW rls_tbl_view; DROP TABLE rls_tbl; -- Bug #16006: whole-row Vars in a policy don't play nice with sub-selects @@ -2126,6 +2243,84 @@ SELECT * FROM rls_tbl; DROP TABLE rls_tbl; RESET SESSION AUTHORIZATION; +-- CVE-2023-2455: inlining an SRF may introduce an RLS dependency +create table rls_t (c text); +insert into rls_t values ('invisible to bob'); +alter table rls_t enable row level security; +grant select on rls_t to regress_rls_alice, regress_rls_bob; +create policy p1 on rls_t for select to regress_rls_alice using (true); +create policy p2 on rls_t for select to regress_rls_bob using (false); +create function rls_f () returns setof rls_t + stable language sql + as $$ select * from rls_t $$; +prepare q as select current_user, * from rls_f(); +set role regress_rls_alice; +execute q; +set role regress_rls_bob; +execute q; + +-- make sure RLS dependencies in CTEs are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ with cte as (select * from rls_t) select * from cte $$; +prepare r as select current_user, * from rls_f(); +set role regress_rls_alice; +execute r; +set role regress_rls_bob; +execute r; + +-- make sure RLS dependencies in subqueries are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select * from rls_t) _ $$; +prepare s as select current_user, * from rls_f(); +set role regress_rls_alice; +execute s; +set role regress_rls_bob; +execute s; + +-- make sure RLS dependencies in sublinks are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select exists(select * from rls_t)::text $$; +prepare t as select current_user, * from rls_f(); +set role regress_rls_alice; +execute t; +set role regress_rls_bob; +execute t; + +-- make sure RLS dependencies are handled when coercion projections are inserted +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select array_agg(c) as cs from rls_t) _ group by cs $$; +prepare u as select current_user, * from rls_f(); +set role regress_rls_alice; +execute u; +set role regress_rls_bob; +execute u; + +-- make sure RLS dependencies in security invoker views are handled +reset role; +create view rls_v with (security_invoker) as select * from rls_t; +grant select on rls_v to regress_rls_alice, regress_rls_bob; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from rls_v $$; +prepare v as select current_user, * from rls_f(); +set role regress_rls_alice; +execute v; +set role regress_rls_bob; +execute v; + +RESET ROLE; +DROP FUNCTION rls_f(); +DROP VIEW rls_v; +DROP TABLE rls_t; + -- -- Clean up objects -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/rowtypes.sql b/parser/src/test/resources/postgres/test/regress/sql/rowtypes.sql index ad5b7e1..76e4ca5 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/rowtypes.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/rowtypes.sql @@ -80,6 +80,11 @@ insert into people select ('Jim', f1, null)::fullname, current_date from pp; select (fn).first, substr((fn).last, 1, 20), length((fn).last) from people; +-- try an update on a toasted composite value, too +update people set fn.first = 'Jack'; + +select (fn).first, substr((fn).last, 1, 20), length((fn).last) from people; + -- Test row comparison semantics. Prior to PG 8.2 we did this in a totally -- non-spec-compliant way. @@ -482,6 +487,52 @@ with r(a,b) as materialized (null,row(1,2)), (null,row(null,null)), (null,null) ) select r, r is null as isnull, r is not null as isnotnull from r; +-- +-- Check parsing of indirect references to composite values (bug #18077) +-- +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select * from cte2 as t +where (select * from (select c as c1) s + where (select (c1).f1 > 0)) is not null; + +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select * from cte2 as t +where (select * from (select c as c1) s + where (select (c1).f1 > 0)) is not null; + +-- Also check deparsing of such cases +create view composite_v as +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select 1 as one from cte2 as t +where (select * from (select c as c1) s + where (select (c1).f1 > 0)) is not null; +select pg_get_viewdef('composite_v', true); +drop view composite_v; + +-- +-- Check cases where the composite comes from a proven-dummy rel (bug #18576) +-- +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss; +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss +where false; + +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t; +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t +where false; -- -- Tests for component access / FieldSelect diff --git a/parser/src/test/resources/postgres/test/regress/sql/rules.sql b/parser/src/test/resources/postgres/test/regress/sql/rules.sql index c28f36c..77964a8 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/rules.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/rules.sql @@ -1024,11 +1024,11 @@ select pg_get_viewdef('shoe'::regclass,0) as prettier; -- check multi-row VALUES in rules -- -create table rules_src(f1 int, f2 int); -create table rules_log(f1 int, f2 int, tag text); +create table rules_src(f1 int, f2 int default 0); +create table rules_log(f1 int, f2 int, tag text, id serial); insert into rules_src values(1,2), (11,12); create rule r1 as on update to rules_src do also - insert into rules_log values(old.*, 'old'), (new.*, 'new'); + insert into rules_log values(old.*, 'old', default), (new.*, 'new', default); update rules_src set f2 = f2 + 1; update rules_src set f2 = f2 * 10; select * from rules_src; @@ -1036,16 +1036,30 @@ select * from rules_log; create rule r2 as on update to rules_src do also values(old.*, 'old'), (new.*, 'new'); update rules_src set f2 = f2 / 10; +create rule r3 as on insert to rules_src do also + insert into rules_log values(null, null, '-', default), (new.*, 'new', default); +insert into rules_src values(22,23), (33,default); select * from rules_src; select * from rules_log; -create rule r3 as on delete to rules_src do notify rules_src_deletion; -\d+ rules_src +create rule r4 as on delete to rules_src do notify rules_src_deletion; -- -- Ensure an aliased target relation for insert is correctly deparsed. -- -create rule r4 as on insert to rules_src do instead insert into rules_log AS trgt SELECT NEW.* RETURNING trgt.f1, trgt.f2; -create rule r5 as on update to rules_src do instead UPDATE rules_log AS trgt SET tag = 'updated' WHERE trgt.f1 = new.f1; +create rule r5 as on insert to rules_src do instead insert into rules_log AS trgt SELECT NEW.* RETURNING trgt.f1, trgt.f2; +create rule r6 as on update to rules_src do instead UPDATE rules_log AS trgt SET tag = 'updated' WHERE trgt.f1 = new.f1; + +-- +-- Check deparse disambiguation of INSERT/UPDATE/DELETE targets. +-- +create rule r7 as on delete to rules_src do instead + with wins as (insert into int4_tbl as trgt values (0) returning *), + wupd as (update int4_tbl trgt set f1 = f1+1 returning *), + wdel as (delete from int4_tbl trgt where f1 = 0 returning *) + insert into rules_log AS trgt select old.* from wins, wupd, wdel + returning trgt.f1, trgt.f2; + +-- check display of all rules added above \d+ rules_src -- @@ -1056,9 +1070,26 @@ create table rule_dest(f1 int, f2 int[], tag text); create rule rr as on update to rule_t1 do instead UPDATE rule_dest trgt SET (f2[1], f1, tag) = (SELECT new.f2, new.f1, 'updated'::varchar) WHERE trgt.f1 = new.f1 RETURNING new.*; --- Deactivated for SplendidDataTest: \d+ rule_t1 +\d+ rule_t1 drop table rule_t1, rule_dest; +-- +-- Test implicit LATERAL references to old/new in rules +-- +CREATE TABLE rule_t1(a int, b text DEFAULT 'xxx', c int); +CREATE VIEW rule_v1 AS SELECT * FROM rule_t1; +CREATE RULE v1_ins AS ON INSERT TO rule_v1 + DO ALSO INSERT INTO rule_t1 + SELECT * FROM (SELECT a + 10 FROM rule_t1 WHERE a = NEW.a) tt; +CREATE RULE v1_upd AS ON UPDATE TO rule_v1 + DO ALSO UPDATE rule_t1 t + SET c = tt.a * 10 + FROM (SELECT a FROM rule_t1 WHERE a = OLD.a) tt WHERE t.a = tt.a; +INSERT INTO rule_v1 VALUES (1, 'a'), (2, 'b'); +UPDATE rule_v1 SET b = upper(b); +SELECT * FROM rule_t1; +DROP TABLE rule_t1 CASCADE; + -- -- check alter rename rule -- @@ -1273,6 +1304,55 @@ MERGE INTO rule_merge2 t USING (SELECT 1 AS a) s WHEN NOT MATCHED THEN INSERT VALUES (s.a, ''); +-- test deparsing +CREATE TABLE sf_target(id int, data text, filling int[]); + +CREATE FUNCTION merge_sf_test() + RETURNS void + LANGUAGE sql +BEGIN ATOMIC + MERGE INTO sf_target t + USING rule_merge1 s + ON (s.a = t.id) +WHEN MATCHED + AND (s.a + t.id) = 42 + THEN UPDATE SET data = repeat(t.data, s.a) || s.b, id = length(s.b) +WHEN NOT MATCHED + AND (s.b IS NOT NULL) + THEN INSERT (data, id) + VALUES (s.b, s.a) +WHEN MATCHED + AND length(s.b || t.data) > 10 + THEN UPDATE SET data = s.b +WHEN MATCHED + AND s.a > 200 + THEN UPDATE SET filling[s.a] = t.id +WHEN MATCHED + AND s.a > 100 + THEN DELETE +WHEN MATCHED + THEN DO NOTHING +WHEN NOT MATCHED + AND s.a > 200 + THEN INSERT DEFAULT VALUES +WHEN NOT MATCHED + AND s.a > 100 + THEN INSERT (id, data) OVERRIDING USER VALUE + VALUES (s.a, DEFAULT) +WHEN NOT MATCHED + AND s.a > 0 + THEN INSERT + VALUES (s.a, s.b, DEFAULT) +WHEN NOT MATCHED + THEN INSERT (filling[1], id) + VALUES (s.a, s.a); +END; + +\sf merge_sf_test + +DROP FUNCTION merge_sf_test; +DROP TABLE sf_target; + -- -- Test enabling/disabling -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/select_parallel.sql b/parser/src/test/resources/postgres/test/regress/sql/select_parallel.sql index 62fb68c..3faf09e 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/select_parallel.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/select_parallel.sql @@ -462,3 +462,57 @@ SELECT 1 FROM tenk1_vw_sec WHERE (SELECT sum(f1) FROM int4_tbl WHERE f1 < unique1) < 100; rollback; + +-- test that function option SET ROLE works in parallel workers. +create role regress_parallel_worker; + +create function set_and_report_role() returns text as + $$ select current_setting('role') $$ language sql parallel safe + set role = regress_parallel_worker; + +create function set_role_and_error(int) returns int as + $$ select 1 / $1 $$ language sql parallel safe + set role = regress_parallel_worker; + +set force_parallel_mode = 0; +select set_and_report_role(); +select set_role_and_error(0); +set force_parallel_mode = 1; +select set_and_report_role(); +select set_role_and_error(0); +reset force_parallel_mode; + +drop function set_and_report_role(); +drop function set_role_and_error(int); +drop role regress_parallel_worker; + +-- don't freeze in ParallelFinish while holding an LWLock +BEGIN; + +CREATE FUNCTION my_cmp (int4, int4) +RETURNS int LANGUAGE sql AS +$$ + SELECT + CASE WHEN $1 < $2 THEN -1 + WHEN $1 > $2 THEN 1 + ELSE 0 + END; +$$; + +CREATE TABLE parallel_hang (i int4); +INSERT INTO parallel_hang + (SELECT * FROM generate_series(1, 400) gs); + +CREATE OPERATOR CLASS int4_custom_ops FOR TYPE int4 USING btree AS + OPERATOR 1 < (int4, int4), OPERATOR 2 <= (int4, int4), + OPERATOR 3 = (int4, int4), OPERATOR 4 >= (int4, int4), + OPERATOR 5 > (int4, int4), FUNCTION 1 my_cmp(int4, int4); + +CREATE UNIQUE INDEX parallel_hang_idx + ON parallel_hang + USING btree (i int4_custom_ops); + +SET force_parallel_mode = on; +DELETE FROM parallel_hang WHERE 380 <= i AND i <= 420; + +ROLLBACK; diff --git a/parser/src/test/resources/postgres/test/regress/sql/stats.sql b/parser/src/test/resources/postgres/test/regress/sql/stats.sql index 3960dfd..2461b4d 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/stats.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/stats.sql @@ -297,6 +297,36 @@ COMMIT; DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4; DROP TABLE prevstats; +----- +-- Test reset of some stats for shared table +----- + +-- This updates the comment of the database currently in use in +-- pg_shdescription with a fake value, then sets it back to its +-- original value. +SELECT shobj_description(d.oid, 'pg_database') as description_before + FROM pg_database d WHERE datname = current_database() \gset + +-- force some stats in pg_shdescription. +BEGIN; +SELECT current_database() as datname \gset +-- Deactivated for SplendidDataTest: COMMENT ON DATABASE :"datname" IS 'This is a test comment'; +SELECT pg_stat_force_next_flush(); +COMMIT; + +-- check that the stats are reset. +SELECT (n_tup_ins + n_tup_upd) > 0 AS has_data FROM pg_stat_all_tables + WHERE relid = 'pg_shdescription'::regclass; +SELECT pg_stat_reset_single_table_counters('pg_shdescription'::regclass); +SELECT (n_tup_ins + n_tup_upd) > 0 AS has_data FROM pg_stat_all_tables + WHERE relid = 'pg_shdescription'::regclass; + +-- set back comment +\if :{?description_before} +-- Deactivated for SplendidDataTest: COMMENT ON DATABASE :"datname" IS :'description_before'; +\else +-- Deactivated for SplendidDataTest: COMMENT ON DATABASE :"datname" IS NULL; +\endif ----- -- Test that various stats views are being properly populated @@ -314,7 +344,7 @@ SELECT pg_stat_force_next_flush(); -- Test pg_stat_wal (and make a temp table so our temp schema exists) -- Deactivated for SplendidDataTest: SELECT wal_bytes AS wal_bytes_before FROM pg_stat_wal \gset -CREATE TEMP TABLE test_stats_temp AS SELECT 17; +CREATE TABLE test_stats_temp AS SELECT 17; DROP TABLE test_stats_temp; -- Checkpoint twice: The checkpointer reports stats after reporting completion @@ -326,12 +356,6 @@ CHECKPOINT; -- Deactivated for SplendidDataTest: SELECT checkpoints_req > :rqst_ckpts_before FROM pg_stat_bgwriter; -- Deactivated for SplendidDataTest: SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal; --- Test pg_stat_get_backend_idset() and some allied functions. --- In particular, verify that their notion of backend ID matches --- our temp schema index. -SELECT (current_schemas(true))[1] = ('pg_temp_' || beid::text) AS match -FROM pg_stat_get_backend_idset() beid -WHERE pg_stat_get_backend_pid(beid) = pg_backend_pid(); ----- -- Test that resetting stats works for reset timestamp @@ -397,6 +421,26 @@ SELECT pg_stat_clear_snapshot(); SELECT pg_stat_get_snapshot_timestamp(); COMMIT; +---- +-- Changing stats_fetch_consistency in a transaction. +---- +BEGIN; +-- Stats filled under the cache mode +SET LOCAL stats_fetch_consistency = cache; +SELECT pg_stat_get_function_calls(0); +SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok; +-- Success in accessing pre-existing snapshot data. +SET LOCAL stats_fetch_consistency = snapshot; +SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok; +SELECT pg_stat_get_function_calls(0); +SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok; +-- Snapshot cleared. +SET LOCAL stats_fetch_consistency = none; +SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok; +SELECT pg_stat_get_function_calls(0); +SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok; +ROLLBACK; + ---- -- pg_stat_have_stats behavior ---- diff --git a/parser/src/test/resources/postgres/test/regress/sql/stats_ext.sql b/parser/src/test/resources/postgres/test/regress/sql/stats_ext.sql index a8f5afe..9980e16 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/stats_ext.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/stats_ext.sql @@ -48,6 +48,17 @@ CREATE STATISTICS tst ON x, x, y, x, x, (x || 'x'), (y + 1), (x || 'x'), (x || ' CREATE STATISTICS tst ON (x || 'x'), (x || 'x'), (y + 1), (x || 'x'), (x || 'x'), (y + 1), (x || 'x'), (x || 'x'), (y + 1) FROM ext_stats_test; CREATE STATISTICS tst ON (x || 'x'), (x || 'x'), y FROM ext_stats_test; CREATE STATISTICS tst (unrecognized) ON x, y FROM ext_stats_test; +-- unsupported targets +CREATE STATISTICS tst ON a FROM (VALUES (x)) AS foo; +CREATE STATISTICS tst ON a FROM foo NATURAL JOIN bar; +CREATE STATISTICS tst ON a FROM (SELECT * FROM ext_stats_test) AS foo; +CREATE STATISTICS tst ON a FROM ext_stats_test s TABLESAMPLE system (x); +CREATE STATISTICS tst ON a FROM XMLTABLE('foo' PASSING 'bar' COLUMNS a text); +CREATE FUNCTION tftest(int) returns table(a int, b int) as $$ +SELECT $1, $1+i FROM generate_series(1,5) g(i); +$$ LANGUAGE sql IMMUTABLE STRICT; +CREATE STATISTICS alt_stat2 ON a FROM tftest(1); +DROP FUNCTION tftest; -- incorrect expressions CREATE STATISTICS tst ON (y) FROM ext_stats_test; -- single column reference -- Deactivated for SplendidDataTest: CREATE STATISTICS tst ON y + z FROM ext_stats_test; -- missing parentheses @@ -65,6 +76,14 @@ DROP STATISTICS ab1_a_b_stats; ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new; RESET SESSION AUTHORIZATION; DROP ROLE regress_stats_ext; +CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1; +SELECT regexp_replace(pg_describe_object(tableoid, oid, 0), + 'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr, + pg_statistics_obj_is_visible(oid) AS visible + FROM pg_statistic_ext + WHERE stxname = 'stats_ext_temp'; +DROP STATISTICS stats_ext_temp; -- shall fail +DROP STATISTICS pg_temp.stats_ext_temp; CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1; DROP STATISTICS ab1_a_b_stats; @@ -82,7 +101,7 @@ CREATE STATISTICS ab1_b_c_stats ON b, c FROM ab1; CREATE STATISTICS ab1_a_b_c_stats ON a, b, c FROM ab1; CREATE STATISTICS ab1_b_a_stats ON b, a FROM ab1; ALTER TABLE ab1 DROP COLUMN a; --- Deactivated for SplendidDataTest: \d ab1 +\d ab1 -- Ensure statistics are dropped when table is SELECT stxname FROM pg_statistic_ext WHERE stxname LIKE 'ab1%'; DROP TABLE ab1; @@ -97,13 +116,13 @@ ANALYZE ab1; ALTER TABLE ab1 ALTER a SET STATISTICS -1; -- setting statistics target 0 skips the statistics, without printing any message, so check catalog ALTER STATISTICS ab1_a_b_stats SET STATISTICS 0; --- Deactivated for SplendidDataTest: \d ab1 +\d ab1 ANALYZE ab1; SELECT stxname, stxdndistinct, stxddependencies, stxdmcv, stxdinherit FROM pg_statistic_ext s LEFT JOIN pg_statistic_ext_data d ON (d.stxoid = s.oid) WHERE s.stxname = 'ab1_a_b_stats'; ALTER STATISTICS ab1_a_b_stats SET STATISTICS -1; --- Deactivated for SplendidDataTest: \d+ ab1 +\d+ ab1 -- partial analyze doesn't build stats either ANALYZE ab1 (a); ANALYZE ab1; @@ -147,10 +166,11 @@ DROP TABLE stxdinh, stxdinh1, stxdinh2; CREATE TABLE stxdinp(i int, a int, b int) PARTITION BY RANGE (i); CREATE TABLE stxdinp1 PARTITION OF stxdinp FOR VALUES FROM (1) TO (100); INSERT INTO stxdinp SELECT 1, a/100, a/100 FROM generate_series(1, 999) a; -CREATE STATISTICS stxdinp ON a, b FROM stxdinp; +CREATE STATISTICS stxdinp ON (a + 1), a, b FROM stxdinp; VACUUM ANALYZE stxdinp; -- partitions are processed recursively SELECT 1 FROM pg_statistic_ext WHERE stxrelid = 'stxdinp'::regclass; SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinp GROUP BY 1, 2'); +SELECT * FROM check_estimated_rows('SELECT a + 1, b FROM ONLY stxdinp GROUP BY 1, 2'); DROP TABLE stxdinp; -- basic test for statistics on expressions @@ -1595,28 +1615,20 @@ insert into stts_t1 select i,i from generate_series(1,100) i; analyze stts_t1; set search_path to public, stts_s1, stts_s2, tststats; --- Deactivated for SplendidDataTest: \dX --- Deactivated for SplendidDataTest: \dX stts_t* --- Deactivated for SplendidDataTest: \dX *stts_hoge --- Deactivated for SplendidDataTest: \dX+ --- Deactivated for SplendidDataTest: \dX+ stts_t* --- Deactivated for SplendidDataTest: \dX+ *stts_hoge --- Deactivated for SplendidDataTest: \dX+ stts_s2.stts_yama - --- Deactivated for SplendidDataTest: create statistics (mcv) ON a, b, (a+b), (a-b) FROM stts_t1; --- Deactivated for SplendidDataTest: create statistics (mcv) ON a, b, (a+b), (a-b) FROM stts_t1; --- Deactivated for SplendidDataTest: create statistics (mcv) ON (a+b), (a-b) FROM stts_t1; --- Deactivated for SplendidDataTest: \dX stts_t*expr* -drop statistics stts_t1_a_b_expr_expr_stat; -drop statistics stts_t1_a_b_expr_expr_stat1; -drop statistics stts_t1_expr_expr_stat; +\dX +\dX stts_? +\dX *stts_hoge +\dX+ +\dX+ stts_? +\dX+ *stts_hoge +\dX+ stts_s2.stts_yama set search_path to public, stts_s1; --- Deactivated for SplendidDataTest: \dX +\dX create role regress_stats_ext nosuperuser; set role regress_stats_ext; --- Deactivated for SplendidDataTest: \dX +\dX reset role; drop table stts_t1, stts_t2, stts_t3; @@ -1640,7 +1652,14 @@ CREATE FUNCTION op_leak(int, int) RETURNS bool LANGUAGE plpgsql; CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); +CREATE FUNCTION op_leak(record, record) RETURNS bool + AS 'BEGIN RAISE NOTICE ''op_leak => %, %'', $1, $2; RETURN $1 < $2; END' + LANGUAGE plpgsql; +CREATE OPERATOR <<< (procedure = op_leak, leftarg = record, rightarg = record, + restrict = scalarltsel); SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied +SELECT * FROM tststats.priv_test_tbl t + WHERE a <<< 0 AND (b <<< 0 OR t.* <<< (1, 1) IS NOT NULL); -- Permission denied DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied -- Grant access via a security barrier view, but hide all data @@ -1652,21 +1671,99 @@ GRANT SELECT, DELETE ON tststats.priv_test_view TO regress_stats_user1; -- Should now have access via the view, but see nothing and leak nothing SET SESSION AUTHORIZATION regress_stats_user1; SELECT * FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not leak +SELECT * FROM tststats.priv_test_view t + WHERE a <<< 0 AND (b <<< 0 OR t.* <<< (1, 1) IS NOT NULL); -- Should not leak DELETE FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not leak -- Grant table access, but hide all data with RLS RESET SESSION AUTHORIZATION; ALTER TABLE tststats.priv_test_tbl ENABLE ROW LEVEL SECURITY; +CREATE POLICY priv_test_tbl_pol ON tststats.priv_test_tbl USING (2 * a < 0); GRANT SELECT, DELETE ON tststats.priv_test_tbl TO regress_stats_user1; -- Should now have direct table access, but see nothing and leak nothing SET SESSION AUTHORIZATION regress_stats_user1; SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak +SELECT * FROM tststats.priv_test_tbl t + WHERE a <<< 0 AND (b <<< 0 OR t.* <<< (1, 1) IS NOT NULL); -- Should not leak DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak +-- Create plain inheritance parent table with no access permissions +RESET SESSION AUTHORIZATION; +CREATE TABLE tststats.priv_test_parent_tbl (a int, b int); +ALTER TABLE tststats.priv_test_tbl INHERIT tststats.priv_test_parent_tbl; + +-- Should not have access to parent, and should leak nothing +SET SESSION AUTHORIZATION regress_stats_user1; +SELECT * FROM tststats.priv_test_parent_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied +SELECT * FROM tststats.priv_test_parent_tbl t + WHERE a <<< 0 AND (b <<< 0 OR t.* <<< (1, 1) IS NOT NULL); -- Permission denied +DELETE FROM tststats.priv_test_parent_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied + +-- Grant table access to parent, but hide all data with RLS +RESET SESSION AUTHORIZATION; +ALTER TABLE tststats.priv_test_parent_tbl ENABLE ROW LEVEL SECURITY; +CREATE POLICY priv_test_parent_tbl_pol ON tststats.priv_test_parent_tbl USING (2 * a < 0); +GRANT SELECT, DELETE ON tststats.priv_test_parent_tbl TO regress_stats_user1; + +-- Should now have direct table access to parent, but see nothing and leak nothing +SET SESSION AUTHORIZATION regress_stats_user1; +SELECT * FROM tststats.priv_test_parent_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak +SELECT * FROM tststats.priv_test_parent_tbl t + WHERE a <<< 0 AND (b <<< 0 OR t.* <<< (1, 1) IS NOT NULL); -- Should not leak +DELETE FROM tststats.priv_test_parent_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak + +-- privilege checks for pg_stats_ext and pg_stats_ext_exprs +RESET SESSION AUTHORIZATION; +CREATE TABLE stats_ext_tbl (id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, col TEXT); +INSERT INTO stats_ext_tbl (col) VALUES ('secret'), ('secret'), ('very secret'); +CREATE STATISTICS s_col ON id, col FROM stats_ext_tbl; +CREATE STATISTICS s_expr ON mod(id, 2), lower(col) FROM stats_ext_tbl; +ANALYZE stats_ext_tbl; + +-- unprivileged role should not have access +SET SESSION AUTHORIZATION regress_stats_user1; +SELECT statistics_name, most_common_vals FROM pg_stats_ext x + WHERE tablename = 'stats_ext_tbl' ORDER BY ROW(x.*); +SELECT statistics_name, most_common_vals FROM pg_stats_ext_exprs x + WHERE tablename = 'stats_ext_tbl' ORDER BY ROW(x.*); + +-- give unprivileged role ownership of table +RESET SESSION AUTHORIZATION; +ALTER TABLE stats_ext_tbl OWNER TO regress_stats_user1; + +-- unprivileged role should now have access +SET SESSION AUTHORIZATION regress_stats_user1; +SELECT statistics_name, most_common_vals FROM pg_stats_ext x + WHERE tablename = 'stats_ext_tbl' ORDER BY ROW(x.*); +SELECT statistics_name, most_common_vals FROM pg_stats_ext_exprs x + WHERE tablename = 'stats_ext_tbl' ORDER BY ROW(x.*); + +-- CREATE STATISTICS checks for CREATE on the schema +RESET SESSION AUTHORIZATION; +CREATE SCHEMA sts_sch1 CREATE TABLE sts_sch1.tbl (a INT, b INT); +GRANT USAGE ON SCHEMA sts_sch1 TO regress_stats_user1; +ALTER TABLE sts_sch1.tbl OWNER TO regress_stats_user1; +SET SESSION AUTHORIZATION regress_stats_user1; +CREATE STATISTICS sts_sch1.fail ON a, b FROM sts_sch1.tbl; +RESET SESSION AUTHORIZATION; +GRANT CREATE ON SCHEMA sts_sch1 TO regress_stats_user1; +SET SESSION AUTHORIZATION regress_stats_user1; +CREATE STATISTICS sts_sch1.pass ON a, b FROM sts_sch1.tbl; + +-- re-creating statistics via ALTER TABLE bypasses checks for CREATE on schema +RESET SESSION AUTHORIZATION; +REVOKE CREATE ON SCHEMA sts_sch1 FROM regress_stats_user1; +SET SESSION AUTHORIZATION regress_stats_user1; +ALTER TABLE sts_sch1.tbl ALTER COLUMN a TYPE SMALLINT; + -- Tidy up DROP OPERATOR <<< (int, int); DROP FUNCTION op_leak(int, int); +DROP OPERATOR <<< (record, record); +DROP FUNCTION op_leak(record, record); RESET SESSION AUTHORIZATION; +DROP TABLE stats_ext_tbl; DROP SCHEMA tststats CASCADE; +DROP SCHEMA sts_sch1 CASCADE; DROP USER regress_stats_user1; diff --git a/parser/src/test/resources/postgres/test/regress/sql/strings.sql b/parser/src/test/resources/postgres/test/regress/sql/strings.sql index 91d02d3..6539d3d 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/strings.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/strings.sql @@ -195,6 +195,29 @@ SELECT 'abcd\efg' SIMILAR TO '_bcd\%' ESCAPE '' AS true; SELECT 'abcdefg' SIMILAR TO '_bcd%' ESCAPE NULL AS null; SELECT 'abcdefg' SIMILAR TO '_bcd#%' ESCAPE '##' AS error; +-- Characters that should be left alone in character classes when a +-- SIMILAR TO regexp pattern is converted to POSIX style. +-- Underscore "_" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '_[_[:alpha:]_]_'; +-- Percentage "%" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '%[%[:alnum:]%]%'; +-- Dot "." +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '.[.[:alnum:].].'; +-- Dollar "$" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '$[$[:alnum:]$]$'; +-- Opening parenthesis "(" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '()[([:alnum:](]()'; +-- Caret "^" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '^[^[:alnum:]^[^^][[^^]][\^][[\^]]\^]^'; +-- Closing square bracket "]" at the beginning of character class +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[]%][^]%][^%]%'; +-- Closing square bracket effective after two carets at the beginning +-- of character class. +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[^^]^'; +-- Closing square bracket after an escape sequence at the beginning of +-- a character closes the character class +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[|a]%' ESCAPE '|'; + -- Test backslash escapes in regexp_replace's replacement string SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3'); SELECT regexp_replace('foobarrbazz', E'(.)\\1', E'X\\&Y', 'g'); @@ -358,7 +381,7 @@ SELECT foo, length(foo) FROM regexp_split_to_table('thE QUick bROWn FOx jUMPs ov SELECT regexp_split_to_array('thE QUick bROWn FOx jUMPs ovEr The lazy dOG', 'e', 'g'); -- change NULL-display back --- Deactivated for SplendidDataTest: \pset null '' +\pset null '' -- E021-11 position expression SELECT POSITION('4' IN '1234567890') = '4' AS "4"; @@ -821,6 +844,7 @@ SELECT ltrim('zzzytrim', 'xyz'); SELECT translate('', '14', 'ax'); SELECT translate('12345', '14', 'ax'); +SELECT translate('12345', '134', 'a'); SELECT ascii('x'); SELECT ascii(''); diff --git a/parser/src/test/resources/postgres/test/regress/sql/subscription.sql b/parser/src/test/resources/postgres/test/regress/sql/subscription.sql index e4d4cab..54abc5a 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/subscription.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/subscription.sql @@ -63,19 +63,16 @@ CREATE SUBSCRIPTION regress_testsub3 CONNECTION 'dbname=regress_doesnotexist' PU ALTER SUBSCRIPTION regress_testsub3 ENABLE; ALTER SUBSCRIPTION regress_testsub3 REFRESH PUBLICATION; --- fail - origin must be either none or any -CREATE SUBSCRIPTION regress_testsub4 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (slot_name = NONE, connect = false, origin = foo); +DROP SUBSCRIPTION regress_testsub3; --- now it works -CREATE SUBSCRIPTION regress_testsub4 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (slot_name = NONE, connect = false, origin = none); -\dRs+ regress_testsub4 -ALTER SUBSCRIPTION regress_testsub4 SET (origin = any); -\dRs+ regress_testsub4 +-- fail, connection string does not parse +CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'i_dont_exist=param' PUBLICATION testpub; -DROP SUBSCRIPTION regress_testsub3; -DROP SUBSCRIPTION regress_testsub4; +-- fail, connection string parses, but doesn't work (and does so without +-- connecting, so this is reliable and safe) +CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'port=-1' PUBLICATION testpub; --- fail - invalid connection string +-- fail - invalid connection string during ALTER ALTER SUBSCRIPTION regress_testsub CONNECTION 'foobar'; \dRs+ diff --git a/parser/src/test/resources/postgres/test/regress/sql/subselect.sql b/parser/src/test/resources/postgres/test/regress/sql/subselect.sql index 4027670..d78510c 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/subselect.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/subselect.sql @@ -1,3 +1,10 @@ +/* + * This file has been altered by SplendidData. + * It is only used for happy flow syntax checking, so erroneous statements are commented out here. + * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: + */ + + -- -- SUBSELECT -- @@ -13,7 +20,7 @@ SELECT 1 AS zero WHERE 1 IN (SELECT 2); SELECT * FROM (SELECT 1 AS x) ss; SELECT * FROM ((SELECT 1 AS x)) ss; -SELECT * FROM ((SELECT 1 AS x)), ((SELECT * FROM ((SELECT 2 AS y)))); +-- Deactivated for SplendidDataTest: SELECT * FROM ((SELECT 1 AS x)), ((SELECT * FROM ((SELECT 2 AS y)))); (SELECT 2) UNION SELECT 2; ((SELECT 2)) UNION SELECT 2; @@ -84,15 +91,15 @@ SELECT f1 AS "Correlated Field" -- Subselects without aliases -SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road); -SELECT COUNT(*) FROM (SELECT DISTINCT name FROM road); +-- Deactivated for SplendidDataTest: SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road); +-- Deactivated for SplendidDataTest: SELECT COUNT(*) FROM (SELECT DISTINCT name FROM road); -SELECT * FROM (SELECT * FROM int4_tbl), (VALUES (123456)) WHERE f1 = column1; +-- Deactivated for SplendidDataTest: SELECT * FROM (SELECT * FROM int4_tbl), (VALUES (123456)) WHERE f1 = column1; -CREATE VIEW view_unnamed_ss AS -SELECT * FROM (SELECT * FROM (SELECT abs(f1) AS a1 FROM int4_tbl)), - (SELECT * FROM int8_tbl) - WHERE a1 < 10 AND q1 > a1 ORDER BY q1, q2; +-- Deactivated for SplendidDataTest: CREATE VIEW view_unnamed_ss AS +-- Deactivated for SplendidDataTest: SELECT * FROM (SELECT * FROM (SELECT abs(f1) AS a1 FROM int4_tbl)), +-- Deactivated for SplendidDataTest: (SELECT * FROM int8_tbl) +-- Deactivated for SplendidDataTest: WHERE a1 < 10 AND q1 > a1 ORDER BY q1, q2; SELECT * FROM view_unnamed_ss; @@ -102,10 +109,10 @@ DROP VIEW view_unnamed_ss; -- Test matching of locking clause to correct alias -CREATE VIEW view_unnamed_ss_locking AS -SELECT * FROM (SELECT * FROM int4_tbl), int8_tbl AS unnamed_subquery - WHERE f1 = q1 - FOR UPDATE OF unnamed_subquery; +-- Deactivated for SplendidDataTest: CREATE VIEW view_unnamed_ss_locking AS +-- Deactivated for SplendidDataTest: SELECT * FROM (SELECT * FROM int4_tbl), int8_tbl AS unnamed_subquery +-- Deactivated for SplendidDataTest: WHERE f1 = q1 +-- Deactivated for SplendidDataTest: FOR UPDATE OF unnamed_subquery; \sv view_unnamed_ss_locking diff --git a/parser/src/test/resources/postgres/test/regress/sql/temp.sql b/parser/src/test/resources/postgres/test/regress/sql/temp.sql index 424d12b..2a487a1 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/temp.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/temp.sql @@ -101,6 +101,22 @@ COMMIT; SELECT * FROM temptest; +-- Test it with a CHECK condition that produces a toasted pg_constraint entry +BEGIN; +do $$ +begin + execute format($cmd$ + CREATE TEMP TABLE temptest (col text CHECK (col < %L)) ON COMMIT DROP + $cmd$, + (SELECT string_agg(g.i::text || ':' || random()::text, '|') + FROM generate_series(1, 100) g(i))); +end$$; + +SELECT * FROM temptest; +COMMIT; + +SELECT * FROM temptest; + -- ON COMMIT is only allowed for TEMP CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS; diff --git a/parser/src/test/resources/postgres/test/regress/sql/timestamp.sql b/parser/src/test/resources/postgres/test/regress/sql/timestamp.sql index ebc969f..bc37803 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/timestamp.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/timestamp.sql @@ -259,6 +259,9 @@ FROM ( -- shift bins using the origin parameter: SELECT date_bin('5 min'::interval, timestamp '2020-02-01 01:01:01', timestamp '2020-02-01 00:02:30'); +-- test roundoff edge case when source < origin +SELECT date_bin('30 minutes'::interval, timestamp '2024-02-01 15:00:00', timestamp '2024-02-01 17:00:00'); + -- disallow intervals with months or years SELECT date_bin('5 months'::interval, timestamp '2020-02-01 01:01:01', timestamp '2001-01-01'); SELECT date_bin('5 years'::interval, timestamp '2020-02-01 01:01:01', timestamp '2001-01-01'); @@ -269,6 +272,11 @@ SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp -- disallow negative intervals SELECT date_bin('-2 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00'); +-- test overflow cases +select date_bin('15 minutes'::interval, timestamp '294276-12-30', timestamp '4000-12-20 BC'); +select date_bin('200000000 days'::interval, '2024-02-01'::timestamp, '2024-01-01'::timestamp); +select date_bin('365000 days'::interval, '4400-01-01 BC'::timestamp, '4000-01-01 BC'::timestamp); + -- Test casting within a BETWEEN qualifier SELECT d1 - timestamp without time zone '1997-01-02' AS diff FROM TIMESTAMP_TBL diff --git a/parser/src/test/resources/postgres/test/regress/sql/timestamptz.sql b/parser/src/test/resources/postgres/test/regress/sql/timestamptz.sql index a107abc..9bebff2 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/timestamptz.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/timestamptz.sql @@ -234,6 +234,9 @@ FROM ( -- shift bins using the origin parameter: SELECT date_bin('5 min'::interval, timestamptz '2020-02-01 01:01:01+00', timestamptz '2020-02-01 00:02:30+00'); +-- test roundoff edge case when source < origin +SELECT date_bin('30 minutes'::interval, timestamptz '2024-02-01 15:00:00', timestamptz '2024-02-01 17:00:00'); + -- disallow intervals with months or years SELECT date_bin('5 months'::interval, timestamp with time zone '2020-02-01 01:01:01+00', timestamp with time zone '2001-01-01+00'); SELECT date_bin('5 years'::interval, timestamp with time zone '2020-02-01 01:01:01+00', timestamp with time zone '2001-01-01+00'); @@ -244,6 +247,11 @@ SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:0 -- disallow negative intervals SELECT date_bin('-2 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00'); +-- test overflow cases +select date_bin('15 minutes'::interval, timestamptz '294276-12-30', timestamptz '4000-12-20 BC'); +select date_bin('200000000 days'::interval, '2024-02-01'::timestamptz, '2024-01-01'::timestamptz); +select date_bin('365000 days'::interval, '4400-01-01 BC'::timestamptz, '4000-01-01 BC'::timestamptz); + -- Test casting within a BETWEEN qualifier SELECT d1 - timestamp with time zone '1997-01-02' AS diff FROM TIMESTAMPTZ_TBL @@ -421,14 +429,18 @@ SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2') = '1973-07-15 08:15:5 -- full timezone names SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') = timestamptz '2014-12-10 00:00:00 Europe/Prague'; SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UTC'; -SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC'; +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Asia/Singapore') AT TIME ZONE 'UTC'; +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Pacific/Honolulu') AT TIME ZONE 'UTC'; SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Europe/Paris') AT TIME ZONE 'UTC'; SELECT make_timestamptz(1910, 12, 24, 0, 0, 0, 'Nehwon/Lankhmar'); -- abbreviations SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'EST'); SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'EDT'); -SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT'); +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'FOO8BAR'); + +-- POSIX +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT,M3.2.0,M11.1.0'); RESET TimeZone; diff --git a/parser/src/test/resources/postgres/test/regress/sql/timetz.sql b/parser/src/test/resources/postgres/test/regress/sql/timetz.sql index 7b70f46..8350dbb 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/timetz.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/timetz.sql @@ -77,3 +77,23 @@ SELECT date_part('microsecond', TIME WITH TIME ZONE '2020-05-26 13:30:25.575401- SELECT date_part('millisecond', TIME WITH TIME ZONE '2020-05-26 13:30:25.575401-04'); SELECT date_part('second', TIME WITH TIME ZONE '2020-05-26 13:30:25.575401-04'); SELECT date_part('epoch', TIME WITH TIME ZONE '2020-05-26 13:30:25.575401-04'); + +-- +-- Test timetz_zone, timetz_izone +-- +BEGIN; +SET LOCAL TimeZone TO 'UTC'; +CREATE VIEW timetz_local_view AS + SELECT f1 AS dat, + f1 AT TIME ZONE current_setting('TimeZone') AS dat_at_tz, + f1 AT TIME ZONE INTERVAL '00:00' AS dat_at_int + FROM TIMETZ_TBL + ORDER BY f1; +SELECT pg_get_viewdef('timetz_local_view', true); +TABLE timetz_local_view; +SELECT f1 AS dat, + f1 AT TIME ZONE 'UTC+10' AS dat_at_tz, + f1 AT TIME ZONE INTERVAL '-10:00' AS dat_at_int + FROM TIMETZ_TBL + ORDER BY f1; +ROLLBACK; diff --git a/parser/src/test/resources/postgres/test/regress/sql/transactions.sql b/parser/src/test/resources/postgres/test/regress/sql/transactions.sql index 8a90ff7..5f7ed20 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/transactions.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/transactions.sql @@ -43,24 +43,6 @@ SELECT oid FROM pg_class WHERE relname = 'disappear'; -- should have members again SELECT * FROM xacttest; --- Test that transaction characteristics cannot be reset. -BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT COUNT(*) FROM xacttest; -RESET transaction_isolation; -- error -END; - -BEGIN TRANSACTION READ ONLY; -SELECT COUNT(*) FROM xacttest; -RESET transaction_read_only; -- error -END; - -BEGIN TRANSACTION DEFERRABLE; -SELECT COUNT(*) FROM xacttest; -RESET transaction_deferrable; -- error -END; - -CREATE FUNCTION errfunc() RETURNS int LANGUAGE SQL AS 'SELECT 1' -SET transaction_read_only = on; -- error -- Read-only tests @@ -386,10 +368,10 @@ drop function inverse(int); begin; savepoint x; -create table abc (a int); -insert into abc values (5); -insert into abc values (10); -declare foo cursor for select * from abc; +create table trans_abc (a int); +insert into trans_abc values (5); +insert into trans_abc values (10); +declare foo cursor for select * from trans_abc; fetch from foo; rollback to x; @@ -399,11 +381,11 @@ commit; begin; -create table abc (a int); -insert into abc values (5); -insert into abc values (10); -insert into abc values (15); -declare foo cursor for select * from abc; +create table trans_abc (a int); +insert into trans_abc values (5); +insert into trans_abc values (10); +insert into trans_abc values (15); +declare foo cursor for select * from trans_abc; fetch from foo; @@ -449,7 +431,7 @@ DROP FUNCTION invert(x float8); -- Tests for AND CHAIN -CREATE TABLE abc (a int); +CREATE TABLE trans_abc (a int); -- set nondefault value so we have something to override below SET default_transaction_read_only = on; @@ -458,19 +440,19 @@ START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE; SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES (1); -INSERT INTO abc VALUES (2); +INSERT INTO trans_abc VALUES (1); +INSERT INTO trans_abc VALUES (2); COMMIT AND CHAIN; -- TBLOCK_END SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES ('error'); -INSERT INTO abc VALUES (3); -- check it's really aborted +INSERT INTO trans_abc VALUES ('error'); +INSERT INTO trans_abc VALUES (3); -- check it's really aborted COMMIT AND CHAIN; -- TBLOCK_ABORT_END SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES (4); +INSERT INTO trans_abc VALUES (4); COMMIT; START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE; @@ -478,12 +460,12 @@ SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; SAVEPOINT x; -INSERT INTO abc VALUES ('error'); +INSERT INTO trans_abc VALUES ('error'); COMMIT AND CHAIN; -- TBLOCK_ABORT_PENDING SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES (5); +INSERT INTO trans_abc VALUES (5); COMMIT; START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE; @@ -497,17 +479,28 @@ SHOW transaction_read_only; SHOW transaction_deferrable; COMMIT; +START TRANSACTION ISOLATION LEVEL READ COMMITTED, READ WRITE, DEFERRABLE; +SHOW transaction_isolation; +SHOW transaction_read_only; +SHOW transaction_deferrable; +SAVEPOINT x; +COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT +SHOW transaction_isolation; +SHOW transaction_read_only; +SHOW transaction_deferrable; +COMMIT; + -- different mix of options just for fun START TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE, NOT DEFERRABLE; SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES (6); +INSERT INTO trans_abc VALUES (6); ROLLBACK AND CHAIN; -- TBLOCK_ABORT_PENDING SHOW transaction_isolation; SHOW transaction_read_only; SHOW transaction_deferrable; -INSERT INTO abc VALUES ('error'); +INSERT INTO trans_abc VALUES ('error'); ROLLBACK AND CHAIN; -- TBLOCK_ABORT_END SHOW transaction_isolation; SHOW transaction_read_only; @@ -518,11 +511,11 @@ ROLLBACK; COMMIT AND CHAIN; -- error ROLLBACK AND CHAIN; -- error -SELECT * FROM abc ORDER BY 1; +SELECT * FROM trans_abc ORDER BY 1; RESET default_transaction_read_only; -DROP TABLE abc; +DROP TABLE trans_abc; -- Test assorted behaviors around the implicit transaction block created @@ -590,8 +583,8 @@ SHOW transaction_read_only; CREATE TABLE abc (a int); -- COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN --- Deactivated for SplendidDataTest: INSERT INTO abc VALUES (7)\; COMMIT\; INSERT INTO abc VALUES (8)\; COMMIT AND CHAIN; -- 7 commit, 8 error --- Deactivated for SplendidDataTest: INSERT INTO abc VALUES (9)\; ROLLBACK\; INSERT INTO abc VALUES (10)\; ROLLBACK AND CHAIN; -- 9 rollback, 10 error +INSERT INTO trans_abc VALUES (7)\; COMMIT\; INSERT INTO trans_abc VALUES (8)\; COMMIT AND CHAIN; -- 7 commit, 8 error +INSERT INTO trans_abc VALUES (9)\; ROLLBACK\; INSERT INTO trans_abc VALUES (10)\; ROLLBACK AND CHAIN; -- 9 rollback, 10 error -- COMMIT/ROLLBACK AND CHAIN + COMMIT/ROLLBACK -- Deactivated for SplendidDataTest: INSERT INTO abc VALUES (11)\; COMMIT AND CHAIN\; INSERT INTO abc VALUES (12)\; COMMIT; -- 11 error, 12 not reached diff --git a/parser/src/test/resources/postgres/test/regress/sql/triggers.sql b/parser/src/test/resources/postgres/test/regress/sql/triggers.sql index 586ecbf..c7f7ee5 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/triggers.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/triggers.sql @@ -11,12 +11,12 @@ -- -- directory paths and dlsuffix are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv libdir PG_LIBDIR --- Deactivated for SplendidDataTest: \getenv dlsuffix PG_DLSUFFIX +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX --- Deactivated for SplendidDataTest: \set autoinclib :libdir '/autoinc' :dlsuffix --- Deactivated for SplendidDataTest: \set refintlib :libdir '/refint' :dlsuffix --- Deactivated for SplendidDataTest: \set regresslib :libdir '/regress' :dlsuffix +\set autoinclib :libdir '/autoinc' :dlsuffix +\set refintlib :libdir '/refint' :dlsuffix +\set regresslib :libdir '/regress' :dlsuffix CREATE FUNCTION autoinc () RETURNS trigger @@ -697,7 +697,7 @@ CREATE TRIGGER z_min_update BEFORE UPDATE ON min_updates_test FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); --- Deactivated for SplendidDataTest: \set QUIET false +\set QUIET false UPDATE min_updates_test SET f1 = f1; @@ -705,7 +705,7 @@ UPDATE min_updates_test SET f2 = f2 + 1; UPDATE min_updates_test SET f3 = 2 WHERE f3 is null; --- Deactivated for SplendidDataTest: \set QUIET true +\set QUIET true SELECT * FROM min_updates_test; @@ -837,7 +837,7 @@ FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_upd_stmt'); CREATE TRIGGER after_del_stmt_trig AFTER DELETE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_del_stmt'); --- Deactivated for SplendidDataTest: \set QUIET false +\set QUIET false -- Insert into view using trigger INSERT INTO main_view VALUES (20, 30); @@ -859,15 +859,15 @@ UPDATE main_view SET b = 0 WHERE false; DELETE FROM main_view WHERE a IN (20,21); DELETE FROM main_view WHERE a = 31 RETURNING a, b; --- Deactivated for SplendidDataTest: \set QUIET true +\set QUIET true -- Describe view should list triggers --- Deactivated for SplendidDataTest: \d main_view +\d main_view -- Test dropping view triggers DROP TRIGGER instead_of_insert_trig ON main_view; DROP TRIGGER instead_of_delete_trig ON main_view; --- Deactivated for SplendidDataTest: \d+ main_view +\d+ main_view DROP VIEW main_view; -- @@ -968,7 +968,7 @@ $$; CREATE TRIGGER city_update_trig INSTEAD OF UPDATE ON city_view FOR EACH ROW EXECUTE PROCEDURE city_update(); --- Deactivated for SplendidDataTest: \set QUIET false +\set QUIET false -- INSERT .. RETURNING INSERT INTO city_view(city_name) VALUES('Tokyo') RETURNING *; @@ -992,7 +992,7 @@ UPDATE city_view v1 SET country_name = v2.country_name FROM city_view v2 -- DELETE .. RETURNING DELETE FROM city_view WHERE city_name = 'Birmingham' RETURNING *; --- Deactivated for SplendidDataTest: \set QUIET true +\set QUIET true -- read-only view with WHERE clause CREATE VIEW european_city_view AS @@ -1005,13 +1005,13 @@ AS 'begin RETURN NULL; end'; CREATE TRIGGER no_op_trig INSTEAD OF INSERT OR UPDATE OR DELETE ON european_city_view FOR EACH ROW EXECUTE PROCEDURE no_op_trig_fn(); --- Deactivated for SplendidDataTest: \set QUIET false +\set QUIET false INSERT INTO european_city_view VALUES (0, 'x', 10000, 'y', 'z'); UPDATE european_city_view SET population = 10000; DELETE FROM european_city_view; --- Deactivated for SplendidDataTest: \set QUIET true +\set QUIET true -- rules bypassing no-op triggers CREATE RULE european_city_insert_rule AS ON INSERT TO european_city_view @@ -1030,7 +1030,7 @@ RETURNING NEW.*; CREATE RULE european_city_delete_rule AS ON DELETE TO european_city_view DO INSTEAD DELETE FROM city_view WHERE city_id = OLD.city_id RETURNING *; --- Deactivated for SplendidDataTest: \set QUIET false +\set QUIET false -- INSERT not limited by view's WHERE clause, but UPDATE AND DELETE are INSERT INTO european_city_view(city_name, country_name) @@ -1054,7 +1054,7 @@ UPDATE city_view v SET population = 599657 RETURNING co.country_id, v.country_name, v.city_id, v.city_name, v.population; --- Deactivated for SplendidDataTest: \set QUIET true +\set QUIET true SELECT * FROM city_view; @@ -1194,9 +1194,13 @@ insert into child values (10, 1, 'b'); select * from parent; select * from child; update parent set val1 = 'b' where aid = 1; -- should fail +merge into parent p using (values (1)) as v(id) on p.aid = v.id + when matched then update set val1 = 'b'; -- should fail select * from parent; select * from child; delete from parent where aid = 1; -- should fail +merge into parent p using (values (1)) as v(id) on p.aid = v.id + when matched then delete; -- should fail select * from parent; select * from child; -- replace the trigger function with one that restarts the deletion after @@ -1450,7 +1454,7 @@ select tgrelid::regclass, tgname, tgfoid::regproc from pg_trigger -- check detach behavior create trigger trg1 after insert on trigpart for each row execute procedure trigger_nothing(); --- Deactivated for SplendidDataTest: \d trigpart3 +\d trigpart3 alter table trigpart detach partition trigpart3; drop trigger trg1 on trigpart3; -- fail due to "does not exist" alter table trigpart detach partition trigpart4; @@ -1465,14 +1469,14 @@ select tgrelid::regclass::text, tgname, tgfoid::regproc, tgenabled, tgisinternal where tgname ~ '^trg1' order by 1; create table trigpart3 (like trigpart); create trigger trg1 after insert on trigpart3 for each row execute procedure trigger_nothing(); --- Deactivated for SplendidDataTest: \d trigpart3 +\d trigpart3 alter table trigpart attach partition trigpart3 FOR VALUES FROM (2000) to (3000); -- fail drop table trigpart3; -- check display of unrelated triggers create trigger samename after delete on trigpart execute function trigger_nothing(); create trigger samename after delete on trigpart1 execute function trigger_nothing(); --- Deactivated for SplendidDataTest: \d trigpart1 +\d trigpart1 drop table trigpart; drop function trigger_nothing(); @@ -1591,6 +1595,42 @@ create trigger qqq after insert on parted_trig_1_1 for each row execute procedur insert into parted_trig values (50), (1500); drop table parted_trig; +-- Verify that the correct triggers fire for cross-partition updates +create table parted_trig (a int) partition by list (a); +create table parted_trig1 partition of parted_trig for values in (1); +create table parted_trig2 partition of parted_trig for values in (2); +insert into parted_trig values (1); + +create or replace function trigger_notice() returns trigger as $$ + begin + raise notice 'trigger % on % % % for %', TG_NAME, TG_TABLE_NAME, TG_WHEN, TG_OP, TG_LEVEL; + if TG_LEVEL = 'ROW' then + if TG_OP = 'DELETE' then + return OLD; + else + return NEW; + end if; + end if; + return null; + end; + $$ language plpgsql; +create trigger parted_trig_before_stmt before insert or update or delete on parted_trig + for each statement execute procedure trigger_notice(); +create trigger parted_trig_before_row before insert or update or delete on parted_trig + for each row execute procedure trigger_notice(); +create trigger parted_trig_after_row after insert or update or delete on parted_trig + for each row execute procedure trigger_notice(); +create trigger parted_trig_after_stmt after insert or update or delete on parted_trig + for each statement execute procedure trigger_notice(); + +update parted_trig set a = 2 where a = 1; + +-- update action in merge should behave the same +merge into parted_trig using (select 1) as ss on true + when matched and a = 2 then update set a = 1; + +drop table parted_trig; + -- Verify propagation of trigger arguments to partitions create table parted_trig (a int) partition by list (a); create table parted_trig1 partition of parted_trig for values in (1); @@ -1886,11 +1926,31 @@ select tgrelid::regclass, tgname, tgenabled from pg_trigger -- The following is a no-op for the parent trigger but not so -- for the child trigger, so recursion should be applied. alter table parent enable always trigger tg; +select tgrelid::regclass, tgname, tgenabled from pg_trigger + where tgrelid in ('parent'::regclass, 'child1'::regclass) + order by tgrelid::regclass::text, tgname; +-- This variant malfunctioned in some releases. +alter table parent disable trigger user; select tgrelid::regclass, tgname, tgenabled from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass) order by tgrelid::regclass::text, tgname; drop table parent, child1; +-- Check processing of foreign key triggers +create table parent (a int primary key, f int references parent) + partition by list (a); +create table child1 partition of parent for values in (1); +select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname, + tgfoid::regproc, tgenabled + from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass) + order by tgrelid::regclass::text, tgfoid; +alter table parent disable trigger all; +select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname, + tgfoid::regproc, tgenabled + from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass) + order by tgrelid::regclass::text, tgfoid; +drop table parent, child1; + -- Verify that firing state propagates correctly on creation, too CREATE TABLE trgfire (i int) PARTITION BY RANGE (i); CREATE TABLE trgfire1 PARTITION OF trgfire FOR VALUES FROM (1) TO (10); @@ -2056,7 +2116,12 @@ copy parent (a, b) from stdin; -- Deactivated for SplendidDataTest: AAA 42 -- Deactivated for SplendidDataTest: BBB 42 -- Deactivated for SplendidDataTest: CCC 42 --- Deactivated for SplendidDataTest: \. +\. + +-- check detach/reattach behavior; statement triggers with transition tables +-- should not prevent a table from becoming a partition again +alter table parent detach partition child1; +alter table parent attach partition child1 for values in ('AAA'); -- DML affecting parent sees tuples collected from children even if -- there is no transition table trigger on the children @@ -2135,6 +2200,52 @@ alter table parent attach partition child for values in ('AAA'); drop table child, parent; +-- +-- Verify access of transition tables with UPDATE triggers and tuples +-- moved across partitions. +-- +create or replace function dump_update_new() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, new table = %', TG_NAME, + (select string_agg(new_table::text, ', ' order by a) from new_table); + return null; + end; +$$; +create or replace function dump_update_old() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, old table = %', TG_NAME, + (select string_agg(old_table::text, ', ' order by a) from old_table); + return null; + end; +$$; +create table trans_tab_parent (a text) partition by list (a); +create table trans_tab_child1 partition of trans_tab_parent for values in ('AAA1', 'AAA2'); +create table trans_tab_child2 partition of trans_tab_parent for values in ('BBB1', 'BBB2'); +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_update_old(); +create trigger trans_tab_parent_insert_trig + after insert on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_insert(); +create trigger trans_tab_parent_delete_trig + after delete on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_delete(); +insert into trans_tab_parent values ('AAA1'), ('BBB1'); +-- should not trigger access to new table when moving across partitions. +update trans_tab_parent set a = 'BBB2' where a = 'AAA1'; +drop trigger trans_tab_parent_update_trig on trans_tab_parent; +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_update_new(); +-- should not trigger access to old table when moving across partitions. +update trans_tab_parent set a = 'AAA2' where a = 'BBB1'; +delete from trans_tab_parent; +-- clean up +drop table trans_tab_parent, trans_tab_child1, trans_tab_child2; +drop function dump_update_new, dump_update_old; + -- -- Verify behavior of statement triggers on (non-partition) -- inheritance hierarchy with transition tables; similar to the @@ -2229,7 +2340,12 @@ copy parent (a, b) from stdin; create index on parent(b); copy parent (a, b) from stdin; -- Deactivated for SplendidDataTest: DDD 42 --- Deactivated for SplendidDataTest: \. +\. + +-- check disinherit/reinherit behavior; statement triggers with transition +-- tables should not prevent a table from becoming an inheritance child again +alter table child1 no inherit parent; +alter table child1 inherit parent; -- DML affecting parent sees tuples collected from children even if -- there is no transition table trigger on the children @@ -2426,6 +2542,20 @@ select * from trig_table; drop table refd_table, trig_table; +-- +-- Test that we can drop a not-yet-fired deferred trigger +-- + +create table refd_table (id int primary key); +create table trig_table (fk int references refd_table initially deferred); + +begin; +insert into trig_table values (1); +drop table refd_table cascade; +commit; + +drop table trig_table; + -- -- self-referential FKs are even more fun -- @@ -2750,7 +2880,7 @@ for each row execute procedure f(); create trigger parenttrig after insert on child for each row execute procedure f(); alter trigger parenttrig on parent rename to anothertrig; --- Deactivated for SplendidDataTest: \d+ child +\d+ child drop table parent, child; drop function f(); diff --git a/parser/src/test/resources/postgres/test/regress/sql/tsdicts.sql b/parser/src/test/resources/postgres/test/regress/sql/tsdicts.sql index ddc6c7f..6a2b003 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/tsdicts.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/tsdicts.sql @@ -251,3 +251,33 @@ CREATE TEXT SEARCH DICTIONARY tsdict_case "DictFile" = ispell_sample, "AffFile" = ispell_sample ); + +-- Test grammar for configurations +CREATE TEXT SEARCH CONFIGURATION dummy_tst (COPY=english); +-- Overriden mapping change with duplicated tokens. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + ALTER MAPPING FOR word, word WITH ispell; +-- Not a token supported by the configuration's parser, fails. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + DROP MAPPING FOR not_a_token, not_a_token; +-- Not a token supported by the configuration's parser, fails even +-- with IF EXISTS. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + DROP MAPPING IF EXISTS FOR not_a_token, not_a_token; +-- Token supported by the configuration's parser, succeeds. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + DROP MAPPING FOR word, word; +-- No mapping for token supported by the configuration's parser, fails. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + DROP MAPPING FOR word; +-- Token supported by the configuration's parser, cannot be found, +-- succeeds with IF EXISTS. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + DROP MAPPING IF EXISTS FOR word, word; +-- Re-add mapping, with duplicated tokens supported by the parser. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + ADD MAPPING FOR word, word WITH ispell; +-- Not a token supported by the configuration's parser, fails. +ALTER TEXT SEARCH CONFIGURATION dummy_tst + ADD MAPPING FOR not_a_token WITH ispell; +DROP TEXT SEARCH CONFIGURATION dummy_tst; diff --git a/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql b/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql index a2bb00d..e37c50b 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql @@ -7,7 +7,7 @@ -- directory paths are passed to us in environment variables --- Deactivated for SplendidDataTest: \getenv abs_srcdir PG_ABS_SRCDIR +\getenv abs_srcdir PG_ABS_SRCDIR -- -- Sanity checks for text search catalogs @@ -55,8 +55,8 @@ CREATE TABLE test_tsvector( t text, a tsvector ); --- Deactivated for SplendidDataTest: --- Deactivated for SplendidDataTest: \set filename :abs_srcdir '/data/tsearch.data' + +\set filename :abs_srcdir '/data/tsearch.data' COPY test_tsvector FROM :'filename'; ANALYZE test_tsvector; @@ -159,8 +159,8 @@ CREATE INDEX wowidx1 ON test_tsvector USING gist (a tsvector_ops(siglen=100,foo= CREATE INDEX wowidx1 ON test_tsvector USING gist (a tsvector_ops(siglen=100, siglen = 200)); CREATE INDEX wowidx2 ON test_tsvector USING gist (a tsvector_ops(siglen=1)); --- Deactivated for SplendidDataTest: --- Deactivated for SplendidDataTest: \d test_tsvector + +\d test_tsvector DROP INDEX wowidx; @@ -194,8 +194,8 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!wd:D'; DROP INDEX wowidx2; CREATE INDEX wowidx ON test_tsvector USING gist (a tsvector_ops(siglen=484)); --- Deactivated for SplendidDataTest: --- Deactivated for SplendidDataTest: \d test_tsvector + +\d test_tsvector EXPLAIN (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; @@ -571,19 +571,25 @@ SELECT ts_headline('english', to_tsquery('english','Lorem') && phraseto_tsquery('english','ullamcorper urna'), 'MaxFragments=100, MaxWords=100, MinWords=1'); +-- Edge cases with empty query +SELECT ts_headline('english', +'', to_tsquery('english', '')); +SELECT ts_headline('english', +'foo bar', to_tsquery('english', '')); + --Rewrite sub system CREATE TABLE test_tsquery (txtkeyword TEXT, txtsample TEXT); --- Deactivated for SplendidDataTest: \set ECHO none --- Deactivated for SplendidDataTest: \copy test_tsquery from stdin +\set ECHO none +\copy test_tsquery from stdin -- Deactivated for SplendidDataTest: 'New York' new <-> york | big <-> apple | nyc -- Deactivated for SplendidDataTest: Moscow moskva | moscow -- Deactivated for SplendidDataTest: 'Sanct Peter' Peterburg | peter | 'Sanct Peterburg' -- Deactivated for SplendidDataTest: foo & bar & qq foo & (bar | qq) & city -- Deactivated for SplendidDataTest: 1 & (2 <-> 3) 2 <-> 4 -- Deactivated for SplendidDataTest: 5 <-> 6 5 <-> 7 --- Deactivated for SplendidDataTest: \. --- Deactivated for SplendidDataTest: \set ECHO all +\. +\set ECHO all ALTER TABLE test_tsquery ADD COLUMN keyword tsquery; UPDATE test_tsquery SET keyword = to_tsquery('english', txtkeyword); @@ -743,7 +749,10 @@ select websearch_to_tsquery('simple', ':'); select websearch_to_tsquery('simple', 'abc & def'); select websearch_to_tsquery('simple', 'abc | def'); select websearch_to_tsquery('simple', 'abc <-> def'); + +-- parens are ignored, too select websearch_to_tsquery('simple', 'abc (pg or class)'); +select websearch_to_tsquery('simple', '(foo bar) or (ding dong)'); -- NOT is ignored in quotes select websearch_to_tsquery('english', 'My brand new smartphone'); diff --git a/parser/src/test/resources/postgres/test/regress/sql/updatable_views.sql b/parser/src/test/resources/postgres/test/regress/sql/updatable_views.sql index fa206a8..0a3176e 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/updatable_views.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/updatable_views.sql @@ -148,7 +148,24 @@ SELECT * FROM base_tbl; EXPLAIN (costs off) UPDATE rw_view1 SET a=6 WHERE a=5; EXPLAIN (costs off) DELETE FROM rw_view1 WHERE a=5; +-- it's still updatable if we add a DO ALSO rule + +CREATE TABLE base_tbl_hist(ts timestamptz default now(), a int, b text); + +CREATE RULE base_tbl_log AS ON INSERT TO rw_view1 DO ALSO + INSERT INTO base_tbl_hist(a,b) VALUES(new.a, new.b); + +SELECT table_name, is_updatable, is_insertable_into + FROM information_schema.views + WHERE table_name = 'rw_view1'; + +-- Check behavior with DEFAULTs (bug #17633) + +INSERT INTO rw_view1 VALUES (9, DEFAULT), (10, DEFAULT); +SELECT a, b FROM base_tbl_hist; + DROP TABLE base_tbl CASCADE; +DROP TABLE base_tbl_hist; -- view on top of view @@ -828,6 +845,7 @@ CREATE VIEW rw_view1 AS INSERT INTO rw_view1 VALUES (null, null, 1.1, null); -- should fail INSERT INTO rw_view1 (s, c, a) VALUES (null, null, 1.1); -- should fail +INSERT INTO rw_view1 (s, c, a) VALUES (default, default, 1.1); -- should fail INSERT INTO rw_view1 (a) VALUES (1.1) RETURNING a, s, c; -- OK UPDATE rw_view1 SET s = s WHERE a = 1.1; -- should fail UPDATE rw_view1 SET a = 1.05 WHERE a = 1.1 RETURNING s; -- OK @@ -1406,6 +1424,23 @@ DROP VIEW v1; DROP TABLE t2; DROP TABLE t1; +-- +-- Test sub-select in nested security barrier views, per bug #17972 +-- +CREATE TABLE t1 (a int); +CREATE VIEW v1 WITH (security_barrier = true) AS + SELECT * FROM t1; +CREATE RULE v1_upd_rule AS ON UPDATE TO v1 DO INSTEAD + UPDATE t1 SET a = NEW.a WHERE a = OLD.a; +CREATE VIEW v2 WITH (security_barrier = true) AS + SELECT * FROM v1 WHERE EXISTS (SELECT 1); + +EXPLAIN (COSTS OFF) UPDATE v2 SET a = 1; + +DROP VIEW v2; +DROP VIEW v1; +DROP TABLE t1; + -- -- Test CREATE OR REPLACE VIEW turning a non-updatable view into an -- auto-updatable view and adding check options in a single step @@ -1700,6 +1735,16 @@ insert into base_tab_def_view values (15, default, default, default, default), insert into base_tab_def_view values (17), (default); select * from base_tab_def order by a, c NULLS LAST; +-- Test a DO ALSO INSERT ... SELECT rule +drop rule base_tab_def_view_ins_rule on base_tab_def_view; +create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view + do also insert into base_tab_def (a, b, e) select new.a, new.b, 'xxx'; +truncate base_tab_def; +insert into base_tab_def_view values (1, default, default, default, default); +insert into base_tab_def_view values (2, default, default, default, default), + (3, default, default, default, default); +select * from base_tab_def order by a, e nulls first; + drop view base_tab_def_view; drop table base_tab_def; diff --git a/parser/src/test/resources/postgres/test/regress/sql/update.sql b/parser/src/test/resources/postgres/test/regress/sql/update.sql index ba91b5e..9111854 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/update.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/update.sql @@ -350,7 +350,7 @@ DROP FUNCTION func_parted_mod_b(); ALTER TABLE range_parted ENABLE ROW LEVEL SECURITY; CREATE USER regress_range_parted_user; GRANT ALL ON range_parted, mintab TO regress_range_parted_user; -CREATE POLICY seeall ON range_parted AS PERMISSIVE FOR SELECT USING (true); +-- Deactivated for SplendidDataTest: CREATE POLICY seeall ON range_parted AS PERMISSIVE FOR SELECT USING (true); CREATE POLICY policy_range_parted ON range_parted for UPDATE USING (true) WITH CHECK (c % 2 = 0); -- Deactivated for SplendidDataTest: :init_range_parted; @@ -393,9 +393,9 @@ DROP FUNCTION func_d_1_15(); -- Policy expression contains SubPlan RESET SESSION AUTHORIZATION; -- Deactivated for SplendidDataTest: :init_range_parted; -CREATE POLICY policy_range_parted_subplan on range_parted - AS RESTRICTIVE for UPDATE USING (true) - WITH CHECK ((SELECT range_parted.c <= c1 FROM mintab)); +-- Deactivated for SplendidDataTest: CREATE POLICY policy_range_parted_subplan on range_parted +-- Deactivated for SplendidDataTest: AS RESTRICTIVE for UPDATE USING (true) +-- Deactivated for SplendidDataTest: WITH CHECK ((SELECT range_parted.c <= c1 FROM mintab)); SET SESSION AUTHORIZATION regress_range_parted_user; -- fail, mintab has row with c1 = 120 UPDATE range_parted set a = 'b', c = 122 WHERE a = 'a' and c = 200; @@ -406,8 +406,8 @@ UPDATE range_parted set a = 'b', c = 120 WHERE a = 'a' and c = 200; RESET SESSION AUTHORIZATION; -- Deactivated for SplendidDataTest: :init_range_parted; -CREATE POLICY policy_range_parted_wholerow on range_parted AS RESTRICTIVE for UPDATE USING (true) - WITH CHECK (range_parted = row('b', 10, 112, 1, NULL)::range_parted); +-- Deactivated for SplendidDataTest: CREATE POLICY policy_range_parted_wholerow on range_parted AS RESTRICTIVE for UPDATE USING (true) +-- Deactivated for SplendidDataTest: WITH CHECK (range_parted = row('b', 10, 112, 1, NULL)::range_parted); SET SESSION AUTHORIZATION regress_range_parted_user; -- ok, should pass the RLS check UPDATE range_parted set a = 'b', c = 112 WHERE a = 'a' and c = 200; diff --git a/parser/src/test/resources/postgres/test/regress/sql/vacuum.sql b/parser/src/test/resources/postgres/test/regress/sql/vacuum.sql index 09da05f..049d2bf 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/vacuum.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/vacuum.sql @@ -75,6 +75,35 @@ DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside ANALYZE vactst; COMMIT; +-- Test ANALYZE setting relhassubclass=f for non-partitioning inheritance +BEGIN; +CREATE TABLE past_inh_parent (); +CREATE TABLE past_inh_child () INHERITS (past_inh_parent); +INSERT INTO past_inh_child DEFAULT VALUES; +INSERT INTO past_inh_child DEFAULT VALUES; +ANALYZE past_inh_parent; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_parent'::regclass; +DROP TABLE past_inh_child; +ANALYZE past_inh_parent; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_parent'::regclass; +COMMIT; + +-- Test ANALYZE setting relhassubclass=f for partitioning +BEGIN; +CREATE TABLE past_parted (i int) PARTITION BY LIST(i); +CREATE TABLE past_part PARTITION OF past_parted FOR VALUES IN (1); +INSERT INTO past_parted VALUES (1),(1); +ANALYZE past_parted; +DROP TABLE past_part; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_parted'::regclass; +ANALYZE past_parted; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_parted'::regclass; +COMMIT; + VACUUM FULL pg_am; VACUUM FULL pg_class; VACUUM FULL pg_database; diff --git a/parser/src/test/resources/postgres/test/regress/sql/window.sql b/parser/src/test/resources/postgres/test/regress/sql/window.sql index eece1fb..adca600 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/window.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/window.sql @@ -1076,14 +1076,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM (SELECT empno, salary, - count(empno) OVER (ORDER BY salary DESC) c + count(1) OVER (ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; SELECT * FROM (SELECT empno, salary, - count(empno) OVER (ORDER BY salary DESC) c + count(1) OVER (ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; @@ -1139,13 +1139,13 @@ SELECT empno, depname FROM FROM empsalary) emp WHERE rn < 3; --- likewise with count(empno) instead of row_number() +-- likewise with count(1) instead of row_number() EXPLAIN (COSTS OFF) SELECT * FROM (SELECT empno, depname, salary, - count(empno) OVER (PARTITION BY depname ORDER BY salary DESC) c + count(1) OVER (PARTITION BY depname ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; @@ -1154,7 +1154,7 @@ SELECT * FROM (SELECT empno, depname, salary, - count(empno) OVER (PARTITION BY depname ORDER BY salary DESC) c + count(1) OVER (PARTITION BY depname ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; @@ -1165,15 +1165,22 @@ SELECT * FROM (SELECT empno, depname, salary, - count(empno) OVER () c + count(1) OVER () c FROM empsalary) emp WHERE c = 1; +-- Try another case with a WindowFunc with a byref return type +SELECT * FROM + (SELECT row_number() OVER (PARTITION BY salary) AS rn, + lead(depname) OVER (PARTITION BY salary) || ' Department' AS n_dep + FROM empsalary) emp +WHERE rn < 1; + -- Some more complex cases with multiple window clauses EXPLAIN (COSTS OFF) SELECT * FROM (SELECT *, - count(salary) OVER (PARTITION BY depname || '') c1, -- w1 + count(1) OVER (PARTITION BY depname || '') c1, -- w1 row_number() OVER (PARTITION BY depname) rn, -- w2 count(*) OVER (PARTITION BY depname) c2, -- w2 count(*) OVER (PARTITION BY '' || depname) c3 -- w3 @@ -1183,7 +1190,7 @@ SELECT * FROM -- Ensure we correctly filter out all of the run conditions from each window SELECT * FROM (SELECT *, - count(salary) OVER (PARTITION BY depname || '') c1, -- w1 + count(1) OVER (PARTITION BY depname || '') c1, -- w1 row_number() OVER (PARTITION BY depname) rn, -- w2 count(*) OVER (PARTITION BY depname) c2, -- w2 count(*) OVER (PARTITION BY '' || depname) c3 -- w3 @@ -1213,15 +1220,33 @@ SELECT * FROM FROM empsalary) emp WHERE 3 <= c; --- Ensure we don't pushdown when there are multiple window clauses to evaluate +-- Ensure we don't use a run condition when there's a volatile function in the +-- WindowFunc EXPLAIN (COSTS OFF) SELECT * FROM (SELECT empno, salary, - count(*) OVER (ORDER BY empno DESC) c, - dense_rank() OVER (ORDER BY salary DESC) dr + count(random()) OVER (ORDER BY empno DESC) c FROM empsalary) emp -WHERE dr = 1; +WHERE c = 1; + +-- Ensure we don't use a run condition when the WindowFunc arg contains a Var +EXPLAIN (COSTS OFF) +SELECT * FROM + (SELECT empno, + salary, + count(empno) OVER (ORDER BY empno DESC) c + FROM empsalary) emp +WHERE c = 1; + +-- Ensure we don't use a run condition when the WindowFunc contains subplans +EXPLAIN (COSTS OFF) +SELECT * FROM + (SELECT empno, + salary, + count((SELECT 1)) OVER (ORDER BY empno DESC) c + FROM empsalary) emp +WHERE c = 1; -- Test Sort node collapsing EXPLAIN (COSTS OFF) diff --git a/parser/src/test/resources/postgres/test/regress/sql/with.sql b/parser/src/test/resources/postgres/test/regress/sql/with.sql index 8cc0306..263671c 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/with.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/with.sql @@ -271,7 +271,7 @@ UNION ALL ) SELECT sum(n) FROM t; --- Deactivated for SplendidDataTest: \d+ sums_1_100 +\d+ sums_1_100 -- corner case in which sub-WITH gets initialized first with recursive q as ( @@ -355,6 +355,18 @@ UNION ALL SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON (t1.id=t2.id); +CREATE TEMP TABLE duplicates (a INT NOT NULL); +INSERT INTO duplicates VALUES(1), (1); + +-- Try out a recursive UNION case where the non-recursive part's table slot +-- uses TTSOpsBufferHeapTuple and contains duplicate rows. +WITH RECURSIVE cte (a) as ( + SELECT a FROM duplicates + UNION + SELECT a FROM cte +) +SELECT a FROM cte; + -- SEARCH clause create temp table graph0( f int, t int, label text ); @@ -422,6 +434,41 @@ with recursive search_graph(f, t, label) as ( ) search breadth first by f, t set seq select * from search_graph order by seq; +-- a constant initial value causes issues for EXPLAIN +explain (verbose, costs off) +with recursive test as ( + select 1 as x + union all + select x + 1 + from test +) search depth first by x set y +select * from test limit 5; + +with recursive test as ( + select 1 as x + union all + select x + 1 + from test +) search depth first by x set y +select * from test limit 5; + +explain (verbose, costs off) +with recursive test as ( + select 1 as x + union all + select x + 1 + from test +) search breadth first by x set y +select * from test limit 5; + +with recursive test as ( + select 1 as x + union all + select x + 1 + from test +) search breadth first by x set y +select * from test limit 5; + -- various syntax errors with recursive search_graph(f, t, label) as ( select * from graph0 g @@ -569,6 +616,32 @@ with recursive search_graph(f, t, label) as ( ) cycle f, t set is_cycle to 'Y' default 'N' using path select * from search_graph; +explain (verbose, costs off) +with recursive test as ( + select 0 as x + union all + select (x + 1) % 10 + from test +) cycle x set is_cycle using path +select * from test; + +with recursive test as ( + select 0 as x + union all + select (x + 1) % 10 + from test +) cycle x set is_cycle using path +select * from test; + +with recursive test as ( + select 0 as x + union all + select (x + 1) % 10 + from test + where not is_cycle -- redundant, but legal +) cycle x set is_cycle using path +select * from test; + -- multiple CTEs with recursive graph(f, t, label) as ( @@ -836,6 +909,42 @@ WITH RECURSIVE x(n) AS (SELECT n FROM x) WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1) SELECT * FROM x; +-- allow this, because we historically have +WITH RECURSIVE x(n) AS ( + WITH x1 AS (SELECT 1 AS n) + SELECT 0 + UNION + SELECT * FROM x1) + SELECT * FROM x; + +-- but this should be rejected +WITH RECURSIVE x(n) AS ( + WITH x1 AS (SELECT 1 FROM x) + SELECT 0 + UNION + SELECT * FROM x1) + SELECT * FROM x; + +-- and this too +WITH RECURSIVE x(n) AS ( + (WITH x1 AS (SELECT 1 FROM x) SELECT * FROM x1) + UNION + SELECT 0) + SELECT * FROM x; + +-- and this +WITH RECURSIVE x(n) AS ( + SELECT 0 UNION SELECT 1 + ORDER BY (SELECT n FROM x)) + SELECT * FROM x; + +-- and this +WITH RECURSIVE x(n) AS ( + WITH sub_cte AS (SELECT * FROM x) + DELETE FROM graph RETURNING f) + SELECT * FROM x; + + CREATE TEMPORARY TABLE y (a INTEGER); INSERT INTO y SELECT generate_series(1, 10); @@ -963,6 +1072,30 @@ select ( with cte(foo) as ( values(f1) ) values((select foo from cte)) ) from int4_tbl; +-- +-- test for bug #19055: interaction of WITH with aggregates +-- +-- For now, we just throw an error if there's a use of a CTE below the +-- semantic level that the SQL standard assigns to the aggregate. +-- It's not entirely clear what we could do instead that doesn't risk +-- breaking more things than it fixes. +select f1, (with cte1(x,y) as (select 1,2) + select count((select i4.f1 from cte1))) as ss +from int4_tbl i4; + +-- +-- test for bug #19106: interaction of WITH with aggregates +-- +-- the initial fix for #19055 was too aggressive and broke this case +explain (verbose, costs off) +with a as ( select id from (values (1), (2)) as v(id) ), + b as ( select max((select sum(id) from a)) as agg ) +select agg from b; + +with a as ( select id from (values (1), (2)) as v(id) ), + b as ( select max((select sum(id) from a)) as agg ) +select agg from b; + -- -- test for nested-recursive-WITH bug -- @@ -1177,7 +1310,7 @@ INSERT INTO bug6051 SELECT * FROM t1; SELECT * FROM bug6051; SELECT * FROM bug6051_2; --- check INSERT ... SELECT rule actions are disallowed on commands +-- check INSERT...SELECT rule actions are disallowed on commands -- that have modifyingCTEs CREATE OR REPLACE RULE bug6051_ins AS ON INSERT TO bug6051 DO INSTEAD INSERT INTO bug6051_2 diff --git a/parser/src/test/resources/postgres/test/regress/sql/xml.sql b/parser/src/test/resources/postgres/test/regress/sql/xml.sql index 484e363..543feb8 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/xml.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/xml.sql @@ -387,19 +387,23 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1; -- errors SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2); +-- Deactivated for SplendidDataTest: SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1); + -- XMLNAMESPACES tests SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), '/zz:rows/zz:row' PASSING '10' COLUMNS a int PATH 'zz:a'); -CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), - '/zz:rows/zz:row' +CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS "Zz"), + '/Zz:rows/Zz:row' PASSING '10' - COLUMNS a int PATH 'zz:a'); + COLUMNS a int PATH 'Zz:a'); SELECT * FROM xmltableview2; +\sv xmltableview2 + SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'), '/rows/row' PASSING '10' @@ -613,7 +617,7 @@ SELECT xmltable.* FROM xmltest2, LATERAL xmltable(('/d/r/' || lower(_path) || 'c -- XPath result can be boolean or number too SELECT * FROM XMLTABLE('*' PASSING 'a' COLUMNS a xml PATH '.', b text PATH '.', c text PATH '"hi"', d boolean PATH '. = "a"', e integer PATH 'string-length(.)'); \x -SELECT * FROM XMLTABLE('*' PASSING 'pre&deeppost' COLUMNS x xml PATH '/e/n2', y xml PATH '/'); +SELECT * FROM XMLTABLE('*' PASSING 'pre&deeppost' COLUMNS x xml PATH 'node()', y xml PATH '/'); \x SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH '""', b xml PATH '""'); diff --git a/pom.xml b/pom.xml index 3b8ee7c..e1f6409 100644 --- a/pom.xml +++ b/pom.xml @@ -38,9 +38,10 @@ ${java.version} UTF-8 file:**/generated-sources/** - 2.23.1 + 2.25.2 11.0.2 - 5.10.2 + + 5.14.1 3.9.1 2.8 @@ -91,40 +92,40 @@ org.apache.maven maven-plugin-api - 3.9.7 + 3.9.11 org.apache.maven.plugin-tools maven-plugin-annotations - 3.13.1 + 3.15.2 provided org.apache.maven.plugin-tools maven-plugin-tools-api - 3.13.1 + 3.15.2 org.apache.maven maven-core - 3.9.7 + 3.9.11 com.github.javaparser javaparser-core - 3.26.0 + 3.27.1 jakarta.xml.bind jakarta.xml.bind-api - 4.0.2 + 4.0.4 org.glassfish.jaxb jaxb-runtime - 4.0.5 + 4.0.6 @@ -148,48 +149,26 @@ org.junit.jupiter - junit-jupiter-api - ${jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-params + junit-jupiter ${jupiter.version} test - - - org.junit.jupiter - junit-jupiter-api - - - org.junit.jupiter - junit-jupiter-engine - ${jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-api - - - org.junit.platform - junit-platform-engine - - + org.checkerframework + checker-qual + 3.47.0 - org.junit.platform - junit-platform-runner - test - 1.10.0 + org.apache.maven + maven-model + 3.9.7 + provided - org.checkerframework - checker-qual - 3.44.0 + org.apache.maven + maven-artifact + 3.9.7 + provided @@ -205,7 +184,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.13.0 + 3.14.1 ${java.version} @@ -216,17 +195,17 @@ org.apache.maven.plugins maven-antrun-plugin - 3.1.0 + 3.2.0 org.codehaus.mojo exec-maven-plugin - 3.3.0 + 3.6.2 org.codehaus.mojo build-helper-maven-plugin - 3.6.0 + 3.6.1 de.jflex @@ -236,12 +215,12 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.9.0 org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.5.0 UTF-8 @@ -254,37 +233,37 @@ org.jacoco jacoco-maven-plugin - 0.8.12 + 0.8.14 org.apache.maven.plugins maven-plugin-plugin - 3.10.2 + 3.15.2 org.apache.maven.plugins maven-site-plugin - 3.12.1 + 3.21.0 org.apache.maven.plugins maven-javadoc-plugin - 3.7.0 + 3.12.0 org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.4 org.apache.maven.plugins maven-clean-plugin - 3.3.2 + 3.5.0 org.apache.maven.plugins maven-deploy-plugin - 3.1.2 + 3.1.4 true @@ -292,7 +271,7 @@ org.apache.maven.plugins maven-install-plugin - 3.1.2 + 3.1.4 org.apache.maven.plugins @@ -302,7 +281,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.5.0 + 3.6.2
@@ -377,7 +356,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.9.0 @@ -413,7 +392,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.2.5 + 3.5.4 @@ -428,7 +407,7 @@ org.apache.maven.plugins maven-jxr-plugin - 3.4.0 + 3.6.0 org.jacoco From 5c5e9cea1c258d240200c6162506b63ae4c0e178 Mon Sep 17 00:00:00 2001 From: Martin Butter Date: Tue, 30 Jun 2026 14:41:13 +0200 Subject: [PATCH 5/6] Adapted Postgres 15.18 & updated some maven dependencies --- .../sqlparser/AbstractParser.java | 5 +- .../postgres/test/regress/sql/alter_table.sql | 8 + .../postgres/test/regress/sql/arrays.sql | 4 + .../test/regress/sql/collate.icu.utf8.sql | 103 + .../test/regress/sql/compression_pglz.sql | 63 + .../test/regress/sql/create_index.sql | 4 + .../postgres/test/regress/sql/create_role.sql | 8 + .../test/regress/sql/create_table_like.sql | 26 + .../postgres/test/regress/sql/encoding.sql | 247 ++ .../postgres/test/regress/sql/euc_kr.sql | 12 + .../postgres/test/regress/sql/expressions.sql | 114 +- .../test/regress/sql/foreign_data.sql | 12 + .../postgres/test/regress/sql/generated.sql | 24 + .../postgres/test/regress/sql/hash_index.sql | 13 + .../postgres/test/regress/sql/indexing.sql | 59 + .../test/regress/sql/jsonb_jsonpath.sql | 5 + .../test/regress/sql/multirangetypes.sql | 19 + .../test/regress/sql/prepared_xacts.sql | 7 +- .../postgres/test/regress/sql/psql.sql | 1995 +++++++++-------- .../postgres/test/regress/sql/stats.sql | 195 +- .../postgres/test/regress/sql/triggers.sql | 14 +- .../postgres/test/regress/sql/tsearch.sql | 8 + .../postgres/test/regress/sql/unicode.sql | 26 +- .../postgres/test/regress/sql/window.sql | 26 + .../postgres/test/regress/sql/with.sql | 23 + .../postgres/test/regress/sql/xml.sql | 31 +- pom.xml | 51 +- 27 files changed, 1974 insertions(+), 1128 deletions(-) create mode 100644 parser/src/test/resources/postgres/test/regress/sql/compression_pglz.sql create mode 100644 parser/src/test/resources/postgres/test/regress/sql/encoding.sql create mode 100644 parser/src/test/resources/postgres/test/regress/sql/euc_kr.sql diff --git a/parser/src/main/java/com/splendiddata/sqlparser/AbstractParser.java b/parser/src/main/java/com/splendiddata/sqlparser/AbstractParser.java index 5de5e16..d21bd67 100644 --- a/parser/src/main/java/com/splendiddata/sqlparser/AbstractParser.java +++ b/parser/src/main/java/com/splendiddata/sqlparser/AbstractParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) Splendid Data Product Development B.V. 2020 - 2022 + * Copyright (c) Splendid Data Product Development B.V. 2020 - 2026 * * This program is free software: You may redistribute and/or modify under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at Client's option) any later @@ -1331,6 +1331,9 @@ protected VacuumRelation makeVacuumRelation(RangeVar relation, Oid oid, List 10); +ALTER TABLE test_add_column + ADD c6 integer; -- omit COLUMN +ALTER TABLE test_add_column + ADD IF NOT EXISTS c6 integer; +ALTER TABLE test_add_column + DROP c6; -- omit COLUMN +ALTER TABLE test_add_column + DROP IF EXISTS c6; \d test_add_column* DROP TABLE test_add_column; \d test_add_column* diff --git a/parser/src/test/resources/postgres/test/regress/sql/arrays.sql b/parser/src/test/resources/postgres/test/regress/sql/arrays.sql index dd15d61..c822133 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/arrays.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/arrays.sql @@ -491,6 +491,10 @@ select array[]::text[]; select '[0:1]={1.1,2.2}'::float8[]; -- all of the above should be accepted +-- some day we might allow these cases, but for now they're errors: +select array[]::oidvector; +select array[]::int2vector; + -- tests for array aggregates CREATE TEMP TABLE arraggtest ( f1 INT[], f2 TEXT[][], f3 FLOAT[]); diff --git a/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql b/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql index d39dd70..9db5852 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/collate.icu.utf8.sql @@ -535,6 +535,109 @@ CREATE UNIQUE INDEX ON test3cs (x); -- ok SELECT string_to_array('ABC,DEF,GHI' COLLATE case_sensitive, ',', 'abc'); SELECT string_to_array('ABCDEFGHI' COLLATE case_sensitive, NULL, 'b'); +-- +-- A unique index under one collation does not prove uniqueness under +-- another, so the planner must not use such a proof for any optimization. +-- + +-- Ensure that we do not use inner-unique join execution +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM test1cs t1, test3cs t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +SELECT * FROM test1cs t1, test3cs t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +-- Ensure that left-join is not removed +EXPLAIN (COSTS OFF) +SELECT t1.* FROM test3cs t1 + LEFT JOIN test3cs t2 ON t1.x = t2.x COLLATE case_insensitive +ORDER BY 1; + +SELECT t1.* FROM test3cs t1 + LEFT JOIN test3cs t2 ON t1.x = t2.x COLLATE case_insensitive +ORDER BY 1; + +-- Ensure that self-join is not removed +EXPLAIN (COSTS OFF) +SELECT * FROM test3cs t1, test3cs t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +SELECT * FROM test3cs t1, test3cs t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +-- Ensure that semijoin is not reduced to innerjoin +EXPLAIN (COSTS OFF) +SELECT * FROM test3cs t1 + WHERE EXISTS (SELECT 1 FROM test3cs t2 WHERE t1.x = t2.x COLLATE case_insensitive) +ORDER BY 1; + +SELECT * FROM test3cs t1 + WHERE EXISTS (SELECT 1 FROM test3cs t2 WHERE t1.x = t2.x COLLATE case_insensitive) +ORDER BY 1; + +-- +-- A DISTINCT / GROUP BY / set-op on a subquery does not prove uniqueness +-- under a different collation, so the planner must not use such a proof for +-- any optimization. +-- + +-- Ensure that we do not use inner-unique join execution +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM test1cs t1, (SELECT DISTINCT x FROM test3cs) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +SELECT * FROM test1cs t1, (SELECT DISTINCT x FROM test3cs) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +-- Same with GROUP BY +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM test1cs t1, (SELECT x FROM test3cs GROUP BY x) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +SELECT * FROM test1cs t1, (SELECT x FROM test3cs GROUP BY x) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +-- Same with set-op +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM test1cs t1, (SELECT x FROM test3cs UNION SELECT x FROM test3cs) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +SELECT * FROM test1cs t1, (SELECT x FROM test3cs UNION SELECT x FROM test3cs) t2 +WHERE t1.x = t2.x COLLATE case_insensitive +ORDER BY 1, 2; + +-- Ensure that left-join is not removed +EXPLAIN (COSTS OFF) +SELECT t1.* FROM test3cs t1 + LEFT JOIN (SELECT DISTINCT x FROM test3cs) t2 ON t1.x = t2.x COLLATE case_insensitive +ORDER BY 1; + +SELECT t1.* FROM test3cs t1 + LEFT JOIN (SELECT DISTINCT x FROM test3cs) t2 ON t1.x = t2.x COLLATE case_insensitive +ORDER BY 1; + +-- Ensure that semijoin is not reduced to innerjoin +EXPLAIN (COSTS OFF) +SELECT * FROM test3cs t1 + WHERE EXISTS (SELECT 1 FROM (SELECT DISTINCT x FROM test3cs) t2 + WHERE t1.x = t2.x COLLATE case_insensitive) +ORDER BY 1; + +SELECT * FROM test3cs t1 + WHERE EXISTS (SELECT 1 FROM (SELECT DISTINCT x FROM test3cs) t2 + WHERE t1.x = t2.x COLLATE case_insensitive) +ORDER BY 1; + CREATE TABLE test1ci (x text COLLATE case_insensitive); CREATE TABLE test2ci (x text COLLATE case_insensitive); CREATE TABLE test3ci (x text COLLATE case_insensitive); diff --git a/parser/src/test/resources/postgres/test/regress/sql/compression_pglz.sql b/parser/src/test/resources/postgres/test/regress/sql/compression_pglz.sql new file mode 100644 index 0000000..dbd37f7 --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/compression_pglz.sql @@ -0,0 +1,63 @@ +-- +-- Tests for PGLZ compression +-- + +-- directory paths and dlsuffix are passed to us in environment variables +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX + +\set regresslib :libdir '/regress' :dlsuffix + +CREATE FUNCTION test_pglz_compress(bytea) + RETURNS bytea + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_pglz_decompress(bytea, int4, bool) + RETURNS bytea + AS :'regresslib' LANGUAGE C STRICT; + +-- Round-trip with pglz: compress then decompress. +SELECT test_pglz_decompress(test_pglz_compress( + decode(repeat('abcd', 100), 'escape')), 400, false) = + decode(repeat('abcd', 100), 'escape') AS roundtrip_ok; +SELECT test_pglz_decompress(test_pglz_compress( + decode(repeat('abcd', 100), 'escape')), 400, true) = + decode(repeat('abcd', 100), 'escape') AS roundtrip_ok; + +-- Decompression with rawsize too large, fails to fill the destination +-- buffer. +SELECT test_pglz_decompress(test_pglz_compress( + decode(repeat('abcd', 100), 'escape')), 500, true); + +-- Decompression with rawsize too small, fails with source not fully +-- consumed. +SELECT test_pglz_decompress(test_pglz_compress( + decode(repeat('abcd', 100), 'escape')), 100, true); + +-- Corrupted compressed data. Set control bit with read of a match tag, +-- no data follows. +SELECT length(test_pglz_decompress('\x01'::bytea, 1024, false)) AS ctrl_only_len; +SELECT test_pglz_decompress('\x01'::bytea, 1024, true); + +-- Corrupted compressed data. Set control bit with read of a match tag, +-- 1 byte follows. +SELECT test_pglz_decompress('\x01ff'::bytea, 1024, false); +SELECT test_pglz_decompress('\x01ff'::bytea, 1024, true); + +-- Corrupted compressed data. Set control bit with match tag where length +-- nibble is 3 bytes (extended length), no data follows. +SELECT test_pglz_decompress('\x010f01'::bytea, 1024, false); +SELECT test_pglz_decompress('\x010f01'::bytea, 1024, true); + +-- Corrupted compressed data. Set control bit with a valid 2-byte match +-- tag where offset exceeds output written. +SELECT test_pglz_decompress('\x011001'::bytea, 1024, false); +SELECT test_pglz_decompress('\x011001'::bytea, 1024, true); + +-- Corrupted compressed data. Set control bit with a valid 2-byte match +-- tag where offset is 0. +SELECT test_pglz_decompress('\x010300'::bytea, 1024, false); +SELECT test_pglz_decompress('\x010300'::bytea, 1024, true); + +-- Clean up +DROP FUNCTION test_pglz_compress; +DROP FUNCTION test_pglz_decompress; diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_index.sql b/parser/src/test/resources/postgres/test/regress/sql/create_index.sql index 2a5a13f..327f4fb 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_index.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_index.sql @@ -54,6 +54,10 @@ CREATE INDEX six ON shighway USING btree (name text_ops); COMMENT ON INDEX six_wrong IS 'bad index'; COMMENT ON INDEX six IS 'good index'; COMMENT ON INDEX six IS NULL; +SELECT obj_description('six'::regclass, 'pg_class') IS NULL AS six_comment_is_null; +COMMENT ON INDEX six IS 'add the comment back'; +COMMENT ON INDEX six IS ''; -- empty string removes the comment, same as NULL +SELECT obj_description('six'::regclass, 'pg_class') IS NULL AS six_comment_is_null; -- -- BTREE partial indices diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_role.sql b/parser/src/test/resources/postgres/test/regress/sql/create_role.sql index 292dc08..5841b57 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_role.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_role.sql @@ -55,6 +55,14 @@ CREATE ROLE regress_rolecreator CREATEROLE; -- ok, roles with CREATEROLE can create new roles with privilege they lack CREATE ROLE regress_tenant CREATEDB CREATEROLE LOGIN INHERIT CONNECTION LIMIT 5; +COMMENT ON ROLE regress_tenant IS 'some comment'; +SELECT shobj_description('regress_tenant'::regrole, 'pg_authid') IS NOT NULL AS has_comment; +COMMENT ON ROLE regress_tenant IS NULL; +SELECT shobj_description('regress_tenant'::regrole, 'pg_authid') IS NULL AS no_comment; +COMMENT ON ROLE regress_tenant IS 'add the comment back'; +SELECT shobj_description('regress_tenant'::regrole, 'pg_authid') IS NOT NULL AS has_comment; +COMMENT ON ROLE regress_tenant IS ''; -- empty string removes the comment, same as NULL +SELECT shobj_description('regress_tenant'::regrole, 'pg_authid') IS NULL AS no_comment; -- ok, regress_tenant can create objects within the database SET SESSION AUTHORIZATION regress_tenant; diff --git a/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql b/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql index 04008a0..7c7206c 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/create_table_like.sql @@ -223,3 +223,29 @@ DROP SEQUENCE ctlseq1; DROP TYPE ctlty1; DROP VIEW ctlv1; DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12; + +-- LIKE ... INCLUDING STATISTICS with dropped columns in the parent, +-- so stxkeys attnums are not contiguous. +CREATE TABLE ctl_stats3_parent (a int, b int, c int); +ALTER TABLE ctl_stats3_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats3_stat ON a, c FROM ctl_stats3_parent; +CREATE TABLE ctl_stats3_child (LIKE ctl_stats3_parent INCLUDING STATISTICS); +CREATE TABLE ctl_stats4_parent (a int, b int, c int, d int); +ALTER TABLE ctl_stats4_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats4_stat ON a, c FROM ctl_stats4_parent; +CREATE TABLE ctl_stats4_child (LIKE ctl_stats4_parent INCLUDING STATISTICS); +SELECT s.stxrelid::regclass AS relation, + array_agg(a.attname ORDER BY u.ord) AS stats_columns +FROM pg_statistic_ext s +CROSS JOIN LATERAL + unnest(s.stxkeys::int2[]) WITH ORDINALITY AS u(attnum, ord) +JOIN pg_attribute a + ON a.attrelid = s.stxrelid AND a.attnum = u.attnum +WHERE s.stxrelid IN ('ctl_stats3_child'::regclass, + 'ctl_stats4_child'::regclass) +GROUP BY s.stxrelid +ORDER BY s.stxrelid::regclass::text; +DROP TABLE ctl_stats3_parent; +DROP TABLE ctl_stats3_child; +DROP TABLE ctl_stats4_parent; +DROP TABLE ctl_stats4_child; diff --git a/parser/src/test/resources/postgres/test/regress/sql/encoding.sql b/parser/src/test/resources/postgres/test/regress/sql/encoding.sql new file mode 100644 index 0000000..d591818 --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/encoding.sql @@ -0,0 +1,247 @@ +/* skip test if not UTF8 server encoding */ +SELECT getdatabaseencoding() <> 'UTF8' AS skip_test \gset +\if :skip_test +\quit +\endif + +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX + +\set regresslib :libdir '/regress' :dlsuffix + +CREATE FUNCTION test_bytea_to_text(bytea) RETURNS text + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_text_to_bytea(text) RETURNS bytea + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_mblen_func(text, text, text, int) RETURNS int + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_text_to_wchars(text, text) RETURNS int[] + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_wchars_to_text(text, int[]) RETURNS text + AS :'regresslib' LANGUAGE C STRICT; +CREATE FUNCTION test_valid_server_encoding(text) RETURNS boolean + AS :'regresslib' LANGUAGE C STRICT; + + +CREATE TABLE regress_encoding(good text, truncated text, with_nul text, truncated_with_nul text); +INSERT INTO regress_encoding +VALUES ('café', + 'caf' || test_bytea_to_text('\xc3'), + 'café' || test_bytea_to_text('\x00') || 'dcba', + 'caf' || test_bytea_to_text('\xc300') || 'dcba'); + +SELECT good, truncated, with_nul FROM regress_encoding; + +SELECT length(good) FROM regress_encoding; +SELECT substring(good, 3, 1) FROM regress_encoding; +SELECT substring(good, 4, 1) FROM regress_encoding; +SELECT regexp_replace(good, '^caf(.)$', '\1') FROM regress_encoding; +SELECT reverse(good) FROM regress_encoding; + +-- invalid short mb character = error +SELECT length(truncated) FROM regress_encoding; +SELECT substring(truncated, 1, 3) FROM regress_encoding; +SELECT substring(truncated, 1, 4) FROM regress_encoding; +SELECT reverse(truncated) FROM regress_encoding; +-- invalid short mb character = silently dropped +SELECT regexp_replace(truncated, '^caf(.)$', '\1') FROM regress_encoding; + +-- PostgreSQL doesn't allow strings to contain NUL. If a corrupted string +-- contains NUL at a character boundary position, some functions treat it as a +-- character while others treat it as a terminator, as implementation details. + +-- NUL = terminator +SELECT length(with_nul) FROM regress_encoding; +SELECT substring(with_nul, 3, 1) FROM regress_encoding; +SELECT substring(with_nul, 4, 1) FROM regress_encoding; +SELECT substring(with_nul, 5, 1) FROM regress_encoding; +SELECT convert_to(substring(with_nul, 5, 1), 'UTF8') FROM regress_encoding; +SELECT regexp_replace(with_nul, '^caf(.)$', '\1') FROM regress_encoding; +-- NUL = character +SELECT with_nul, reverse(with_nul), reverse(reverse(with_nul)) FROM regress_encoding; + +-- If a corrupted string contains NUL in the tail bytes of a multibyte +-- character (invalid in all encodings), it is considered part of the +-- character for length purposes. An error will only be raised in code paths +-- that convert or verify encodings. + +SELECT length(truncated_with_nul) FROM regress_encoding; +SELECT substring(truncated_with_nul, 3, 1) FROM regress_encoding; +SELECT substring(truncated_with_nul, 4, 1) FROM regress_encoding; +SELECT convert_to(substring(truncated_with_nul, 4, 1), 'UTF8') FROM regress_encoding; +SELECT substring(truncated_with_nul, 5, 1) FROM regress_encoding; +SELECT regexp_replace(truncated_with_nul, '^caf(.)dcba$', '\1') = test_bytea_to_text('\xc300') FROM regress_encoding; +SELECT reverse(truncated_with_nul) FROM regress_encoding; + +-- unbounded: sequence would overrun the string! +SELECT test_mblen_func('pg_mblen_unbounded', 'UTF8', truncated, 3) +FROM regress_encoding; + +-- condition detected when using the length/range variants +SELECT test_mblen_func('pg_mblen_with_len', 'UTF8', truncated, 3) +FROM regress_encoding; +SELECT test_mblen_func('pg_mblen_range', 'UTF8', truncated, 3) +FROM regress_encoding; + +-- unbounded: sequence would overrun the string, if the terminator were really +-- the end of it +SELECT test_mblen_func('pg_mblen_unbounded', 'UTF8', truncated_with_nul, 3) +FROM regress_encoding; +SELECT test_mblen_func('pg_encoding_mblen', 'GB18030', truncated_with_nul, 3) +FROM regress_encoding; + +-- condition detected when using the cstr variants +SELECT test_mblen_func('pg_mblen_cstr', 'UTF8', truncated_with_nul, 3) +FROM regress_encoding; + +DROP TABLE regress_encoding; + +-- mb<->wchar conversions +CREATE FUNCTION test_encoding(encoding text, description text, input bytea) +RETURNS VOID LANGUAGE plpgsql AS +$$ +DECLARE + prefix text; + len int; + wchars int[]; + round_trip bytea; + result text; +BEGIN + prefix := rpad(encoding || ' ' || description || ':', 28); + + -- XXX could also test validation, length functions and include client + -- only encodings with these test cases + + IF test_valid_server_encoding(encoding) THEN + wchars := test_text_to_wchars(encoding, test_bytea_to_text(input)); + round_trip = test_text_to_bytea(test_wchars_to_text(encoding, wchars)); + if input = round_trip then + result := 'OK'; + elsif length(input) > length(round_trip) and round_trip = substr(input, 1, length(round_trip)) then + result := 'truncated'; + else + result := 'failed'; + end if; + RAISE NOTICE '% % -> % -> % = %', prefix, input, wchars, round_trip, result; + END IF; +END; +$$; +-- No validation is done on the encoding itself, just the length to avoid +-- overruns, so some of the byte sequences below are bogus. They cover +-- all code branches, server encodings only for now. +CREATE TABLE encoding_tests (encoding text, description text, input bytea); +INSERT INTO encoding_tests VALUES + -- LATIN1, other single-byte encodings + ('LATIN1', 'ASCII', 'a'), + ('LATIN1', 'extended', '\xe9'), + -- EUC_JP, EUC_JIS_2004, EUR_KR (for the purposes of wchar conversion): + -- 2 8e (CS2, not used by EUR_KR but arbitrarily considered to have EUC_JP length) + -- 3 8f (CS3, not used by EUR_KR but arbitrarily considered to have EUC_JP length) + -- 2 80..ff (CS1) + ('EUC_JP', 'ASCII', 'a'), + ('EUC_JP', 'CS1, short', '\x80'), + ('EUC_JP', 'CS1', '\x8002'), + ('EUC_JP', 'CS2, short', '\x8e'), + ('EUC_JP', 'CS2', '\x8e02'), + ('EUC_JP', 'CS3, short', '\x8f'), + ('EUC_JP', 'CS3, short', '\x8f02'), + ('EUC_JP', 'CS3', '\x8f0203'), + -- EUC_CN + -- 3 8e (CS2, not used but arbitrarily considered to have length 3) + -- 3 8f (CS3, not used but arbitrarily considered to have length 3) + -- 2 80..ff (CS1) + ('EUC_CN', 'ASCII', 'a'), + ('EUC_CN', 'CS1, short', '\x80'), + ('EUC_CN', 'CS1', '\x8002'), + ('EUC_CN', 'CS2, short', '\x8e'), + ('EUC_CN', 'CS2, short', '\x8e02'), + ('EUC_CN', 'CS2', '\x8e0203'), + ('EUC_CN', 'CS3, short', '\x8f'), + ('EUC_CN', 'CS3, short', '\x8f02'), + ('EUC_CN', 'CS3', '\x8f0203'), + -- EUC_TW: + -- 4 8e (CS2) + -- 3 8f (CS3, not used but arbitrarily considered to have length 3) + -- 2 80..ff (CS1) + ('EUC_TW', 'ASCII', 'a'), + ('EUC_TW', 'CS1, short', '\x80'), + ('EUC_TW', 'CS1', '\x8002'), + ('EUC_TW', 'CS2, short', '\x8e'), + ('EUC_TW', 'CS2, short', '\x8e02'), + ('EUC_TW', 'CS2, short', '\x8e0203'), + ('EUC_TW', 'CS2', '\x8e020304'), + ('EUC_TW', 'CS3, short', '\x8f'), + ('EUC_TW', 'CS3, short', '\x8f02'), + ('EUC_TW', 'CS3', '\x8f0203'), + -- UTF8 + -- 2 c0..df + -- 3 e0..ef + -- 4 f0..f7 (but maximum real codepoint U+10ffff has f4) + -- 5 f8..fb (not supported) + -- 6 fc..fd (not supported) + ('UTF8', 'ASCII', 'a'), + ('UTF8', '2 byte, short', '\xdf'), + ('UTF8', '2 byte', '\xdf82'), + ('UTF8', '3 byte, short', '\xef'), + ('UTF8', '3 byte, short', '\xef82'), + ('UTF8', '3 byte', '\xef8283'), + ('UTF8', '4 byte, short', '\xf7'), + ('UTF8', '4 byte, short', '\xf782'), + ('UTF8', '4 byte, short', '\xf78283'), + ('UTF8', '4 byte', '\xf7828384'), + ('UTF8', '5 byte, unsupported', '\xfb'), + ('UTF8', '5 byte, unsupported', '\xfb82'), + ('UTF8', '5 byte, unsupported', '\xfb8283'), + ('UTF8', '5 byte, unsupported', '\xfb828384'), + ('UTF8', '5 byte, unsupported', '\xfb82838485'), + ('UTF8', '6 byte, unsupported', '\xfd'), + ('UTF8', '6 byte, unsupported', '\xfd82'), + ('UTF8', '6 byte, unsupported', '\xfd8283'), + ('UTF8', '6 byte, unsupported', '\xfd828384'), + ('UTF8', '6 byte, unsupported', '\xfd82838485'), + ('UTF8', '6 byte, unsupported', '\xfd8283848586'), + -- MULE_INTERNAL + -- 2 81..8d LC1 + -- 3 90..99 LC2 + ('MULE_INTERNAL', 'ASCII', 'a'), + ('MULE_INTERNAL', 'LC1, short', '\x81'), + ('MULE_INTERNAL', 'LC1', '\x8182'), + ('MULE_INTERNAL', 'LC2, short', '\x90'), + ('MULE_INTERNAL', 'LC2, short', '\x9082'), + ('MULE_INTERNAL', 'LC2', '\x908283'); + +SELECT COUNT(test_encoding(encoding, description, input)) > 0 +FROM encoding_tests; + +-- substring fetches a slice of a toasted value; unused tail of that slice is +-- an incomplete char (bug #19406) +CREATE TABLE toast_3b_utf8 (c text); +INSERT INTO toast_3b_utf8 VALUES (repeat(U&'\2026', 4000)); +SELECT SUBSTRING(c FROM 1 FOR 1) FROM toast_3b_utf8; +SELECT SUBSTRING(c FROM 4001 FOR 1) FROM toast_3b_utf8; +-- diagnose incomplete char iff within the substring +UPDATE toast_3b_utf8 SET c = c || test_bytea_to_text('\xe280'); +SELECT SUBSTRING(c FROM 4000 FOR 1) FROM toast_3b_utf8; +SELECT SUBSTRING(c FROM 4001 FOR 1) FROM toast_3b_utf8; +-- substring needing last byte of its slice_size +ALTER TABLE toast_3b_utf8 RENAME TO toast_4b_utf8; +UPDATE toast_4b_utf8 SET c = repeat(U&'\+01F680', 3000); +SELECT SUBSTRING(c FROM 3000 FOR 1) FROM toast_4b_utf8; + +DROP TABLE encoding_tests; +DROP TABLE toast_4b_utf8; +DROP FUNCTION test_encoding; +DROP FUNCTION test_wchars_to_text; +DROP FUNCTION test_text_to_wchars; +DROP FUNCTION test_valid_server_encoding; +DROP FUNCTION test_mblen_func; +DROP FUNCTION test_bytea_to_text; +DROP FUNCTION test_text_to_bytea; + + +-- substring slow path: multi-byte escape char vs. multi-byte pattern char. +SELECT SUBSTRING('a' SIMILAR U&'\00AC' ESCAPE U&'\00A7'); +-- Levenshtein distance metric: exercise character length cache. +SELECT U&"real\00A7_name" FROM (select 1) AS x(real_name); +-- JSON errcontext: truncate long data. +SELECT repeat(U&'\00A7', 30)::json; diff --git a/parser/src/test/resources/postgres/test/regress/sql/euc_kr.sql b/parser/src/test/resources/postgres/test/regress/sql/euc_kr.sql new file mode 100644 index 0000000..1851b2a --- /dev/null +++ b/parser/src/test/resources/postgres/test/regress/sql/euc_kr.sql @@ -0,0 +1,12 @@ +-- This test is about EUC_KR encoding, chosen as perhaps the most prevalent +-- non-UTF8, multibyte encoding as of 2026-01. Since UTF8 can represent all +-- of EUC_KR, also run the test in UTF8. +SELECT getdatabaseencoding() NOT IN ('EUC_KR', 'UTF8') AS skip_test \gset +\if :skip_test +\quit +\endif + +-- Exercise is_multibyte_char_in_char (non-UTF8) slow path. +SELECT POSITION( + convert_from('\xbcf6c7d0', 'EUC_KR') IN + convert_from('\xb0fac7d02c20bcf6c7d02c20b1e2bcfa2c20bbee', 'EUC_KR')); diff --git a/parser/src/test/resources/postgres/test/regress/sql/expressions.sql b/parser/src/test/resources/postgres/test/regress/sql/expressions.sql index aebd08f..89e2976 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/expressions.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/expressions.sql @@ -191,16 +191,108 @@ default for type myint using hash as function 1 myinthash(myint); create table inttest (a myint); -insert into inttest values(1::myint),(null); - --- try an array with enough elements to cause hashing -select * from inttest where a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint, null); -select * from inttest where a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint, null); -select * from inttest where a not in (0::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint, null); --- ensure the result matched with the non-hashed version. We simply remove --- some array elements so that we don't reach the hashing threshold. -select * from inttest where a in (1::myint,2::myint,3::myint,4::myint,5::myint, null); -select * from inttest where a not in (1::myint,2::myint,3::myint,4::myint,5::myint, null); -select * from inttest where a not in (0::myint,2::myint,3::myint,4::myint,5::myint, null); +insert into inttest values (null), (0::myint), (1::myint); + +-- Test EEOP_HASHED_SCALARARRAYOP against EEOP_SCALARARRAYOP. Ensure the +-- result of non-hashed vs hashed is the same. +select + a, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed +from inttest; + +select + a, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed + from inttest; + +select + a, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed +from inttest; + +select + a, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed +from inttest; + +-- Now make the equal function return false when given two NULLs +create or replace function myinteq(myint, myint) returns bool as $$ +begin + if $1 is null and $2 is null then + return false; + else + return $1::int = $2::int; + end if; +end; +$$ language plpgsql immutable; + +-- And try the same again to ensure EEOP_HASHED_SCALARARRAYOP does the same +-- thing as EEOP_SCALARARRAYOP. +select + a, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed +from inttest; + +select + a, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed + from inttest; + +select + a, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed +from inttest; + +select + a, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed +from inttest; + +-- Try again with an equality function that treats NULLs as equal to 0. +create or replace function myinteq(myint, myint) returns bool as $$ +begin + if $1 is null and $2 is null then + return false; + else + return coalesce($1::int,0) = coalesce($2::int, 0); + end if; +end; +$$ language plpgsql immutable; + +select + a, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed, + a in (0::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed_zero, + a in (0::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed_zero +from inttest; + +select + a, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed + from inttest; + +select + a, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as not_hashed, + a not in (1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint,9::myint) as hashed, + a not in (0::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed_zero, + a not in (0::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed_zero +from inttest; + +select + a, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint) as not_hashed, + a not in (null::myint,1::myint,2::myint,3::myint,4::myint,5::myint,6::myint,7::myint,8::myint) as hashed +from inttest; rollback; diff --git a/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql b/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql index e1a5ae9..8e65c81 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/foreign_data.sql @@ -75,6 +75,11 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;'; CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler; + +-- should preserve dependency on test_fdw_handler +ALTER FOREIGN DATA WRAPPER test_fdw VALIDATOR postgresql_fdw_validator; +DROP FUNCTION test_fdw_handler(); -- ERROR + DROP FOREIGN DATA WRAPPER test_fdw; -- ALTER FOREIGN DATA WRAPPER @@ -391,10 +396,12 @@ COMMENT ON COLUMN ft1.c1 IS NULL; ALTER FOREIGN TABLE ft1 ADD COLUMN c4 integer; ALTER FOREIGN TABLE ft1 ADD COLUMN c5 integer DEFAULT 0; ALTER FOREIGN TABLE ft1 ADD COLUMN c6 integer; +ALTER FOREIGN TABLE ft1 ADD COLUMN IF NOT EXISTS c6 integer; ALTER FOREIGN TABLE ft1 ADD COLUMN c7 integer NOT NULL; ALTER FOREIGN TABLE ft1 ADD COLUMN c8 integer; ALTER FOREIGN TABLE ft1 ADD COLUMN c9 integer; ALTER FOREIGN TABLE ft1 ADD COLUMN c10 integer OPTIONS (p1 'v1'); +ALTER FOREIGN TABLE ft1 ADD c11 integer; ALTER FOREIGN TABLE ft1 ALTER COLUMN c4 SET DEFAULT 0; ALTER FOREIGN TABLE ft1 ALTER COLUMN c5 DROP DEFAULT; @@ -427,6 +434,7 @@ ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@'); ALTER FOREIGN TABLE ft1 DROP COLUMN no_column; -- ERROR ALTER FOREIGN TABLE ft1 DROP COLUMN IF EXISTS no_column; ALTER FOREIGN TABLE ft1 DROP COLUMN c9; +ALTER FOREIGN TABLE ft1 DROP c11; ALTER FOREIGN TABLE ft1 ADD COLUMN c11 serial; ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema; ALTER FOREIGN TABLE ft1 SET TABLESPACE ts; -- ERROR @@ -438,10 +446,12 @@ ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1; -- alter noexisting table ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c4 integer; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c6 integer; +ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN IF NOT EXISTS c6 integer; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c7 integer NOT NULL; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c8 integer; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c9 integer; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c10 integer OPTIONS (p1 'v1'); +ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD c11 integer; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ALTER COLUMN c6 SET NOT NULL; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ALTER COLUMN c7 DROP NOT NULL; @@ -455,8 +465,10 @@ ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP CONSTRAINT IF EXISTS no_cons ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP CONSTRAINT ft1_c1_check; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 OWNER TO regress_test_role; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@'); +ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP COLUMN no_column; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP COLUMN IF EXISTS no_column; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP COLUMN c9; +ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 DROP c11; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 SET SCHEMA foreign_schema; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 RENAME c1 TO foreign_column_1; ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 RENAME TO foreign_table_1; diff --git a/parser/src/test/resources/postgres/test/regress/sql/generated.sql b/parser/src/test/resources/postgres/test/regress/sql/generated.sql index 442c8ac..3b5ee2e 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/generated.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/generated.sql @@ -632,3 +632,27 @@ ALTER TABLE gtest28a DROP COLUMN a; CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); \d gtest28* + +-- rule actions referring to generated columns: +-- NEW.b in a rule action should reflect the generated column's new value +CREATE TABLE gtest_rule (a int, b int GENERATED ALWAYS AS (a * 2) STORED); +CREATE TABLE gtest_rule_log (op text, old_b int, new_b int); +CREATE RULE gtest_rule_upd AS ON UPDATE TO gtest_rule + DO ALSO INSERT INTO gtest_rule_log VALUES ('UPD', OLD.b, NEW.b); +CREATE RULE gtest_rule_ins AS ON INSERT TO gtest_rule + DO ALSO INSERT INTO gtest_rule_log VALUES ('INS', NULL, NEW.b); +INSERT INTO gtest_rule (a) VALUES (1); +UPDATE gtest_rule SET a = 10; +UPDATE gtest_rule SET a = (SELECT max(b) FROM gtest_rule); +SELECT * FROM gtest_rule_log; +DROP RULE gtest_rule_upd ON gtest_rule; +DROP RULE gtest_rule_ins ON gtest_rule; +DROP TABLE gtest_rule_log; + +-- rule quals referring to generated columns: +-- NEW.b in the rule qual should reflect the generated column's new value +CREATE RULE gtest_rule_qual AS ON UPDATE TO gtest_rule WHERE NEW.b > 100 + DO INSTEAD NOTHING; +UPDATE gtest_rule SET a = 100; +SELECT * FROM gtest_rule; +DROP TABLE gtest_rule; diff --git a/parser/src/test/resources/postgres/test/regress/sql/hash_index.sql b/parser/src/test/resources/postgres/test/regress/sql/hash_index.sql index 1504780..16548ee 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/hash_index.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/hash_index.sql @@ -61,6 +61,9 @@ CREATE INDEX hash_txt_index ON hash_txt_heap USING hash (random text_ops); CREATE INDEX hash_f8_index ON hash_f8_heap USING hash (random float8_ops) WITH (fillfactor=60); +CREATE INDEX hash_i4_partial_index ON hash_i4_heap USING hash (seqno) + WHERE seqno = 9999; + -- -- Also try building functional, expressional, and partial indexes on -- tables that already contain data. @@ -125,6 +128,16 @@ SELECT * FROM hash_f8_heap SELECT * FROM hash_f8_heap WHERE hash_f8_heap.random = '88888888'::float8; +-- +-- partial hash index +-- +EXPLAIN (COSTS OFF) +SELECT * FROM hash_i4_heap + WHERE seqno = 9999; + +SELECT * FROM hash_i4_heap + WHERE seqno = 9999; + -- -- hash index -- grep '^90[^0-9]' hashovfl.data diff --git a/parser/src/test/resources/postgres/test/regress/sql/indexing.sql b/parser/src/test/resources/postgres/test/regress/sql/indexing.sql index a48a317..f0b0dcc 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/indexing.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/indexing.sql @@ -246,6 +246,65 @@ select relname, indisvalid from pg_class join pg_index on indexrelid = oid where relname like 'idxpart%' order by relname; drop table idxpart; +-- Verify that re-attaching an already-attached partition index can +-- validate the parent index if it was still invalid, including +-- indirect ancestors in subpartitions. +create table idxpart (a int, b int) partition by range (a); +create table idxpart1 partition of idxpart for values from (0) to (1000) partition by range (a); +create table idxpart11 partition of idxpart1 for values from (0) to (500); +-- Partitioned table with no partitions +create table idxpart2 partition of idxpart for values from (1000) to (2000) partition by range (a); +-- create parent indexes +create index on only idxpart ((a/b)); +create index on only idxpart1 ((a/b)); +create index on only idxpart2 ((a/b)); +-- fail, leaves behind an invalid index on the leaf partition +insert into idxpart11 values (1, 0); +create index concurrently on idxpart11 ((a/b)); +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +-- attach the indexes; parents stay invalid +alter index idxpart1_expr_idx attach partition idxpart11_expr_idx; +alter index idxpart_expr_idx attach partition idxpart1_expr_idx; +alter index idxpart_expr_idx attach partition idxpart2_expr_idx; +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +-- fix the index on the leaf partition +delete from idxpart11 where b = 0; +reindex index concurrently idxpart11_expr_idx; +-- reattach the leaf partition index; parents should now be valid +alter index idxpart1_expr_idx attach partition idxpart11_expr_idx; +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +drop table idxpart; + +-- Verify that re-attaching does not validate the parent when another +-- child index is still invalid. +create table idxpart (a int, b int) partition by range (a); +create table idxpart1 partition of idxpart for values from (0) to (500); +create table idxpart2 partition of idxpart for values from (500) to (1000); +create index on only idxpart ((a/b)); +-- create invalid indexes on both children +insert into idxpart1 values (1, 0); +insert into idxpart2 values (501, 0); +create index concurrently on idxpart1 ((a/b)); +create index concurrently on idxpart2 ((a/b)); +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +-- attach both; parent stays invalid +alter index idxpart_expr_idx attach partition idxpart1_expr_idx; +alter index idxpart_expr_idx attach partition idxpart2_expr_idx; +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +-- fix only idxpart1's index, leave idxpart2's still invalid +delete from idxpart1 where b = 0; +reindex index concurrently idxpart1_expr_idx; +-- re-attach the fixed child; parent should stay invalid +alter index idxpart_expr_idx attach partition idxpart1_expr_idx; +select relname, indisvalid from pg_class join pg_index on indexrelid = oid + where relname like 'idxpart%' order by relname; +drop table idxpart; + -- verify dependency handling during ALTER TABLE DETACH PARTITION create table idxpart (a int) partition by range (a); create table idxpart1 (like idxpart); diff --git a/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql b/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql index e0ce509..8163fc6 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/jsonb_jsonpath.sql @@ -98,6 +98,11 @@ select jsonb_path_query('[1,2,3]', '$[last ? (@.type() == "string")]', silent => select * from jsonb_path_query('{"a": 10}', '$'); select * from jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)'); +-- the @? and @@ operators supply no variables, so a variable reference +-- must be reported as undefined rather than silently treated as NULL +-- (the latter gave wrong results and could drive unbounded memory use) +select jsonb '42' @? '$"no_such_var"'; +select jsonb '42' @@ '$"no_such_var" == 1'; select * from jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '1'); select * from jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '[{"value" : 13}]'); select * from jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{"value" : 13}'); diff --git a/parser/src/test/resources/postgres/test/regress/sql/multirangetypes.sql b/parser/src/test/resources/postgres/test/regress/sql/multirangetypes.sql index 1abcaed..a67f458 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/multirangetypes.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/multirangetypes.sql @@ -693,6 +693,22 @@ select _textrange1(textrange2('a','z')) @> 'b'::text; drop type textrange1; drop type textrange2; +-- +-- CREATE TYPE checks for CREATE on multirange schema +-- +create role regress_mr; +create schema mr_sch; +set role regress_mr; +create type mytype as range (subtype=int4, multirange_type_name=mr_sch.mr_type); +reset role; +grant create on schema mr_sch to regress_mr; +set role regress_mr; +create type mytype as range (subtype=int4, multirange_type_name=mr_sch.mr_type); +reset role; +drop type mytype; +drop schema mr_sch; +drop role regress_mr; + -- -- Test polymorphic type system -- @@ -787,6 +803,9 @@ select *, row_to_json(upper(t)) as u from (values (two_ints_multirange(two_ints_range(row(1,2), row(3,4)))), (two_ints_multirange(two_ints_range(row(5,6), row(7,8))))) v(t); +-- this must be rejected to avoid self-inclusion issues: +alter type two_ints add attribute c two_ints_multirange; + drop type two_ints cascade; -- diff --git a/parser/src/test/resources/postgres/test/regress/sql/prepared_xacts.sql b/parser/src/test/resources/postgres/test/regress/sql/prepared_xacts.sql index 2f0bb55..6800fcd 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/prepared_xacts.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/prepared_xacts.sql @@ -1,3 +1,8 @@ +SELECT current_setting('max_prepared_transactions')::integer < 2 AS skip_test \gset +\if :skip_test +\quit +\endif + -- -- PREPARED TRANSACTIONS (two-phase commit) -- @@ -160,5 +165,5 @@ SELECT gid FROM pg_prepared_xacts; -- Clean up DROP TABLE pxtest2; -DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled +-- pxtest3 was already dropped DROP TABLE pxtest4; diff --git a/parser/src/test/resources/postgres/test/regress/sql/psql.sql b/parser/src/test/resources/postgres/test/regress/sql/psql.sql index 74f6349..d28956f 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/psql.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/psql.sql @@ -1,12 +1,10 @@ + /* - * This file has been altered by SplendidData. - * It is only used for happy flow syntax checking, so erroneous statements are commented out here. - * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: - */ - + * This file is completely commented out as it is there to test psql. + * It hardly has added value for testing sql. + * + * - - -- -- Tests for psql features that aren't closely connected to any -- specific server features @@ -15,155 +13,163 @@ -- \set -- fail: invalid name --- Deactivated for SplendidDataTest: \set invalid/name foo +\set invalid/name foo -- fail: invalid value for special variable --- Deactivated for SplendidDataTest: \set AUTOCOMMIT foo --- Deactivated for SplendidDataTest: \set FETCH_COUNT foo +\set AUTOCOMMIT foo +\set FETCH_COUNT foo -- check handling of built-in boolean variable --- Deactivated for SplendidDataTest: \echo :ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \echo :ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK foo --- Deactivated for SplendidDataTest: \echo :ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK on --- Deactivated for SplendidDataTest: \echo :ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \unset ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \echo :ON_ERROR_ROLLBACK +\echo :ON_ERROR_ROLLBACK +\set ON_ERROR_ROLLBACK +\echo :ON_ERROR_ROLLBACK +\set ON_ERROR_ROLLBACK foo +\echo :ON_ERROR_ROLLBACK +\set ON_ERROR_ROLLBACK on +\echo :ON_ERROR_ROLLBACK +\unset ON_ERROR_ROLLBACK +\echo :ON_ERROR_ROLLBACK -- \g and \gx --- Deactivated for SplendidDataTest: SELECT 1 as one, 2 as two \g --- Deactivated for SplendidDataTest: \gx --- Deactivated for SplendidDataTest: SELECT 3 as three, 4 as four \gx --- Deactivated for SplendidDataTest: \g +SELECT 1 as one, 2 as two \g +\gx +SELECT 3 as three, 4 as four \gx +\g -- \gx should work in FETCH_COUNT mode too --- Deactivated for SplendidDataTest: \set FETCH_COUNT 1 +\set FETCH_COUNT 1 --- Deactivated for SplendidDataTest: SELECT 1 as one, 2 as two \g --- Deactivated for SplendidDataTest: \gx --- Deactivated for SplendidDataTest: SELECT 3 as three, 4 as four \gx --- Deactivated for SplendidDataTest: \g +SELECT 1 as one, 2 as two \g +\gx +SELECT 3 as three, 4 as four \gx +\g --- Deactivated for SplendidDataTest: \unset FETCH_COUNT +\unset FETCH_COUNT -- \g/\gx with pset options --- Deactivated for SplendidDataTest: SELECT 1 as one, 2 as two \g (format=csv csv_fieldsep='\t') --- Deactivated for SplendidDataTest: \g --- Deactivated for SplendidDataTest: SELECT 1 as one, 2 as two \gx (title='foo bar') --- Deactivated for SplendidDataTest: \g +SELECT 1 as one, 2 as two \g (format=csv csv_fieldsep='\t') +\g +SELECT 1 as one, 2 as two \gx (title='foo bar') +\g -- \gset --- Deactivated for SplendidDataTest: select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_ +select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_ --- Deactivated for SplendidDataTest: \echo :pref01_test01 :pref01_test02 :pref01_test03 +\echo :pref01_test01 :pref01_test02 :pref01_test03 -- should fail: bad variable name --- Deactivated for SplendidDataTest: select 10 as "bad name" --- Deactivated for SplendidDataTest: \gset +select 10 as "bad name" +\gset --- Deactivated for SplendidDataTest: select 97 as "EOF", 'ok' as _foo \gset IGNORE --- Deactivated for SplendidDataTest: \echo :IGNORE_foo :IGNOREEOF +select 97 as "EOF", 'ok' as _foo \gset IGNORE +\echo :IGNORE_foo :IGNOREEOF -- multiple backslash commands in one line --- Deactivated for SplendidDataTest: select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x --- Deactivated for SplendidDataTest: select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y --- Deactivated for SplendidDataTest: select 5 as x, 6 as y \gset pref01_ \\ \g \echo :pref01_x :pref01_y --- Deactivated for SplendidDataTest: select 7 as x, 8 as y \g \gset pref01_ \echo :pref01_x :pref01_y +select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x +select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y +select 5 as x, 6 as y \gset pref01_ \\ \g \echo :pref01_x :pref01_y +select 7 as x, 8 as y \g \gset pref01_ \echo :pref01_x :pref01_y -- NULL should unset the variable --- Deactivated for SplendidDataTest: \set var2 xyz --- Deactivated for SplendidDataTest: select 1 as var1, NULL as var2, 3 as var3 \gset --- Deactivated for SplendidDataTest: \echo :var1 :var2 :var3 +\set var2 xyz +select 1 as var1, NULL as var2, 3 as var3 \gset +\echo :var1 :var2 :var3 -- \gset requires just one tuple --- Deactivated for SplendidDataTest: select 10 as test01, 20 as test02 from generate_series(1,3) \gset --- Deactivated for SplendidDataTest: select 10 as test01, 20 as test02 from generate_series(1,0) \gset +select 10 as test01, 20 as test02 from generate_series(1,3) \gset +select 10 as test01, 20 as test02 from generate_series(1,0) \gset -- \gset should work in FETCH_COUNT mode too --- Deactivated for SplendidDataTest: \set FETCH_COUNT 1 +\set FETCH_COUNT 1 --- Deactivated for SplendidDataTest: select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x --- Deactivated for SplendidDataTest: select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y --- Deactivated for SplendidDataTest: select 10 as test01, 20 as test02 from generate_series(1,3) \gset --- Deactivated for SplendidDataTest: select 10 as test01, 20 as test02 from generate_series(1,0) \gset +select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x +select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y +select 10 as test01, 20 as test02 from generate_series(1,3) \gset +select 10 as test01, 20 as test02 from generate_series(1,0) \gset --- Deactivated for SplendidDataTest: \unset FETCH_COUNT +\unset FETCH_COUNT -- \gdesc --- Deactivated for SplendidDataTest: SELECT --- Deactivated for SplendidDataTest: NULL AS zero, --- Deactivated for SplendidDataTest: 1 AS one, --- Deactivated for SplendidDataTest: 2.0 AS two, --- Deactivated for SplendidDataTest: 'three' AS three, --- Deactivated for SplendidDataTest: $1 AS four, --- Deactivated for SplendidDataTest: sin($2) as five, --- Deactivated for SplendidDataTest: 'foo'::varchar(4) as six, --- Deactivated for SplendidDataTest: CURRENT_DATE AS now --- Deactivated for SplendidDataTest: \gdesc +SELECT + NULL AS zero, + 1 AS one, + 2.0 AS two, + 'three' AS three, + $1 AS four, + sin($2) as five, + 'foo'::varchar(4) as six, + CURRENT_DATE AS now +\gdesc -- should work with tuple-returning utilities, such as EXECUTE PREPARE test AS SELECT 1 AS first, 2 AS second; --- Deactivated for SplendidDataTest: EXECUTE test \gdesc --- Deactivated for SplendidDataTest: EXPLAIN EXECUTE test \gdesc +EXECUTE test \gdesc +EXPLAIN EXECUTE test \gdesc -- should fail cleanly - syntax error --- Deactivated for SplendidDataTest: SELECT 1 + \gdesc +SELECT 1 + \gdesc -- check behavior with empty results --- Deactivated for SplendidDataTest: SELECT \gdesc --- Deactivated for SplendidDataTest: CREATE TABLE bububu(a int) \gdesc +SELECT \gdesc +CREATE TABLE bububu(a int) \gdesc -- subject command should not have executed TABLE bububu; -- fail -- query buffer should remain unchanged --- Deactivated for SplendidDataTest: SELECT 1 AS x, 'Hello', 2 AS y, true AS "dirty\name" --- Deactivated for SplendidDataTest: \gdesc --- Deactivated for SplendidDataTest: \g +SELECT 1 AS x, 'Hello', 2 AS y, true AS "dirty\name" +\gdesc +\g -- all on one line --- Deactivated for SplendidDataTest: SELECT 3 AS x, 'Hello', 4 AS y, true AS "dirty\name" \gdesc \g +SELECT 3 AS x, 'Hello', 4 AS y, true AS "dirty\name" \gdesc \g + +-- test for server bug #17983 with empty statement in aborted transaction +set search_path = default; +begin; +bogus; +; +\gdesc +rollback; -- \gexec create temporary table gexec_test(a int, b text, c date, d float); --- Deactivated for SplendidDataTest: select format('create index on gexec_test(%I)', attname) --- Deactivated for SplendidDataTest: from pg_attribute --- Deactivated for SplendidDataTest: where attrelid = 'gexec_test'::regclass and attnum > 0 --- Deactivated for SplendidDataTest: order by attnum --- Deactivated for SplendidDataTest: \gexec +select format('create index on gexec_test(%I)', attname) +from pg_attribute +where attrelid = 'gexec_test'::regclass and attnum > 0 +order by attnum +\gexec -- \gexec should work in FETCH_COUNT mode too -- (though the fetch limit applies to the executed queries not the meta query) --- Deactivated for SplendidDataTest: \set FETCH_COUNT 1 +\set FETCH_COUNT 1 --- Deactivated for SplendidDataTest: select 'select 1 as ones', 'select x.y, x.y*2 as double from generate_series(1,4) as x(y)' --- Deactivated for SplendidDataTest: union all --- Deactivated for SplendidDataTest: select 'drop table gexec_test', NULL --- Deactivated for SplendidDataTest: union all --- Deactivated for SplendidDataTest: select 'drop table gexec_test', 'select ''2000-01-01''::date as party_over' --- Deactivated for SplendidDataTest: \gexec +select 'select 1 as ones', 'select x.y, x.y*2 as double from generate_series(1,4) as x(y)' +union all +select 'drop table gexec_test', NULL +union all +select 'drop table gexec_test', 'select ''2000-01-01''::date as party_over' +\gexec --- Deactivated for SplendidDataTest: \unset FETCH_COUNT +\unset FETCH_COUNT -- \setenv, \getenv -- ensure MYVAR isn't set --- Deactivated for SplendidDataTest: \setenv MYVAR +\setenv MYVAR -- in which case, reading it doesn't change the target --- Deactivated for SplendidDataTest: \getenv res MYVAR --- Deactivated for SplendidDataTest: \echo :res +\getenv res MYVAR +\echo :res -- now set it --- Deactivated for SplendidDataTest: \setenv MYVAR 'environment value' --- Deactivated for SplendidDataTest: \getenv res MYVAR --- Deactivated for SplendidDataTest: \echo :res +\setenv MYVAR 'environment value' +\getenv res MYVAR +\echo :res -- show all pset options --- Deactivated for SplendidDataTest: \pset +\pset -- test multi-line headers, wrapping, and newline indicators -- in aligned, unaligned, and wrapped formats @@ -172,116 +178,116 @@ prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab c", array_to_string(array_agg(repeat('y',20-2*n)),E'\n') as "a bc" from generate_series(1,10) as n(n) group by n>1 order by n>1; --- Deactivated for SplendidDataTest: \pset linestyle ascii +\pset linestyle ascii --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset columns 40 +\pset expanded off +\pset columns 40 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset columns 20 +\pset expanded on +\pset columns 20 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset linestyle old-ascii +\pset linestyle old-ascii --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset columns 40 +\pset expanded off +\pset columns 40 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset columns 20 +\pset expanded on +\pset columns 20 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; deallocate q; @@ -289,148 +295,159 @@ deallocate q; -- test single-line header and data prepare q as select repeat('x',2*n) as "0123456789abcdef", repeat('y',20-2*n) as "0123456789" from generate_series(1,10) as n; --- Deactivated for SplendidDataTest: \pset linestyle ascii +\pset linestyle ascii --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset columns 40 +\pset expanded off +\pset columns 40 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset columns 30 +\pset expanded on +\pset columns 30 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset columns 20 +\pset expanded on +\pset columns 20 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset linestyle old-ascii +\pset linestyle old-ascii --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset columns 40 +\pset expanded off +\pset columns 40 --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset expanded on +\pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 0 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 1 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; --- Deactivated for SplendidDataTest: \pset border 2 --- Deactivated for SplendidDataTest: \pset format unaligned +\pset border 2 +\pset format unaligned execute q; --- Deactivated for SplendidDataTest: \pset format aligned +\pset format aligned execute q; --- Deactivated for SplendidDataTest: \pset format wrapped +\pset format wrapped execute q; deallocate q; --- Deactivated for SplendidDataTest: \pset linestyle ascii --- Deactivated for SplendidDataTest: \pset border 1 +-- expanded output with short-width columns +\pset border 2 +\pset expanded on +create table psql_short_tab(a int, b int); +insert into psql_short_tab values(10,20),(30,40); +\pset format aligned +select * from psql_short_tab; +\pset format wrapped +select * from psql_short_tab; +drop table psql_short_tab; + +\pset linestyle ascii +\pset border 1 -- support table for output-format tests (useful to create a footer) @@ -438,49 +455,49 @@ create table psql_serial_tab (id serial); -- test header/footer/tuples_only behavior in aligned/unaligned/wrapped cases --- Deactivated for SplendidDataTest: \pset format aligned - --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset format aligned + +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false -- empty table is a special case for this format select 1 where false; --- Deactivated for SplendidDataTest: \pset format unaligned - --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false - --- Deactivated for SplendidDataTest: \pset format wrapped - --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset format unaligned + +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false + +\pset format wrapped + +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false -- check conditional am display --- Deactivated for SplendidDataTest: \pset expanded off +\pset expanded off CREATE SCHEMA tableam_display; CREATE ROLE regress_display_role; @@ -493,19 +510,19 @@ CREATE TABLE tbl_heap_psql(f1 int, f2 char(100)) using heap_psql; CREATE TABLE tbl_heap(f1 int, f2 char(100)) using heap; CREATE VIEW view_heap_psql AS SELECT f1 from tbl_heap_psql; CREATE MATERIALIZED VIEW mat_view_heap_psql USING heap_psql AS SELECT f1 from tbl_heap_psql; --- Deactivated for SplendidDataTest: \d+ tbl_heap_psql --- Deactivated for SplendidDataTest: \d+ tbl_heap --- Deactivated for SplendidDataTest: \set HIDE_TABLEAM off --- Deactivated for SplendidDataTest: \d+ tbl_heap_psql --- Deactivated for SplendidDataTest: \d+ tbl_heap +\d+ tbl_heap_psql +\d+ tbl_heap +\set HIDE_TABLEAM off +\d+ tbl_heap_psql +\d+ tbl_heap -- AM is displayed for tables, indexes and materialized views. --- Deactivated for SplendidDataTest: \d+ --- Deactivated for SplendidDataTest: \dt+ --- Deactivated for SplendidDataTest: \dm+ +\d+ +\dt+ +\dm+ -- But not for views and sequences. --- Deactivated for SplendidDataTest: \dv+ --- Deactivated for SplendidDataTest: \set HIDE_TABLEAM on --- Deactivated for SplendidDataTest: \d+ +\dv+ +\set HIDE_TABLEAM on +\d+ RESET ROLE; RESET search_path; DROP SCHEMA tableam_display CASCADE; @@ -514,555 +531,557 @@ DROP ROLE regress_display_role; -- test numericlocale (as best we can without control of psql's locale) --- Deactivated for SplendidDataTest: \pset format aligned --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset numericlocale true +\pset format aligned +\pset expanded off +\pset numericlocale true select n, -n as m, n * 111 as x, '1e90'::float8 as f from generate_series(0,3) n; --- Deactivated for SplendidDataTest: \pset numericlocale false +\pset numericlocale false -- test asciidoc output format --- Deactivated for SplendidDataTest: \pset format asciidoc +\pset format asciidoc --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some|text' as "a|title", ' ' as "empty ", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded off +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded on +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; deallocate q; -- test csv output format --- Deactivated for SplendidDataTest: \pset format csv +\pset format csv --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some"text' as "a""title", E' \n' as "junk", ' ' as "empty", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off +\pset expanded off execute q; --- Deactivated for SplendidDataTest: \pset expanded on +\pset expanded on execute q; deallocate q; -- special cases --- Deactivated for SplendidDataTest: \pset expanded off +\pset expanded off select 'comma,comma' as comma, 'semi;semi' as semi; --- Deactivated for SplendidDataTest: \pset csv_fieldsep ';' +\pset csv_fieldsep ';' select 'comma,comma' as comma, 'semi;semi' as semi; select '\.' as data; --- Deactivated for SplendidDataTest: \pset csv_fieldsep '.' +\pset csv_fieldsep '.' select '\' as d1, '' as d2; -- illegal csv separators --- Deactivated for SplendidDataTest: \pset csv_fieldsep '' --- Deactivated for SplendidDataTest: \pset csv_fieldsep '\0' --- Deactivated for SplendidDataTest: \pset csv_fieldsep '\n' --- Deactivated for SplendidDataTest: \pset csv_fieldsep '\r' --- Deactivated for SplendidDataTest: \pset csv_fieldsep '"' --- Deactivated for SplendidDataTest: \pset csv_fieldsep ',,' +\pset csv_fieldsep '' +\pset csv_fieldsep '\0' +\pset csv_fieldsep '\n' +\pset csv_fieldsep '\r' +\pset csv_fieldsep '"' +\pset csv_fieldsep ',,' --- Deactivated for SplendidDataTest: \pset csv_fieldsep ',' +\pset csv_fieldsep ',' -- test html output format --- Deactivated for SplendidDataTest: \pset format html +\pset format html --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some"text' as "a&title", E' \n' as "junk", ' ' as "empty", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded off +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset tableattr foobar +\pset tableattr foobar execute q; --- Deactivated for SplendidDataTest: \pset tableattr +\pset tableattr --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded on +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset tableattr foobar +\pset tableattr foobar execute q; --- Deactivated for SplendidDataTest: \pset tableattr +\pset tableattr deallocate q; -- test latex output format --- Deactivated for SplendidDataTest: \pset format latex +\pset format latex --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some\more_text' as "a$title", E' #%&^~|\n{bar}' as "junk", ' ' as "empty", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded off +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset border 3 +\pset border 3 execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded on +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset border 3 +\pset border 3 execute q; deallocate q; -- test latex-longtable output format --- Deactivated for SplendidDataTest: \pset format latex-longtable +\pset format latex-longtable --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some\more_text' as "a$title", E' #%&^~|\n{bar}' as "junk", ' ' as "empty", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded off +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset border 3 +\pset border 3 execute q; --- Deactivated for SplendidDataTest: \pset tableattr lr +\pset tableattr lr execute q; --- Deactivated for SplendidDataTest: \pset tableattr +\pset tableattr --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded on +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset border 3 +\pset border 3 execute q; --- Deactivated for SplendidDataTest: \pset tableattr lr +\pset tableattr lr execute q; --- Deactivated for SplendidDataTest: \pset tableattr +\pset tableattr deallocate q; -- test troff-ms output format --- Deactivated for SplendidDataTest: \pset format troff-ms +\pset format troff-ms --- Deactivated for SplendidDataTest: \pset border 1 --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \d psql_serial_tab_id_seq --- Deactivated for SplendidDataTest: \pset tuples_only true --- Deactivated for SplendidDataTest: \df exp --- Deactivated for SplendidDataTest: \pset tuples_only false +\pset border 1 +\pset expanded off +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false +\pset expanded on +\d psql_serial_tab_id_seq +\pset tuples_only true +\df exp +\pset tuples_only false prepare q as select 'some\text' as "a\title", E' \n' as "junk", ' ' as "empty", n as int from generate_series(1,2) as n; --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded off +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; --- Deactivated for SplendidDataTest: \pset expanded on --- Deactivated for SplendidDataTest: \pset border 0 +\pset expanded on +\pset border 0 execute q; --- Deactivated for SplendidDataTest: \pset border 1 +\pset border 1 execute q; --- Deactivated for SplendidDataTest: \pset border 2 +\pset border 2 execute q; deallocate q; -- check ambiguous format requests --- Deactivated for SplendidDataTest: \pset format a --- Deactivated for SplendidDataTest: \pset format l +\pset format a +\pset format l -- clean up after output format tests drop table psql_serial_tab; --- Deactivated for SplendidDataTest: \pset format aligned --- Deactivated for SplendidDataTest: \pset expanded off --- Deactivated for SplendidDataTest: \pset border 1 +\pset format aligned +\pset expanded off +\pset border 1 -- \echo and allied features --- Deactivated for SplendidDataTest: \echo this is a test --- Deactivated for SplendidDataTest: \echo -n without newline --- Deactivated for SplendidDataTest: \echo with -n newline --- Deactivated for SplendidDataTest: \echo '-n' with newline +\echo this is a test +\echo -n without newline +\echo with -n newline +\echo '-n' with newline --- Deactivated for SplendidDataTest: \set foo bar --- Deactivated for SplendidDataTest: \echo foo = :foo +\set foo bar +\echo foo = :foo --- Deactivated for SplendidDataTest: \qecho this is a test --- Deactivated for SplendidDataTest: \qecho foo = :foo +\qecho this is a test +\qecho foo = :foo --- Deactivated for SplendidDataTest: \warn this is a test --- Deactivated for SplendidDataTest: \warn foo = :foo +\warn this is a test +\warn foo = :foo -- tests for \if ... \endif --- Deactivated for SplendidDataTest: \if true +\if true select 'okay'; select 'still okay'; --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: not okay; --- Deactivated for SplendidDataTest: still not okay --- Deactivated for SplendidDataTest: \endif +\else + not okay; + still not okay +\endif -- at this point query buffer should still have last valid line --- Deactivated for SplendidDataTest: \g +\g -- \if should work okay on part of a query select --- Deactivated for SplendidDataTest: \if true + \if true 42 --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: (bogus --- Deactivated for SplendidDataTest: \endif + \else + (bogus + \endif forty_two; --- Deactivated for SplendidDataTest: select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; +select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; -- test a large nested if using a variety of true-equivalents --- Deactivated for SplendidDataTest: \if true --- Deactivated for SplendidDataTest: \if 1 --- Deactivated for SplendidDataTest: \if yes --- Deactivated for SplendidDataTest: \if on --- Deactivated for SplendidDataTest: \echo 'all true' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #1-1' --- Deactivated for SplendidDataTest: \endif --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #1-2' --- Deactivated for SplendidDataTest: \endif --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #1-3' --- Deactivated for SplendidDataTest: \endif --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #1-4' --- Deactivated for SplendidDataTest: \endif +\if true + \if 1 + \if yes + \if on + \echo 'all true' + \else + \echo 'should not print #1-1' + \endif + \else + \echo 'should not print #1-2' + \endif + \else + \echo 'should not print #1-3' + \endif +\else + \echo 'should not print #1-4' +\endif -- test a variety of false-equivalents in an if/elif/else structure --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: \echo 'should not print #2-1' --- Deactivated for SplendidDataTest: \elif 0 --- Deactivated for SplendidDataTest: \echo 'should not print #2-2' --- Deactivated for SplendidDataTest: \elif no --- Deactivated for SplendidDataTest: \echo 'should not print #2-3' --- Deactivated for SplendidDataTest: \elif off --- Deactivated for SplendidDataTest: \echo 'should not print #2-4' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'all false' --- Deactivated for SplendidDataTest: \endif +\if false + \echo 'should not print #2-1' +\elif 0 + \echo 'should not print #2-2' +\elif no + \echo 'should not print #2-3' +\elif off + \echo 'should not print #2-4' +\else + \echo 'all false' +\endif -- test true-false elif after initial true branch --- Deactivated for SplendidDataTest: \if true --- Deactivated for SplendidDataTest: \echo 'should print #2-5' --- Deactivated for SplendidDataTest: \elif true --- Deactivated for SplendidDataTest: \echo 'should not print #2-6' --- Deactivated for SplendidDataTest: \elif false --- Deactivated for SplendidDataTest: \echo 'should not print #2-7' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #2-8' --- Deactivated for SplendidDataTest: \endif +\if true + \echo 'should print #2-5' +\elif true + \echo 'should not print #2-6' +\elif false + \echo 'should not print #2-7' +\else + \echo 'should not print #2-8' +\endif -- test simple true-then-else --- Deactivated for SplendidDataTest: \if true --- Deactivated for SplendidDataTest: \echo 'first thing true' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #3-1' --- Deactivated for SplendidDataTest: \endif +\if true + \echo 'first thing true' +\else + \echo 'should not print #3-1' +\endif -- test simple false-true-else --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: \echo 'should not print #4-1' --- Deactivated for SplendidDataTest: \elif true --- Deactivated for SplendidDataTest: \echo 'second thing true' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #5-1' --- Deactivated for SplendidDataTest: \endif +\if false + \echo 'should not print #4-1' +\elif true + \echo 'second thing true' +\else + \echo 'should not print #5-1' +\endif -- invalid boolean expressions are false --- Deactivated for SplendidDataTest: \if invalid boolean expression --- Deactivated for SplendidDataTest: \echo 'will not print #6-1' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'will print anyway #6-2' --- Deactivated for SplendidDataTest: \endif +\if invalid boolean expression + \echo 'will not print #6-1' +\else + \echo 'will print anyway #6-2' +\endif -- test un-matched endif --- Deactivated for SplendidDataTest: \endif +\endif -- test un-matched else --- Deactivated for SplendidDataTest: \else +\else -- test un-matched elif --- Deactivated for SplendidDataTest: \elif +\elif -- test double-else error --- Deactivated for SplendidDataTest: \if true --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \endif +\if true +\else +\else +\endif -- test elif out-of-order --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \elif --- Deactivated for SplendidDataTest: \endif +\if false +\else +\elif +\endif -- test if-endif matching in a false branch --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: \echo 'should not print #7-1' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #7-2' --- Deactivated for SplendidDataTest: \endif --- Deactivated for SplendidDataTest: \echo 'should not print #7-3' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should print #7-4' --- Deactivated for SplendidDataTest: \endif +\if false + \if false + \echo 'should not print #7-1' + \else + \echo 'should not print #7-2' + \endif + \echo 'should not print #7-3' +\else + \echo 'should print #7-4' +\endif -- show that vars and backticks are not expanded when ignoring extra args --- Deactivated for SplendidDataTest: \set foo bar --- Deactivated for SplendidDataTest: \echo :foo :'foo' :"foo" --- Deactivated for SplendidDataTest: \pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" +\set foo bar +\echo :foo :'foo' :"foo" +\pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" -- show that vars and backticks are not expanded and commands are ignored -- when in a false if-branch --- Deactivated for SplendidDataTest: \set try_to_quit '\\q' --- Deactivated for SplendidDataTest: \if false --- Deactivated for SplendidDataTest: :try_to_quit --- Deactivated for SplendidDataTest: \echo `nosuchcommand` :foo :'foo' :"foo" --- Deactivated for SplendidDataTest: \pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" --- Deactivated for SplendidDataTest: \a --- Deactivated for SplendidDataTest: \C arg1 --- Deactivated for SplendidDataTest: \c arg1 arg2 arg3 arg4 --- Deactivated for SplendidDataTest: \cd arg1 --- Deactivated for SplendidDataTest: \conninfo --- Deactivated for SplendidDataTest: \copy arg1 arg2 arg3 arg4 arg5 arg6 --- Deactivated for SplendidDataTest: \copyright --- Deactivated for SplendidDataTest: SELECT 1 as one, 2, 3 \crosstabview --- Deactivated for SplendidDataTest: \dt arg1 --- Deactivated for SplendidDataTest: \e arg1 arg2 --- Deactivated for SplendidDataTest: \ef whole_line --- Deactivated for SplendidDataTest: \ev whole_line --- Deactivated for SplendidDataTest: \echo arg1 arg2 arg3 arg4 arg5 --- Deactivated for SplendidDataTest: \echo arg1 --- Deactivated for SplendidDataTest: \encoding arg1 --- Deactivated for SplendidDataTest: \errverbose --- Deactivated for SplendidDataTest: \f arg1 --- Deactivated for SplendidDataTest: \g arg1 --- Deactivated for SplendidDataTest: \gx arg1 --- Deactivated for SplendidDataTest: \gexec --- Deactivated for SplendidDataTest: SELECT 1 AS one \gset --- Deactivated for SplendidDataTest: \h --- Deactivated for SplendidDataTest: \? --- Deactivated for SplendidDataTest: \html --- Deactivated for SplendidDataTest: \i arg1 --- Deactivated for SplendidDataTest: \ir arg1 --- Deactivated for SplendidDataTest: \l arg1 --- Deactivated for SplendidDataTest: \lo arg1 arg2 --- Deactivated for SplendidDataTest: \lo_list --- Deactivated for SplendidDataTest: \o arg1 --- Deactivated for SplendidDataTest: \p --- Deactivated for SplendidDataTest: \password arg1 --- Deactivated for SplendidDataTest: \prompt arg1 arg2 --- Deactivated for SplendidDataTest: \pset arg1 arg2 --- Deactivated for SplendidDataTest: \q --- Deactivated for SplendidDataTest: \reset --- Deactivated for SplendidDataTest: \s arg1 --- Deactivated for SplendidDataTest: \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 --- Deactivated for SplendidDataTest: \setenv arg1 arg2 --- Deactivated for SplendidDataTest: \sf whole_line --- Deactivated for SplendidDataTest: \sv whole_line --- Deactivated for SplendidDataTest: \t arg1 --- Deactivated for SplendidDataTest: \T arg1 --- Deactivated for SplendidDataTest: \timing arg1 --- Deactivated for SplendidDataTest: \unset arg1 --- Deactivated for SplendidDataTest: \w arg1 --- Deactivated for SplendidDataTest: \watch arg1 --- Deactivated for SplendidDataTest: \x arg1 +\set try_to_quit '\\q' +\if false + :try_to_quit + \echo `nosuchcommand` :foo :'foo' :"foo" + \pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" + \a + \C arg1 + \c arg1 arg2 arg3 arg4 + \cd arg1 + \conninfo + \copy arg1 arg2 arg3 arg4 arg5 arg6 + \copyright + SELECT 1 as one, 2, 3 \crosstabview + \dt arg1 + \e arg1 arg2 + \ef whole_line + \ev whole_line + \echo arg1 arg2 arg3 arg4 arg5 + \echo arg1 + \encoding arg1 + \errverbose + \f arg1 + \g arg1 + \gx arg1 + \gexec + SELECT 1 AS one \gset + \h + \? + \html + \i arg1 + \ir arg1 + \l arg1 + \lo arg1 arg2 + \lo_list + \o arg1 + \p + \password arg1 + \prompt arg1 arg2 + \pset arg1 arg2 + \q + \reset + \restrict test + \s arg1 + \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 + \setenv arg1 arg2 + \sf whole_line + \sv whole_line + \t arg1 + \T arg1 + \timing arg1 + \unrestrict not_valid + \unset arg1 + \w arg1 + \watch arg1 + \x arg1 -- \else here is eaten as part of OT_FILEPIPE argument --- Deactivated for SplendidDataTest: \w |/no/such/file \else + \w |/no/such/file \else -- \endif here is eaten as part of whole-line argument --- Deactivated for SplendidDataTest: \! whole_line \endif --- Deactivated for SplendidDataTest: \z --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should print #8-1' --- Deactivated for SplendidDataTest: \endif + \! whole_line \endif + \z +\else + \echo 'should print #8-1' +\endif -- :{?...} defined variable test --- Deactivated for SplendidDataTest: \set i 1 --- Deactivated for SplendidDataTest: \if :{?i} --- Deactivated for SplendidDataTest: \echo '#9-1 ok, variable i is defined' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo 'should not print #9-2' --- Deactivated for SplendidDataTest: \endif +\set i 1 +\if :{?i} + \echo '#9-1 ok, variable i is defined' +\else + \echo 'should not print #9-2' +\endif --- Deactivated for SplendidDataTest: \if :{?no_such_variable} --- Deactivated for SplendidDataTest: \echo 'should not print #10-1' --- Deactivated for SplendidDataTest: \else --- Deactivated for SplendidDataTest: \echo '#10-2 ok, variable no_such_variable is not defined' --- Deactivated for SplendidDataTest: \endif +\if :{?no_such_variable} + \echo 'should not print #10-1' +\else + \echo '#10-2 ok, variable no_such_variable is not defined' +\endif --- Deactivated for SplendidDataTest: SELECT :{?i} AS i_is_defined; +SELECT :{?i} AS i_is_defined; --- Deactivated for SplendidDataTest: SELECT NOT :{?no_such_var} AS no_such_var_is_not_defined; +SELECT NOT :{?no_such_var} AS no_such_var_is_not_defined; -- SHOW_CONTEXT --- Deactivated for SplendidDataTest: \set SHOW_CONTEXT never +\set SHOW_CONTEXT never do $$ begin raise notice 'foo'; raise exception 'bar'; end $$; --- Deactivated for SplendidDataTest: \set SHOW_CONTEXT errors +\set SHOW_CONTEXT errors do $$ begin raise notice 'foo'; raise exception 'bar'; end $$; --- Deactivated for SplendidDataTest: \set SHOW_CONTEXT always +\set SHOW_CONTEXT always do $$ begin raise notice 'foo'; @@ -1071,94 +1090,94 @@ end $$; -- test printing and clearing the query buffer SELECT 1; --- Deactivated for SplendidDataTest: \p --- Deactivated for SplendidDataTest: SELECT 2 \r --- Deactivated for SplendidDataTest: \p --- Deactivated for SplendidDataTest: SELECT 3 \p --- Deactivated for SplendidDataTest: UNION SELECT 4 \p --- Deactivated for SplendidDataTest: UNION SELECT 5 --- Deactivated for SplendidDataTest: ORDER BY 1; --- Deactivated for SplendidDataTest: \r --- Deactivated for SplendidDataTest: \p +\p +SELECT 2 \r +\p +SELECT 3 \p +UNION SELECT 4 \p +UNION SELECT 5 +ORDER BY 1; +\r +\p -- tests for special result variables -- working query, 2 rows selected SELECT 1 AS stuff UNION SELECT 2; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT -- syntax error --- Deactivated for SplendidDataTest: SELECT 1 UNION; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \echo 'last error code:' :LAST_ERROR_SQLSTATE +SELECT 1 UNION; +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT +\echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'last error code:' :LAST_ERROR_SQLSTATE -- empty query ; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT -- must have kept previous values --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \echo 'last error code:' :LAST_ERROR_SQLSTATE +\echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'last error code:' :LAST_ERROR_SQLSTATE -- other query error DROP TABLE this_table_does_not_exist; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \echo 'last error code:' :LAST_ERROR_SQLSTATE +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT +\echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'last error code:' :LAST_ERROR_SQLSTATE -- nondefault verbosity error settings (except verbose, which is too unstable) --- Deactivated for SplendidDataTest: \set VERBOSITY terse --- Deactivated for SplendidDataTest: SELECT 1 UNION; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE +\set VERBOSITY terse +SELECT 1 UNION; +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \set VERBOSITY sqlstate +\set VERBOSITY sqlstate SELECT 1/0; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \set VERBOSITY default +\set VERBOSITY default -- working \gdesc --- Deactivated for SplendidDataTest: SELECT 3 AS three, 4 AS four \gdesc --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT +SELECT 3 AS three, 4 AS four \gdesc +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT -- \gdesc with an error --- Deactivated for SplendidDataTest: SELECT 4 AS \gdesc --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \echo 'last error code:' :LAST_ERROR_SQLSTATE +SELECT 4 AS \gdesc +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT +\echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'last error code:' :LAST_ERROR_SQLSTATE -- check row count for a cursor-fetched query --- Deactivated for SplendidDataTest: \set FETCH_COUNT 10 +\set FETCH_COUNT 10 select unique2 from tenk1 order by unique2 limit 19; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT -- cursor-fetched query with an error after the first group select 1/(15-unique2) from tenk1 order by unique2 limit 19; --- Deactivated for SplendidDataTest: \echo 'error:' :ERROR --- Deactivated for SplendidDataTest: \echo 'error code:' :SQLSTATE --- Deactivated for SplendidDataTest: \echo 'number of rows:' :ROW_COUNT --- Deactivated for SplendidDataTest: \echo 'last error message:' :LAST_ERROR_MESSAGE --- Deactivated for SplendidDataTest: \echo 'last error code:' :LAST_ERROR_SQLSTATE +\echo 'error:' :ERROR +\echo 'error code:' :SQLSTATE +\echo 'number of rows:' :ROW_COUNT +\echo 'last error message:' :LAST_ERROR_MESSAGE +\echo 'last error code:' :LAST_ERROR_SQLSTATE --- Deactivated for SplendidDataTest: \unset FETCH_COUNT +\unset FETCH_COUNT create schema testpart; create role regress_partitioning_role; @@ -1182,9 +1201,9 @@ create index testpart_apple_index on testpart_apple(logdate); create index testpart_orange_index on testpart_orange(logdate); -- only partition related object should be displayed --- Deactivated for SplendidDataTest: \dP test*apple* --- Deactivated for SplendidDataTest: \dPt test*apple* --- Deactivated for SplendidDataTest: \dPi test*apple* +\dP test*apple* +\dPt test*apple* +\dPi test*apple* drop table testtable_apple; drop table testtable_orange; @@ -1209,16 +1228,16 @@ create table child_35_40 partition of child_30_40 for values from (35) to (40); insert into parent_tab values (generate_series(30,39)); --- Deactivated for SplendidDataTest: \dPt --- Deactivated for SplendidDataTest: \dPi +\dPt +\dPi --- Deactivated for SplendidDataTest: \dP testpart.* --- Deactivated for SplendidDataTest: \dP +\dP testpart.* +\dP --- Deactivated for SplendidDataTest: \dPtn --- Deactivated for SplendidDataTest: \dPin --- Deactivated for SplendidDataTest: \dPn --- Deactivated for SplendidDataTest: \dPn testpart.* +\dPtn +\dPin +\dPn +\dPn testpart.* drop table parent_tab cascade; @@ -1230,49 +1249,57 @@ set role to default; drop role regress_partitioning_role; -- \d on toast table (use pg_statistic's toast table, which has a known name) --- Deactivated for SplendidDataTest: \d pg_toast.pg_toast_2619 +\d pg_toast.pg_toast_2619 -- check printing info about access methods --- Deactivated for SplendidDataTest: \dA --- Deactivated for SplendidDataTest: \dA * --- Deactivated for SplendidDataTest: \dA h* --- Deactivated for SplendidDataTest: \dA foo --- Deactivated for SplendidDataTest: \dA foo bar --- Deactivated for SplendidDataTest: \dA+ --- Deactivated for SplendidDataTest: \dA+ * --- Deactivated for SplendidDataTest: \dA+ h* --- Deactivated for SplendidDataTest: \dA+ foo --- Deactivated for SplendidDataTest: \dAc brin pg*.oid* --- Deactivated for SplendidDataTest: \dAf spgist --- Deactivated for SplendidDataTest: \dAf btree int4 --- Deactivated for SplendidDataTest: \dAo+ btree float_ops --- Deactivated for SplendidDataTest: \dAo * pg_catalog.jsonb_path_ops --- Deactivated for SplendidDataTest: \dAp+ btree float_ops --- Deactivated for SplendidDataTest: \dAp * pg_catalog.uuid_ops +\dA +\dA * +\dA h* +\dA foo +\dA foo bar +\dA+ +\dA+ * +\dA+ h* +\dA+ foo +\dAc brin pg*.oid* +\dAf spgist +\dAf btree int4 +\dAo+ btree float_ops +\dAo * pg_catalog.jsonb_path_ops +\dAp+ btree float_ops +\dAp * pg_catalog.uuid_ops -- check \dconfig set work_mem = 10240; --- Deactivated for SplendidDataTest: \dconfig work_mem --- Deactivated for SplendidDataTest: \dconfig+ work* +\dconfig work_mem +\dconfig+ work* reset work_mem; -- check \df, \do with argument specifications --- Deactivated for SplendidDataTest: \df *sqrt --- Deactivated for SplendidDataTest: \df *sqrt num* --- Deactivated for SplendidDataTest: \df int*pl --- Deactivated for SplendidDataTest: \df int*pl int4 --- Deactivated for SplendidDataTest: \df int*pl * pg_catalog.int8 --- Deactivated for SplendidDataTest: \df acl* aclitem[] --- Deactivated for SplendidDataTest: \df has_database_privilege oid text --- Deactivated for SplendidDataTest: \df has_database_privilege oid text - --- Deactivated for SplendidDataTest: \dfa bit* small* --- Deactivated for SplendidDataTest: \do - pg_catalog.int4 --- Deactivated for SplendidDataTest: \do && anyarray * +\df *sqrt +\df *sqrt num* +\df int*pl +\df int*pl int4 +\df int*pl * pg_catalog.int8 +\df acl* aclitem[] +\df has_database_privilege oid text +\df has_database_privilege oid text - +\dfa bit* small* +\df *._pg_expandarray +\do - pg_catalog.int4 +\do && anyarray * + +-- check \sf +\sf information_schema._pg_expandarray +\sf+ information_schema._pg_expandarray +\sf+ interval_pl_time +\sf ts_debug(text) +\sf+ ts_debug(text) -- AUTOCOMMIT CREATE TABLE ac_test (a int); --- Deactivated for SplendidDataTest: \set AUTOCOMMIT off +\set AUTOCOMMIT off INSERT INTO ac_test VALUES (1); COMMIT; @@ -1296,13 +1323,13 @@ ROLLBACK; SELECT * FROM ac_test; COMMIT; --- Deactivated for SplendidDataTest: \set AUTOCOMMIT on +\set AUTOCOMMIT on DROP TABLE ac_test; SELECT * FROM ac_test; -- should be gone now -- ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK on +\set ON_ERROR_ROLLBACK on CREATE TABLE oer_test (a int); BEGIN; @@ -1325,12 +1352,12 @@ COMMIT; SELECT * FROM oer_test; DROP TABLE oer_test; --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK off +\set ON_ERROR_ROLLBACK off -- ECHO errors --- Deactivated for SplendidDataTest: \set ECHO errors +\set ECHO errors SELECT * FROM notexists; --- Deactivated for SplendidDataTest: \set ECHO all +\set ECHO all -- -- combined queries @@ -1341,76 +1368,76 @@ AS $$ $$; -- show both --- Deactivated for SplendidDataTest: SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ; +SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ; -- \gset applies to last query only --- Deactivated for SplendidDataTest: SELECT 3 AS three \; SELECT warn('3.5') \; SELECT 4 AS four \gset --- Deactivated for SplendidDataTest: \echo :three :four +SELECT 3 AS three \; SELECT warn('3.5') \; SELECT 4 AS four \gset +\echo :three :four -- syntax error stops all processing --- Deactivated for SplendidDataTest: SELECT 5 \; SELECT 6 + \; SELECT warn('6.5') \; SELECT 7 ; +SELECT 5 \; SELECT 6 + \; SELECT warn('6.5') \; SELECT 7 ; -- with aborted transaction, stop on first error --- Deactivated for SplendidDataTest: BEGIN \; SELECT 8 AS eight \; SELECT 9/0 AS nine \; ROLLBACK \; SELECT 10 AS ten ; +BEGIN \; SELECT 8 AS eight \; SELECT 9/0 AS nine \; ROLLBACK \; SELECT 10 AS ten ; -- close previously aborted transaction ROLLBACK; -- miscellaneous SQL commands -- (non SELECT output is sent to stderr, thus is not shown in expected results) --- Deactivated for SplendidDataTest: SELECT 'ok' AS "begin" \; --- Deactivated for SplendidDataTest: CREATE TABLE psql_comics(s TEXT) \; --- Deactivated for SplendidDataTest: INSERT INTO psql_comics VALUES ('Calvin'), ('hobbes') \; --- Deactivated for SplendidDataTest: COPY psql_comics FROM STDIN \; --- Deactivated for SplendidDataTest: UPDATE psql_comics SET s = 'Hobbes' WHERE s = 'hobbes' \; --- Deactivated for SplendidDataTest: DELETE FROM psql_comics WHERE s = 'Moe' \; --- Deactivated for SplendidDataTest: COPY psql_comics TO STDOUT \; --- Deactivated for SplendidDataTest: TRUNCATE psql_comics \; --- Deactivated for SplendidDataTest: DROP TABLE psql_comics \; +SELECT 'ok' AS "begin" \; +CREATE TABLE psql_comics(s TEXT) \; +INSERT INTO psql_comics VALUES ('Calvin'), ('hobbes') \; +COPY psql_comics FROM STDIN \; +UPDATE psql_comics SET s = 'Hobbes' WHERE s = 'hobbes' \; +DELETE FROM psql_comics WHERE s = 'Moe' \; +COPY psql_comics TO STDOUT \; +TRUNCATE psql_comics \; +DROP TABLE psql_comics \; SELECT 'ok' AS "done" ; --- Deactivated for SplendidDataTest: Moe --- Deactivated for SplendidDataTest: Susie --- Deactivated for SplendidDataTest: \. +Moe +Susie +\. --- Deactivated for SplendidDataTest: \set SHOW_ALL_RESULTS off --- Deactivated for SplendidDataTest: SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ; +\set SHOW_ALL_RESULTS off +SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ; --- Deactivated for SplendidDataTest: \set SHOW_ALL_RESULTS on +\set SHOW_ALL_RESULTS on DROP FUNCTION warn(TEXT); -- -- AUTOCOMMIT and combined queries -- --- Deactivated for SplendidDataTest: \set AUTOCOMMIT off --- Deactivated for SplendidDataTest: \echo '# AUTOCOMMIT:' :AUTOCOMMIT +\set AUTOCOMMIT off +\echo '# AUTOCOMMIT:' :AUTOCOMMIT -- BEGIN is now implicit --- Deactivated for SplendidDataTest: CREATE TABLE foo(s TEXT) \; +CREATE TABLE foo(s TEXT) \; ROLLBACK; --- Deactivated for SplendidDataTest: CREATE TABLE foo(s TEXT) \; --- Deactivated for SplendidDataTest: INSERT INTO foo(s) VALUES ('hello'), ('world') \; +CREATE TABLE foo(s TEXT) \; +INSERT INTO foo(s) VALUES ('hello'), ('world') \; COMMIT; --- Deactivated for SplendidDataTest: DROP TABLE foo \; +DROP TABLE foo \; ROLLBACK; -- table foo is still there --- Deactivated for SplendidDataTest: SELECT * FROM foo ORDER BY 1 \; --- Deactivated for SplendidDataTest: DROP TABLE foo \; +SELECT * FROM foo ORDER BY 1 \; +DROP TABLE foo \; COMMIT; --- Deactivated for SplendidDataTest: \set AUTOCOMMIT on --- Deactivated for SplendidDataTest: \echo '# AUTOCOMMIT:' :AUTOCOMMIT +\set AUTOCOMMIT on +\echo '# AUTOCOMMIT:' :AUTOCOMMIT -- BEGIN now explicit for multi-statement transactions --- Deactivated for SplendidDataTest: BEGIN \; --- Deactivated for SplendidDataTest: CREATE TABLE foo(s TEXT) \; --- Deactivated for SplendidDataTest: INSERT INTO foo(s) VALUES ('hello'), ('world') \; +BEGIN \; +CREATE TABLE foo(s TEXT) \; +INSERT INTO foo(s) VALUES ('hello'), ('world') \; COMMIT; --- Deactivated for SplendidDataTest: BEGIN \; --- Deactivated for SplendidDataTest: DROP TABLE foo \; --- Deactivated for SplendidDataTest: ROLLBACK \; +BEGIN \; +DROP TABLE foo \; +ROLLBACK \; -- implicit transactions --- Deactivated for SplendidDataTest: SELECT * FROM foo ORDER BY 1 \; +SELECT * FROM foo ORDER BY 1 \; DROP TABLE foo; -- @@ -1422,9 +1449,9 @@ CREATE FUNCTION psql_error(msg TEXT) RETURNS BOOLEAN AS $$ END; $$ LANGUAGE plpgsql; --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK on --- Deactivated for SplendidDataTest: \echo '# ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK --- Deactivated for SplendidDataTest: \echo '# AUTOCOMMIT:' :AUTOCOMMIT +\set ON_ERROR_ROLLBACK on +\echo '# ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK +\echo '# AUTOCOMMIT:' :AUTOCOMMIT BEGIN; CREATE TABLE bla(s NO_SUCH_TYPE); -- fails @@ -1438,279 +1465,283 @@ SELECT * FROM bla ORDER BY 1; BEGIN; INSERT INTO bla VALUES ('Susie'); -- succeeds -- now with combined queries --- Deactivated for SplendidDataTest: INSERT INTO bla VALUES ('Rosalyn') \; -- will rollback --- Deactivated for SplendidDataTest: SELECT 'before error' AS show \; -- will show nevertheless! --- Deactivated for SplendidDataTest: SELECT psql_error('boum!') \; -- failure +INSERT INTO bla VALUES ('Rosalyn') \; -- will rollback +SELECT 'before error' AS show \; -- will show nevertheless! + SELECT psql_error('boum!') \; -- failure SELECT 'after error' AS noshow; -- hidden by preceding error --- Deactivated for SplendidDataTest: INSERT INTO bla(s) VALUES ('Moe') \; -- will rollback +INSERT INTO bla(s) VALUES ('Moe') \; -- will rollback SELECT psql_error('bam!'); INSERT INTO bla VALUES ('Miss Wormwood'); -- succeeds COMMIT; SELECT * FROM bla ORDER BY 1; -- some with autocommit off --- Deactivated for SplendidDataTest: \set AUTOCOMMIT off --- Deactivated for SplendidDataTest: \echo '# AUTOCOMMIT:' :AUTOCOMMIT +\set AUTOCOMMIT off +\echo '# AUTOCOMMIT:' :AUTOCOMMIT -- implicit BEGIN INSERT INTO bla VALUES ('Dad'); -- succeeds SELECT psql_error('bad!'); -- implicit partial rollback --- Deactivated for SplendidDataTest: INSERT INTO bla VALUES ('Mum') \; -- will rollback --- Deactivated for SplendidDataTest: SELECT COUNT(*) AS "#mum" --- Deactivated for SplendidDataTest: FROM bla WHERE s = 'Mum' \; -- but be counted here --- Deactivated for SplendidDataTest: SELECT psql_error('bad!'); -- implicit partial rollback +INSERT INTO bla VALUES ('Mum') \; -- will rollback +SELECT COUNT(*) AS "#mum" +FROM bla WHERE s = 'Mum' \; -- but be counted here +SELECT psql_error('bad!'); -- implicit partial rollback COMMIT; --- Deactivated for SplendidDataTest: SELECT COUNT(*) AS "#mum" --- Deactivated for SplendidDataTest: FROM bla WHERE s = 'Mum' \; -- no mum here +SELECT COUNT(*) AS "#mum" +FROM bla WHERE s = 'Mum' \; -- no mum here SELECT * FROM bla ORDER BY 1; -- reset all --- Deactivated for SplendidDataTest: \set AUTOCOMMIT on --- Deactivated for SplendidDataTest: \set ON_ERROR_ROLLBACK off --- Deactivated for SplendidDataTest: \echo '# final ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK +\set AUTOCOMMIT on +\set ON_ERROR_ROLLBACK off +\echo '# final ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK DROP TABLE bla; DROP FUNCTION psql_error; -- check describing invalid multipart names --- Deactivated for SplendidDataTest: \dA regression.heap --- Deactivated for SplendidDataTest: \dA nonesuch.heap --- Deactivated for SplendidDataTest: \dt host.regression.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dt |.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dt nonesuch.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \da host.regression.pg_catalog.sum --- Deactivated for SplendidDataTest: \da +.pg_catalog.sum --- Deactivated for SplendidDataTest: \da nonesuch.pg_catalog.sum --- Deactivated for SplendidDataTest: \dAc nonesuch.brin --- Deactivated for SplendidDataTest: \dAc regression.brin --- Deactivated for SplendidDataTest: \dAf nonesuch.brin --- Deactivated for SplendidDataTest: \dAf regression.brin --- Deactivated for SplendidDataTest: \dAo nonesuch.brin --- Deactivated for SplendidDataTest: \dAo regression.brin --- Deactivated for SplendidDataTest: \dAp nonesuch.brin --- Deactivated for SplendidDataTest: \dAp regression.brin --- Deactivated for SplendidDataTest: \db nonesuch.pg_default --- Deactivated for SplendidDataTest: \db regression.pg_default --- Deactivated for SplendidDataTest: \dc host.regression.public.conversion --- Deactivated for SplendidDataTest: \dc (.public.conversion --- Deactivated for SplendidDataTest: \dc nonesuch.public.conversion --- Deactivated for SplendidDataTest: \dC host.regression.pg_catalog.int8 --- Deactivated for SplendidDataTest: \dC ).pg_catalog.int8 --- Deactivated for SplendidDataTest: \dC nonesuch.pg_catalog.int8 --- Deactivated for SplendidDataTest: \dd host.regression.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dd [.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dd nonesuch.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dD host.regression.public.gtestdomain1 --- Deactivated for SplendidDataTest: \dD ].public.gtestdomain1 --- Deactivated for SplendidDataTest: \dD nonesuch.public.gtestdomain1 --- Deactivated for SplendidDataTest: \ddp host.regression.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \ddp {.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \ddp nonesuch.pg_catalog.pg_class --- Deactivated for SplendidDataTest: \dE host.regression.public.ft --- Deactivated for SplendidDataTest: \dE }.public.ft --- Deactivated for SplendidDataTest: \dE nonesuch.public.ft --- Deactivated for SplendidDataTest: \di host.regression.public.tenk1_hundred --- Deactivated for SplendidDataTest: \di ..public.tenk1_hundred --- Deactivated for SplendidDataTest: \di nonesuch.public.tenk1_hundred --- Deactivated for SplendidDataTest: \dm host.regression.public.mvtest_bb --- Deactivated for SplendidDataTest: \dm ^.public.mvtest_bb --- Deactivated for SplendidDataTest: \dm nonesuch.public.mvtest_bb --- Deactivated for SplendidDataTest: \ds host.regression.public.check_seq --- Deactivated for SplendidDataTest: \ds regression|mydb.public.check_seq --- Deactivated for SplendidDataTest: \ds nonesuch.public.check_seq --- Deactivated for SplendidDataTest: \dt host.regression.public.b_star --- Deactivated for SplendidDataTest: \dt regres+ion.public.b_star --- Deactivated for SplendidDataTest: \dt nonesuch.public.b_star --- Deactivated for SplendidDataTest: \dv host.regression.public.shoe --- Deactivated for SplendidDataTest: \dv regress(ion).public.shoe --- Deactivated for SplendidDataTest: \dv nonesuch.public.shoe --- Deactivated for SplendidDataTest: \des nonesuch.server --- Deactivated for SplendidDataTest: \des regression.server --- Deactivated for SplendidDataTest: \des nonesuch.server --- Deactivated for SplendidDataTest: \des regression.server --- Deactivated for SplendidDataTest: \des nonesuch.username --- Deactivated for SplendidDataTest: \des regression.username --- Deactivated for SplendidDataTest: \dew nonesuch.fdw --- Deactivated for SplendidDataTest: \dew regression.fdw --- Deactivated for SplendidDataTest: \df host.regression.public.namelen --- Deactivated for SplendidDataTest: \df regres[qrstuv]ion.public.namelen --- Deactivated for SplendidDataTest: \df nonesuch.public.namelen --- Deactivated for SplendidDataTest: \dF host.regression.pg_catalog.arabic --- Deactivated for SplendidDataTest: \dF regres{1,2}ion.pg_catalog.arabic --- Deactivated for SplendidDataTest: \dF nonesuch.pg_catalog.arabic --- Deactivated for SplendidDataTest: \dFd host.regression.pg_catalog.arabic_stem --- Deactivated for SplendidDataTest: \dFd regres?ion.pg_catalog.arabic_stem --- Deactivated for SplendidDataTest: \dFd nonesuch.pg_catalog.arabic_stem --- Deactivated for SplendidDataTest: \dFp host.regression.pg_catalog.default --- Deactivated for SplendidDataTest: \dFp ^regression.pg_catalog.default --- Deactivated for SplendidDataTest: \dFp nonesuch.pg_catalog.default --- Deactivated for SplendidDataTest: \dFt host.regression.pg_catalog.ispell --- Deactivated for SplendidDataTest: \dFt regression$.pg_catalog.ispell --- Deactivated for SplendidDataTest: \dFt nonesuch.pg_catalog.ispell --- Deactivated for SplendidDataTest: \dg nonesuch.pg_database_owner --- Deactivated for SplendidDataTest: \dg regression.pg_database_owner --- Deactivated for SplendidDataTest: \dL host.regression.plpgsql --- Deactivated for SplendidDataTest: \dL *.plpgsql --- Deactivated for SplendidDataTest: \dL nonesuch.plpgsql --- Deactivated for SplendidDataTest: \dn host.regression.public --- Deactivated for SplendidDataTest: \dn """".public --- Deactivated for SplendidDataTest: \dn nonesuch.public --- Deactivated for SplendidDataTest: \do host.regression.public.!=- --- Deactivated for SplendidDataTest: \do "regression|mydb".public.!=- --- Deactivated for SplendidDataTest: \do nonesuch.public.!=- --- Deactivated for SplendidDataTest: \dO host.regression.pg_catalog.POSIX --- Deactivated for SplendidDataTest: \dO .pg_catalog.POSIX --- Deactivated for SplendidDataTest: \dO nonesuch.pg_catalog.POSIX --- Deactivated for SplendidDataTest: \dp host.regression.public.a_star --- Deactivated for SplendidDataTest: \dp "regres+ion".public.a_star --- Deactivated for SplendidDataTest: \dp nonesuch.public.a_star --- Deactivated for SplendidDataTest: \dP host.regression.public.mlparted --- Deactivated for SplendidDataTest: \dP "regres(sion)".public.mlparted --- Deactivated for SplendidDataTest: \dP nonesuch.public.mlparted --- Deactivated for SplendidDataTest: \drds nonesuch.lc_messages --- Deactivated for SplendidDataTest: \drds regression.lc_messages --- Deactivated for SplendidDataTest: \dRp public.mypub --- Deactivated for SplendidDataTest: \dRp regression.mypub --- Deactivated for SplendidDataTest: \dRs public.mysub --- Deactivated for SplendidDataTest: \dRs regression.mysub --- Deactivated for SplendidDataTest: \dT host.regression.public.widget --- Deactivated for SplendidDataTest: \dT "regression{1,2}".public.widget --- Deactivated for SplendidDataTest: \dT nonesuch.public.widget --- Deactivated for SplendidDataTest: \dx regression.plpgsql --- Deactivated for SplendidDataTest: \dx nonesuch.plpgsql --- Deactivated for SplendidDataTest: \dX host.regression.public.func_deps_stat --- Deactivated for SplendidDataTest: \dX "^regression$".public.func_deps_stat --- Deactivated for SplendidDataTest: \dX nonesuch.public.func_deps_stat --- Deactivated for SplendidDataTest: \dy regression.myevt --- Deactivated for SplendidDataTest: \dy nonesuch.myevt +\dA regression.heap +\dA nonesuch.heap +\dt host.regression.pg_catalog.pg_class +\dt |.pg_catalog.pg_class +\dt nonesuch.pg_catalog.pg_class +\da host.regression.pg_catalog.sum +\da +.pg_catalog.sum +\da nonesuch.pg_catalog.sum +\dAc nonesuch.brin +\dAc regression.brin +\dAf nonesuch.brin +\dAf regression.brin +\dAo nonesuch.brin +\dAo regression.brin +\dAp nonesuch.brin +\dAp regression.brin +\db nonesuch.pg_default +\db regression.pg_default +\dc host.regression.public.conversion +\dc (.public.conversion +\dc nonesuch.public.conversion +\dC host.regression.pg_catalog.int8 +\dC ).pg_catalog.int8 +\dC nonesuch.pg_catalog.int8 +\dd host.regression.pg_catalog.pg_class +\dd [.pg_catalog.pg_class +\dd nonesuch.pg_catalog.pg_class +\dD host.regression.public.gtestdomain1 +\dD ].public.gtestdomain1 +\dD nonesuch.public.gtestdomain1 +\ddp host.regression.pg_catalog.pg_class +\ddp {.pg_catalog.pg_class +\ddp nonesuch.pg_catalog.pg_class +\dE host.regression.public.ft +\dE }.public.ft +\dE nonesuch.public.ft +\di host.regression.public.tenk1_hundred +\di ..public.tenk1_hundred +\di nonesuch.public.tenk1_hundred +\dm host.regression.public.mvtest_bb +\dm ^.public.mvtest_bb +\dm nonesuch.public.mvtest_bb +\ds host.regression.public.check_seq +\ds regression|mydb.public.check_seq +\ds nonesuch.public.check_seq +\dt host.regression.public.b_star +\dt regres+ion.public.b_star +\dt nonesuch.public.b_star +\dv host.regression.public.shoe +\dv regress(ion).public.shoe +\dv nonesuch.public.shoe +\des nonesuch.server +\des regression.server +\des nonesuch.server +\des regression.server +\des nonesuch.username +\des regression.username +\dew nonesuch.fdw +\dew regression.fdw +\df host.regression.public.namelen +\df regres[qrstuv]ion.public.namelen +\df nonesuch.public.namelen +\dF host.regression.pg_catalog.arabic +\dF regres{1,2}ion.pg_catalog.arabic +\dF nonesuch.pg_catalog.arabic +\dFd host.regression.pg_catalog.arabic_stem +\dFd regres?ion.pg_catalog.arabic_stem +\dFd nonesuch.pg_catalog.arabic_stem +\dFp host.regression.pg_catalog.default +\dFp ^regression.pg_catalog.default +\dFp nonesuch.pg_catalog.default +\dFt host.regression.pg_catalog.ispell +\dFt regression$.pg_catalog.ispell +\dFt nonesuch.pg_catalog.ispell +\dg nonesuch.pg_database_owner +\dg regression.pg_database_owner +\dL host.regression.plpgsql +\dL *.plpgsql +\dL nonesuch.plpgsql +\dn host.regression.public +\dn """".public +\dn nonesuch.public +\do host.regression.public.!=- +\do "regression|mydb".public.!=- +\do nonesuch.public.!=- +\dO host.regression.pg_catalog.POSIX +\dO .pg_catalog.POSIX +\dO nonesuch.pg_catalog.POSIX +\dp host.regression.public.a_star +\dp "regres+ion".public.a_star +\dp nonesuch.public.a_star +\dP host.regression.public.mlparted +\dP "regres(sion)".public.mlparted +\dP nonesuch.public.mlparted +\drds nonesuch.lc_messages +\drds regression.lc_messages +\dRp public.mypub +\dRp regression.mypub +\dRs public.mysub +\dRs regression.mysub +\dT host.regression.public.widget +\dT "regression{1,2}".public.widget +\dT nonesuch.public.widget +\dx regression.plpgsql +\dx nonesuch.plpgsql +\dX host.regression.public.func_deps_stat +\dX "^regression$".public.func_deps_stat +\dX nonesuch.public.func_deps_stat +\dy regression.myevt +\dy nonesuch.myevt -- check that dots within quoted name segments are not counted --- Deactivated for SplendidDataTest: \dA "no.such.access.method" --- Deactivated for SplendidDataTest: \dt "no.such.table.relation" --- Deactivated for SplendidDataTest: \da "no.such.aggregate.function" --- Deactivated for SplendidDataTest: \dAc "no.such.operator.class" --- Deactivated for SplendidDataTest: \dAf "no.such.operator.family" --- Deactivated for SplendidDataTest: \dAo "no.such.operator.of.operator.family" --- Deactivated for SplendidDataTest: \dAp "no.such.operator.support.function.of.operator.family" --- Deactivated for SplendidDataTest: \db "no.such.tablespace" --- Deactivated for SplendidDataTest: \dc "no.such.conversion" --- Deactivated for SplendidDataTest: \dC "no.such.cast" --- Deactivated for SplendidDataTest: \dd "no.such.object.description" --- Deactivated for SplendidDataTest: \dD "no.such.domain" --- Deactivated for SplendidDataTest: \ddp "no.such.default.access.privilege" --- Deactivated for SplendidDataTest: \di "no.such.index.relation" --- Deactivated for SplendidDataTest: \dm "no.such.materialized.view" --- Deactivated for SplendidDataTest: \ds "no.such.relation" --- Deactivated for SplendidDataTest: \dt "no.such.relation" --- Deactivated for SplendidDataTest: \dv "no.such.relation" --- Deactivated for SplendidDataTest: \des "no.such.foreign.server" --- Deactivated for SplendidDataTest: \dew "no.such.foreign.data.wrapper" --- Deactivated for SplendidDataTest: \df "no.such.function" --- Deactivated for SplendidDataTest: \dF "no.such.text.search.configuration" --- Deactivated for SplendidDataTest: \dFd "no.such.text.search.dictionary" --- Deactivated for SplendidDataTest: \dFp "no.such.text.search.parser" --- Deactivated for SplendidDataTest: \dFt "no.such.text.search.template" --- Deactivated for SplendidDataTest: \dg "no.such.role" --- Deactivated for SplendidDataTest: \dL "no.such.language" --- Deactivated for SplendidDataTest: \dn "no.such.schema" --- Deactivated for SplendidDataTest: \do "no.such.operator" --- Deactivated for SplendidDataTest: \dO "no.such.collation" --- Deactivated for SplendidDataTest: \dp "no.such.access.privilege" --- Deactivated for SplendidDataTest: \dP "no.such.partitioned.relation" --- Deactivated for SplendidDataTest: \drds "no.such.setting" --- Deactivated for SplendidDataTest: \dRp "no.such.publication" --- Deactivated for SplendidDataTest: \dRs "no.such.subscription" --- Deactivated for SplendidDataTest: \dT "no.such.data.type" --- Deactivated for SplendidDataTest: \dx "no.such.installed.extension" --- Deactivated for SplendidDataTest: \dX "no.such.extended.statistics" --- Deactivated for SplendidDataTest: \dy "no.such.event.trigger" +\dA "no.such.access.method" +\dt "no.such.table.relation" +\da "no.such.aggregate.function" +\dAc "no.such.operator.class" +\dAf "no.such.operator.family" +\dAo "no.such.operator.of.operator.family" +\dAp "no.such.operator.support.function.of.operator.family" +\db "no.such.tablespace" +\dc "no.such.conversion" +\dC "no.such.cast" +\dd "no.such.object.description" +\dD "no.such.domain" +\ddp "no.such.default.access.privilege" +\di "no.such.index.relation" +\dm "no.such.materialized.view" +\ds "no.such.relation" +\dt "no.such.relation" +\dv "no.such.relation" +\des "no.such.foreign.server" +\dew "no.such.foreign.data.wrapper" +\df "no.such.function" +\dF "no.such.text.search.configuration" +\dFd "no.such.text.search.dictionary" +\dFp "no.such.text.search.parser" +\dFt "no.such.text.search.template" +\dg "no.such.role" +\dL "no.such.language" +\dn "no.such.schema" +\do "no.such.operator" +\dO "no.such.collation" +\dp "no.such.access.privilege" +\dP "no.such.partitioned.relation" +\drds "no.such.setting" +\dRp "no.such.publication" +\dRs "no.such.subscription" +\dT "no.such.data.type" +\dx "no.such.installed.extension" +\dX "no.such.extended.statistics" +\dy "no.such.event.trigger" -- again, but with dotted schema qualifications. --- Deactivated for SplendidDataTest: \dA "no.such.schema"."no.such.access.method" --- Deactivated for SplendidDataTest: \dt "no.such.schema"."no.such.table.relation" --- Deactivated for SplendidDataTest: \da "no.such.schema"."no.such.aggregate.function" --- Deactivated for SplendidDataTest: \dAc "no.such.schema"."no.such.operator.class" --- Deactivated for SplendidDataTest: \dAf "no.such.schema"."no.such.operator.family" --- Deactivated for SplendidDataTest: \dAo "no.such.schema"."no.such.operator.of.operator.family" --- Deactivated for SplendidDataTest: \dAp "no.such.schema"."no.such.operator.support.function.of.operator.family" --- Deactivated for SplendidDataTest: \db "no.such.schema"."no.such.tablespace" --- Deactivated for SplendidDataTest: \dc "no.such.schema"."no.such.conversion" --- Deactivated for SplendidDataTest: \dC "no.such.schema"."no.such.cast" --- Deactivated for SplendidDataTest: \dd "no.such.schema"."no.such.object.description" --- Deactivated for SplendidDataTest: \dD "no.such.schema"."no.such.domain" --- Deactivated for SplendidDataTest: \ddp "no.such.schema"."no.such.default.access.privilege" --- Deactivated for SplendidDataTest: \di "no.such.schema"."no.such.index.relation" --- Deactivated for SplendidDataTest: \dm "no.such.schema"."no.such.materialized.view" --- Deactivated for SplendidDataTest: \ds "no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dt "no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dv "no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \des "no.such.schema"."no.such.foreign.server" --- Deactivated for SplendidDataTest: \dew "no.such.schema"."no.such.foreign.data.wrapper" --- Deactivated for SplendidDataTest: \df "no.such.schema"."no.such.function" --- Deactivated for SplendidDataTest: \dF "no.such.schema"."no.such.text.search.configuration" --- Deactivated for SplendidDataTest: \dFd "no.such.schema"."no.such.text.search.dictionary" --- Deactivated for SplendidDataTest: \dFp "no.such.schema"."no.such.text.search.parser" --- Deactivated for SplendidDataTest: \dFt "no.such.schema"."no.such.text.search.template" --- Deactivated for SplendidDataTest: \dg "no.such.schema"."no.such.role" --- Deactivated for SplendidDataTest: \dL "no.such.schema"."no.such.language" --- Deactivated for SplendidDataTest: \do "no.such.schema"."no.such.operator" --- Deactivated for SplendidDataTest: \dO "no.such.schema"."no.such.collation" --- Deactivated for SplendidDataTest: \dp "no.such.schema"."no.such.access.privilege" --- Deactivated for SplendidDataTest: \dP "no.such.schema"."no.such.partitioned.relation" --- Deactivated for SplendidDataTest: \drds "no.such.schema"."no.such.setting" --- Deactivated for SplendidDataTest: \dRp "no.such.schema"."no.such.publication" --- Deactivated for SplendidDataTest: \dRs "no.such.schema"."no.such.subscription" --- Deactivated for SplendidDataTest: \dT "no.such.schema"."no.such.data.type" --- Deactivated for SplendidDataTest: \dx "no.such.schema"."no.such.installed.extension" --- Deactivated for SplendidDataTest: \dX "no.such.schema"."no.such.extended.statistics" --- Deactivated for SplendidDataTest: \dy "no.such.schema"."no.such.event.trigger" +\dA "no.such.schema"."no.such.access.method" +\dt "no.such.schema"."no.such.table.relation" +\da "no.such.schema"."no.such.aggregate.function" +\dAc "no.such.schema"."no.such.operator.class" +\dAf "no.such.schema"."no.such.operator.family" +\dAo "no.such.schema"."no.such.operator.of.operator.family" +\dAp "no.such.schema"."no.such.operator.support.function.of.operator.family" +\db "no.such.schema"."no.such.tablespace" +\dc "no.such.schema"."no.such.conversion" +\dC "no.such.schema"."no.such.cast" +\dd "no.such.schema"."no.such.object.description" +\dD "no.such.schema"."no.such.domain" +\ddp "no.such.schema"."no.such.default.access.privilege" +\di "no.such.schema"."no.such.index.relation" +\dm "no.such.schema"."no.such.materialized.view" +\ds "no.such.schema"."no.such.relation" +\dt "no.such.schema"."no.such.relation" +\dv "no.such.schema"."no.such.relation" +\des "no.such.schema"."no.such.foreign.server" +\dew "no.such.schema"."no.such.foreign.data.wrapper" +\df "no.such.schema"."no.such.function" +\dF "no.such.schema"."no.such.text.search.configuration" +\dFd "no.such.schema"."no.such.text.search.dictionary" +\dFp "no.such.schema"."no.such.text.search.parser" +\dFt "no.such.schema"."no.such.text.search.template" +\dg "no.such.schema"."no.such.role" +\dL "no.such.schema"."no.such.language" +\do "no.such.schema"."no.such.operator" +\dO "no.such.schema"."no.such.collation" +\dp "no.such.schema"."no.such.access.privilege" +\dP "no.such.schema"."no.such.partitioned.relation" +\drds "no.such.schema"."no.such.setting" +\dRp "no.such.schema"."no.such.publication" +\dRs "no.such.schema"."no.such.subscription" +\dT "no.such.schema"."no.such.data.type" +\dx "no.such.schema"."no.such.installed.extension" +\dX "no.such.schema"."no.such.extended.statistics" +\dy "no.such.schema"."no.such.event.trigger" -- again, but with current database and dotted schema qualifications. --- Deactivated for SplendidDataTest: \dt regression."no.such.schema"."no.such.table.relation" --- Deactivated for SplendidDataTest: \da regression."no.such.schema"."no.such.aggregate.function" --- Deactivated for SplendidDataTest: \dc regression."no.such.schema"."no.such.conversion" --- Deactivated for SplendidDataTest: \dC regression."no.such.schema"."no.such.cast" --- Deactivated for SplendidDataTest: \dd regression."no.such.schema"."no.such.object.description" --- Deactivated for SplendidDataTest: \dD regression."no.such.schema"."no.such.domain" --- Deactivated for SplendidDataTest: \di regression."no.such.schema"."no.such.index.relation" --- Deactivated for SplendidDataTest: \dm regression."no.such.schema"."no.such.materialized.view" --- Deactivated for SplendidDataTest: \ds regression."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dt regression."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dv regression."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \df regression."no.such.schema"."no.such.function" --- Deactivated for SplendidDataTest: \dF regression."no.such.schema"."no.such.text.search.configuration" --- Deactivated for SplendidDataTest: \dFd regression."no.such.schema"."no.such.text.search.dictionary" --- Deactivated for SplendidDataTest: \dFp regression."no.such.schema"."no.such.text.search.parser" --- Deactivated for SplendidDataTest: \dFt regression."no.such.schema"."no.such.text.search.template" --- Deactivated for SplendidDataTest: \do regression."no.such.schema"."no.such.operator" --- Deactivated for SplendidDataTest: \dO regression."no.such.schema"."no.such.collation" --- Deactivated for SplendidDataTest: \dp regression."no.such.schema"."no.such.access.privilege" --- Deactivated for SplendidDataTest: \dP regression."no.such.schema"."no.such.partitioned.relation" --- Deactivated for SplendidDataTest: \dT regression."no.such.schema"."no.such.data.type" --- Deactivated for SplendidDataTest: \dX regression."no.such.schema"."no.such.extended.statistics" +\dt regression."no.such.schema"."no.such.table.relation" +\da regression."no.such.schema"."no.such.aggregate.function" +\dc regression."no.such.schema"."no.such.conversion" +\dC regression."no.such.schema"."no.such.cast" +\dd regression."no.such.schema"."no.such.object.description" +\dD regression."no.such.schema"."no.such.domain" +\di regression."no.such.schema"."no.such.index.relation" +\dm regression."no.such.schema"."no.such.materialized.view" +\ds regression."no.such.schema"."no.such.relation" +\dt regression."no.such.schema"."no.such.relation" +\dv regression."no.such.schema"."no.such.relation" +\df regression."no.such.schema"."no.such.function" +\dF regression."no.such.schema"."no.such.text.search.configuration" +\dFd regression."no.such.schema"."no.such.text.search.dictionary" +\dFp regression."no.such.schema"."no.such.text.search.parser" +\dFt regression."no.such.schema"."no.such.text.search.template" +\do regression."no.such.schema"."no.such.operator" +\dO regression."no.such.schema"."no.such.collation" +\dp regression."no.such.schema"."no.such.access.privilege" +\dP regression."no.such.schema"."no.such.partitioned.relation" +\dT regression."no.such.schema"."no.such.data.type" +\dX regression."no.such.schema"."no.such.extended.statistics" -- again, but with dotted database and dotted schema qualifications. --- Deactivated for SplendidDataTest: \dt "no.such.database"."no.such.schema"."no.such.table.relation" --- Deactivated for SplendidDataTest: \da "no.such.database"."no.such.schema"."no.such.aggregate.function" --- Deactivated for SplendidDataTest: \dc "no.such.database"."no.such.schema"."no.such.conversion" --- Deactivated for SplendidDataTest: \dC "no.such.database"."no.such.schema"."no.such.cast" --- Deactivated for SplendidDataTest: \dd "no.such.database"."no.such.schema"."no.such.object.description" --- Deactivated for SplendidDataTest: \dD "no.such.database"."no.such.schema"."no.such.domain" --- Deactivated for SplendidDataTest: \ddp "no.such.database"."no.such.schema"."no.such.default.access.privilege" --- Deactivated for SplendidDataTest: \di "no.such.database"."no.such.schema"."no.such.index.relation" --- Deactivated for SplendidDataTest: \dm "no.such.database"."no.such.schema"."no.such.materialized.view" --- Deactivated for SplendidDataTest: \ds "no.such.database"."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dt "no.such.database"."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \dv "no.such.database"."no.such.schema"."no.such.relation" --- Deactivated for SplendidDataTest: \df "no.such.database"."no.such.schema"."no.such.function" --- Deactivated for SplendidDataTest: \dF "no.such.database"."no.such.schema"."no.such.text.search.configuration" --- Deactivated for SplendidDataTest: \dFd "no.such.database"."no.such.schema"."no.such.text.search.dictionary" --- Deactivated for SplendidDataTest: \dFp "no.such.database"."no.such.schema"."no.such.text.search.parser" --- Deactivated for SplendidDataTest: \dFt "no.such.database"."no.such.schema"."no.such.text.search.template" --- Deactivated for SplendidDataTest: \do "no.such.database"."no.such.schema"."no.such.operator" --- Deactivated for SplendidDataTest: \dO "no.such.database"."no.such.schema"."no.such.collation" --- Deactivated for SplendidDataTest: \dp "no.such.database"."no.such.schema"."no.such.access.privilege" --- Deactivated for SplendidDataTest: \dP "no.such.database"."no.such.schema"."no.such.partitioned.relation" --- Deactivated for SplendidDataTest: \dT "no.such.database"."no.such.schema"."no.such.data.type" --- Deactivated for SplendidDataTest: \dX "no.such.database"."no.such.schema"."no.such.extended.statistics" +\dt "no.such.database"."no.such.schema"."no.such.table.relation" +\da "no.such.database"."no.such.schema"."no.such.aggregate.function" +\dc "no.such.database"."no.such.schema"."no.such.conversion" +\dC "no.such.database"."no.such.schema"."no.such.cast" +\dd "no.such.database"."no.such.schema"."no.such.object.description" +\dD "no.such.database"."no.such.schema"."no.such.domain" +\ddp "no.such.database"."no.such.schema"."no.such.default.access.privilege" +\di "no.such.database"."no.such.schema"."no.such.index.relation" +\dm "no.such.database"."no.such.schema"."no.such.materialized.view" +\ds "no.such.database"."no.such.schema"."no.such.relation" +\dt "no.such.database"."no.such.schema"."no.such.relation" +\dv "no.such.database"."no.such.schema"."no.such.relation" +\df "no.such.database"."no.such.schema"."no.such.function" +\dF "no.such.database"."no.such.schema"."no.such.text.search.configuration" +\dFd "no.such.database"."no.such.schema"."no.such.text.search.dictionary" +\dFp "no.such.database"."no.such.schema"."no.such.text.search.parser" +\dFt "no.such.database"."no.such.schema"."no.such.text.search.template" +\do "no.such.database"."no.such.schema"."no.such.operator" +\dO "no.such.database"."no.such.schema"."no.such.collation" +\dp "no.such.database"."no.such.schema"."no.such.access.privilege" +\dP "no.such.database"."no.such.schema"."no.such.partitioned.relation" +\dT "no.such.database"."no.such.schema"."no.such.data.type" +\dX "no.such.database"."no.such.schema"."no.such.extended.statistics" + +* +*/ +select 1; \ No newline at end of file diff --git a/parser/src/test/resources/postgres/test/regress/sql/stats.sql b/parser/src/test/resources/postgres/test/regress/sql/stats.sql index 2461b4d..65d5389 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/stats.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/stats.sql @@ -4,8 +4,9 @@ * So input for the copy statements is removed. * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: */ - - + + + -- -- Test cumulative stats system -- @@ -25,7 +26,7 @@ SET enable_indexonlyscan TO off; SET track_functions TO 'all'; -- record dboid for later use --- Deactivated for SplendidDataTest:SELECT oid AS dboid from pg_database where datname = current_database() \gset +SELECT oid AS dboid from pg_database where datname = current_database() \gset -- save counters BEGIN; @@ -138,20 +139,20 @@ COMMIT; -- Basic tests for track_functions --- CREATE FUNCTION stats_test_func1() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$; --- Deactivated for SplendidDataTest: SELECT 'stats_test_func1()'::regprocedure::oid AS stats_test_func1_oid \gset +SELECT 'stats_test_func1()'::regprocedure::oid AS stats_test_func1_oid \gset CREATE FUNCTION stats_test_func2() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$; --- Deactivated for SplendidDataTest: SELECT 'stats_test_func2()'::regprocedure::oid AS stats_test_func2_oid \gset +SELECT 'stats_test_func2()'::regprocedure::oid AS stats_test_func2_oid \gset -- test that stats are accumulated BEGIN; SET LOCAL stats_fetch_consistency = none; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func1_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); SELECT stats_test_func1(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); SELECT stats_test_func1(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_xact_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_function_calls(:stats_test_func1_oid); COMMIT; -- Verify that function stats are not transactional @@ -162,7 +163,7 @@ SELECT stats_test_func2(); SAVEPOINT foo; SELECT stats_test_func2(); ROLLBACK TO SAVEPOINT foo; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_function_calls(:stats_test_func2_oid); +SELECT pg_stat_get_xact_function_calls(:stats_test_func2_oid); SELECT stats_test_func2(); COMMIT; @@ -174,29 +175,29 @@ ROLLBACK; SELECT pg_stat_force_next_flush(); -- check collected stats --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid; +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid; -- check that a rolled back drop function stats leaves stats alive BEGIN; --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; DROP FUNCTION stats_test_func1(); -- shouldn't be visible via view --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; -- but still via oid access --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func1_oid); +SELECT pg_stat_get_function_calls(:stats_test_func1_oid); ROLLBACK; --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func1_oid); +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; +SELECT pg_stat_get_function_calls(:stats_test_func1_oid); -- check that function dropped in main transaction leaves no stats behind BEGIN; DROP FUNCTION stats_test_func1(); COMMIT; --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func1_oid); +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func1_oid; +SELECT pg_stat_get_function_calls(:stats_test_func1_oid); -- check that function dropped in a subtransaction leaves no stats behind BEGIN; @@ -206,93 +207,93 @@ SELECT stats_test_func2(); SAVEPOINT b; DROP FUNCTION stats_test_func2(); COMMIT; --- Deactivated for SplendidDataTest: SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_function_calls(:stats_test_func2_oid); +SELECT funcname, calls FROM pg_stat_user_functions WHERE funcid = :stats_test_func2_oid; +SELECT pg_stat_get_function_calls(:stats_test_func2_oid); -- Check that stats for relations are dropped. For that we need to access stats -- by oid after the DROP TABLE. Save oids. CREATE TABLE drop_stats_test(); INSERT INTO drop_stats_test DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT 'drop_stats_test'::regclass::oid AS drop_stats_test_oid \gset +SELECT 'drop_stats_test'::regclass::oid AS drop_stats_test_oid \gset CREATE TABLE drop_stats_test_xact(); INSERT INTO drop_stats_test_xact DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT 'drop_stats_test_xact'::regclass::oid AS drop_stats_test_xact_oid \gset +SELECT 'drop_stats_test_xact'::regclass::oid AS drop_stats_test_xact_oid \gset CREATE TABLE drop_stats_test_subxact(); INSERT INTO drop_stats_test_subxact DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \gset +SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \gset SELECT pg_stat_force_next_flush(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_oid); DROP TABLE drop_stats_test; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid); -- check that rollback protects against having stats dropped and that local -- modifications don't pose a problem --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); +SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); BEGIN; INSERT INTO drop_stats_test_xact DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); DROP TABLE drop_stats_test_xact; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); ROLLBACK; SELECT pg_stat_force_next_flush(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); +SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); -- transactional drop --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); +SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); BEGIN; INSERT INTO drop_stats_test_xact DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); DROP TABLE drop_stats_test_xact; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid); COMMIT; SELECT pg_stat_force_next_flush(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid); +SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid); -- savepoint rollback (2 levels) --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); BEGIN; INSERT INTO drop_stats_test_subxact DEFAULT VALUES; SAVEPOINT sp1; INSERT INTO drop_stats_test_subxact DEFAULT VALUES; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid); SAVEPOINT sp2; DROP TABLE drop_stats_test_subxact; ROLLBACK TO SAVEPOINT sp2; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid); COMMIT; SELECT pg_stat_force_next_flush(); --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); -- savepoint rolback (1 level) --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); BEGIN; SAVEPOINT sp1; DROP TABLE drop_stats_test_subxact; SAVEPOINT sp2; ROLLBACK TO SAVEPOINT sp1; COMMIT; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); -- and now actually drop --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); BEGIN; SAVEPOINT sp1; DROP TABLE drop_stats_test_subxact; SAVEPOINT sp2; RELEASE SAVEPOINT sp1; COMMIT; --- Deactivated for SplendidDataTest: SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); +SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid); DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4; DROP TABLE prevstats; @@ -317,9 +318,17 @@ COMMIT; -- check that the stats are reset. SELECT (n_tup_ins + n_tup_upd) > 0 AS has_data FROM pg_stat_all_tables WHERE relid = 'pg_shdescription'::regclass; +-- stats_reset may not be set for datid=0 and shared objects in +-- pg_stat_database, so reset once. SELECT pg_stat_reset_single_table_counters('pg_shdescription'::regclass); SELECT (n_tup_ins + n_tup_upd) > 0 AS has_data FROM pg_stat_all_tables WHERE relid = 'pg_shdescription'::regclass; +SELECT stats_reset AS shared_db_reset_before + FROM pg_stat_database WHERE datid = 0 \gset +-- Second reset for comparison. +SELECT pg_stat_reset_single_table_counters('pg_shdescription'::regclass); +SELECT stats_reset > :'shared_db_reset_before'::timestamptz AS has_updated + FROM pg_stat_database WHERE datid = 0; -- set back comment \if :{?description_before} @@ -333,16 +342,16 @@ SELECT (n_tup_ins + n_tup_upd) > 0 AS has_data FROM pg_stat_all_tables ----- -- Test that sessions is incremented when a new session is started in pg_stat_database --- Deactivated for SplendidDataTest: SELECT sessions AS db_stat_sessions FROM pg_stat_database WHERE datname = (SELECT current_database()) \gset --- Deactivated for SplendidDataTest: \c +SELECT sessions AS db_stat_sessions FROM pg_stat_database WHERE datname = (SELECT current_database()) \gset +\c SELECT pg_stat_force_next_flush(); --- Deactivated for SplendidDataTest: SELECT sessions > :db_stat_sessions FROM pg_stat_database WHERE datname = (SELECT current_database()); +SELECT sessions > :db_stat_sessions FROM pg_stat_database WHERE datname = (SELECT current_database()); -- Test pg_stat_bgwriter checkpointer-related stats, together with pg_stat_wal --- Deactivated for SplendidDataTest: SELECT checkpoints_req AS rqst_ckpts_before FROM pg_stat_bgwriter \gset +SELECT checkpoints_req AS rqst_ckpts_before FROM pg_stat_bgwriter \gset --- Test pg_stat_wal (and make a temp table so our temp schema exists) --- Deactivated for SplendidDataTest: SELECT wal_bytes AS wal_bytes_before FROM pg_stat_wal \gset +-- Test pg_stat_wal +SELECT wal_bytes AS wal_bytes_before FROM pg_stat_wal \gset CREATE TABLE test_stats_temp AS SELECT 17; DROP TABLE test_stats_temp; @@ -353,8 +362,8 @@ DROP TABLE test_stats_temp; CHECKPOINT; CHECKPOINT; --- Deactivated for SplendidDataTest: SELECT checkpoints_req > :rqst_ckpts_before FROM pg_stat_bgwriter; --- Deactivated for SplendidDataTest: SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal; +SELECT checkpoints_req > :rqst_ckpts_before FROM pg_stat_bgwriter; +SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal; ----- @@ -362,48 +371,48 @@ CHECKPOINT; ----- -- Test that reset_slru with a specified SLRU works. --- Deactivated for SplendidDataTest: SELECT stats_reset AS slru_commit_ts_reset_ts FROM pg_stat_slru WHERE name = 'CommitTs' \gset --- Deactivated for SplendidDataTest: SELECT stats_reset AS slru_notify_reset_ts FROM pg_stat_slru WHERE name = 'Notify' \gset +SELECT stats_reset AS slru_commit_ts_reset_ts FROM pg_stat_slru WHERE name = 'CommitTs' \gset +SELECT stats_reset AS slru_notify_reset_ts FROM pg_stat_slru WHERE name = 'Notify' \gset SELECT pg_stat_reset_slru('CommitTs'); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'slru_commit_ts_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'CommitTs'; --- Deactivated for SplendidDataTest: SELECT stats_reset AS slru_commit_ts_reset_ts FROM pg_stat_slru WHERE name = 'CommitTs' \gset +SELECT stats_reset > :'slru_commit_ts_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'CommitTs'; +SELECT stats_reset AS slru_commit_ts_reset_ts FROM pg_stat_slru WHERE name = 'CommitTs' \gset -- Test that multiple SLRUs are reset when no specific SLRU provided to reset function SELECT pg_stat_reset_slru(NULL); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'slru_commit_ts_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'CommitTs'; --- Deactivated for SplendidDataTest: SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'Notify'; +SELECT stats_reset > :'slru_commit_ts_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'CommitTs'; +SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHERE name = 'Notify'; -- Test that reset_shared with archiver specified as the stats type works --- Deactivated for SplendidDataTest: SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset +SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset SELECT pg_stat_reset_shared('archiver'); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; --- Deactivated for SplendidDataTest: SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset +SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; +SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset -- Test that reset_shared with bgwriter specified as the stats type works --- Deactivated for SplendidDataTest: SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset +SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset SELECT pg_stat_reset_shared('bgwriter'); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; --- Deactivated for SplendidDataTest: SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset +SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; +SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset -- Test that reset_shared with wal specified as the stats type works --- Deactivated for SplendidDataTest: SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset +SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset SELECT pg_stat_reset_shared('wal'); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal; --- Deactivated for SplendidDataTest: SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset +SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal; +SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset -- Test that reset_shared with no specified stats type doesn't reset anything SELECT pg_stat_reset_shared(NULL); --- Deactivated for SplendidDataTest: SELECT stats_reset = :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; --- Deactivated for SplendidDataTest: SELECT stats_reset = :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; --- Deactivated for SplendidDataTest: SELECT stats_reset = :'wal_reset_ts'::timestamptz FROM pg_stat_wal; +SELECT stats_reset = :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; +SELECT stats_reset = :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; +SELECT stats_reset = :'wal_reset_ts'::timestamptz FROM pg_stat_wal; -- Test that reset works for pg_stat_database -- Since pg_stat_database stats_reset starts out as NULL, reset it once first so we have something to compare it to SELECT pg_stat_reset(); --- Deactivated for SplendidDataTest: SELECT stats_reset AS db_reset_ts FROM pg_stat_database WHERE datname = (SELECT current_database()) \gset +SELECT stats_reset AS db_reset_ts FROM pg_stat_database WHERE datname = (SELECT current_database()) \gset SELECT pg_stat_reset(); --- Deactivated for SplendidDataTest: SELECT stats_reset > :'db_reset_ts'::timestamptz FROM pg_stat_database WHERE datname = (SELECT current_database()); +SELECT stats_reset > :'db_reset_ts'::timestamptz FROM pg_stat_database WHERE datname = (SELECT current_database()); ---- @@ -449,49 +458,49 @@ SELECT pg_stat_have_stats('bgwriter', 0, 0); -- unknown stats kinds error out SELECT pg_stat_have_stats('zaphod', 0, 0); -- db stats have objoid 0 --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('database', :dboid, 1); --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('database', :dboid, 0); +SELECT pg_stat_have_stats('database', :dboid, 1); +SELECT pg_stat_have_stats('database', :dboid, 0); -- pg_stat_have_stats returns true for committed index creation CREATE table stats_test_tab1 as select generate_series(1,10) a; CREATE index stats_test_idx1 on stats_test_tab1(a); --- Deactivated for SplendidDataTest: SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset +SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset SET enable_seqscan TO off; select a from stats_test_tab1 where a = 3; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- pg_stat_have_stats returns false for dropped index with stats --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); DROP index stats_test_idx1; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- pg_stat_have_stats returns false for rolled back index creation BEGIN; CREATE index stats_test_idx1 on stats_test_tab1(a); --- Deactivated for SplendidDataTest: SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset +SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset select a from stats_test_tab1 where a = 3; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); ROLLBACK; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- pg_stat_have_stats returns true for reindex CONCURRENTLY CREATE index stats_test_idx1 on stats_test_tab1(a); --- Deactivated for SplendidDataTest: SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset +SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset select a from stats_test_tab1 where a = 3; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); REINDEX index CONCURRENTLY stats_test_idx1; -- false for previous oid --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- true for new oid --- Deactivated for SplendidDataTest: SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- pg_stat_have_stats returns true for a rolled back drop index with stats BEGIN; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); DROP index stats_test_idx1; ROLLBACK; --- Deactivated for SplendidDataTest: SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); +SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid); -- put enable_seqscan back to on SET enable_seqscan TO on; diff --git a/parser/src/test/resources/postgres/test/regress/sql/triggers.sql b/parser/src/test/resources/postgres/test/regress/sql/triggers.sql index c7f7ee5..e068bba 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/triggers.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/triggers.sql @@ -65,13 +65,13 @@ create unique index pkeys_i on pkeys (pkey1, pkey2); -- (fkey3) --> fkeys2 (pkey23) -- create trigger check_fkeys_pkey_exist - before insert or update on fkeys + after insert or update on fkeys for each row execute function check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); create trigger check_fkeys_pkey2_exist - before insert or update on fkeys + after insert or update on fkeys for each row execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); @@ -80,7 +80,7 @@ create trigger check_fkeys_pkey2_exist -- (fkey21, fkey22) --> pkeys (pkey1, pkey2) -- create trigger check_fkeys2_pkey_exist - before insert or update on fkeys2 + after insert or update on fkeys2 for each row execute procedure check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2'); @@ -96,7 +96,7 @@ COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS NULL; -- fkeys (fkey1, fkey2) and fkeys2 (fkey21, fkey22) -- create trigger check_pkeys_fkey_cascade - before delete or update on pkeys + after delete or update on pkeys for each row execute procedure check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', @@ -108,7 +108,7 @@ create trigger check_pkeys_fkey_cascade -- fkeys (fkey3) -- create trigger check_fkeys2_fkey_restrict - before delete or update on fkeys2 + after delete or update on fkeys2 for each row execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'fkeys', 'fkey3'); @@ -2411,6 +2411,10 @@ with wcte as (insert into table1 values (42)) with wcte as (insert into table1 values (43)) insert into table1 values (44); +with wcte as (insert into table1 values (45)) + merge into table1 using (values (46)) as v(a) on table1.a = v.a + when not matched then insert values (v.a); + select * from table1; select * from table2; diff --git a/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql b/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql index e37c50b..675983f 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/tsearch.sql @@ -577,6 +577,14 @@ SELECT ts_headline('english', SELECT ts_headline('english', 'foo bar', to_tsquery('english', '')); +-- Test for large values of StartSel, StopSel and FragmentDelimiter +SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'), + 'StartSel=' || repeat('x', 32768)); +SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'), + 'StopSel=' || repeat('x', 32768)); +SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'), + 'FragmentDelimiter=' || repeat('x', 32768)); + --Rewrite sub system CREATE TABLE test_tsquery (txtkeyword TEXT, txtsample TEXT); diff --git a/parser/src/test/resources/postgres/test/regress/sql/unicode.sql b/parser/src/test/resources/postgres/test/regress/sql/unicode.sql index 7218ab4..5d6e91e 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/unicode.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/unicode.sql @@ -6,9 +6,9 @@ -- Deactivated for SplendidDataTest: SELECT getdatabaseencoding() <> 'UTF8' AS skip_test \gset --- Deactivated for SplendidDataTest: \if :skip_test --- Deactivated for SplendidDataTest: \quit --- Deactivated for SplendidDataTest: \endif +\if :skip_test +\quit +\endif SELECT U&'\0061\0308bc' <> U&'\00E4bc' COLLATE "C" AS sanity_check; @@ -39,3 +39,23 @@ FROM ORDER BY num; SELECT is_normalized('abc', 'def'); -- run-time error + +-- Hangul NFC recomposition tests +-- L+V -> LV composition (first and last) +SELECT normalize(U&'\1100\1161', NFC) = U&'\AC00' COLLATE "C" AS hangul_lv_first; +SELECT normalize(U&'\1112\1175', NFC) = U&'\D788' COLLATE "C" AS hangul_lv_last; +-- LV+T -> LVT composition +SELECT normalize(U&'\AC00\11A8', NFC) = U&'\AC01' COLLATE "C" AS hangul_lvt_first_t; +SELECT normalize(U&'\AC00\11C2', NFC) = U&'\AC1B' COLLATE "C" AS hangul_lvt_last_t; +SELECT normalize(U&'\D788\11A8', NFC) = U&'\D789' COLLATE "C" AS hangul_lvt_last_lv; +-- L+V+T -> LVT composition +SELECT normalize(U&'\1100\1161\11A8', NFC) = U&'\AC01' COLLATE "C" AS hangul_full_lvt; +SELECT normalize(U&'\1112\1175\11C2', NFC) = U&'\D7A3' COLLATE "C" AS hangul_full_lvt; +-- TBASE invalid T syllable +SELECT normalize(U&'\AC00\11A7', NFC) = U&'\AC00\11A7' COLLATE "C" AS hangul_tbase_not_combined; +SELECT normalize(U&'\1100\1161\11A7', NFC) = U&'\AC00\11A7' COLLATE "C" AS hangul_lv_tbase_separate; + +-- Hangul NFD decomposition tests +SELECT normalize(U&'\AC00', NFD) = U&'\1100\1161' COLLATE "C" AS hangul_nfd_lv; +SELECT normalize(U&'\AC01', NFD) = U&'\1100\1161\11A8' COLLATE "C" AS hangul_nfd_lvt; +SELECT normalize(U&'\D7A3', NFD) = U&'\1112\1175\11C2' COLLATE "C" AS hangul_nfd_last; diff --git a/parser/src/test/resources/postgres/test/regress/sql/window.sql b/parser/src/test/resources/postgres/test/regress/sql/window.sql index adca600..2a5aa57 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/window.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/window.sql @@ -334,6 +334,32 @@ CREATE TEMP VIEW v_window AS SELECT pg_get_viewdef('v_window'); +-- test overflow frame specifications +SELECT sum(unique1) over (rows between current row and 9223372036854775807 following exclude current row), + unique1, four +FROM tenk1 WHERE unique1 < 10; + +SELECT sum(unique1) over (rows between 9223372036854775807 following and 1 following), + unique1, four +FROM tenk1 WHERE unique1 < 10; + +SELECT last_value(unique1) over (ORDER BY four rows between current row and 9223372036854775807 following exclude current row), + unique1, four +FROM tenk1 WHERE unique1 < 10; + +-- These test GROUPS mode with an offset large enough to cause overflow when +-- added to currentgroup. Although the overflow doesn't produce visibly wrong +-- results (due to the incremental nature of group pointer advancement), we +-- still need to protect against it as signed integer overflow is undefined +-- behavior in C. +SELECT sum(unique1) over (ORDER BY four groups between current row and 9223372036854775807 following), + unique1, four +FROM tenk1 WHERE unique1 < 10; + +SELECT sum(unique1) over (ORDER BY four groups between 9223372036854775807 following and unbounded following), + unique1, four +FROM tenk1 WHERE unique1 < 10; + -- RANGE offset PRECEDING/FOLLOWING tests SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding), diff --git a/parser/src/test/resources/postgres/test/regress/sql/with.sql b/parser/src/test/resources/postgres/test/regress/sql/with.sql index 263671c..c5d95db 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/with.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/with.sql @@ -1335,6 +1335,29 @@ COMMIT; SELECT * FROM bug6051_3; +-- check that recursive CTE processing doesn't rewrite a CTE more than once +-- (must not try to expand GENERATED ALWAYS IDENTITY columns more than once) +CREATE TEMP TABLE id_alw1 (i int GENERATED ALWAYS AS IDENTITY); + +CREATE TEMP TABLE id_alw2 (i int GENERATED ALWAYS AS IDENTITY); +CREATE TEMP VIEW id_alw2_view AS SELECT * FROM id_alw2; + +CREATE TEMP TABLE id_alw3 (i int GENERATED ALWAYS AS IDENTITY); +CREATE RULE id_alw3_ins AS ON INSERT TO id_alw3 DO INSTEAD + WITH t1 AS (INSERT INTO id_alw1 DEFAULT VALUES RETURNING i) + INSERT INTO id_alw2_view DEFAULT VALUES RETURNING i; +CREATE TEMP VIEW id_alw3_view AS SELECT * FROM id_alw3; + +CREATE TEMP TABLE id_alw4 (i int GENERATED ALWAYS AS IDENTITY); + +WITH t4 AS (INSERT INTO id_alw4 DEFAULT VALUES RETURNING i) + INSERT INTO id_alw3_view DEFAULT VALUES RETURNING i; + +SELECT * from id_alw1; +SELECT * from id_alw2; +SELECT * from id_alw3; +SELECT * from id_alw4; + -- check case where CTE reference is removed due to optimization EXPLAIN (VERBOSE, COSTS OFF) SELECT q1 FROM diff --git a/parser/src/test/resources/postgres/test/regress/sql/xml.sql b/parser/src/test/resources/postgres/test/regress/sql/xml.sql index 543feb8..18143a2 100644 --- a/parser/src/test/resources/postgres/test/regress/sql/xml.sql +++ b/parser/src/test/resources/postgres/test/regress/sql/xml.sql @@ -1,3 +1,12 @@ +/* + * This file has been altered by SplendidData. + * It is only used for syntax checking, not for the testing of a commandline paser. + * So input for the copy statements is removed. + * The deactivated lines are marked by: -- Deactivated for SplendidDataTest: + */ + + + CREATE TABLE xmltest ( id int, data xml @@ -5,7 +14,14 @@ CREATE TABLE xmltest ( INSERT INTO xmltest VALUES (1, 'one'); INSERT INTO xmltest VALUES (2, 'two'); -INSERT INTO xmltest VALUES (3, 'three '); + +-- If no XML data could be inserted, skip the tests as the server has been +-- compiled without libxml support. +SELECT count(*) = 0 AS skip_test FROM xmltest \gset +\if :skip_test +\quit +\endif SELECT * FROM xmltest; @@ -23,7 +39,7 @@ SELECT xmlconcat(xmlcomment('hello'), SELECT xmlconcat('hello', 'you'); SELECT xmlconcat(1, 2); -SELECT xmlconcat('bad', ' '); SELECT xmlconcat('', NULL, ''); SELECT xmlconcat('', NULL, ''); SELECT xmlconcat(NULL); @@ -68,17 +84,17 @@ SELECT xmlparse(content '&'); SELECT xmlparse(content '&idontexist;'); SELECT xmlparse(content ''); SELECT xmlparse(content ''); -SELECT xmlparse(content '&idontexist;'); +SELECT xmlparse(content '&idontexist; '); SELECT xmlparse(content ''); -SELECT xmlparse(document ' '); +SELECT xmlparse(document '!'); SELECT xmlparse(document 'abc'); SELECT xmlparse(document 'x'); -SELECT xmlparse(document '&'); -SELECT xmlparse(document '&idontexist;'); +SELECT xmlparse(document '& '); +SELECT xmlparse(document '&idontexist; '); SELECT xmlparse(document ''); SELECT xmlparse(document ''); -SELECT xmlparse(document '&idontexist;'); +SELECT xmlparse(document '&idontexist; '); SELECT xmlparse(document ''); @@ -196,6 +212,7 @@ SELECT xpath('count(//*)=3', ''); SELECT xpath('name(/*)', ''); SELECT xpath('/nosuchtag', ''); SELECT xpath('root', ''); +SELECT xpath('//namespace::foo', ''); -- Round-trip non-ASCII data through xpath(). DO $$ diff --git a/pom.xml b/pom.xml index e1f6409..324f5a3 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ ${java.version} UTF-8 file:**/generated-sources/** - 2.25.2 + 2.26.0 11.0.2 5.14.1 @@ -92,7 +92,7 @@ org.apache.maven maven-plugin-api - 3.9.11 + 3.9.16 org.apache.maven.plugin-tools @@ -108,24 +108,24 @@ org.apache.maven maven-core - 3.9.11 + 3.9.16 com.github.javaparser javaparser-core - 3.27.1 + 3.28.2 jakarta.xml.bind jakarta.xml.bind-api - 4.0.4 + 4.0.5 org.glassfish.jaxb jaxb-runtime - 4.0.6 + 4.0.9 @@ -156,18 +156,18 @@ org.checkerframework checker-qual - 3.47.0 + 4.2.0 org.apache.maven maven-model - 3.9.7 + 3.9.16 provided org.apache.maven maven-artifact - 3.9.7 + 3.9.16 provided @@ -184,7 +184,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.15.0 ${java.version} @@ -200,7 +200,7 @@ org.codehaus.mojo exec-maven-plugin - 3.6.2 + 3.6.3 org.codehaus.mojo @@ -215,7 +215,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.9.0 + 3.11.0 org.apache.maven.plugins @@ -233,7 +233,7 @@ org.jacoco jacoco-maven-plugin - 0.8.14 + 0.8.15 org.apache.maven.plugins @@ -243,7 +243,7 @@ org.apache.maven.plugins maven-site-plugin - 3.21.0 + 3.22.0 org.apache.maven.plugins @@ -253,7 +253,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.4 + 3.5.6 org.apache.maven.plugins @@ -276,12 +276,12 @@ org.apache.maven.plugins maven-resources-plugin - 3.3.1 + 3.5.0 org.apache.maven.plugins maven-enforcer-plugin - 3.6.2 + 3.6.3 @@ -338,7 +338,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.1 + 3.4.0 attach-sources @@ -369,7 +369,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.10.0 public false @@ -392,7 +392,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.5.4 + 3.5.6 @@ -420,7 +420,7 @@ - aggreagte + aggregate report-aggregate @@ -431,9 +431,10 @@ - - www.splendiddata.com - scp://www.splediddata.com/www/docs/pg_sqlparser/ - + + github + GitHub Splendid Data Apache Maven Packages + https://maven.pkg.github.com//splendiddata/pg_sqlparser + \ No newline at end of file From 183b31ea8789d50d5f9f9c74e859cd9f0cb36069 Mon Sep 17 00:00:00 2001 From: Martin Butter Date: Tue, 30 Jun 2026 17:24:37 +0200 Subject: [PATCH 6/6] Finalized version 15.2 --- grammar-to-java/pom.xml | 2 +- parser-enums/pom.xml | 2 +- parser-test-gui/pom.xml | 2 +- parser/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grammar-to-java/pom.xml b/grammar-to-java/pom.xml index fb830d3..b9cbcb1 100644 --- a/grammar-to-java/pom.xml +++ b/grammar-to-java/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.2-SNAPSHOT + 15.2 com.splendiddata.pg_sqlparser grammar-to-java diff --git a/parser-enums/pom.xml b/parser-enums/pom.xml index 449af3d..f26fe1e 100644 --- a/parser-enums/pom.xml +++ b/parser-enums/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.2-SNAPSHOT + 15.2 com.splendiddata.pg_sqlparser parser-enums diff --git a/parser-test-gui/pom.xml b/parser-test-gui/pom.xml index c5744c8..580db22 100644 --- a/parser-test-gui/pom.xml +++ b/parser-test-gui/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.2-SNAPSHOT + 15.2 parser-test-gui com.splendiddata.pg_sqlparser diff --git a/parser/pom.xml b/parser/pom.xml index 320acbe..a92e192 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -5,7 +5,7 @@ com.splendiddata pg_sqlparser - 15.2-SNAPSHOT + 15.2 com.splendiddata.pg_sqlparser parser diff --git a/pom.xml b/pom.xml index 324f5a3..08d8482 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.splendiddata pg_sqlparser - 15.2-SNAPSHOT + 15.2 pom pg_sqlparser Java implementation of the Postgres sql parser. This version of the sqlparser is generated from the Postgres version 15 parser.