From be2e6fe5c070dad9bad1914960ac8db4adbe2f67 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Thu, 15 Aug 2024 15:10:04 +0200 Subject: [PATCH 1/5] Add support for CREATE TABLE AS This adds support for queries like: ``` CREATE TABLE mytable AS SELECT column00 from read_csv("my_data.csv"); ``` The table will be then be created in Postgres (not in DuckDB). The main change that supports this is that we now start "deparsing" the parsed `Query` type from Postgres to an actual query string, instead of sending the original string that Postgres received to DuckDB. This also accidentally fixes some differences such as the DuckDB `count(*)` aggregate creating a `count_star` vs Postgres its `count` column. So it reduces the need for #36 a bit. The reason this happens is because it is deparsed very explicitly like `count(*) AS count`. For similar reasons this also changes the behaviour of the following query to only return the `id` and `name` columns, instead of all the columns. It's arguable whether that's a good thing or not. ``` SELECT * FROM read_parquet(...) AS (id int, name text); ``` --- include/pgduckdb/pgduckdb_planner.hpp | 2 +- src/pgduckdb_hooks.cpp | 14 ++--- src/pgduckdb_planner.cpp | 9 ++- test/regression/data/web_page.csv | 60 +++++++++++++++++++ test/regression/expected/basic.out | 42 ++++++------- test/regression/expected/create_table_as.out | 16 +++++ test/regression/expected/execution_error.out | 4 +- .../expected/hugeint_conversion.out | 4 +- .../regression/expected/materialized_view.out | 36 +++++------ test/regression/expected/search_path.out | 48 +++++++-------- test/regression/expected/views.out | 6 +- test/regression/schedule | 1 + test/regression/sql/create_table_as.sql | 7 +++ 13 files changed, 171 insertions(+), 78 deletions(-) create mode 100644 test/regression/data/web_page.csv create mode 100644 test/regression/expected/create_table_as.out create mode 100644 test/regression/sql/create_table_as.sql diff --git a/include/pgduckdb/pgduckdb_planner.hpp b/include/pgduckdb/pgduckdb_planner.hpp index 8bf87993..f70d93e7 100644 --- a/include/pgduckdb/pgduckdb_planner.hpp +++ b/include/pgduckdb/pgduckdb_planner.hpp @@ -5,4 +5,4 @@ extern "C" { #include "optimizer/planner.h" } -PlannedStmt *DuckdbPlanNode(Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params); +PlannedStmt *DuckdbPlanNode(Query *parse, int cursor_options, ParamListInfo bound_params); diff --git a/src/pgduckdb_hooks.cpp b/src/pgduckdb_hooks.cpp index 45548b9c..c34e0419 100644 --- a/src/pgduckdb_hooks.cpp +++ b/src/pgduckdb_hooks.cpp @@ -46,20 +46,18 @@ IsAllowedStatement(Query *query) { if (query->hasModifyingCTE) { return false; } - /* For `SELECT ..` ActivePortal doesn't exist */ - if (!ActivePortal) - return true; - /* `EXPLAIN ...` should be allowed */ - if (ActivePortal->commandTag == CMDTAG_EXPLAIN) - return true; - return false; + /* We don't support modifying statements yet */ + if (query->commandType != CMD_SELECT) { + return false; + } + return true; } static PlannedStmt * DuckdbPlannerHook(Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params) { if (duckdb_execution && IsAllowedStatement(parse) && pgduckdb::IsExtensionRegistered() && parse->rtable && !IsCatalogTable(parse->rtable) && parse->commandType == CMD_SELECT) { - PlannedStmt *duckdb_plan = DuckdbPlanNode(parse, query_string, cursor_options, bound_params); + PlannedStmt *duckdb_plan = DuckdbPlanNode(parse, cursor_options, bound_params); if (duckdb_plan) { return duckdb_plan; } diff --git a/src/pgduckdb_planner.cpp b/src/pgduckdb_planner.cpp index b771e62c..c69f2fb1 100644 --- a/src/pgduckdb_planner.cpp +++ b/src/pgduckdb_planner.cpp @@ -5,6 +5,8 @@ extern "C" { #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "optimizer/optimizer.h" +#include "tcop/pquery.h" +#include "utils/ruleutils.h" #include "utils/syscache.h" } @@ -100,7 +102,12 @@ CreatePlan(Query *query, const char *query_string, ParamListInfo bound_params) { } PlannedStmt * -DuckdbPlanNode(Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params) { +DuckdbPlanNode(Query *parse, int cursor_options, ParamListInfo bound_params) { + const char *query_string = pg_get_querydef(parse, false); + + if (ActivePortal && ActivePortal->commandTag == CMDTAG_EXPLAIN) { + query_string = psprintf("EXPLAIN %s", query_string); + } /* We need to check can we DuckDB create plan */ Plan *duckdb_plan = (Plan *)castNode(CustomScan, CreatePlan(parse, query_string, bound_params)); diff --git a/test/regression/data/web_page.csv b/test/regression/data/web_page.csv new file mode 100644 index 00000000..07980174 --- /dev/null +++ b/test/regression/data/web_page.csv @@ -0,0 +1,60 @@ +1|AAAAAAAABAAAAAAA|1997-09-03||2450810|2452620|Y|98539|http://www.foo.com|welcome|2531|8|3|4 +2|AAAAAAAACAAAAAAA|1997-09-03|2000-09-02|2450814|2452580|N||http://www.foo.com|protected|1564|4|3|1 +3|AAAAAAAACAAAAAAA|2000-09-03||2450814|2452611|N||http://www.foo.com|feedback|1564|4|3|4 +4|AAAAAAAAEAAAAAAA|1997-09-03|1999-09-03|2450812|2452579|N||http://www.foo.com|general|3732|18|7|1 +5|AAAAAAAAEAAAAAAA|1999-09-04|2001-09-02|2450812|2452597|N||http://www.foo.com|welcome|3732|18|3|1 +6|AAAAAAAAEAAAAAAA|2001-09-03||2450814|2452597|N||http://www.foo.com|ad|3732|18|7|4 +7|AAAAAAAAHAAAAAAA|1997-09-03||2450815|2452574|N||http://www.foo.com|feedback|3034|18|7|4 +8|AAAAAAAAIAAAAAAA|1997-09-03|2000-09-02|2450815|2452646|Y|1898|http://www.foo.com|protected|3128|12|2|4 +9|AAAAAAAAIAAAAAAA|2000-09-03||2450807|2452579|Y|84146|http://www.foo.com|welcome|3128|13|5|3 +10|AAAAAAAAKAAAAAAA|1997-09-03|1999-09-03||2452623|N||http://www.foo.com||||| +11|AAAAAAAAKAAAAAAA|1999-09-04|2001-09-02|2450814|2452611|N||http://www.foo.com|welcome|7046|23|4|4 +12|AAAAAAAAKAAAAAAA|2001-09-03||2450815|2452611|N||http://www.foo.com|protected|7046|17|4|4 +13|AAAAAAAANAAAAAAA|1997-09-03||2450807|2452629|N||http://www.foo.com|protected|2281|6|4|1 +14|AAAAAAAAOAAAAAAA|1997-09-03|2000-09-02|2450810|2452639|N||http://www.foo.com|dynamic|5676|19|6|0 +15|AAAAAAAAOAAAAAAA|2000-09-03||2450810|2452639|N||http://www.foo.com|dynamic|2469|10|5|2 +16|AAAAAAAAABAAAAAA|1997-09-03|1999-09-03|2450814|2452601|Y|33463|http://www.foo.com|feedback|701|2|1|4 +17|AAAAAAAAABAAAAAA|1999-09-04|2001-09-02|2450812|2452645|N||http://www.foo.com|general|701|11|1|3 +18|AAAAAAAAABAAAAAA|2001-09-03||2450812|2452608|N||http://www.foo.com|ad|4080|11|6|3 +19|AAAAAAAADBAAAAAA|1997-09-03||2450808|2452648|Y|57610|http://www.foo.com|general|2347|9|7|4 +20|AAAAAAAAEBAAAAAA|1997-09-03|2000-09-02|2450809|2452555|Y|46487|http://www.foo.com|ad|1147|3|6|0 +21|AAAAAAAAEBAAAAAA|2000-09-03||2450809|2452555|Y|10897|http://www.foo.com|general|1147|3|6|4 +22|AAAAAAAAGBAAAAAA|1997-09-03|1999-09-03|2450812|2452565|Y|20213|http://www.foo.com|general|5663|25|3|4 +23|AAAAAAAAGBAAAAAA|1999-09-04|2001-09-02|2450812|2452623|Y|20213|http://www.foo.com|order|4729|23|6|4 +24|AAAAAAAAGBAAAAAA|2001-09-03||2450812|2452646|Y|20213|http://www.foo.com|dynamic|5918|23|6|1 +25|AAAAAAAAJBAAAAAA|1997-09-03||2450811|2452620|N||http://www.foo.com|feedback|1526|9|4|2 +26|AAAAAAAAKBAAAAAA|1997-09-03|2000-09-02|2450812|2452636|Y|98376|http://www.foo.com|ad|1826|9|3|1 +27|AAAAAAAAKBAAAAAA|2000-09-03||2450812|2452607|Y|98376|http://www.foo.com|protected|1553|9|1|1 +28|AAAAAAAAMBAAAAAA|1997-09-03|1999-09-03|2450807|2452572|N||http://www.foo.com|protected|1308|4|1|2 +29|AAAAAAAAMBAAAAAA|1999-09-04|2001-09-02|2450808|2452611|N||http://www.foo.com|order|1308|4|1|2 +30|AAAAAAAAMBAAAAAA|2001-09-03||2450808|2452611|N||http://www.foo.com|general|3872|18|1|4 +31|AAAAAAAAPBAAAAAA|1997-09-03||2450810|2452596|N||http://www.foo.com|general|1732|3|6|0 +32|AAAAAAAAACAAAAAA|1997-09-03|2000-09-02|2450808|2452585|N||http://www.foo.com|welcome|5104|20|7|4 +33|AAAAAAAAACAAAAAA|2000-09-03||2450808|2452585|N||http://www.foo.com|protected|2129|7|1|0 +34|AAAAAAAACCAAAAAA|1997-09-03|1999-09-03|2450808|2452616|N||http://www.foo.com|welcome|2726|12|5|2 +35|AAAAAAAACCAAAAAA|1999-09-04|2001-09-02|2450808|2452591|N||http://www.foo.com|protected|2726|12|1|2 +36|AAAAAAAACCAAAAAA|2001-09-03||2450812|2452613|N||http://www.foo.com|dynamic|2726|3|1|2 +37|AAAAAAAAFCAAAAAA|1997-09-03||2450809|2452556|N||http://www.foo.com|ad|3076|15|3|0 +38|AAAAAAAAGCAAAAAA|1997-09-03|2000-09-02|2450811|2452583|Y|37285|http://www.foo.com|general|3096|18|3|0 +39|AAAAAAAAGCAAAAAA|2000-09-03||2450815|2452583|N||http://www.foo.com|general|3096|18|3|0 +40|AAAAAAAAICAAAAAA|1997-09-03|1999-09-03|2450813|2452576|N||http://www.foo.com|general|4402|18|4|2 +41|AAAAAAAAICAAAAAA|1999-09-04|2001-09-02|2450813|2452579|Y|16769|http://www.foo.com|welcome|784|3|4|4 +42|AAAAAAAAICAAAAAA|2001-09-03||2450813|2452579|Y|60150|http://www.foo.com|dynamic|1451|3|4|4 +43|AAAAAAAALCAAAAAA|1997-09-03||2450814|2452580|Y|64793|http://www.foo.com|ad|3760|12|3|2 +44|AAAAAAAAMCAAAAAA|1997-09-03|2000-09-02|2450811|2452602|Y|92078|http://www.foo.com|ad|4179|19|7|1 +45|AAAAAAAAMCAAAAAA|2000-09-03||2450811|2452575|Y|98633|http://www.foo.com|feedback|4584|19|7|4 +46|AAAAAAAAOCAAAAAA|1997-09-03|1999-09-03|2450809|2452574|N||http://www.foo.com|protected|1711|4|5|1 +47|AAAAAAAAOCAAAAAA|1999-09-04|2001-09-02|2450815|2452574|N||http://www.foo.com|welcome|1711|4|5|1 +48|AAAAAAAAOCAAAAAA|2001-09-03||2450815|2452622|N||http://www.foo.com|ad|1732|9|5|1 +49|AAAAAAAABDAAAAAA|1997-09-03||2450809|2452618|N||http://www.foo.com|order|4894|20|3|2 +50|AAAAAAAACDAAAAAA|1997-09-03|2000-09-02|2450808|2452615|N||http://www.foo.com|welcome|5262|16|5|2 +51|AAAAAAAACDAAAAAA|2000-09-03||2450811|2452564|N||http://www.foo.com|general|3423|19|7|1 +52|AAAAAAAAEDAAAAAA|1997-09-03|1999-09-03|2450815|2452606|N||http://www.foo.com|welcome|3306|21|7|1 +53|AAAAAAAAEDAAAAAA|1999-09-04|2001-09-02|2450808|2452636|N||http://www.foo.com|dynamic|3306|21|7|1 +54|AAAAAAAAEDAAAAAA|2001-09-03||2450808|2452629|N||http://www.foo.com|protected|1931|7|2|2 +55|AAAAAAAAHDAAAAAA|1997-09-03||2450811|2452549|N||http://www.foo.com|order|3788|19|1|0 +56|AAAAAAAAIDAAAAAA|1997-09-03|2000-09-02|2450815|2452554|N||http://www.foo.com|protected|5733|24|2|2 +57|AAAAAAAAIDAAAAAA|2000-09-03||2450811|2452568|N||http://www.foo.com|ad|5733|16|2|2 +58|AAAAAAAAKDAAAAAA|1997-09-03|1999-09-03|2450813|2452619|Y|7625|http://www.foo.com|ad|6577|24|4|3 +59|AAAAAAAAKDAAAAAA|1999-09-04|2001-09-02|2450813|2452624|Y|80555|http://www.foo.com|general|6577|24|2|3 +60|AAAAAAAAKDAAAAAA|2001-09-03||2450813|2452566|Y|80555|http://www.foo.com|welcome|6577|24|2|3 diff --git a/test/regression/expected/basic.out b/test/regression/expected/basic.out index 0f9f12bf..126f8e1e 100644 --- a/test/regression/expected/basic.out +++ b/test/regression/expected/basic.out @@ -2,41 +2,41 @@ CREATE TABLE t(a INT); INSERT INTO t SELECT g % 10 from generate_series(1,1000000) g; SET client_min_messages to 'DEBUG1'; SELECT COUNT(*) FROM t; - count_star() --------------- - 1000000 + count +--------- + 1000000 (1 row) SELECT a, COUNT(*) FROM t WHERE a > 5 GROUP BY a ORDER BY a; - a | count_star() ----+-------------- - 6 | 100000 - 7 | 100000 - 8 | 100000 - 9 | 100000 + a | count +---+-------- + 6 | 100000 + 7 | 100000 + 8 | 100000 + 9 | 100000 (4 rows) SET duckdb.max_threads_per_query to 4; SELECT COUNT(*) FROM t; - count_star() --------------- - 1000000 + count +--------- + 1000000 (1 row) SELECT a, COUNT(*) FROM t WHERE a > 5 GROUP BY a ORDER BY a; - a | count_star() ----+-------------- - 6 | 100000 - 7 | 100000 - 8 | 100000 - 9 | 100000 + a | count +---+-------- + 6 | 100000 + 7 | 100000 + 8 | 100000 + 9 | 100000 (4 rows) CREATE TABLE empty(a INT); SELECT COUNT(*) FROM empty; - count_star() --------------- - 0 + count +------- + 0 (1 row) SET duckdb.max_threads_per_query TO default; diff --git a/test/regression/expected/create_table_as.out b/test/regression/expected/create_table_as.out new file mode 100644 index 00000000..bac215c3 --- /dev/null +++ b/test/regression/expected/create_table_as.out @@ -0,0 +1,16 @@ +\getenv pwd PWD +CREATE TABLE webpages AS SELECT * FROM read_csv(:'pwd' || '/data/web_page.csv') as (column00 int, column01 text, column02 date); +select * from webpages order by column00 limit 2; + column00 | column01 | column02 +----------+------------------+------------ + 1 | AAAAAAAABAAAAAAA | 09-03-1997 + 2 | AAAAAAAACAAAAAAA | 09-03-1997 +(2 rows) + +select count(*) from webpages; + count +------- + 60 +(1 row) + +DROP TABLE webpages; diff --git a/test/regression/expected/execution_error.out b/test/regression/expected/execution_error.out index 96ae5507..2b93a606 100644 --- a/test/regression/expected/execution_error.out +++ b/test/regression/expected/execution_error.out @@ -5,5 +5,5 @@ insert into int_as_varchar SELECT * from ( ) t(a); select a::INTEGER from int_as_varchar; ERROR: Duckdb execute returned an error: Conversion Error: Could not convert string 'abc' to INT32 -LINE 1: select a::INTEGER from int_as_varchar; - ^ +LINE 1: SELECT (a)::integer AS a + ^ diff --git a/test/regression/expected/hugeint_conversion.out b/test/regression/expected/hugeint_conversion.out index 6e7dd4bb..8b263285 100644 --- a/test/regression/expected/hugeint_conversion.out +++ b/test/regression/expected/hugeint_conversion.out @@ -1,8 +1,8 @@ create table hugeint_sum(a int); insert into hugeint_sum select g from generate_series(1,100) g; select pg_typeof(sum(a)) from hugeint_sum; - pg_typeof(sum(a)) -------------------- + pg_typeof +----------- hugeint (1 row) diff --git a/test/regression/expected/materialized_view.out b/test/regression/expected/materialized_view.out index 5c9708d2..1e8020f7 100644 --- a/test/regression/expected/materialized_view.out +++ b/test/regression/expected/materialized_view.out @@ -1,42 +1,42 @@ CREATE TABLE t(a INT, b TEXT); INSERT INTO t SELECT g % 1000, MD5(g::TEXT) FROM generate_series(1,20000) g; SELECT COUNT(*) FROM t WHERE a % 100 = 0; - count_star() --------------- - 200 + count +------- + 200 (1 row) CREATE MATERIALIZED VIEW tv AS SELECT * FROM t WHERE a % 100 = 0; SELECT COUNT(*) FROM tv; - count_star() --------------- - 200 + count +------- + 200 (1 row) INSERT INTO t SELECT g % 1000, MD5(g::TEXT) FROM generate_series(1,20000) g; SELECT COUNT(*) FROM t WHERE a % 100 = 0; - count_star() --------------- - 400 + count +------- + 400 (1 row) REFRESH MATERIALIZED VIEW tv; SELECT COUNT(*) FROM tv; - count_star() --------------- - 400 + count +------- + 400 (1 row) SELECT COUNT(*) FROM t WHERE (a % 100 = 0) AND (a < 30); - count_star() --------------- - 40 + count +------- + 40 (1 row) SELECT COUNT(*) FROM tv WHERE a < 30; - count_star() --------------- - 40 + count +------- + 40 (1 row) DROP MATERIALIZED VIEW tv; diff --git a/test/regression/expected/search_path.out b/test/regression/expected/search_path.out index 157399d4..0a99588e 100644 --- a/test/regression/expected/search_path.out +++ b/test/regression/expected/search_path.out @@ -1,15 +1,15 @@ CREATE TABLE t(a INT); INSERT INTO t SELECT g from generate_series(1,10) g; SELECT count(*) FROM t; - count_star() --------------- - 10 + count +------- + 10 (1 row) SELECT count(*) FROM public.t; - count_star() --------------- - 10 + count +------- + 10 (1 row) -- Create schema `other` @@ -17,22 +17,22 @@ CREATE SCHEMA other; CREATE TABLE other.t(a INT); INSERT INTO other.t SELECT g from generate_series(1,100) g; SELECT count(*) FROM other.t; - count_star() --------------- - 100 + count +------- + 100 (1 row) -- Test fully qualified table name combinations SELECT count(*) FROM public.t, other.t; - count_star() --------------- - 1000 + count +------- + 1000 (1 row) SELECT count(*) FROM t, other.t; - count_star() --------------- - 1000 + count +------- + 1000 (1 row) SELECT count(*) FROM t,t; @@ -40,15 +40,15 @@ ERROR: table name "t" specified more than once -- search_path ORDER matters. SET search_path TO other, public; SELECT count(*) FROM t; - count_star() --------------- - 100 + count +------- + 100 (1 row) SELECT count(*) FROM t, public.t; - count_star() --------------- - 1000 + count +------- + 1000 (1 row) -- No search_path @@ -58,9 +58,9 @@ ERROR: relation "t" does not exist LINE 1: SELECT count(*) FROM t, other.t; ^ SELECT count(*) FROM public.t, other.t; - count_star() --------------- - 1000 + count +------- + 1000 (1 row) -- Cleanup diff --git a/test/regression/expected/views.out b/test/regression/expected/views.out index 89dca127..362c6d0e 100644 --- a/test/regression/expected/views.out +++ b/test/regression/expected/views.out @@ -27,9 +27,13 @@ create table "s.t" as select 42; create view vw1 as select * from s.t; create view vw2 as select * from "s.t"; select * from vw1, vw2; +WARNING: (DuckDB) Binder Error: Referenced table "t" not found! +Candidate tables: "s.t" +LINE 3: FROM ( SELECT t."?column?" + ^ ?column? | ?column? ----------+---------- - 21 | 21 + 21 | 42 (1 row) drop view vw1; diff --git a/test/regression/schedule b/test/regression/schedule index 944db8ce..e6ac7c96 100644 --- a/test/regression/schedule +++ b/test/regression/schedule @@ -8,3 +8,4 @@ test: projection_pushdown_unsupported_type test: materialized_view test: hugeint_conversion test: cte +test: create_table_as diff --git a/test/regression/sql/create_table_as.sql b/test/regression/sql/create_table_as.sql new file mode 100644 index 00000000..5732f3f4 --- /dev/null +++ b/test/regression/sql/create_table_as.sql @@ -0,0 +1,7 @@ +\getenv pwd PWD +CREATE TABLE webpages AS SELECT * FROM read_csv(:'pwd' || '/data/web_page.csv') as (column00 int, column01 text, column02 date); + +select * from webpages order by column00 limit 2; +select count(*) from webpages; + +DROP TABLE webpages; From 2c8ed3b7ac5b6fa6dabac02ec91c023a44f0531c Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 16 Aug 2024 14:48:40 +0200 Subject: [PATCH 2/5] Fix materialized view error on PG16 --- test/regression/expected/materialized_view.out | 4 ++-- test/regression/sql/materialized_view.sql | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/regression/expected/materialized_view.out b/test/regression/expected/materialized_view.out index 1e8020f7..eb4ac488 100644 --- a/test/regression/expected/materialized_view.out +++ b/test/regression/expected/materialized_view.out @@ -1,5 +1,5 @@ -CREATE TABLE t(a INT, b TEXT); -INSERT INTO t SELECT g % 1000, MD5(g::TEXT) FROM generate_series(1,20000) g; +CREATE TABLE t(a INT, b VARCHAR); +INSERT INTO t SELECT g % 1000, MD5(g::VARCHAR) FROM generate_series(1,20000) g; SELECT COUNT(*) FROM t WHERE a % 100 = 0; count ------- diff --git a/test/regression/sql/materialized_view.sql b/test/regression/sql/materialized_view.sql index b26a8832..921b74c3 100644 --- a/test/regression/sql/materialized_view.sql +++ b/test/regression/sql/materialized_view.sql @@ -1,5 +1,5 @@ -CREATE TABLE t(a INT, b TEXT); -INSERT INTO t SELECT g % 1000, MD5(g::TEXT) FROM generate_series(1,20000) g; +CREATE TABLE t(a INT, b VARCHAR); +INSERT INTO t SELECT g % 1000, MD5(g::VARCHAR) FROM generate_series(1,20000) g; SELECT COUNT(*) FROM t WHERE a % 100 = 0; CREATE MATERIALIZED VIEW tv AS SELECT * FROM t WHERE a % 100 = 0; SELECT COUNT(*) FROM tv; From 16244b6108bb7ff99f7bbac10f8bd586f5b45136 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 16 Aug 2024 15:47:21 +0200 Subject: [PATCH 3/5] Remove duplicate CMD_SELECT check --- src/pgduckdb_hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pgduckdb_hooks.cpp b/src/pgduckdb_hooks.cpp index c34e0419..757c2acd 100644 --- a/src/pgduckdb_hooks.cpp +++ b/src/pgduckdb_hooks.cpp @@ -56,7 +56,7 @@ IsAllowedStatement(Query *query) { static PlannedStmt * DuckdbPlannerHook(Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params) { if (duckdb_execution && IsAllowedStatement(parse) && pgduckdb::IsExtensionRegistered() && parse->rtable && - !IsCatalogTable(parse->rtable) && parse->commandType == CMD_SELECT) { + !IsCatalogTable(parse->rtable)) { PlannedStmt *duckdb_plan = DuckdbPlanNode(parse, cursor_options, bound_params); if (duckdb_plan) { return duckdb_plan; From 04ebbf3b0f5e37e0b503cdeef5a4d9a6110fd0db Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 16 Aug 2024 15:55:06 +0200 Subject: [PATCH 4/5] Move more checks to IsAllowedStatement --- src/pgduckdb_hooks.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/pgduckdb_hooks.cpp b/src/pgduckdb_hooks.cpp index 757c2acd..36b7db11 100644 --- a/src/pgduckdb_hooks.cpp +++ b/src/pgduckdb_hooks.cpp @@ -46,17 +46,36 @@ IsAllowedStatement(Query *query) { if (query->hasModifyingCTE) { return false; } + /* We don't support modifying statements yet */ if (query->commandType != CMD_SELECT) { return false; } + + /* + * If there's no rtable, we're only selecting constants. There's no point + * in using DuckDB for that. + */ + if (!query->rtable) { + return false; + } + + /* + * If any table is from pg_catalog, we don't want to use DuckDB. This is + * because DuckDB has its own pg_catalog tables that contain different data + * then Postgres its pg_catalog tables. + */ + if (!IsCatalogTable(query->rtable)) { + return false; + } + + /* Anything else is hopefully fine... */ return true; } static PlannedStmt * DuckdbPlannerHook(Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params) { - if (duckdb_execution && IsAllowedStatement(parse) && pgduckdb::IsExtensionRegistered() && parse->rtable && - !IsCatalogTable(parse->rtable)) { + if (duckdb_execution && IsAllowedStatement(parse) && pgduckdb::IsExtensionRegistered()) { PlannedStmt *duckdb_plan = DuckdbPlanNode(parse, cursor_options, bound_params); if (duckdb_plan) { return duckdb_plan; From 7af2b52f709618ff6b75857533fda0677795b0d4 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 16 Aug 2024 15:57:20 +0200 Subject: [PATCH 5/5] Fix condition... --- src/pgduckdb_hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pgduckdb_hooks.cpp b/src/pgduckdb_hooks.cpp index 36b7db11..24a55a5c 100644 --- a/src/pgduckdb_hooks.cpp +++ b/src/pgduckdb_hooks.cpp @@ -65,7 +65,7 @@ IsAllowedStatement(Query *query) { * because DuckDB has its own pg_catalog tables that contain different data * then Postgres its pg_catalog tables. */ - if (!IsCatalogTable(query->rtable)) { + if (IsCatalogTable(query->rtable)) { return false; }