Skip to content
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
2 changes: 2 additions & 0 deletions src/firebolt/async_db/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
CursorState,
QueryStatus,
Statistics,
_raise_if_internal_set_parameter,
check_not_closed,
check_query_executed,
)
Expand Down Expand Up @@ -126,6 +127,7 @@ async def _raise_if_error(self, resp: Response) -> None:

async def _validate_set_parameter(self, parameter: SetParameter) -> None:
"""Validate parameter by executing simple query with it."""
_raise_if_internal_set_parameter(parameter)
if parameter.name == "async_execution":
raise AsyncExecutionUnavailableError(
"It is not possible to set async_execution using a SET command. "
Expand Down
24 changes: 24 additions & 0 deletions src/firebolt/common/base_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
)
from firebolt.utils.exception import (
AsyncExecutionUnavailableError,
ConfigurationError,
CursorClosedError,
DataError,
QueryNotRunError,
Expand Down Expand Up @@ -55,6 +56,29 @@ class QueryStatus(Enum):
# known parameters that can be set on the server side
SERVER_SIDE_PARAMETERS = ["database"]

# Parameters that should be set using USE instead of SET
USE_PARAMETER_LIST = ["database", "engine"]
# parameters that can only be set by the backend
DISALLOWED_PARAMETER_LIST = ["account_id", "output_format"]


def _raise_if_internal_set_parameter(parameter: SetParameter) -> None:
"""
Check if parameter is internal and raise an error if it is.
"""
if parameter.name in USE_PARAMETER_LIST:
raise ConfigurationError(
"Could not set parameter. "
f"Set parameter '{parameter.name}' is not allowed. "
f"Try again with 'USE {str(parameter.name).upper()}' instead of SET"
)
if parameter.name in DISALLOWED_PARAMETER_LIST:
raise ConfigurationError(
"Could not set parameter. "
f"Set parameter '{parameter.name}' is not allowed. "
"Try again with a different parameter name."
)


@dataclass
class Statistics:
Expand Down
2 changes: 2 additions & 0 deletions src/firebolt/db/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
CursorState,
QueryStatus,
Statistics,
_raise_if_internal_set_parameter,
check_not_closed,
check_query_executed,
)
Expand Down Expand Up @@ -123,6 +124,7 @@ def _api_request(

def _validate_set_parameter(self, parameter: SetParameter) -> None:
"""Validate parameter by executing simple query with it."""
_raise_if_internal_set_parameter(parameter)
if parameter.name == "async_execution":
raise AsyncExecutionUnavailableError(
"It is not possible to set async_execution using a SET command. "
Expand Down
22 changes: 21 additions & 1 deletion tests/unit/async_db/V1/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from unittest.mock import patch

from httpx import HTTPStatusError, StreamError, codes
from pytest import LogCaptureFixture, raises
from pytest import LogCaptureFixture, mark, raises
from pytest_httpx import HTTPXMock

from firebolt.async_db import Cursor
from firebolt.common._types import Column
from firebolt.common.base_cursor import ColType, CursorState, QueryStatus
from firebolt.utils.exception import (
AsyncExecutionUnavailableError,
ConfigurationError,
CursorClosedError,
DataError,
EngineNotRunningError,
Expand Down Expand Up @@ -878,3 +879,22 @@ async def test_cursor_unknown_error_body_logging(
with raises(HTTPStatusError):
await cursor.execute("select 1")
assert actual_error_body in caplog.text


@mark.parametrize(
"parameter",
[
"database",
"engine",
"account_id",
"output_format",
],
)
async def test_disallowed_set_parameter(cursor: Cursor, parameter: str) -> None:
"""Test that setting disallowed parameters raises an error."""
with raises(ConfigurationError) as e:
await cursor.execute(f"SET {parameter}=dummy")
assert f"Set parameter '{parameter}' is not allowed" in str(
e.value
), "invalid error"
assert cursor._set_parameters == {}, "set parameters should not be updated"
22 changes: 21 additions & 1 deletion tests/unit/async_db/V2/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from unittest.mock import patch

from httpx import HTTPStatusError, StreamError, codes
from pytest import LogCaptureFixture, raises
from pytest import LogCaptureFixture, mark, raises
from pytest_httpx import HTTPXMock

from firebolt.async_db import Cursor
from firebolt.common._types import Column
from firebolt.common.base_cursor import ColType, CursorState, QueryStatus
from firebolt.utils.exception import (
AsyncExecutionUnavailableError,
ConfigurationError,
CursorClosedError,
DataError,
EngineNotRunningError,
Expand Down Expand Up @@ -893,3 +894,22 @@ async def test_cursor_unknown_error_body_logging(
with raises(HTTPStatusError):
await cursor.execute("select 1")
assert actual_error_body in caplog.text


@mark.parametrize(
"parameter",
[
"database",
"engine",
"account_id",
"output_format",
],
)
async def test_disallowed_set_parameter(cursor: Cursor, parameter: str) -> None:
"""Test that setting disallowed parameters raises an error."""
with raises(ConfigurationError) as e:
await cursor.execute(f"SET {parameter}=dummy")
assert f"Set parameter '{parameter}' is not allowed" in str(
e.value
), "invalid error"
assert cursor._set_parameters == {}, "set parameters should not be updated"
22 changes: 21 additions & 1 deletion tests/unit/db/V1/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from unittest.mock import patch

from httpx import HTTPStatusError, StreamError, codes
from pytest import LogCaptureFixture, raises
from pytest import LogCaptureFixture, mark, raises
from pytest_httpx import HTTPXMock

from firebolt.db import Cursor
from firebolt.db.cursor import ColType, Column, CursorState, QueryStatus
from firebolt.utils.exception import (
ConfigurationError,
CursorClosedError,
DataError,
OperationalError,
Expand Down Expand Up @@ -737,3 +738,22 @@ def test_cursor_unknown_error_body_logging(
with raises(HTTPStatusError):
cursor.execute("select 1")
assert actual_error_body in caplog.text


@mark.parametrize(
"parameter",
[
"database",
"engine",
"account_id",
"output_format",
],
)
def test_disallowed_set_parameter(cursor: Cursor, parameter: str) -> None:
"""Test that setting disallowed parameters raises an error."""
with raises(ConfigurationError) as e:
cursor.execute(f"SET {parameter}=dummy")
assert f"Set parameter '{parameter}' is not allowed" in str(
e.value
), "invalid error"
assert cursor._set_parameters == {}, "set parameters should not be updated"
22 changes: 21 additions & 1 deletion tests/unit/db/V2/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from unittest.mock import patch

from httpx import HTTPStatusError, StreamError, codes
from pytest import LogCaptureFixture, raises
from pytest import LogCaptureFixture, mark, raises
from pytest_httpx import HTTPXMock

from firebolt.db import Cursor
from firebolt.db.cursor import ColType, Column, CursorState, QueryStatus
from firebolt.utils.exception import (
ConfigurationError,
CursorClosedError,
DataError,
EngineNotRunningError,
Expand Down Expand Up @@ -798,3 +799,22 @@ def test_cursor_unknown_error_body_logging(
with raises(HTTPStatusError):
cursor.execute("select 1")
assert actual_error_body in caplog.text


@mark.parametrize(
"parameter",
[
"database",
"engine",
"account_id",
"output_format",
],
)
def test_disallowed_set_parameter(cursor: Cursor, parameter: str) -> None:
"""Test that setting disallowed parameters raises an error."""
with raises(ConfigurationError) as e:
cursor.execute(f"SET {parameter}=dummy")
assert f"Set parameter '{parameter}' is not allowed" in str(
e.value
), "invalid error"
assert cursor._set_parameters == {}, "set parameters should not be updated"