Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(flink): port to sqlglot #8268

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 50 additions & 58 deletions .github/workflows/ibis-backends.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,22 +177,28 @@ jobs:
- oracle
services:
- oracle
# - name: flink
# title: Flink
# serial: true
# extras:
# - flink
# additional_deps:
# - apache-flink
# - pytest-split
# services:
# - flink
# - name: risingwave
# title: Risingwave
# services:
# - risingwave
# extras:
# - risingwave
- name: flink
title: Flink
serial: true
extras:
- flink
additional_deps:
- apache-flink
services:
- flink
include:
- os: ubuntu-latest
python-version: "3.10"
backend:
name: flink
title: Flink
serial: true
extras:
- flink
additional_deps:
- apache-flink
services:
- flink
exclude:
- os: windows-latest
backend:
Expand Down Expand Up @@ -296,32 +302,29 @@ jobs:
- oracle
services:
- oracle
# - os: windows-latest
# backend:
# name: flink
# title: Flink
# serial: true
# extras:
# - flink
# services:
# - flink
# - python-version: "3.11"
# backend:
# name: flink
# title: Flink
# serial: true
# extras:
# - flink
# services:
# - flink
# - os: windows-latest
# backend:
# name: risingwave
# title: Risingwave
# services:
# - risingwave
# extras:
# - risingwave
- os: windows-latest
backend:
name: flink
title: Flink
serial: true
extras:
- flink
additional_deps:
- apache-flink
services:
- flink
- os: ubuntu-latest
python-version: "3.11"
backend:
name: flink
title: Flink
serial: true
extras:
- flink
additional_deps:
- apache-flink
services:
- flink
- os: windows-latest
backend:
name: exasol
Expand Down Expand Up @@ -390,29 +393,18 @@ jobs:
IBIS_TEST_IMPALA_PORT: 21050
IBIS_EXAMPLES_DATA: ${{ runner.temp }}/examples-${{ matrix.backend.name }}-${{ matrix.os }}-${{ steps.install_python.outputs.python-version }}

# FIXME(deepyaman): If some backend-specific test, in test_ddl.py,
# executes before common tests, they will fail with:
# org.apache.flink.table.api.ValidationException: Table `default_catalog`.`default_database`.`functional_alltypes` was not found.
# Therefore, we run backend-specific tests second to avoid this.
# - name: "run serial tests: ${{ matrix.backend.name }}"
# if: matrix.backend.serial && matrix.backend.name == 'flink'
# run: |
# just ci-check -m ${{ matrix.backend.name }} ibis/backends/tests
# just ci-check -m ${{ matrix.backend.name }} ibis/backends/flink/tests
# env:
# IBIS_EXAMPLES_DATA: ${{ runner.temp }}/examples-${{ matrix.backend.name }}-${{ matrix.os }}-${{ steps.install_python.outputs.python-version }}
# FLINK_REMOTE_CLUSTER_ADDR: localhost
# FLINK_REMOTE_CLUSTER_PORT: "8081"
#
- name: "run serial tests: ${{ matrix.backend.name }}"
if: matrix.backend.serial # && matrix.backend.name != 'flink'
if: matrix.backend.serial
run: just ci-check -m ${{ matrix.backend.name }}
env:
FLINK_REMOTE_CLUSTER_ADDR: localhost
FLINK_REMOTE_CLUSTER_PORT: "8081"
IBIS_EXAMPLES_DATA: ${{ runner.temp }}/examples-${{ matrix.backend.name }}-${{ matrix.os }}-${{ steps.install_python.outputs.python-version }}

- name: check that no untracked files were produced
shell: bash
run: git checkout poetry.lock pyproject.toml && ! git status --porcelain | tee /dev/stderr | grep .
run: |
! git status --porcelain | tee /dev/stderr | grep .

- name: upload code coverage
if: success()
Expand Down
9 changes: 7 additions & 2 deletions ibis/backends/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1277,9 +1277,14 @@


@functools.cache
def _get_backend_names() -> frozenset[str]:
def _get_backend_names(*, exclude: tuple[str] = ()) -> frozenset[str]:
"""Return the set of known backend names.

Parameters
----------
exclude
Exclude these backend names from the result

Notes
-----
This function returns a frozenset to prevent cache pollution.
Expand All @@ -1293,7 +1298,7 @@
entrypoints = importlib.metadata.entry_points()["ibis.backends"]
else:
entrypoints = importlib.metadata.entry_points(group="ibis.backends")
return frozenset(ep.name for ep in entrypoints)
return frozenset(ep.name for ep in entrypoints).difference(exclude)


def connect(resource: Path | str, **kwargs: Any) -> BaseBackend:
Expand Down Expand Up @@ -1431,11 +1436,11 @@

for name, value in query_params.items():
if len(value) > 1:
kwargs[name] = value

Check warning on line 1439 in ibis/backends/base/__init__.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/__init__.py#L1439

Added line #L1439 was not covered by tests
elif len(value) == 1:
kwargs[name] = value[0]
else:
raise exc.IbisError(f"Invalid URL parameter: {name}")

Check warning on line 1443 in ibis/backends/base/__init__.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/__init__.py#L1443

Added line #L1443 was not covered by tests

self._convert_kwargs(kwargs)
return self.connect(database=database, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion ibis/backends/base/sqlglot/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
)

def __getitem__(self, key: str) -> Callable[..., sge.Anonymous]:
return getattr(self, key)

Check warning on line 74 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L74

Added line #L74 was not covered by tests


class FuncGen:
Expand Down Expand Up @@ -124,17 +124,17 @@
return sg.column(name, table=self.table)

def __getitem__(self, key: str) -> sge.Column:
return sg.column(key, table=self.table)

Check warning on line 127 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L127

Added line #L127 was not covered by tests


def paren(expr):
"""Wrap a sqlglot expression in parentheses."""
return sge.Paren(this=expr)
return sge.Paren(this=sge.convert(expr))


def parenthesize(op, arg):
if isinstance(op, (ops.Binary, ops.Unary)):
return paren(arg)

Check warning on line 137 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L137

Added line #L137 was not covered by tests
# function calls don't need parens
return arg

Expand Down Expand Up @@ -297,7 +297,7 @@

@singledispatchmethod
def visit_node(self, op: ops.Node, **_):
raise com.OperationNotDefinedError(

Check warning on line 300 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L300

Added line #L300 was not covered by tests
f"No translation rule for {type(op).__name__}"
)

Expand Down Expand Up @@ -340,7 +340,7 @@
if value is None:
if dtype.nullable:
return NULL if dtype.is_null() else self.cast(NULL, dtype)
raise com.UnsupportedOperationError(

Check warning on line 343 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L343

Added line #L343 was not covered by tests
f"Unsupported NULL for non-nullable type: {dtype!r}"
)
else:
Expand Down Expand Up @@ -636,7 +636,7 @@
@visit_node.register(ops.StringFind)
def visit_StringFind(self, op, *, arg, substr, start, end):
if end is not None:
raise com.UnsupportedOperationError(

Check warning on line 639 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L639

Added line #L639 was not covered by tests
"String find doesn't support `end` argument"
)

Expand Down Expand Up @@ -965,7 +965,7 @@
def visit_Select(self, op, *, parent, selections, predicates, sort_keys):
# if we've constructed a useless projection return the parent relation
if not selections and not predicates and not sort_keys:
return parent

Check warning on line 968 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L968

Added line #L968 was not covered by tests

result = parent

Expand Down Expand Up @@ -1022,7 +1022,7 @@

for link in rest:
if isinstance(link, sge.Alias):
link = link.this

Check warning on line 1025 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1025

Added line #L1025 was not covered by tests
result = result.join(link)
return result

Expand Down Expand Up @@ -1085,17 +1085,17 @@
self._add_parens(raw_predicate, predicate)
for raw_predicate, predicate in zip(op.predicates, predicates)
)
try:
return parent.where(*predicates)
except AttributeError:
return sg.select(STAR).from_(parent).where(*predicates)

Check warning on line 1091 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1088-L1091

Added lines #L1088 - L1091 were not covered by tests

@visit_node.register(ops.Sort)
def visit_Sort(self, op, *, parent, keys):
try:
return parent.order_by(*keys)
except AttributeError:
return sg.select(STAR).from_(parent).order_by(*keys)

Check warning on line 1098 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1095-L1098

Added lines #L1095 - L1098 were not covered by tests

@visit_node.register(ops.Union)
def visit_Union(self, op, *, left, right, distinct):
Expand All @@ -1114,10 +1114,10 @@
@visit_node.register(ops.Intersection)
def visit_Intersection(self, op, *, left, right, distinct):
if isinstance(left, sge.Table):
left = sg.select(STAR).from_(left)

Check warning on line 1117 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1117

Added line #L1117 was not covered by tests

if isinstance(right, sge.Table):
right = sg.select(STAR).from_(right)

Check warning on line 1120 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1120

Added line #L1120 was not covered by tests

return sg.intersect(
left.args.get("this", left),
Expand All @@ -1128,10 +1128,10 @@
@visit_node.register(ops.Difference)
def visit_Difference(self, op, *, left, right, distinct):
if isinstance(left, sge.Table):
left = sg.select(STAR).from_(left)

Check warning on line 1131 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1131

Added line #L1131 was not covered by tests

if isinstance(right, sge.Table):
right = sg.select(STAR).from_(right)

Check warning on line 1134 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1134

Added line #L1134 was not covered by tests

return sg.except_(
left.args.get("this", left),
Expand All @@ -1156,7 +1156,7 @@
else:
assert n is None, n
if self.no_limit_value is not None:
result = result.limit(self.no_limit_value)

Check warning on line 1159 in ibis/backends/base/sqlglot/compiler.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/compiler.py#L1159

Added line #L1159 was not covered by tests

assert offset is not None, "offset is None"

Expand Down
10 changes: 10 additions & 0 deletions ibis/backends/base/sqlglot/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@
unit = precision_or_span.this.this
return dt.Interval(unit=unit, nullable=nullable)
elif isinstance(precision_or_span, sge.Var):
return dt.Interval(unit=precision_or_span.this, nullable=nullable)

Check warning on line 257 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L257

Added line #L257 was not covered by tests
elif precision_or_span is None:
raise com.IbisTypeError("Interval precision is None")
else:
Expand Down Expand Up @@ -334,7 +334,7 @@

if scale is not None:
if precision is None:
raise com.IbisTypeError(

Check warning on line 337 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L337

Added line #L337 was not covered by tests
"Decimal scale cannot be specified without precision"
)
expressions.append(sge.DataTypeParam(this=sge.Literal.number(scale)))
Expand Down Expand Up @@ -390,7 +390,7 @@
@classmethod
def _from_ibis_Map(cls, dtype: dt.Map) -> sge.DataType:
if not dtype.key_type.is_string():
raise com.IbisTypeError("Postgres only supports string keys in maps")

Check warning on line 393 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L393

Added line #L393 was not covered by tests
if not dtype.value_type.is_string():
raise com.IbisTypeError("Postgres only supports string values in maps")
return sge.DataType(this=typecode.HSTORE)
Expand Down Expand Up @@ -511,9 +511,9 @@

@classmethod
def _from_ibis_Interval(cls, dtype: dt.Interval) -> sge.DataType:
assert dtype.unit is not None, "interval unit cannot be None"

Check warning on line 514 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L514

Added line #L514 was not covered by tests
if (short := dtype.unit.short) in ("Y", "Q", "M"):
return sge.DataType(

Check warning on line 516 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L516

Added line #L516 was not covered by tests
this=typecode.INTERVAL,
expressions=[
sge.IntervalSpan(
Expand All @@ -521,8 +521,8 @@
)
],
)
elif short in ("D", "h", "m", "s", "ms", "us", "ns"):
return sge.DataType(

Check warning on line 525 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L524-L525

Added lines #L524 - L525 were not covered by tests
this=typecode.INTERVAL,
expressions=[
sge.IntervalSpan(
Expand All @@ -537,7 +537,7 @@

@classmethod
def _from_sqlglot_UBIGINT(cls):
return dt.Decimal(precision=19, scale=0, nullable=cls.default_nullable)

Check warning on line 540 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L540

Added line #L540 was not covered by tests

@classmethod
def _from_ibis_UInt64(cls, dtype):
Expand All @@ -551,7 +551,7 @@

@classmethod
def _from_sqlglot_UINT(cls):
return dt.Int64(nullable=cls.default_nullable)

Check warning on line 554 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L554

Added line #L554 was not covered by tests

@classmethod
def _from_ibis_UInt32(cls, dtype):
Expand All @@ -559,7 +559,7 @@

@classmethod
def _from_sqlglot_USMALLINT(cls):
return dt.Int32(nullable=cls.default_nullable)

Check warning on line 562 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L562

Added line #L562 was not covered by tests

@classmethod
def _from_ibis_UInt16(cls, dtype):
Expand All @@ -567,7 +567,7 @@

@classmethod
def _from_sqlglot_UTINYINT(cls):
return dt.Int16(nullable=cls.default_nullable)

Check warning on line 570 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L570

Added line #L570 was not covered by tests

@classmethod
def _from_ibis_UInt8(cls, dtype):
Expand Down Expand Up @@ -599,7 +599,7 @@
if scale is None or int(scale.this.this) == 0:
return dt.Int64(nullable=cls.default_nullable)
else:
return super()._from_sqlglot_DECIMAL(precision, scale)

Check warning on line 602 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L602

Added line #L602 was not covered by tests

@classmethod
def _from_ibis_String(cls, dtype: dt.String) -> sge.DataType:
Expand Down Expand Up @@ -633,19 +633,19 @@

@classmethod
def _from_ibis_JSON(cls, dtype: dt.JSON) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.VARIANT)

Check warning on line 636 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L636

Added line #L636 was not covered by tests

@classmethod
def _from_ibis_Array(cls, dtype: dt.Array) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.ARRAY, nested=True)

Check warning on line 640 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L640

Added line #L640 was not covered by tests

@classmethod
def _from_ibis_Map(cls, dtype: dt.Map) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.OBJECT, nested=True)

Check warning on line 644 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L644

Added line #L644 was not covered by tests

@classmethod
def _from_ibis_Struct(cls, dtype: dt.Struct) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.OBJECT, nested=True)

Check warning on line 648 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L648

Added line #L648 was not covered by tests


class SQLiteType(SqlglotType):
Expand Down Expand Up @@ -684,7 +684,7 @@

@classmethod
def _from_ibis_Map(cls, dtype: dt.Map) -> NoReturn:
raise com.UnsupportedBackendType("Map types aren't supported in Impala")

Check warning on line 687 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L687

Added line #L687 was not covered by tests

@classmethod
def _from_ibis_Struct(cls, dtype: dt.Struct) -> sge.DataType:
Expand All @@ -706,7 +706,7 @@

@classmethod
def _from_sqlglot_NUMERIC(cls) -> dt.Decimal:
return dt.Decimal(

Check warning on line 709 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L709

Added line #L709 was not covered by tests
cls.default_decimal_precision,
cls.default_decimal_scale,
nullable=cls.default_nullable,
Expand All @@ -714,25 +714,25 @@

@classmethod
def _from_sqlglot_BIGNUMERIC(cls) -> dt.Decimal:
return dt.Decimal(76, 38, nullable=cls.default_nullable)

Check warning on line 717 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L717

Added line #L717 was not covered by tests

@classmethod
def _from_sqlglot_DATETIME(cls) -> dt.Timestamp:
return dt.Timestamp(timezone=None, nullable=cls.default_nullable)

Check warning on line 721 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L721

Added line #L721 was not covered by tests

@classmethod
def _from_sqlglot_TIMESTAMP(cls) -> dt.Timestamp:
return dt.Timestamp(timezone="UTC", nullable=cls.default_nullable)

Check warning on line 725 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L725

Added line #L725 was not covered by tests

@classmethod
def _from_sqlglot_GEOGRAPHY(cls) -> dt.GeoSpatial:
return dt.GeoSpatial(

Check warning on line 729 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L729

Added line #L729 was not covered by tests
geotype="geography", srid=4326, nullable=cls.default_nullable
)

@classmethod
def _from_sqlglot_TINYINT(cls) -> dt.Int64:
return dt.Int64(nullable=cls.default_nullable)

Check warning on line 735 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L735

Added line #L735 was not covered by tests

_from_sqlglot_UINT = (
_from_sqlglot_USMALLINT
Expand All @@ -742,43 +742,43 @@

@classmethod
def _from_sqlglot_UBIGINT(cls) -> NoReturn:
raise com.UnsupportedBackendType(

Check warning on line 745 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L745

Added line #L745 was not covered by tests
"Unsigned BIGINT isn't representable in BigQuery INT64"
)

@classmethod
def _from_sqlglot_FLOAT(cls) -> dt.Float64:
return dt.Float64(nullable=cls.default_nullable)

Check warning on line 751 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L751

Added line #L751 was not covered by tests

@classmethod
def _from_sqlglot_MAP(cls) -> NoReturn:
raise com.UnsupportedBackendType("Maps are not supported in BigQuery")

Check warning on line 755 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L755

Added line #L755 was not covered by tests

@classmethod
def _from_ibis_Map(cls, dtype: dt.Map) -> NoReturn:
raise com.UnsupportedBackendType("Maps are not supported in BigQuery")

Check warning on line 759 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L759

Added line #L759 was not covered by tests

@classmethod
def _from_ibis_Timestamp(cls, dtype: dt.Timestamp) -> sge.DataType:
if dtype.timezone is None:
return sge.DataType(this=sge.DataType.Type.DATETIME)

Check warning on line 764 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L764

Added line #L764 was not covered by tests
elif dtype.timezone == "UTC":
return sge.DataType(this=sge.DataType.Type.TIMESTAMPTZ)

Check warning on line 766 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L766

Added line #L766 was not covered by tests
else:
raise com.UnsupportedBackendType(

Check warning on line 768 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L768

Added line #L768 was not covered by tests
"BigQuery does not support timestamps with timezones other than 'UTC'"
)

@classmethod
def _from_ibis_Decimal(cls, dtype: dt.Decimal) -> sge.DataType:
precision = dtype.precision
scale = dtype.scale

Check warning on line 775 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L774-L775

Added lines #L774 - L775 were not covered by tests
if (precision, scale) == (76, 38):
return sge.DataType(this=sge.DataType.Type.BIGDECIMAL)

Check warning on line 777 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L777

Added line #L777 was not covered by tests
elif (precision, scale) in ((38, 9), (None, None)):
return sge.DataType(this=sge.DataType.Type.DECIMAL)

Check warning on line 779 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L779

Added line #L779 was not covered by tests
else:
raise com.UnsupportedBackendType(

Check warning on line 781 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L781

Added line #L781 was not covered by tests
"BigQuery only supports decimal types with precision of 38 and "
f"scale of 9 (NUMERIC) or precision of 76 and scale of 38 (BIGNUMERIC). "
f"Current precision: {dtype.precision}. Current scale: {dtype.scale}"
Expand All @@ -786,22 +786,22 @@

@classmethod
def _from_ibis_UInt64(cls, dtype: dt.UInt64) -> NoReturn:
raise com.UnsupportedBackendType(

Check warning on line 789 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L789

Added line #L789 was not covered by tests
f"Conversion from {dtype} to BigQuery integer type (Int64) is lossy"
)

@classmethod
def _from_ibis_UInt32(cls, dtype: dt.UInt32) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.BIGINT)

Check warning on line 795 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L795

Added line #L795 was not covered by tests

_from_ibis_UInt8 = _from_ibis_UInt16 = _from_ibis_UInt32

@classmethod
def _from_ibis_GeoSpatial(cls, dtype: dt.GeoSpatial) -> sge.DataType:
if (dtype.geotype, dtype.srid) == ("geography", 4326):
return sge.DataType(this=sge.DataType.Type.GEOGRAPHY)

Check warning on line 802 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L802

Added line #L802 was not covered by tests
else:
raise com.UnsupportedBackendType(

Check warning on line 804 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L804

Added line #L804 was not covered by tests
"BigQuery geography uses points on WGS84 reference ellipsoid."
f"Current geotype: {dtype.geotype}, Current srid: {dtype.srid}"
)
Expand All @@ -810,7 +810,7 @@
class BigQueryUDFType(BigQueryType):
@classmethod
def _from_ibis_Int64(cls, dtype: dt.Int64) -> NoReturn:
raise com.UnsupportedBackendType(

Check warning on line 813 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L813

Added line #L813 was not covered by tests
"int64 is not a supported input or output type in BigQuery UDFs; use float64 instead"
)

Expand All @@ -837,18 +837,18 @@
scale: sge.DataTypeParam | None = None,
) -> dt.Decimal:
if precision is None:
precision = cls.default_decimal_precision

Check warning on line 840 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L840

Added line #L840 was not covered by tests
else:
precision = int(precision.this.this)

if scale is None:
scale = cls.default_decimal_scale

Check warning on line 845 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L845

Added line #L845 was not covered by tests
else:
scale = int(scale.this.this)

if not scale:
if 0 < precision <= 3:
return dt.Int8(nullable=cls.default_nullable)

Check warning on line 851 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L851

Added line #L851 was not covered by tests
elif 3 < precision <= 9:
return dt.Int16(nullable=cls.default_nullable)
elif 9 < precision <= 18:
Expand All @@ -856,10 +856,10 @@
elif 18 < precision <= 36:
return dt.Int64(nullable=cls.default_nullable)
else:
raise com.UnsupportedBackendType(

Check warning on line 859 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L859

Added line #L859 was not covered by tests
"Decimal precision is too large; Exasol supports precision up to 36."
)
return dt.Decimal(precision, scale, nullable=cls.default_nullable)

Check warning on line 862 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L862

Added line #L862 was not covered by tests

@classmethod
def _from_ibis_Array(cls, dtype: dt.Array) -> NoReturn:
Expand All @@ -880,15 +880,15 @@

@classmethod
def _from_sqlglot_ARRAY(cls, value_type: sge.DataType) -> NoReturn:
raise com.UnsupportedBackendType("Arrays not supported in Exasol")

Check warning on line 883 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L883

Added line #L883 was not covered by tests

@classmethod
def _from_sqlglot_MAP(cls, key: sge.DataType, value: sge.DataType) -> NoReturn:
raise com.UnsupportedBackendType("Maps not supported in Exasol")

Check warning on line 887 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L887

Added line #L887 was not covered by tests

@classmethod
def _from_sqlglot_STRUCT(cls, *cols: sge.ColumnDef) -> NoReturn:
raise com.UnsupportedBackendType("Structs not supported in Exasol")

Check warning on line 891 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L891

Added line #L891 was not covered by tests


class MSSQLType(SqlglotType):
Expand Down Expand Up @@ -933,15 +933,15 @@

@classmethod
def _from_sqlglot_ARRAY(cls) -> sge.DataType:
raise com.UnsupportedBackendType("SQL Server does not support arrays")

Check warning on line 936 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L936

Added line #L936 was not covered by tests

@classmethod
def _from_sqlglot_MAP(cls) -> sge.DataType:
raise com.UnsupportedBackendType("SQL Server does not support map")

Check warning on line 940 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L940

Added line #L940 was not covered by tests

@classmethod
def _from_sqlglot_STRUCT(cls) -> sge.DataType:
raise com.UnsupportedBackendType("SQL Server does not support structs")

Check warning on line 944 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L944

Added line #L944 was not covered by tests


class ClickHouseType(SqlglotType):
Expand Down Expand Up @@ -1029,3 +1029,13 @@
key_type = cls.from_ibis(dtype.key_type.copy(nullable=False))
value_type = cls.from_ibis(dtype.value_type)
return sge.DataType(this=typecode.MAP, expressions=[key_type, value_type])


class FlinkType(SqlglotType):
dialect = "flink"
default_decimal_precision = 38
default_decimal_scale = 18

@classmethod
def _from_ibis_Binary(cls, dtype: dt.Binary) -> sge.DataType:
return sge.DataType(this=sge.DataType.Type.VARBINARY)

Check warning on line 1041 in ibis/backends/base/sqlglot/datatypes.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/datatypes.py#L1041

Added line #L1041 was not covered by tests
17 changes: 17 additions & 0 deletions ibis/backends/base/sqlglot/dialects.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@

class Flink(Hive):
class Generator(Hive.Generator):
TYPE_MAPPING = Hive.Generator.TYPE_MAPPING.copy() | {
sge.DataType.Type.TIME: "TIME",
}

TRANSFORMS = Hive.Generator.TRANSFORMS.copy() | {
sge.Stddev: rename_func("stddev_samp"),
sge.StddevPop: rename_func("stddev_pop"),
Expand All @@ -82,8 +86,21 @@
),
sge.ArrayConcat: rename_func("array_concat"),
sge.Length: rename_func("char_length"),
sge.TryCast: lambda self,
e: f"TRY_CAST({e.this.sql(self.dialect)} AS {e.to.sql(self.dialect)})",
sge.DayOfYear: rename_func("dayofyear"),
sge.DayOfWeek: rename_func("dayofweek"),
sge.DayOfMonth: rename_func("dayofmonth"),
}

class Tokenizer(Hive.Tokenizer):
# In Flink, embedded single quotes are escaped like most other SQL
# dialects: doubling up the single quote
#
# We override it here because we inherit from Hive's dialect and Hive
# uses a backslash to escape single quotes
STRING_ESCAPES = ["'"]


class Impala(Hive):
class Generator(Hive.Generator):
Expand Down Expand Up @@ -137,7 +154,7 @@
kind = expression.args["kind"]
if (obj := kind.upper()) in ("TABLE", "VIEW") and temporary:
if expression.expression:
return f"CREATE GLOBAL TEMPORARY {obj} {self.sql(expression, 'this')} AS {self.sql(expression, 'expression')}"

Check warning on line 157 in ibis/backends/base/sqlglot/dialects.py

View check run for this annotation

Codecov / codecov/patch

ibis/backends/base/sqlglot/dialects.py#L157

Added line #L157 was not covered by tests
else:
# TODO: why does autocommit not work here? need to specify the ON COMMIT part...
return f"CREATE GLOBAL TEMPORARY {obj} {self.sql(expression, 'this')} ON COMMIT PRESERVE ROWS"
Expand Down
Loading
Loading