mirror of
https://github.com/hanzo-ds/connect.git
synced 2026-10-30 20:31:24 +00:00
* sqa dict and alembic work * sqa dialect improvements * import shim * engine shim * implement alembic support * clickhouse dictionary support * compat shim * add alembic to test reqs * integration/unit tests * update readme * update changelog * fix to support sqa 1.4 and 2.x * update readme * add alembic worked example * consolidate duplicate code * add sql parse logic file * cloud quirk reflection fixes * cc_sqalchemy ergonomics * chcsqa prewhere, limit by, lambda chainables * preserve ARRAY JOIN labels, fix Tuple adapt * wording edits, name fixes * linting * linting, use format * simplify docstrings * update migration guide * update migration guide * fix alembic enum render for autogen migrations * fix alembic enum render for nested container types * 1.1.0a1 release prep * preserve CH select modifiers when compiling from ORM-mapped attributes * 1.1.0a2 release prep * address pr comments
94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
import pytest
|
|
from sqlalchemy import Column, MetaData, Table, column, func, select
|
|
from sqlalchemy.dialects import registry
|
|
|
|
# Import sql module so any monkey-patches are installed.
|
|
import clickhouse_connect.cc_sqlalchemy.sql # noqa: F401
|
|
from clickhouse_connect.cc_sqlalchemy import Lambda, dialect_name
|
|
from clickhouse_connect.cc_sqlalchemy.datatypes.sqltypes import Array, String, UInt32
|
|
|
|
dialect = registry.load(dialect_name)()
|
|
metadata = MetaData()
|
|
|
|
data = Table(
|
|
"data",
|
|
metadata,
|
|
Column("id", UInt32),
|
|
Column("nums", Array(UInt32)),
|
|
Column("ks", Array(String)),
|
|
Column("vs", Array(UInt32)),
|
|
)
|
|
|
|
|
|
def compile_sql(stmt):
|
|
return str(stmt.compile(dialect=dialect, compile_kwargs={"literal_binds": True}))
|
|
|
|
|
|
def compile_default(stmt):
|
|
"""Compile with SA's default StrSQLCompiler (no dialect)."""
|
|
return str(stmt.compile(compile_kwargs={"literal_binds": True}))
|
|
|
|
|
|
def _strip_backticks(sql):
|
|
return sql.replace("`", "")
|
|
|
|
|
|
def test_lambda_array_map_single_param():
|
|
stmt = select(func.arrayMap(Lambda("x", column("x") * 2), data.c.nums).label("doubled"))
|
|
sql = compile_sql(stmt)
|
|
assert "arrayMap(" in sql
|
|
assert "x -> " in sql
|
|
assert "x -> x * 2" in _strip_backticks(sql)
|
|
|
|
|
|
def test_lambda_array_filter_comparison_body():
|
|
stmt = select(func.arrayFilter(Lambda("x", column("x") > 0), data.c.nums).label("positives"))
|
|
sql = compile_sql(stmt)
|
|
assert "arrayFilter(" in sql
|
|
assert "x -> " in sql
|
|
assert "x -> x > 0" in _strip_backticks(sql)
|
|
|
|
|
|
def test_lambda_multi_param():
|
|
stmt = select(func.arrayMap(Lambda(["k", "v"], column("v") > 10), data.c.ks, data.c.vs).label("pairs"))
|
|
sql = compile_sql(stmt)
|
|
assert "arrayMap(" in sql
|
|
assert "(k, v) -> " in sql
|
|
assert "(k, v) -> v > 10" in _strip_backticks(sql)
|
|
|
|
|
|
def test_lambda_body_is_func_call():
|
|
stmt = select(func.arrayMap(Lambda("x", func.toString(column("x"))), data.c.nums).label("strs"))
|
|
sql = compile_sql(stmt)
|
|
assert "x -> " in sql
|
|
assert "x -> toString(x)" in _strip_backticks(sql)
|
|
|
|
|
|
def test_lambda_renders_under_both_compilers():
|
|
"""Lambda renders identically under the dialect compiler and the default StrSQLCompiler."""
|
|
stmt = select(func.arrayMap(Lambda("x", column("x") * 2), data.c.nums).label("doubled"))
|
|
dialect_sql = compile_sql(stmt)
|
|
default_sql = compile_default(stmt)
|
|
assert "x -> x * 2" in _strip_backticks(dialect_sql)
|
|
assert "x -> x * 2" in _strip_backticks(default_sql)
|
|
|
|
|
|
def test_lambda_empty_params_raises_value_error():
|
|
with pytest.raises(ValueError):
|
|
Lambda([], column("x"))
|
|
|
|
|
|
def test_lambda_non_string_param_in_list_raises_type_error():
|
|
with pytest.raises(TypeError):
|
|
Lambda([1, 2], column("x"))
|
|
|
|
|
|
def test_lambda_non_string_single_param_raises_type_error():
|
|
with pytest.raises(TypeError):
|
|
Lambda(1, column("x"))
|
|
|
|
|
|
def test_lambda_non_identifier_param_raises_value_error():
|
|
with pytest.raises(ValueError):
|
|
Lambda("x y", column("x"))
|