Skip to content

Commit

Permalink
Provide support for Postgres-specific ATTACH options
Browse files Browse the repository at this point in the history
  • Loading branch information
jwills committed Dec 14, 2023
1 parent 439a328 commit 5dccaa2
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
23 changes: 16 additions & 7 deletions dbt/adapters/duckdb/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

@dataclass
class Attachment(dbtClassMixin):
# The path to the database to be attached (may be a URL)
# The path to the database to be attached (may be a URL or Postgres dsn)
path: str

# Any other options for the attachment path (e.g., the Postgres attachment type has
# source_schema, sink_schema, and overwrite options)
options: Optional[Dict[str, Any]] = None

# The type of the attached database (defaults to duckdb, but may be supported by an extension)
type: Optional[str] = None

Expand All @@ -29,16 +33,21 @@ class Attachment(dbtClassMixin):
read_only: bool = False

def to_sql(self) -> str:
base = f"ATTACH '{self.path}'"
if self.options:
opts = ", ".join([f"{key} = '{value}'" for key, value in self.options.items()])
base = f"ATTACH ('{self.path}', {opts})"
else:
base = f"ATTACH '{self.path}'"
if self.alias:
base += f" AS {self.alias}"
options = []

type_options = []
if self.type:
options.append(f"TYPE {self.type}")
type_options.append(f"TYPE {self.type}")
if self.read_only:
options.append("READ_ONLY")
if options:
joined = ", ".join(options)
type_options.append("READ_ONLY")
if type_options:
joined = ", ".join(type_options)
base += f" ({joined})"
return base

Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ def test_load_aws_creds(mock_session_class):

def test_attachments():
creds = DuckDBCredentials()
opts = {"source_schema": "public", "sink_schema": "snk"}
creds.attach = [
{"path": "/tmp/f1234.db"},
{"path": "/tmp/g1234.db", "alias": "g"},
{"path": "/tmp/h5678.db", "read_only": 1},
{"path": "/tmp/i9101.db", "type": "sqlite"},
{"path": "/tmp/jklm.db", "alias": "jk", "read_only": 1, "type": "sqlite"},
{"path": "dbname=prod host=127.0.0.1 user=postgres", "type": "postgres"},
{"path": "dbname=postgres", "options": opts, "alias": "pg"}
]

expected_sql = [
Expand All @@ -54,6 +57,8 @@ def test_attachments():
"ATTACH '/tmp/h5678.db' (READ_ONLY)",
"ATTACH '/tmp/i9101.db' (TYPE sqlite)",
"ATTACH '/tmp/jklm.db' AS jk (TYPE sqlite, READ_ONLY)",
"ATTACH 'dbname=prod host=127.0.0.1 user=postgres' (TYPE postgres)",
"ATTACH ('dbname=postgres', source_schema = 'public', sink_schema = 'snk') AS pg"
]

for i, a in enumerate(creds.attach):
Expand Down

0 comments on commit 5dccaa2

Please sign in to comment.