Skip to content

Commit

Permalink
Fix table dropping in non-default MotherDuck database
Browse files Browse the repository at this point in the history
  • Loading branch information
JelteF committed Oct 12, 2024
1 parent 73192c5 commit 927d340
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
1 change: 1 addition & 0 deletions include/pgduckdb/pgduckdb_ruleutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
char *pgduckdb_relation_name(Oid relid);
char *pgduckdb_function_name(Oid function_oid);
char *pgduckdb_get_tabledef(Oid relation_id);
const char *pgduckdb_db_and_schema(const char *postgres_schema_name, bool is_duckdb_table);
14 changes: 8 additions & 6 deletions src/pgduckdb_ddl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,12 @@ duckdb_drop_trigger(PG_FUNCTION_ARGS) {
int ret = SPI_exec(R"(
DELETE FROM duckdb.tables
USING (
SELECT objid, object_name, object_identity
SELECT objid, schema_name, object_name
FROM pg_catalog.pg_event_trigger_dropped_objects()
WHERE object_type = 'table'
) objs
WHERE relid = objid
RETURNING objs.object_identity
RETURNING objs.schema_name, objs.object_name
)",
0);

Expand Down Expand Up @@ -346,9 +346,11 @@ duckdb_drop_trigger(PG_FUNCTION_ARGS) {
}
HeapTuple tuple = SPI_tuptable->vals[proc];

char *object_identity = SPI_getvalue(tuple, SPI_tuptable->tupdesc, 1);
// TODO: Handle std::string creation in a safe way for allocation failures
pgduckdb::DuckDBQueryOrThrow(*connection, "DROP TABLE IF EXISTS " + std::string(object_identity));
char *postgres_schema_name = SPI_getvalue(tuple, SPI_tuptable->tupdesc, 1);
char *table_name = SPI_getvalue(tuple, SPI_tuptable->tupdesc, 2);
char *drop_query = psprintf("DROP TABLE %s.%s", pgduckdb_db_and_schema(postgres_schema_name, true),
quote_identifier(table_name));
pgduckdb::DuckDBQueryOrThrow(*connection, drop_query);
}
}

Expand Down Expand Up @@ -392,7 +394,7 @@ duckdb_drop_trigger(PG_FUNCTION_ARGS) {
}
char *table_name = SPI_getvalue(tuple, SPI_tuptable->tupdesc, 2);
pgduckdb::DuckDBQueryOrThrow(*connection,
std::string("DROP TABLE IF EXISTS pg_temp.main.") + quote_identifier(table_name));
std::string("DROP TABLE pg_temp.main.") + quote_identifier(table_name));
temporary_duckdb_tables.erase(relid);
}

Expand Down
28 changes: 19 additions & 9 deletions src/pgduckdb_ruleutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ pgduckdb_function_name(Oid function_oid) {
return psprintf("system.main.%s", quote_identifier(func_name));
}

static List *
/*
* Given a postgres schema name, this returns a list of two elements: the first
* is the DuckDB database name and the second is the duckdb schema name. These
* are not escaped yet.
*/
List *
GetDuckdbCatalogAndSchema(const char *postgres_schema_name) {
if (strncmp("ddb$", postgres_schema_name, 4) != 0) {
auto dbname = pgduckdb::DuckDBManager::Get().GetDefaultDBName().c_str();
Expand Down Expand Up @@ -79,19 +84,22 @@ GetDuckdbCatalogAndSchema(const char *postgres_schema_name) {
return list_make2(db_name.data, schema_name.data);
}

static const char *
DuckdbCatalogAndSchemaString(Form_pg_class relation) {
if (relation->relam == pgduckdb::DuckdbTableAmOid() && relation->relpersistence == RELPERSISTENCE_TEMP) {
/*
* Returns the fully qualified DuckDB database and schema. The schema and
* database are quoted if necessary.
*/
const char *
pgduckdb_db_and_schema(const char *postgres_schema_name, bool is_duckdb_table) {
if (is_duckdb_table && strcmp("pg_temp", postgres_schema_name) == 0) {
return "pg_temp.main";
}

const char *postgres_schema_name = get_namespace_name_or_temp(relation->relnamespace);
const char *db_name;
const char *schema_name;
if (relation->relam == pgduckdb::DuckdbTableAmOid()) {
if (is_duckdb_table) {
List *db_and_schema = GetDuckdbCatalogAndSchema(postgres_schema_name);
db_name = (const char *)linitial(db_and_schema);
schema_name = (const char *)lsecond(db_and_schema);
return psprintf("%s.%s", quote_identifier(db_name), quote_identifier(schema_name));
} else {
db_name = "pgduckdb";
schema_name = postgres_schema_name;
Expand All @@ -112,7 +120,8 @@ pgduckdb_relation_name(Oid relation_oid) {
elog(ERROR, "cache lookup failed for relation %u", relation_oid);
Form_pg_class relation = (Form_pg_class)GETSTRUCT(tp);
const char *relname = NameStr(relation->relname);
const char *db_and_schema = DuckdbCatalogAndSchemaString(relation);
const char *postgres_schema_name = get_namespace_name_or_temp(relation->relnamespace);
const char *db_and_schema = pgduckdb_db_and_schema(postgres_schema_name, pgduckdb::IsDuckdbTable(relation));

char *result = psprintf("%s.%s", db_and_schema, quote_identifier(relname));

Expand All @@ -137,7 +146,8 @@ char *
pgduckdb_get_tabledef(Oid relation_oid) {
Relation relation = relation_open(relation_oid, AccessShareLock);
const char *relation_name = pgduckdb_relation_name(relation_oid);
const char *db_and_schema = DuckdbCatalogAndSchemaString(relation->rd_rel);
const char *postgres_schema_name = get_namespace_name_or_temp(relation->rd_rel->relnamespace);
const char *db_and_schema = pgduckdb_db_and_schema(postgres_schema_name, pgduckdb::IsDuckdbTable(relation));

StringInfoData buffer;
initStringInfo(&buffer);
Expand Down

0 comments on commit 927d340

Please sign in to comment.