diff --git a/ibis-server/app/routers/v3/connector.py b/ibis-server/app/routers/v3/connector.py index 01f1acb25..6626dfb25 100644 --- a/ibis-server/app/routers/v3/connector.py +++ b/ibis-server/app/routers/v3/connector.py @@ -199,18 +199,25 @@ async def query( "Failed to execute v3 query, try to fallback to v2: {}\n", str(e) ) headers = append_fallback_context(headers, span) - return await v2.connector.query( - data_source=data_source, - dto=dto, - dry_run=dry_run, - cache_enable=cache_enable, - override_cache=override_cache, - limit=limit, - java_engine_connector=java_engine_connector, - query_cache_manager=query_cache_manager, - headers=headers, - is_fallback=True, - ) + try: + return await v2.connector.query( + data_source=data_source, + dto=dto, + dry_run=dry_run, + limit=limit, + java_engine_connector=java_engine_connector, + headers=headers, + is_fallback=True, + cache_enable=cache_enable, + override_cache=override_cache, + query_cache_manager=query_cache_manager, + ) + except Exception as ve: + # ignore v2 error messages in fallback, return v3 error instead. + logger.debug( + "v2 fallback failed for v3 query; suppressing v2 error: %s", ve + ) + raise e from None @router.post("/dry-plan", description="get the planned WrenSQL") @@ -245,12 +252,19 @@ async def dry_plan( "Failed to execute v3 dry-plan, try to fallback to v2: {}", str(e) ) headers = append_fallback_context(headers, span) - return await v2.connector.dry_plan( - dto=dto, - java_engine_connector=java_engine_connector, - headers=headers, - is_fallback=True, - ) + try: + return await v2.connector.dry_plan( + dto=dto, + java_engine_connector=java_engine_connector, + headers=headers, + is_fallback=True, + ) + except Exception as ve: + # ignore v2 error messages in fallback, return v3 error instead. + logger.debug( + "v2 fallback failed for v3 dry-plan; suppressing v2 error: %s", ve + ) + raise e from None @router.post( @@ -294,13 +308,20 @@ async def dry_plan_for_data_source( str(e), ) headers = append_fallback_context(headers, span) - return await v2.connector.dry_plan_for_data_source( - data_source=data_source, - dto=dto, - java_engine_connector=java_engine_connector, - headers=headers, - is_fallback=True, - ) + try: + return await v2.connector.dry_plan_for_data_source( + data_source=data_source, + dto=dto, + java_engine_connector=java_engine_connector, + headers=headers, + is_fallback=True, + ) + except Exception as ve: + # ignore v2 error messages in fallback, return v3 error instead. + logger.debug( + "v2 fallback failed for v3 dry-plan; suppressing v2 error: %s", ve + ) + raise e from None @router.post( @@ -360,14 +381,21 @@ async def validate( str(e), ) headers = append_fallback_context(headers, span) - return await v2.connector.validate( - data_source=data_source, - rule_name=rule_name, - dto=dto, - java_engine_connector=java_engine_connector, - headers=headers, - is_fallback=True, - ) + try: + return await v2.connector.validate( + data_source=data_source, + rule_name=rule_name, + dto=dto, + java_engine_connector=java_engine_connector, + headers=headers, + is_fallback=True, + ) + except Exception as ve: + # ignore v2 error messages in fallback, return v3 error instead. + logger.debug( + "v2 fallback failed for v3 validate; suppressing v2 error: %s", ve + ) + raise e from None @router.get( @@ -455,10 +483,18 @@ async def model_substitute( str(e), ) headers = append_fallback_context(headers, span) - return await v2.connector.model_substitute( - data_source=data_source, - dto=dto, - headers=headers, - java_engine_connector=java_engine_connector, - is_fallback=True, - ) + try: + return await v2.connector.model_substitute( + data_source=data_source, + dto=dto, + headers=headers, + java_engine_connector=java_engine_connector, + is_fallback=True, + ) + except Exception as ve: + # ignore v2 error messages in fallback, return v3 error instead. + logger.debug( + "v2 fallback failed for v3 model-substitute; suppressing v2 error: %s", + ve, + ) + raise e from None diff --git a/ibis-server/resources/function_list/postgres.csv b/ibis-server/resources/function_list/postgres.csv index 86d433a40..e3df82327 100644 --- a/ibis-server/resources/function_list/postgres.csv +++ b/ibis-server/resources/function_list/postgres.csv @@ -33,4 +33,4 @@ scalar,sign,numeric,,numeric,"Sign of number" scalar,to_json,json,,boolean,"Convert to JSON" scalar,to_number,numeric,,"text,text","Convert string to number" scalar,unistr,varchar,,text,"Postgres: Evaluate escaped Unicode characters in the argument" -scalar,pg_sleep,,,"numeric","Sleep for specified time in seconds" +scalar,pg_sleep,,,"bigint","Sleep for specified time in seconds" diff --git a/ibis-server/tests/routers/v3/connector/postgres/conftest.py b/ibis-server/tests/routers/v3/connector/postgres/conftest.py index 36b003a0d..20388e7cf 100644 --- a/ibis-server/tests/routers/v3/connector/postgres/conftest.py +++ b/ibis-server/tests/routers/v3/connector/postgres/conftest.py @@ -5,6 +5,7 @@ import sqlalchemy from testcontainers.postgres import PostgresContainer +from app.config import get_config from tests.conftest import file_path pytestmark = pytest.mark.postgres @@ -19,6 +20,9 @@ def pytest_collection_modifyitems(items): item.add_marker(pytestmark) +function_list_path = file_path("../resources/function_list") + + @pytest.fixture(scope="module") def postgres(request) -> PostgresContainer: pg = PostgresContainer("postgres:16-alpine").start() @@ -56,3 +60,11 @@ def connection_info(postgres: PostgresContainer) -> dict[str, str]: def connection_url(connection_info: dict[str, str]): info = connection_info return f"postgres://{info['user']}:{info['password']}@{info['host']}:{info['port']}/{info['database']}" + + +@pytest.fixture(autouse=True) +def set_remote_function_list_path(): + config = get_config() + config.set_remote_function_list_path(function_list_path) + yield + config.set_remote_function_list_path(None) diff --git a/ibis-server/tests/routers/v3/connector/postgres/test_functions.py b/ibis-server/tests/routers/v3/connector/postgres/test_functions.py index 27d31c5fd..b9b68eb84 100644 --- a/ibis-server/tests/routers/v3/connector/postgres/test_functions.py +++ b/ibis-server/tests/routers/v3/connector/postgres/test_functions.py @@ -4,8 +4,8 @@ import pytest from app.config import get_config -from tests.conftest import DATAFUSION_FUNCTION_COUNT, file_path -from tests.routers.v3.connector.postgres.conftest import base_url +from tests.conftest import DATAFUSION_FUNCTION_COUNT +from tests.routers.v3.connector.postgres.conftest import base_url, function_list_path pytestmark = pytest.mark.functions @@ -26,22 +26,12 @@ ], } -function_list_path = file_path("../resources/function_list") - @pytest.fixture(scope="module") def manifest_str(): return base64.b64encode(orjson.dumps(manifest)).decode("utf-8") -@pytest.fixture(autouse=True) -def set_remote_function_list_path(): - config = get_config() - config.set_remote_function_list_path(function_list_path) - yield - config.set_remote_function_list_path(None) - - async def test_function_list(client): config = get_config()