Skip to content

Commit 7a9d086

Browse files
committed
refactor(builder): share dialect and column helpers
1 parent 3c87c06 commit 7a9d086

5 files changed

Lines changed: 53 additions & 41 deletions

File tree

sqlspec/builder/_base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from typing_extensions import Self
2121

2222
from sqlspec.builder._locking import register_lock_generator
23+
from sqlspec.builder._parsing_utils import _resolve_dialect
2324
from sqlspec.builder._vector_distance import has_vector_distance_ancestor
2425
from sqlspec.core import (
2526
SQL,
@@ -647,7 +648,7 @@ def build(self, dialect: DialectType = None) -> "BuiltQuery":
647648
err_msg = f"Error generating SQL from expression: {e!s}"
648649
self._raise_builder_error(err_msg, e)
649650

650-
return BuiltQuery(sql=sql_string, parameters=self._parameters.copy(), dialect=dialect or self.dialect)
651+
return BuiltQuery(sql=sql_string, parameters=self._parameters.copy(), dialect=_resolve_dialect(dialect, self.dialect))
651652

652653
def to_sql(self, show_parameters: bool = False, dialect: DialectType = None) -> str:
653654
"""Return SQL string with optional parameter substitution.
@@ -988,7 +989,7 @@ def build_static_expression(
988989
identify = self._should_identify(target_dialect)
989990
sql_string = expr.sql(dialect=target_dialect, pretty=True, identify=identify)
990991
return BuiltQuery(
991-
sql=sql_string, parameters=parameters.copy() if parameters else {}, dialect=dialect or self.dialect
992+
sql=sql_string, parameters=parameters.copy() if parameters else {}, dialect=_resolve_dialect(dialect, self.dialect)
992993
)
993994

994995

sqlspec/builder/_factory.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@
4444
from sqlspec.builder._join import JoinBuilder, create_join_builder
4545
from sqlspec.builder._merge import Merge
4646
from sqlspec.builder._parsing_utils import (
47+
_coerce_column,
4748
_normalize_order_by,
4849
_normalize_partition_by,
50+
_resolve_dialect,
4951
extract_expression,
5052
to_expression,
5153
)
@@ -283,7 +285,7 @@ def __call__(self, statement: str, dialect: DialectType = None) -> "Any":
283285
"""
284286

285287
try:
286-
parsed_expr = sqlglot.parse_one(statement, read=dialect or self.dialect)
288+
parsed_expr = sqlglot.parse_one(statement, read=_resolve_dialect(dialect, self.dialect))
287289
except Exception as e:
288290
msg = f"Failed to parse SQL: {e}"
289291
raise SQLBuilderError(msg) from e
@@ -300,7 +302,7 @@ def __call__(self, statement: str, dialect: DialectType = None) -> "Any":
300302
if actual_type_str == "SELECT" or (
301303
actual_type_str == "WITH" and parsed_expr.this and isinstance(parsed_expr.this, exp.Select)
302304
):
303-
builder = Select(dialect=dialect or self.dialect)
305+
builder = Select(dialect=_resolve_dialect(dialect, self.dialect))
304306
builder.set_expression(parsed_expr)
305307
return builder
306308

@@ -317,7 +319,7 @@ def __call__(self, statement: str, dialect: DialectType = None) -> "Any":
317319
def select(
318320
self, *columns_or_sql: Union[str, exp.Expr, Column, "SQL", "Case"], dialect: DialectType = None
319321
) -> "Select":
320-
builder_dialect = dialect or self.dialect
322+
builder_dialect = _resolve_dialect(dialect, self.dialect)
321323
if len(columns_or_sql) == 1 and isinstance(columns_or_sql[0], str):
322324
sql_candidate = columns_or_sql[0].strip()
323325
if self._looks_like_sql(sql_candidate):
@@ -337,7 +339,7 @@ def select(
337339
return select_builder
338340

339341
def insert(self, table_or_sql: str | None = None, dialect: DialectType = None) -> "Insert":
340-
builder_dialect = dialect or self.dialect
342+
builder_dialect = _resolve_dialect(dialect, self.dialect)
341343
builder = Insert(dialect=builder_dialect)
342344
if table_or_sql:
343345
if self._looks_like_sql(table_or_sql):
@@ -355,7 +357,7 @@ def insert(self, table_or_sql: str | None = None, dialect: DialectType = None) -
355357
return builder
356358

357359
def update(self, table_or_sql: str | None = None, dialect: DialectType = None) -> "Update":
358-
builder_dialect = dialect or self.dialect
360+
builder_dialect = _resolve_dialect(dialect, self.dialect)
359361
builder = Update(dialect=builder_dialect)
360362
if table_or_sql:
361363
if self._looks_like_sql(table_or_sql):
@@ -372,7 +374,7 @@ def update(self, table_or_sql: str | None = None, dialect: DialectType = None) -
372374
return builder
373375

374376
def delete(self, table_or_sql: str | None = None, dialect: DialectType = None) -> "Delete":
375-
builder_dialect = dialect or self.dialect
377+
builder_dialect = _resolve_dialect(dialect, self.dialect)
376378
if table_or_sql and self._looks_like_sql(table_or_sql):
377379
builder = Delete(dialect=builder_dialect)
378380
parsed_expr = self._parse_sql_expression(table_or_sql, builder_dialect)
@@ -388,7 +390,7 @@ def delete(self, table_or_sql: str | None = None, dialect: DialectType = None) -
388390
return Delete(table_or_sql, dialect=builder_dialect) if table_or_sql else Delete(dialect=builder_dialect)
389391

390392
def merge(self, table_or_sql: str | None = None, dialect: DialectType = None) -> "Merge":
391-
builder_dialect = dialect or self.dialect
393+
builder_dialect = _resolve_dialect(dialect, self.dialect)
392394
if table_or_sql and self._looks_like_sql(table_or_sql):
393395
builder = Merge(dialect=builder_dialect)
394396
parsed_expr = self._parse_sql_expression(table_or_sql, builder_dialect)
@@ -427,7 +429,7 @@ def explain(
427429
Returns:
428430
Explain builder for further configuration
429431
"""
430-
builder_dialect = dialect or self.dialect
432+
builder_dialect = _resolve_dialect(dialect, self.dialect)
431433

432434
fmt = None
433435
if format is not None:
@@ -463,7 +465,7 @@ def upsert(self, table: str, dialect: DialectType = None) -> "Merge | Insert":
463465
Returns:
464466
MERGE builder for supported databases, INSERT builder otherwise
465467
"""
466-
builder_dialect = dialect or self.dialect
468+
builder_dialect = _resolve_dialect(dialect, self.dialect)
467469
dialect_str = str(builder_dialect).lower() if builder_dialect else None
468470

469471
merge_supported = {"postgres", "postgresql", "oracle", "bigquery"}
@@ -483,7 +485,7 @@ def create_table(self, table_name: str, dialect: DialectType = None) -> "CreateT
483485
Returns:
484486
CreateTable builder instance
485487
"""
486-
return CreateTable(table_name, dialect=dialect or self.dialect)
488+
return CreateTable(table_name, dialect=_resolve_dialect(dialect, self.dialect))
487489

488490
def create_table_as_select(self, dialect: DialectType = None) -> "CreateTableAsSelect":
489491
"""Create a CREATE TABLE AS SELECT builder.
@@ -494,7 +496,7 @@ def create_table_as_select(self, dialect: DialectType = None) -> "CreateTableAsS
494496
Returns:
495497
CreateTableAsSelect builder instance
496498
"""
497-
return CreateTableAsSelect(dialect=dialect or self.dialect)
499+
return CreateTableAsSelect(dialect=_resolve_dialect(dialect, self.dialect))
498500

499501
def create_view(self, view_name: str, dialect: DialectType = None) -> "CreateView":
500502
"""Create a CREATE VIEW builder.
@@ -506,7 +508,7 @@ def create_view(self, view_name: str, dialect: DialectType = None) -> "CreateVie
506508
Returns:
507509
CreateView builder instance
508510
"""
509-
return CreateView(view_name, dialect=dialect or self.dialect)
511+
return CreateView(view_name, dialect=_resolve_dialect(dialect, self.dialect))
510512

511513
def create_materialized_view(self, view_name: str, dialect: DialectType = None) -> "CreateMaterializedView":
512514
"""Create a CREATE MATERIALIZED VIEW builder.
@@ -518,7 +520,7 @@ def create_materialized_view(self, view_name: str, dialect: DialectType = None)
518520
Returns:
519521
CreateMaterializedView builder instance
520522
"""
521-
return CreateMaterializedView(view_name, dialect=dialect or self.dialect)
523+
return CreateMaterializedView(view_name, dialect=_resolve_dialect(dialect, self.dialect))
522524

523525
def create_index(self, index_name: str, dialect: DialectType = None) -> "CreateIndex":
524526
"""Create a CREATE INDEX builder.
@@ -530,7 +532,7 @@ def create_index(self, index_name: str, dialect: DialectType = None) -> "CreateI
530532
Returns:
531533
CreateIndex builder instance
532534
"""
533-
return CreateIndex(index_name, dialect=dialect or self.dialect)
535+
return CreateIndex(index_name, dialect=_resolve_dialect(dialect, self.dialect))
534536

535537
def create_schema(self, schema_name: str, dialect: DialectType = None) -> "CreateSchema":
536538
"""Create a CREATE SCHEMA builder.
@@ -542,7 +544,7 @@ def create_schema(self, schema_name: str, dialect: DialectType = None) -> "Creat
542544
Returns:
543545
CreateSchema builder instance
544546
"""
545-
return CreateSchema(schema_name, dialect=dialect or self.dialect)
547+
return CreateSchema(schema_name, dialect=_resolve_dialect(dialect, self.dialect))
546548

547549
def drop_table(self, table_name: str, dialect: DialectType = None) -> "DropTable":
548550
"""Create a DROP TABLE builder.
@@ -554,7 +556,7 @@ def drop_table(self, table_name: str, dialect: DialectType = None) -> "DropTable
554556
Returns:
555557
DropTable builder instance
556558
"""
557-
return DropTable(table_name, dialect=dialect or self.dialect)
559+
return DropTable(table_name, dialect=_resolve_dialect(dialect, self.dialect))
558560

559561
def drop_view(self, view_name: str, dialect: DialectType = None) -> "DropView":
560562
"""Create a DROP VIEW builder.
@@ -566,7 +568,7 @@ def drop_view(self, view_name: str, dialect: DialectType = None) -> "DropView":
566568
Returns:
567569
DropView builder instance
568570
"""
569-
return DropView(view_name, dialect=dialect or self.dialect)
571+
return DropView(view_name, dialect=_resolve_dialect(dialect, self.dialect))
570572

571573
def drop_materialized_view(self, view_name: str, dialect: DialectType = None) -> "DropMaterializedView":
572574
"""Create a DROP MATERIALIZED VIEW builder.
@@ -578,7 +580,7 @@ def drop_materialized_view(self, view_name: str, dialect: DialectType = None) ->
578580
Returns:
579581
DropMaterializedView builder instance
580582
"""
581-
return DropMaterializedView(view_name, dialect=dialect or self.dialect)
583+
return DropMaterializedView(view_name, dialect=_resolve_dialect(dialect, self.dialect))
582584

583585
def drop_index(self, index_name: str, dialect: DialectType = None) -> "DropIndex":
584586
"""Create a DROP INDEX builder.
@@ -590,7 +592,7 @@ def drop_index(self, index_name: str, dialect: DialectType = None) -> "DropIndex
590592
Returns:
591593
DropIndex builder instance
592594
"""
593-
return DropIndex(index_name, dialect=dialect or self.dialect)
595+
return DropIndex(index_name, dialect=_resolve_dialect(dialect, self.dialect))
594596

595597
def drop_schema(self, schema_name: str, dialect: DialectType = None) -> "DropSchema":
596598
"""Create a DROP SCHEMA builder.
@@ -602,7 +604,7 @@ def drop_schema(self, schema_name: str, dialect: DialectType = None) -> "DropSch
602604
Returns:
603605
DropSchema builder instance
604606
"""
605-
return DropSchema(schema_name, dialect=dialect or self.dialect)
607+
return DropSchema(schema_name, dialect=_resolve_dialect(dialect, self.dialect))
606608

607609
def alter_table(self, table_name: str, dialect: DialectType = None) -> "AlterTable":
608610
"""Create an ALTER TABLE builder.
@@ -614,7 +616,7 @@ def alter_table(self, table_name: str, dialect: DialectType = None) -> "AlterTab
614616
Returns:
615617
AlterTable builder instance
616618
"""
617-
return AlterTable(table_name, dialect=dialect or self.dialect)
619+
return AlterTable(table_name, dialect=_resolve_dialect(dialect, self.dialect))
618620

619621
def rename_table(self, old_name: str, dialect: DialectType = None) -> "RenameTable":
620622
"""Create a RENAME TABLE builder.
@@ -626,7 +628,7 @@ def rename_table(self, old_name: str, dialect: DialectType = None) -> "RenameTab
626628
Returns:
627629
RenameTable builder instance
628630
"""
629-
return RenameTable(old_name, dialect=dialect or self.dialect)
631+
return RenameTable(old_name, dialect=_resolve_dialect(dialect, self.dialect))
630632

631633
def comment_on(self, dialect: DialectType = None) -> "CommentOn":
632634
"""Create a COMMENT ON builder.
@@ -637,7 +639,7 @@ def comment_on(self, dialect: DialectType = None) -> "CommentOn":
637639
Returns:
638640
CommentOn builder instance
639641
"""
640-
return CommentOn(dialect=dialect or self.dialect)
642+
return CommentOn(dialect=_resolve_dialect(dialect, self.dialect))
641643

642644
def copy_from(
643645
self,
@@ -650,7 +652,7 @@ def copy_from(
650652
) -> SQL:
651653
"""Build a COPY ... FROM statement."""
652654

653-
effective_dialect = dialect or self.dialect
655+
effective_dialect = _resolve_dialect(dialect, self.dialect)
654656
return build_copy_from_statement(table, source, columns=columns, options=options, dialect=effective_dialect)
655657

656658
def copy_to(
@@ -664,7 +666,7 @@ def copy_to(
664666
) -> SQL:
665667
"""Build a COPY ... TO statement."""
666668

667-
effective_dialect = dialect or self.dialect
669+
effective_dialect = _resolve_dialect(dialect, self.dialect)
668670
return build_copy_to_statement(table, target, columns=columns, options=options, dialect=effective_dialect)
669671

670672
def copy(
@@ -1182,7 +1184,7 @@ def rollup(*columns: str | exp.Expr) -> FunctionExpression:
11821184
Returns:
11831185
ROLLUP expression.
11841186
"""
1185-
column_exprs = [exp.column(col) if isinstance(col, str) else col for col in columns]
1187+
column_exprs = [_coerce_column(col) for col in columns]
11861188
return FunctionExpression(exp.Rollup(expressions=column_exprs))
11871189

11881190
@staticmethod
@@ -1195,7 +1197,7 @@ def cube(*columns: str | exp.Expr) -> FunctionExpression:
11951197
Returns:
11961198
CUBE expression.
11971199
"""
1198-
column_exprs = [exp.column(col) if isinstance(col, str) else col for col in columns]
1200+
column_exprs = [_coerce_column(col) for col in columns]
11991201
return FunctionExpression(exp.Cube(expressions=column_exprs))
12001202

12011203
@staticmethod
@@ -1261,7 +1263,7 @@ def concat(*expressions: str | exp.Expr) -> StringExpression:
12611263
Returns:
12621264
CONCAT expression.
12631265
"""
1264-
exprs = [exp.column(expr) if isinstance(expr, str) else expr for expr in expressions]
1266+
exprs = [_coerce_column(expr) for expr in expressions]
12651267
return StringExpression(exp.Concat(expressions=exprs))
12661268

12671269
@staticmethod
@@ -1408,7 +1410,7 @@ def coalesce(*expressions: str | exp.Expr) -> ConversionExpression:
14081410
Returns:
14091411
COALESCE expression.
14101412
"""
1411-
exprs = [exp.column(expr) if isinstance(expr, str) else expr for expr in expressions]
1413+
exprs = [_coerce_column(expr) for expr in expressions]
14121414
return ConversionExpression(exp.Coalesce(expressions=exprs))
14131415

14141416
@staticmethod

sqlspec/builder/_merge.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from sqlspec.builder._base import QueryBuilder
2020
from sqlspec.builder._explain import ExplainMixin
21-
from sqlspec.builder._parsing_utils import extract_sql_object_expression
21+
from sqlspec.builder._parsing_utils import _coerce_column, _resolve_dialect, extract_sql_object_expression
2222
from sqlspec.builder._select import is_explicitly_quoted
2323
from sqlspec.core import SQLResult
2424
from sqlspec.exceptions import DialectNotSupportedError, SQLBuilderError
@@ -137,7 +137,7 @@ def _is_column_reference(self, value: str) -> bool:
137137
return False
138138

139139
def _process_assignment(self, target_column: str, value: Any) -> exp.Expr:
140-
column_identifier = exp.column(target_column) if isinstance(target_column, str) else target_column
140+
column_identifier = _coerce_column(target_column)
141141

142142
if has_expression_and_sql(value):
143143
value_expr = extract_sql_object_expression(value, builder=self)
@@ -724,7 +724,7 @@ def build(self, dialect: "DialectType" = None) -> "Any":
724724
Built statement object.
725725
"""
726726
self._validate_dialect_support()
727-
target_dialect = dialect or self.dialect
727+
target_dialect = _resolve_dialect(dialect, self.dialect)
728728
if isinstance(target_dialect, str):
729729
dialect_name = target_dialect
730730
elif isinstance(target_dialect, type):

sqlspec/builder/_parsing_utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,11 @@ def _normalize_order_by(order_by: str | list[str] | exp.Expr | None) -> exp.Orde
398398
if isinstance(order_by, exp.Expr):
399399
return exp.Order(expressions=[order_by])
400400
return None
401+
402+
403+
def _coerce_column(value: str | exp.Expr) -> exp.Expr:
404+
return exp.column(value) if isinstance(value, str) else value
405+
406+
407+
def _resolve_dialect(dialect: "DialectType | None", default: "DialectType | None") -> "DialectType | None":
408+
return dialect or default

sqlspec/builder/_select.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sqlspec.builder._join import JoinClauseMixin, _attach_as_of_version
1919
from sqlspec.builder._parsing_utils import (
2020
_PARAMETER_VALIDATOR,
21+
_coerce_column,
2122
extract_column_name,
2223
extract_expression,
2324
parse_column_expression,
@@ -222,7 +223,7 @@ def __call__(self, *function_args: Any) -> "WindowFunctionBuilder":
222223
return self
223224

224225
def partition_by(self, *columns: str | exp.Expr) -> "WindowFunctionBuilder":
225-
self._partition_by = [exp.column(column) if isinstance(column, str) else column for column in columns]
226+
self._partition_by = [_coerce_column(column) for column in columns]
226227
return self
227228

228229
def order_by(self, *columns: str | exp.Expr) -> "WindowFunctionBuilder":
@@ -357,24 +358,24 @@ def group_by(self, *columns: str | exp.Expr) -> Self:
357358
return cast("Self", builder)
358359

359360
for column in columns:
360-
column_expr = exp.column(column) if isinstance(column, str) else column
361+
column_expr = _coerce_column(column)
361362
select_expr = select_expr.group_by(column_expr, copy=False)
362363
builder.set_expression(select_expr)
363364
return cast("Self", builder)
364365

365366
def group_by_rollup(self, *columns: str | exp.Expr) -> Self:
366-
column_exprs = [exp.column(column) if isinstance(column, str) else column for column in columns]
367+
column_exprs = [_coerce_column(column) for column in columns]
367368
rollup_expr = exp.Rollup(expressions=column_exprs)
368369
return self.group_by(rollup_expr)
369370

370371
def group_by_cube(self, *columns: str | exp.Expr) -> Self:
371-
column_exprs = [exp.column(column) if isinstance(column, str) else column for column in columns]
372+
column_exprs = [_coerce_column(column) for column in columns]
372373
cube_expr = exp.Cube(expressions=column_exprs)
373374
return self.group_by(cube_expr)
374375

375376
def group_by_grouping_sets(self, *column_sets: tuple[str, ...] | list[str]) -> Self:
376377
grouping_sets = [
377-
exp.Tuple(expressions=[exp.column(col) if isinstance(col, str) else col for col in column_set])
378+
exp.Tuple(expressions=[_coerce_column(col) for col in column_set])
378379
for column_set in column_sets
379380
]
380381
grouping_expr = exp.GroupingSets(expressions=grouping_sets)
@@ -1053,8 +1054,8 @@ def pivot(
10531054
raise TypeError(msg)
10541055

10551056
agg_name = aggregate_function if isinstance(aggregate_function, str) else aggregate_function.name
1056-
agg_column = exp.column(aggregate_column) if isinstance(aggregate_column, str) else aggregate_column
1057-
pivot_col_expr = exp.column(pivot_column) if isinstance(pivot_column, str) else pivot_column
1057+
agg_column = _coerce_column(aggregate_column)
1058+
pivot_col_expr = _coerce_column(pivot_column)
10581059

10591060
pivot_agg_expr = exp.func(agg_name, agg_column)
10601061

0 commit comments

Comments
 (0)