Skip to content

Commit ba3c113

Browse files
committed
improve behavior of creating/dropping schema
1 parent bdc4102 commit ba3c113

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dbt_sqlite:
2323
# sqlite locks the whole db on writes so anything > 1 won't help
2424
threads: 1
2525

26-
# value of 'database' is arbitrary
26+
# value is arbitrary
2727
database: "database"
2828

2929
# value of 'schema' must be defined in schema_paths below. in most cases,
@@ -33,11 +33,11 @@ dbt_sqlite:
3333
# connect schemas to paths: at least one of these must be 'main'
3434
schemas_and_paths: 'main=/my_project/data/etl.db;dataset=/my_project/data/dataset_v1.db'
3535

36-
# directory where new schemas are created by dbt as new database files
36+
# directory where all *.db files are attached as schema
3737
schema_directory: '/myproject/data/schemas'
3838

3939
# optional: semi-colon separated list of file paths for SQLite extensions to load.
40-
# digesto.so is needed to provide the md5 function needed for snapshots to work.
40+
# digest.so is needed to provide the md5 function needed for snapshots to work.
4141
# see section in README on how to install it
4242
extensions: "/path/to/sqlite-digest/digest.so"
4343

@@ -58,10 +58,9 @@ and schemas.)
5858
so this must be defined in your profile. Other schemas defined in your profile
5959
get attached when database connection is created.
6060

61-
- If dbt needs to create a new schema, it will be created in `schema_directory`.
62-
Dropping a schema results in dropping all its relations but NOT detaching the
63-
database, since this may result in a confusing conflict with the schemas you
64-
defined in your profile.
61+
- If dbt needs to create a new schema, it will be created in `schema_directory`
62+
as `schema_name.db`. Dropping a schema results in dropping all its relations
63+
and detaching the database file from the session.
6564

6665
- Schema names are stored in view definitions, so when you access a non-'main'
6766
database file outside dbt, you'll need to attach it using the same name, or

dbt/adapters/sqlite/connections.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
from contextlib import contextmanager
33
from dataclasses import dataclass
4+
import glob
5+
import os.path
46
import sqlite3
57
from typing import List, Optional, Tuple, Any, Iterable, Dict
68

@@ -65,9 +67,18 @@ def open(cls, connection):
6567

6668
cursor = handle.cursor()
6769

70+
attached = []
6871
for schema in set(schemas_and_paths.keys()) - set(['main']):
6972
path = schemas_and_paths[schema]
7073
cursor.execute(f"attach '{path}' as '{schema}'")
74+
attached.append(schema)
75+
76+
for path in glob.glob(os.path.join(credentials.schema_directory, "*.db")):
77+
schema = os.path.basename(path)[:-3]
78+
if path in schema:
79+
raise DatabaseException(
80+
f"cannot attach schema '{schema}': defined in profile but also exists in schema_directory: {path}")
81+
cursor.execute(f"attach '{path}' as '{schema}'")
7182

7283
# # uncomment these lines to print out SQL: this only happens if statement is successful
7384
# handle.set_trace_callback(print)

dbt/adapters/sqlite/impl.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,10 @@ def timestamp_add_sql(
264264
self, add_to: str, number: int = 1, interval: str = 'hour'
265265
) -> str:
266266
return f"DATETIME({add_to}, '{number} {interval}')"
267+
268+
def drop_schema(self, relation: BaseRelation) -> None:
269+
super().drop_schema(relation)
270+
271+
# never detach main
272+
if relation.schema != 'main':
273+
self.connections.execute(f"DETACH DATABASE {relation.schema}")

dbt/include/sqlite/macros/adapters.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
{# see SQLiteAdapter.list_schemas() #}
44
{% endmacro %}
55

6-
{% macro sqlite__create_schema(database_name, schema_name, auto_begin=False) %}
7-
{% set path = '/'.join(adapter.config.credentials.schema_directory, schema_name, '.db') %}
6+
{% macro sqlite__create_schema(relation, auto_begin=False) %}
7+
{% set path = [ adapter.config.credentials.schema_directory, relation.without_identifier().include(database=False) | string + '.db' ] | join('/') %}
88
{%- call statement('create_schema') -%}
9-
attach database '{{ path }}' as {{ schema_name }}
9+
attach database '{{ path }}' as {{ relation.without_identifier().include(database=False) }}
1010
{%- endcall -%}
1111
{% endmacro %}
1212

1313
{% macro sqlite__drop_schema(relation) -%}
14-
{# drop all tables in the schema, but leave the scgema itself alone. we can't detach 'main' #}
14+
{# drop all tables in the schema; detaching happens in the adapter class #}
1515

1616
{% set relations_in_schema = list_relations_without_caching(relation.without_identifier()) %}
1717

0 commit comments

Comments
 (0)