Skip to content

Commit 12dee2e

Browse files
authored
Support MotherDuck views (#822)
This adds support for creating, querying and syncing VIEWs from MotherDuck. Views created by `CREATE VIEW` get created in MotherDuck if one of the following conditions is met: 1. The view is created in a `ddb$` schema. 2. The query of the view accesses DuckDB tables or DuckDB views. 3. `duckdb.force_motherduck_views` is set to `true`. Fixes #474
1 parent d8f548b commit 12dee2e

19 files changed

+1099
-89
lines changed

.github/workflows/docker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
6464
# If main or tag, then push to `pgduckdb/pgduckdb`
6565
git fetch --tags --force
66-
if [ "$BRANCH" = "main" ] || git rev-parse --verify $BRANCH^{tag} > /dev/null 2>&1; then
66+
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "duckdb-views" ] || git rev-parse --verify $BRANCH^{tag} > /dev/null 2>&1; then
6767
TARGET_REPO='pgduckdb/pgduckdb'
6868
else
6969
TARGET_REPO='pgduckdb/ci-builds'

include/pgduckdb/pg/declarations.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,7 @@ struct PlanState;
8787

8888
struct Plan;
8989

90+
struct FuncExpr;
91+
9092
typedef struct FunctionCallInfoBaseData *FunctionCallInfo;
9193
}

include/pgduckdb/pgduckdb_ddl.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
#include "pgduckdb/pg/declarations.hpp"
44

55
namespace pgduckdb {
6-
enum class DDLType { NONE, CREATE_TABLE, ALTER_TABLE, REFRESH_MATERIALIZED_VIEW };
6+
enum class DDLType { NONE, CREATE_TABLE, ALTER_TABLE, REFRESH_MATERIALIZED_VIEW, RENAME_VIEW };
77
/* Tracks the type of DDL statement that is currently being executed */
88
extern DDLType top_level_duckdb_ddl_type;
9+
bool IsMotherDuckView(Form_pg_class relation);
10+
bool IsMotherDuckView(Relation relation);
11+
FuncExpr *GetDuckdbViewExprFromQuery(Query *query);
912
} // namespace pgduckdb
1013

1114
void DuckdbTruncateTable(Oid relation_oid);

include/pgduckdb/pgduckdb_guc.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern int duckdb_threads_for_postgres_scan;
1919
extern int duckdb_max_workers_per_postgres_scan;
2020
extern char *duckdb_postgres_role;
2121
extern char *duckdb_motherduck_session_hint;
22+
extern bool duckdb_force_motherduck_views;
2223
extern char *duckdb_temporary_directory;
2324
extern char *duckdb_extension_directory;
2425
extern char *duckdb_max_temp_directory_size;

include/pgduckdb/pgduckdb_ruleutils.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ char *pgduckdb_function_name(Oid function_oid, bool *use_variadic_p);
1313
char *pgduckdb_get_querydef(Query *);
1414
char *pgduckdb_get_tabledef(Oid relation_id);
1515
char *pgduckdb_get_alter_tabledef(Oid relation_oid, AlterTableStmt *alter_stmt);
16-
char *pgduckdb_get_rename_tabledef(Oid relation_oid, RenameStmt *rename_stmt);
16+
char *pgduckdb_get_rename_relationdef(Oid relation_oid, RenameStmt *rename_stmt);
1717
bool pgduckdb_is_not_default_expr(Node *node, void *context);
1818
List *pgduckdb_db_and_schema(const char *postgres_schema_name, bool is_duckdb_table);
1919
const char *pgduckdb_db_and_schema_string(const char *postgres_schema_name, bool is_duckdb_table);
@@ -24,12 +24,15 @@ bool pgduckdb_var_is_duckdb_row(Var *var);
2424
bool pgduckdb_func_returns_duckdb_row(RangeTblFunction *rtfunc);
2525
Var *pgduckdb_duckdb_row_subscript_var(Expr *expr);
2626
bool pgduckdb_reconstruct_star_step(StarReconstructionContext *ctx, ListCell *tle_cell);
27+
bool pgduckdb_replace_subquery_with_view(Query *query, StringInfo buf);
2728
int pgduckdb_show_type(Const *constval, int original_showtype);
2829
bool pgduckdb_subscript_has_custom_alias(Plan *plan, List *rtable, Var *subscript_var, char *colname);
2930
SubscriptingRef *pgduckdb_strip_first_subscript(SubscriptingRef *sbsref, StringInfo buf);
3031
char *pgduckdb_write_row_refname(StringInfo buf, char *refname, bool is_top_level);
3132
bool is_system_sampling(const char *tsm_name, int num_args);
3233
bool is_bernoulli_sampling(const char *tsm_name, int num_args);
3334
void pgduckdb_add_tablesample_percent(const char *tsm_name, StringInfo buf, int num_args);
35+
char *pgduckdb_get_viewdef(const ViewStmt *stmt, const char *postgres_schema_name, const char *view_name,
36+
const char *duckdb_query_string);
3437

3538
extern bool outermost_query;

include/pgduckdb/utility/rename_ruleutils.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
#include "postgres.h"
4+
#include "fmgr.h"
5+
36
/*
47
* This file contains the renaming of the functions exposed by
58
* vendor/pg_ruleutils.h functions to avoid conflicts with the PostgreSQL
@@ -29,3 +32,24 @@
2932
*/
3033
#define generate_qualified_relation_name pgduckdb_relation_name
3134
#define generate_relation_name(relid, namespaces) pgduckdb_relation_name(relid)
35+
36+
#define declare_pgduckdb_ruleutils_function(original_name) extern Datum pgduckdb_##original_name(PG_FUNCTION_ARGS);
37+
38+
#define pg_get_viewdef pgduckdb_pg_get_viewdef
39+
#define pg_get_viewdef_ext pgduckdb_pg_get_viewdef_ext
40+
#define pg_get_viewdef_wrap pgduckdb_pg_get_viewdef_wrap
41+
#define pg_get_viewdef_name pgduckdb_pg_get_viewdef_name
42+
#define pg_get_viewdef_name_ext pgduckdb_pg_get_viewdef_name_ext
43+
#define pg_get_triggerdef pgduckdb_pg_get_triggerdef
44+
#define pg_get_triggerdef_ext pgduckdb_pg_get_triggerdef_ext
45+
#define pg_get_indexdef_name pgduckdb_pg_get_indexdef_name
46+
#define pg_get_indexdef_name_ext pgduckdb_pg_get_indexdef_name_ext
47+
declare_pgduckdb_ruleutils_function(pg_get_viewdef);
48+
declare_pgduckdb_ruleutils_function(pg_get_viewdef_ext);
49+
declare_pgduckdb_ruleutils_function(pg_get_viewdef_wrap);
50+
declare_pgduckdb_ruleutils_function(pg_get_viewdef_name);
51+
declare_pgduckdb_ruleutils_function(pg_get_viewdef_name_ext);
52+
declare_pgduckdb_ruleutils_function(pg_get_triggerdef);
53+
declare_pgduckdb_ruleutils_function(pg_get_triggerdef_ext);
54+
declare_pgduckdb_ruleutils_function(pg_get_indexdef);
55+
declare_pgduckdb_ruleutils_function(pg_get_indexdef_ext);

sql/pg_duckdb--0.3.0--1.0.0.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,3 +781,9 @@ LANGUAGE C AS 'MODULE_PATHNAME', 'pgduckdb_create_azure_secret';
781781
ALTER TABLE duckdb.extensions ADD COLUMN repository TEXT NOT NULL DEFAULT 'core';
782782
ALTER TABLE duckdb.extensions RENAME COLUMN enabled TO autoload;
783783
ALTER TABLE duckdb.extensions ALTER COLUMN autoload SET NOT NULL;
784+
785+
CREATE FUNCTION duckdb.view(dbname text, schema text, view_name text, query text)
786+
RETURNS SETOF duckdb.row
787+
SET search_path = pg_catalog, pg_temp
788+
AS 'MODULE_PATHNAME', 'duckdb_only_function'
789+
LANGUAGE C;

0 commit comments

Comments
 (0)