Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Commit 6db9f66

Browse files
author
Sergey Vasilyev
committed
Move the compiler closer to dialects & databases that it uses & is used in
1 parent e072b35 commit 6db9f66

4 files changed

Lines changed: 63 additions & 61 deletions

File tree

data_diff/databases/base.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
from dataclasses import field
23
from datetime import datetime
34
import math
45
import sys
@@ -15,10 +16,10 @@
1516
from runtype import dataclass
1617
from typing_extensions import Self
1718

18-
from data_diff.queries.compiler import CompileError
19+
from data_diff.abcs.compiler import AbstractCompiler
1920
from data_diff.queries.extras import ApplyFuncAndNormalizeAsString, Checksum, NormalizeAsString
2021
from data_diff.utils import ArithString, is_uuid, join_iter, safezip
21-
from data_diff.queries.api import Expr, Compiler, table, Select, SKIP, Explain, Code, this
22+
from data_diff.queries.api import Expr, table, Select, SKIP, Explain, Code, this
2223
from data_diff.queries.ast_classes import Alias, BinOp, CaseWhen, Cast, Column, Commit, Concat, ConstantTable, Count, \
2324
CreateTable, Cte, \
2425
CurrentTimestamp, DropTable, Func, \
@@ -64,6 +65,65 @@
6465
cv_params = contextvars.ContextVar("params")
6566

6667

68+
class CompileError(Exception):
69+
pass
70+
71+
72+
# TODO: LATER: Resolve the circular imports of databases-compiler-dialects:
73+
# A database uses a compiler to render the SQL query.
74+
# The compiler delegates to a dialect.
75+
# The dialect renders the SQL.
76+
# AS IS: The dialect requires the db to normalize table paths — leading to the back-dependency.
77+
# TO BE: All the tables paths must be pre-normalized before SQL rendering.
78+
# Also: c.database.is_autocommit in render_commit().
79+
# After this, the Compiler can cease referring Database/Dialect at all,
80+
# and be used only as a CompilingContext (a counter/data-bearing class).
81+
# As a result, it becomes low-level util, and the circular dependency auto-resolves.
82+
# Meanwhile, the easy fix is to simply move the Compiler here.
83+
@dataclass
84+
class Compiler(AbstractCompiler):
85+
"""
86+
Compiler bears the context for a single compilation.
87+
88+
There can be multiple compilation per app run.
89+
There can be multiple compilers in one compilation (with varying contexts).
90+
"""
91+
92+
# Database is needed to normalize tables. Dialect is needed for recursive compilations.
93+
# In theory, it is many-to-many relations: e.g. a generic ODBC driver with multiple dialects.
94+
# In practice, we currently bind the dialects to the specific database classes.
95+
database: AbstractDatabase
96+
97+
in_select: bool = False # Compilation runtime flag
98+
in_join: bool = False # Compilation runtime flag
99+
100+
_table_context: List = field(default_factory=list) # List[ITable]
101+
_subqueries: Dict[str, Any] = field(default_factory=dict) # XXX not thread-safe
102+
root: bool = True
103+
104+
_counter: List = field(default_factory=lambda: [0])
105+
106+
@property
107+
def dialect(self) -> AbstractDialect:
108+
return self.database.dialect
109+
110+
# TODO: DEPRECATED: Remove once the dialect is used directly in all places.
111+
def compile(self, elem, params=None) -> str:
112+
return self.dialect.compile(self, elem, params)
113+
114+
def new_unique_name(self, prefix="tmp"):
115+
self._counter[0] += 1
116+
return f"{prefix}{self._counter[0]}"
117+
118+
def new_unique_table_name(self, prefix="tmp") -> DbPath:
119+
self._counter[0] += 1
120+
table_name = f"{prefix}{self._counter[0]}_{'%x'%random.randrange(2**32)}"
121+
return self.database.dialect.parse_table_name(table_name)
122+
123+
def add_table_context(self, *tables: Sequence, **kw) -> Self:
124+
return self.replace(_table_context=self._table_context + list(tables), **kw)
125+
126+
67127
def parse_table_name(t):
68128
return tuple(t.split("."))
69129

data_diff/queries/ast_classes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from data_diff.abcs.database_types import AbstractTable
1111
from data_diff.schema import Schema
1212

13-
from data_diff.queries.compiler import Compiler
1413
from data_diff.queries.base import SKIP, args_as_tuple, SqeletonError
1514
from data_diff.abcs.database_types import DbPath
1615

data_diff/queries/compiler.py

Lines changed: 0 additions & 57 deletions
This file was deleted.

tests/test_query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from data_diff.abcs.database_types import AbstractDatabase, AbstractDialect
55
from data_diff.utils import CaseInsensitiveDict, CaseSensitiveDict
66

7-
from data_diff.queries.compiler import Compiler, CompileError
7+
from data_diff.databases.base import Compiler, CompileError
88
from data_diff.queries.api import outerjoin, cte, when, coalesce
99
from data_diff.queries.ast_classes import Random
1010
from data_diff.queries.api import code, this, table

0 commit comments

Comments
 (0)