Skip to content

Commit 5536a75

Browse files
feat: Improve table creation logic and add test for rerunning stats on DuckDB
1 parent a05cc9e commit 5536a75

3 files changed

Lines changed: 68 additions & 19 deletions

File tree

sqlcompare/db/connection.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -152,22 +152,27 @@ def create_table_from_file(self, table_name: str, file_path: str | Path) -> None
152152
raise ValueError(f"Unsupported file type: {suffix}")
153153

154154
tmp = f"tmp_{uuid.uuid4().hex}"
155-
self.conn.execute(text(f"CREATE TABLE {tmp} AS {read_query}"))
156-
cols = [
157-
row[1]
158-
for row in self.conn.execute(text(f"PRAGMA table_info('{tmp}')")).fetchall()
159-
]
160-
exprs = []
161-
for c in cols:
162-
t = self._infer_column_type(tmp, c)
163-
if t == "VARCHAR":
164-
exprs.append(f'"{c}"')
165-
else:
166-
exprs.append(f'CAST("{c}" AS {t}) AS "{c}"')
167-
self.conn.execute(
168-
text(f"CREATE TABLE {table_name} AS SELECT {', '.join(exprs)} FROM {tmp}")
169-
)
170-
self.conn.execute(text(f"DROP TABLE {tmp}"))
155+
try:
156+
self.conn.execute(text(f"CREATE TABLE {tmp} AS {read_query}"))
157+
cols = [
158+
row[1]
159+
for row in self.conn.execute(
160+
text(f"PRAGMA table_info('{tmp}')")
161+
).fetchall()
162+
]
163+
exprs = []
164+
for c in cols:
165+
t = self._infer_column_type(tmp, c)
166+
if t == "VARCHAR":
167+
exprs.append(f'"{c}"')
168+
else:
169+
exprs.append(f'CAST("{c}" AS {t}) AS "{c}"')
170+
self.conn.execute(text(f"DROP TABLE IF EXISTS {table_name}"))
171+
self.conn.execute(
172+
text(f"CREATE TABLE {table_name} AS SELECT {', '.join(exprs)} FROM {tmp}")
173+
)
174+
finally:
175+
self.conn.execute(text(f"DROP TABLE IF EXISTS {tmp}"))
171176

172177
@property
173178
def conn(self) -> Connection:

sqlcompare/stats/runner.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,8 @@ def compare_table_stats(
163163

164164
def prepare_inputs(db: DBConnection) -> None:
165165
if spec_prev.kind == "file" and spec_new.kind == "file":
166-
if connection is None and connection_id == "duckdb:///:memory:":
167-
db.create_table_from_file(table1_name, spec_prev.value)
168-
db.create_table_from_file(table2_name, spec_new.value)
166+
db.create_table_from_file(table1_name, spec_prev.value)
167+
db.create_table_from_file(table2_name, spec_new.value)
169168
materialize_sql_inputs(
170169
db,
171170
previous_spec=spec_prev,

tests/test_stats_comparison.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,51 @@ def test_table_command_with_stats_from_files() -> None:
8383
assert "0 (no change)" in result.output
8484

8585

86+
def test_table_command_with_stats_from_files_can_rerun_on_same_duckdb(
87+
tmp_path, monkeypatch
88+
) -> None:
89+
db_path = tmp_path / "sqlcompare.duckdb"
90+
config_dir = tmp_path / "config"
91+
set_cli_env(
92+
monkeypatch,
93+
config_dir,
94+
"duckdb_test",
95+
f"duckdb:///{db_path}",
96+
schema="analysis_schema",
97+
)
98+
runner = CliRunner()
99+
base = Path(__file__).resolve().parent
100+
prev_path = base / "datasets" / "stats_compare" / "previous.csv"
101+
curr_path = base / "datasets" / "stats_compare" / "current.csv"
102+
103+
first = runner.invoke(
104+
app,
105+
[
106+
"run",
107+
"stats",
108+
str(prev_path),
109+
str(curr_path),
110+
"--connection",
111+
"duckdb_test",
112+
],
113+
)
114+
second = runner.invoke(
115+
app,
116+
[
117+
"run",
118+
"stats",
119+
str(prev_path),
120+
str(curr_path),
121+
"--connection",
122+
"duckdb_test",
123+
],
124+
)
125+
126+
assert first.exit_code == 0, first.output
127+
assert second.exit_code == 0, second.output
128+
assert "already exists" not in second.output.lower()
129+
130+
86131
def test_stats_command_with_inline_sql(tmp_path, monkeypatch) -> None:
87132
db_path = tmp_path / "sqlcompare.duckdb"
88133
seed_duckdb(db_path)

0 commit comments

Comments
 (0)