From 042cb45ae81e13ae62d68ad09b28d7eb139cf134 Mon Sep 17 00:00:00 2001 From: Grieve Date: Wed, 23 Oct 2024 16:33:11 +0800 Subject: [PATCH 1/2] fix(bigquery): fix Interval precision is None and format interval to str --- ibis-server/app/custom_ibis/__init__.py | 0 .../app/custom_ibis/backends/__init__.py | 0 .../app/custom_ibis/backends/sql/__init__.py | 0 .../app/custom_ibis/backends/sql/datatypes.py | 8 +++++ ibis-server/app/model/connector.py | 4 +++ ibis-server/app/util.py | 19 ++++++++++++ .../routers/v2/connector/test_bigquery.py | 29 ++++++++++++++++++- 7 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 ibis-server/app/custom_ibis/__init__.py create mode 100644 ibis-server/app/custom_ibis/backends/__init__.py create mode 100644 ibis-server/app/custom_ibis/backends/sql/__init__.py create mode 100644 ibis-server/app/custom_ibis/backends/sql/datatypes.py diff --git a/ibis-server/app/custom_ibis/__init__.py b/ibis-server/app/custom_ibis/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ibis-server/app/custom_ibis/backends/__init__.py b/ibis-server/app/custom_ibis/backends/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ibis-server/app/custom_ibis/backends/sql/__init__.py b/ibis-server/app/custom_ibis/backends/sql/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ibis-server/app/custom_ibis/backends/sql/datatypes.py b/ibis-server/app/custom_ibis/backends/sql/datatypes.py new file mode 100644 index 000000000..a04514674 --- /dev/null +++ b/ibis-server/app/custom_ibis/backends/sql/datatypes.py @@ -0,0 +1,8 @@ +from ibis.backends.sql import datatypes + + +class BigQueryType(datatypes.BigQueryType): + default_interval_precision = "s" + + +datatypes.BigQueryType = BigQueryType diff --git a/ibis-server/app/model/connector.py b/ibis-server/app/model/connector.py index ec578a164..a433860b2 100644 --- a/ibis-server/app/model/connector.py +++ b/ibis-server/app/model/connector.py @@ -1,3 +1,4 @@ +import importlib from functools import cache from typing import Any @@ -12,6 +13,9 @@ from app.model import ConnectionInfo, UnknownIbisError, UnprocessableEntityError from app.model.data_source import DataSource +# Override datatypes of ibis +importlib.import_module("app.custom_ibis.backends.sql.datatypes") + class Connector: def __init__(self, data_source: DataSource, connection_info: ConnectionInfo): diff --git a/ibis-server/app/util.py b/ibis-server/app/util.py index 615c5ff86..fc55ab1b5 100644 --- a/ibis-server/app/util.py +++ b/ibis-server/app/util.py @@ -32,6 +32,8 @@ def default(obj): return str(obj) if isinstance(obj, (bytes, bytearray)): return obj.hex() + if isinstance(obj, pd.tseries.offsets.DateOffset): + return _date_offset_to_str(obj) raise TypeError json_obj = orjson.loads( @@ -43,3 +45,20 @@ def default(obj): ) json_obj["dtypes"] = df.dtypes.astype(str).to_dict() return json_obj + + +def _date_offset_to_str(offset: pd.tseries.offsets.DateOffset) -> str: + parts = [] + units = [ + "months", + "days", + "microseconds", + "nanoseconds", + ] + + for unit in units: + value = getattr(offset, unit, 0) + if value: + parts.append(f"{value} {unit if value > 1 else unit.rstrip('s')}") + + return " ".join(parts) diff --git a/ibis-server/tests/routers/v2/connector/test_bigquery.py b/ibis-server/tests/routers/v2/connector/test_bigquery.py index 507c2a784..854b9742c 100644 --- a/ibis-server/tests/routers/v2/connector/test_bigquery.py +++ b/ibis-server/tests/routers/v2/connector/test_bigquery.py @@ -65,7 +65,6 @@ "type": "bytea", }, ], - "primaryKey": "orderkey", }, ], } @@ -196,6 +195,34 @@ def test_query_values(manifest_str): assert response.status_code == 204 + def test_interval(manifest_str): + response = client.post( + url=f"{base_url}/query", + json={ + "connectionInfo": connection_info, + "manifestStr": manifest_str, + "sql": "SELECT INTERVAL '1' YEAR + INTERVAL '100' MONTH + INTERVAL '100' DAY + INTERVAL '1' HOUR AS col", + }, + ) + assert response.status_code == 200 + result = response.json() + assert result["data"][0] == ["112 months 100 days 3600000000 microseconds"] + assert result["dtypes"] == {"col": "object"} + + def test_avg_interval(manifest_str): + response = client.post( + url=f"{base_url}/query", + json={ + "connectionInfo": connection_info, + "manifestStr": manifest_str, + "sql": 'SELECT AVG(CURRENT_DATE - orderdate) AS col from "Orders"', + }, + ) + assert response.status_code == 200 + result = response.json() + assert result["data"][0] == ["10780 days 32054400000 microseconds"] + assert result["dtypes"] == {"col": "object"} + def test_validate_with_unknown_rule(manifest_str): response = client.post( url=f"{base_url}/validate/unknown_rule", From bd9a9820d8b797e8dfb3f272ed5c6a5e7269fd0d Mon Sep 17 00:00:00 2001 From: Grieve Date: Wed, 23 Oct 2024 16:54:50 +0800 Subject: [PATCH 2/2] chore: re-trigger ci