From 67683d32a4aaa1302813ff46afe697695ae53e9f Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:51:15 -0500 Subject: [PATCH] feat(trino): compile timestamp types with scale --- ibis/backends/base/sql/alchemy/__init__.py | 4 ++- ibis/backends/tests/test_client.py | 36 ++++++++++++++++++++++ ibis/backends/trino/tests/conftest.py | 14 +++++++++ ibis/tests/benchmarks/test_benchmarks.py | 11 +++++-- 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/ibis/backends/base/sql/alchemy/__init__.py b/ibis/backends/base/sql/alchemy/__init__.py index 980dbaccadff..51743076698e 100644 --- a/ibis/backends/base/sql/alchemy/__init__.py +++ b/ibis/backends/base/sql/alchemy/__init__.py @@ -242,7 +242,9 @@ def _get_insert_method(self, expr): def _columns_from_schema(self, name: str, schema: sch.Schema) -> list[sa.Column]: return [ - sa.Column(colname, to_sqla_type(dtype), nullable=dtype.nullable) + sa.Column( + colname, to_sqla_type(self.con.dialect, dtype), nullable=dtype.nullable + ) for colname, dtype in zip(schema.names, schema.types) ] diff --git a/ibis/backends/tests/test_client.py b/ibis/backends/tests/test_client.py index 3aeb3192c04c..48157f33e703 100644 --- a/ibis/backends/tests/test_client.py +++ b/ibis/backends/tests/test_client.py @@ -2,6 +2,7 @@ import os import platform import re +import string import numpy as np import pandas as pd @@ -875,3 +876,38 @@ def test_get_backend(con, alltypes, monkeypatch): assert ibis.get_backend() is con expr = ibis.literal(1) + 2 assert ibis.get_backend(expr) is con + + +@pytest.mark.notyet( + [ + "bigquery", + "dask", + "datafusion", + "duckdb", + "impala", + "mssql", + "mysql", + "pandas", + "polars", + "postgres", + "pyspark", + "sqlite", + ], + reason="backend doesn't support timestamp with scale parameter", +) +@pytest.mark.notimpl(["clickhouse"], reason="create table isn't implemented") +@pytest.mark.notimpl( + ["snowflake"], reason="scale not implemented in ibis's snowflake backend" +) +def test_create_table_timestamp(con): + schema = ibis.schema( + dict(zip(string.ascii_letters, map("timestamp({:d})".format, range(10)))) + ) + name = f"timestamp_scale_{guid()}" + con.create_table(name, schema=schema, force=True) + try: + rows = con.raw_sql(f"DESCRIBE {name}").fetchall() + result = ibis.schema((name, typ) for name, typ, *_ in rows) + assert result == schema + finally: + con.drop_table(name, force=True) diff --git a/ibis/backends/trino/tests/conftest.py b/ibis/backends/trino/tests/conftest.py index 66d91facab3f..95fbd4d44dde 100644 --- a/ibis/backends/trino/tests/conftest.py +++ b/ibis/backends/trino/tests/conftest.py @@ -103,6 +103,20 @@ def _load_data(data_dir: Path, script_dir: Path, **_: Any) -> None: "INSERT INTO map VALUES (MAP(ARRAY['d', 'e', 'f'], ARRAY[4, 5, 6]))" ) ) + c.execute(sa.text("DROP TABLE IF EXISTS ts")) + c.execute( + sa.text( + "CREATE TABLE ts (x TIMESTAMP(3), y TIMESTAMP(6), z TIMESTAMP(9))" + ) + ) + c.execute( + sa.text( + "INSERT INTO ts VALUES " + "(TIMESTAMP '2023-01-07 13:20:05.561', " + " TIMESTAMP '2023-01-07 13:20:05.561021', " + " TIMESTAMP '2023-01-07 13:20:05.561000231')" + ) + ) @staticmethod def connect(data_directory: Path): diff --git a/ibis/tests/benchmarks/test_benchmarks.py b/ibis/tests/benchmarks/test_benchmarks.py index b9da46117c3f..721b7a257df6 100644 --- a/ibis/tests/benchmarks/test_benchmarks.py +++ b/ibis/tests/benchmarks/test_benchmarks.py @@ -7,6 +7,7 @@ import numpy as np import pandas as pd import pytest +import sqlalchemy as sa from packaging.version import parse as vparse import ibis @@ -188,7 +189,10 @@ def test_compile(benchmark, module, expr_fn, t, base, large_expr): pytest.skip(str(e)) else: expr = expr_fn(t, base, large_expr) - benchmark(mod.compile, expr) + try: + benchmark(mod.compile, expr) + except sa.exc.NoSuchModuleError as e: + pytest.skip(str(e)) @pytest.fixture(scope="module") @@ -691,7 +695,10 @@ def test_compile_with_drops( except (AttributeError, ImportError) as e: pytest.skip(str(e)) else: - benchmark(mod.compile, expr) + try: + benchmark(mod.compile, expr) + except sa.exc.NoSuchModuleError as e: + pytest.skip(str(e)) def test_repr_join(benchmark, customers, orders, orders_items, products):