From f5490c3347a6ba1f597f68e6b4fdca69a9ca4ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Sz=C5=B1cs?= Date: Wed, 23 Aug 2023 12:16:55 +0200 Subject: [PATCH] chore: rewrite sqlite parse --- ibis/backends/base/sql/glot/datatypes.py | 4 +++ ibis/backends/sqlite/__init__.py | 4 +-- ibis/backends/sqlite/datatypes.py | 38 ++++-------------------- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/ibis/backends/base/sql/glot/datatypes.py b/ibis/backends/base/sql/glot/datatypes.py index 8b04c66f329c..4dc5e9bf65fd 100644 --- a/ibis/backends/base/sql/glot/datatypes.py +++ b/ibis/backends/base/sql/glot/datatypes.py @@ -340,3 +340,7 @@ class OracleType(SqlglotType): class SnowflakeType(SqlglotType): dialect = "snowflake" + + +class SQLiteType(SqlglotType): + dialect = "sqlite" diff --git a/ibis/backends/sqlite/__init__.py b/ibis/backends/sqlite/__init__.py index d87b556a1f15..a7d0ac4b44d9 100644 --- a/ibis/backends/sqlite/__init__.py +++ b/ibis/backends/sqlite/__init__.py @@ -30,7 +30,7 @@ from ibis.backends.base.sql.alchemy import BaseAlchemyBackend from ibis.backends.sqlite import udf from ibis.backends.sqlite.compiler import SQLiteCompiler -from ibis.backends.sqlite.datatypes import ISODATETIME, SqliteType, parse +from ibis.backends.sqlite.datatypes import ISODATETIME, SqliteType if TYPE_CHECKING: from collections.abc import Iterator @@ -204,7 +204,7 @@ def _metadata(self, query: str) -> Iterator[tuple[str, dt.DataType]]: for name, notnull, raw_typ, typ in zip( names, notnulls, raw_types, single_row_types ): - ibis_type = parse(raw_typ or typ) + ibis_type = SqliteType.from_string(raw_typ or typ) yield name, ibis_type(nullable=not notnull) # drop the view when we're done with it diff --git a/ibis/backends/sqlite/datatypes.py b/ibis/backends/sqlite/datatypes.py index bc7bf49b0dd5..c0da14504085 100644 --- a/ibis/backends/sqlite/datatypes.py +++ b/ibis/backends/sqlite/datatypes.py @@ -9,39 +9,7 @@ import ibis.expr.datatypes as dt from ibis.backends.base.sql.alchemy.datatypes import AlchemyType - - -def parse(text: str) -> dt.DataType: - """Parse `text` into an ibis data type.""" - text = text.strip().upper() - - # SQLite affinity rules - # (see https://www.sqlite.org/datatype3.html). - - # 1. If the declared type contains the string "INT" then it is - # assigned INTEGER affinity. - if "INT" in text: - return dt.int64 - - # 2. If the declared type of the column contains any of the - # strings "CHAR", "CLOB", or "TEXT" then that column has TEXT - # affinity. Notice that the type VARCHAR contains the string - # "CHAR" and is thus assigned TEXT affinity. - if "CHAR" in text or "CLOB" in text or "TEXT" in text: - return dt.string - - # 3. If the declared type for a column contains the string "BLOB" - # or if no type is specified then the column has affinity BLOB. - if not text or "BLOB" in text: - return dt.binary - - # 4. If the declared type for a column contains any of the strings - # "REAL", "FLOA", or "DOUB" then the column has REAL affinity. - if "REAL" in text or "FLOA" in text or "DOUB" in text: - return dt.float64 - - # 5. Otherwise, the affinity is NUMERIC. - return dt.decimal +from ibis.backends.base.sql.glot.datatypes import SQLiteType as SqlglotSQLiteType class SqliteType(AlchemyType): @@ -63,6 +31,10 @@ def to_ibis(cls, typ: sat.TypeEngine, nullable: bool = True) -> dt.DataType: else: return super().to_ibis(typ, nullable=nullable) + @classmethod + def from_string(cls, type_string, nullable=True): + return SqlglotSQLiteType.from_string(type_string, nullable=nullable) + class ISODATETIME(sqlite.DATETIME): """A thin `datetime` type to override sqlalchemy's datetime parsing.