From dce2111b8c82a0baea48d227e9f33ae5cd06044e Mon Sep 17 00:00:00 2001 From: Jax Liu Date: Thu, 16 Oct 2025 15:29:08 +0800 Subject: [PATCH 1/2] enhance snowflake function list --- ibis-server/app/model/metadata/dto.py | 1 + ibis-server/app/model/metadata/snowflake.py | 2 ++ .../resources/function_list/snowflake.csv | 35 +++++++++++++++++++ ibis-server/tools/query_local_run.py | 5 ++- .../core/src/mdl/function/remote_function.rs | 3 +- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ibis-server/app/model/metadata/dto.py b/ibis-server/app/model/metadata/dto.py index ae1dc04f5..70524121a 100644 --- a/ibis-server/app/model/metadata/dto.py +++ b/ibis-server/app/model/metadata/dto.py @@ -50,6 +50,7 @@ class RustWrenEngineColumnType(Enum): INT64 = "INT64" TIME = "TIME" NULL = "NULL" + VARIANT = "VARIANT" # Extension types ## PostGIS diff --git a/ibis-server/app/model/metadata/snowflake.py b/ibis-server/app/model/metadata/snowflake.py index e864d8016..099ede661 100644 --- a/ibis-server/app/model/metadata/snowflake.py +++ b/ibis-server/app/model/metadata/snowflake.py @@ -48,6 +48,8 @@ "timestamp": RustWrenEngineColumnType.TIMESTAMP, "timestamp_ntz": RustWrenEngineColumnType.TIMESTAMP, "timestamp_tz": RustWrenEngineColumnType.TIMESTAMPTZ, + "variant": RustWrenEngineColumnType.VARIANT, + "object": RustWrenEngineColumnType.JSON, } diff --git a/ibis-server/resources/function_list/snowflake.csv b/ibis-server/resources/function_list/snowflake.csv index 67ea88bed..0f892239d 100644 --- a/ibis-server/resources/function_list/snowflake.csv +++ b/ibis-server/resources/function_list/snowflake.csv @@ -9,6 +9,9 @@ scalar,add_months,date,"Adds months to date" scalar,array_compact,array,"Removes null values from array" scalar,array_insert,array,"Inserts element into array" scalar,array_size,numeric,"Returns number of elements in array" +scalar,array_contains,boolean,"Tests if array contains element" +scalar,array_construct,array,"Constructs array from elements" +scalar,array_slice,array,"Returns subarray from array" scalar,base64_encode,string,"Encodes binary to base64" scalar,base64_decode,binary,"Decodes base64 to binary" scalar,char,string,"Returns character from ASCII code" @@ -52,13 +55,45 @@ scalar,timestampadd,timestamp,"Adds interval to timestamp" scalar,timestampdiff,interval,"Calculates difference between two timestamps" scalar,to_array,array,"Converts value to array" scalar,to_json,string,"Converts to JSON string" +scalar,to_variant,variant,"Converts to VARIANT" +scalar,to_object,object,"Converts to OBJECT" scalar,to_number,numeric,"Converts to number" scalar,to_time,time,"Converts to time" scalar,to_xml,string,"Converts to XML string" scalar,try_cast,same_as_input,"Safe type conversion" +scalar,to_date,date,"Converts to date" +scalar,to_timestamp,timestamp,"Converts to timestamp" +scalar,to_timestamp_ntz,timestamp,"Converts to timestamp without time zone" +scalar,to_timestamp_ltz,timestamp,"Converts to timestamp with local time zone" +scalar,to_timestamp_tz,timestamp,"Converts to timestamp with time zone" +scalar,to_decimal,decimal,"Converts to decimal" +scalar,to_numeric,numeric,"Converts to numeric" +scalar,to_binary,binary,"Converts to binary" +scalar,to_boolean,boolean,"Converts to boolean" +scalar,to_integer,integer,"Converts to integer" +scalar,to_bigint,bigint,"Converts to bigint" +scalar,to_smallint,smallint,"Converts to smallint" +scalar,to_tinyint,tinyint,"Converts to tinyint" +scalar,to_varchar,string,"Converts to varchar" scalar,try_to_date,date,"Safe date conversion" +scalar,try_to_time,time,"Safe time conversion" +scalar,try_to_timestamp_ntz,timestamp,"Safe timestamp without time zone conversion" +scalar,try_to_timestamp_ltz,timestamp,"Safe timestamp with local time zone conversion" +scalar,try_to_timestamp_tz,timestamp,"Safe timestamp with time zone conversion" +scalar,try_to_timestmp,timestamp,"Safe timestamp conversion" scalar,try_to_number,numeric,"Safe number conversion" scalar,try_to_timestamp,timestamp,"Safe timestamp conversion" +scalar,try_to_decimal,decimal,"Safe decimal conversion" +scalar,try_to_numeric,numeric,"Safe numeric conversion" +scalar,try_to_binary,binary,"Safe binary conversion" +scalar,try_to_boolean,boolean,"Safe boolean conversion" +scalar,try_to_integer,integer,"Safe integer conversion" +scalar,try_to_bigint,bigint,"Safe bigint conversion" +scalar,try_to_smallint,smallint,"Safe smallint conversion" +scalar,try_to_tinyint,tinyint,"Safe tinyint conversion" +scalar,try_to_varchar,string,"Safe varchar conversion" scalar,uuid_string,string,"Generates UUID" scalar,xmlget,xml,"Gets XML element" +scalar,get_path,variant,"Extracts value from VARIANT using path" +scalar,get,variant,"Extracts value from OBJECT using key" window,ratio_to_report,numeric,"Returns ratio to sum" diff --git a/ibis-server/tools/query_local_run.py b/ibis-server/tools/query_local_run.py index 72c510931..2e846e721 100644 --- a/ibis-server/tools/query_local_run.py +++ b/ibis-server/tools/query_local_run.py @@ -15,7 +15,7 @@ import json import os from app.custom_sqlglot.dialects.wren import Wren -from app.model import MSSqlConnectionInfo, MySqlConnectionInfo, OracleConnectionInfo, PostgresConnectionInfo +from app.model import MSSqlConnectionInfo, MySqlConnectionInfo, OracleConnectionInfo, PostgresConnectionInfo, SnowflakeConnectionInfo from app.util import to_json import sqlglot import sys @@ -105,6 +105,9 @@ elif data_source == "mssql": connection_info = MSSqlConnectionInfo.model_validate_json(json.dumps(connection_info)) connection = DataSourceExtension.get_mssql_connection(connection_info) +elif data_source == "snowflake": + connection_info = SnowflakeConnectionInfo.model_validate_json(json.dumps(connection_info)) + connection = DataSourceExtension.get_snowflake_connection(connection_info) else: raise Exception("Unsupported data source:", data_source) diff --git a/wren-core/core/src/mdl/function/remote_function.rs b/wren-core/core/src/mdl/function/remote_function.rs index a01e42a7f..849f7df6b 100644 --- a/wren-core/core/src/mdl/function/remote_function.rs +++ b/wren-core/core/src/mdl/function/remote_function.rs @@ -187,7 +187,8 @@ impl ByPassScalarUDF { impl From for ByPassScalarUDF { fn from(func: RemoteFunction) -> Self { // just panic if the return type is not valid to avoid we input invalid type - let return_type = ReturnType::from_str(&func.return_type).unwrap(); + let return_type = ReturnType::from_str(&func.return_type) + .unwrap_or(ReturnType::Specific(DataType::Utf8)); ByPassScalarUDF { return_type, signature: func.get_signature(), From 3b0b662467c2e1e3d8daf6cc0762b3e96aabc5c3 Mon Sep 17 00:00:00 2001 From: Jax Liu Date: Mon, 20 Oct 2025 10:55:20 +0800 Subject: [PATCH 2/2] fix test --- .../tests/routers/v3/connector/snowflake/test_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibis-server/tests/routers/v3/connector/snowflake/test_functions.py b/ibis-server/tests/routers/v3/connector/snowflake/test_functions.py index 18a2e5f11..02e304c65 100644 --- a/ibis-server/tests/routers/v3/connector/snowflake/test_functions.py +++ b/ibis-server/tests/routers/v3/connector/snowflake/test_functions.py @@ -53,7 +53,7 @@ async def test_function_list(client): response = await client.get(url=f"{base_url}/functions") assert response.status_code == 200 result = response.json() - assert len(result) == DATAFUSION_FUNCTION_COUNT + 63 + assert len(result) == DATAFUSION_FUNCTION_COUNT + 93 the_func = next(filter(lambda x: x["name"] == "is_null_value", result)) assert the_func == { "name": "is_null_value",