|
3 | 3 | import pytest |
4 | 4 |
|
5 | 5 | from snuba import settings as snubasettings |
| 6 | +from snuba import state |
6 | 7 | from snuba.attribution import get_app_id |
7 | 8 | from snuba.attribution.attribution_info import AttributionInfo |
8 | 9 | from snuba.clickhouse.columns import ColumnSet |
|
11 | 12 | from snuba.datasets.entities.entity_key import EntityKey |
12 | 13 | from snuba.datasets.storages.storage_key import StorageKey |
13 | 14 | from snuba.pipeline.query_pipeline import QueryPipelineResult |
14 | | -from snuba.pipeline.stages.query_execution import ExecutionStage |
| 15 | +from snuba.pipeline.stages.query_execution import ( |
| 16 | + DISABLE_MAX_QUERY_SIZE_CHECK_FOR_CLUSTERS_CONFIG, |
| 17 | + MAX_QUERY_SIZE_BYTES_CONFIG, |
| 18 | + ExecutionStage, |
| 19 | +) |
15 | 20 | from snuba.query import SelectedExpression |
16 | 21 | from snuba.query.allocation_policies import ( |
17 | 22 | MAX_THRESHOLD, |
|
35 | 40 | from snuba.request import Request |
36 | 41 | from snuba.utils.metrics.timer import Timer |
37 | 42 | from snuba.utils.schemas import UUID, String, UInt |
| 43 | +from snuba.web import QueryException |
38 | 44 |
|
39 | 45 |
|
40 | 46 | class MockAllocationPolicy(AllocationPolicy): |
@@ -72,9 +78,7 @@ def get_fake_metadata() -> SnubaQueryMetadata: |
72 | 78 | Request( |
73 | 79 | uuid.uuid4(), |
74 | 80 | {}, |
75 | | - LogicalQuery( |
76 | | - from_clause=Entity(key=EntityKey.TRANSACTIONS, schema=ColumnSet([])) |
77 | | - ), |
| 81 | + LogicalQuery(from_clause=Entity(key=EntityKey.TRANSACTIONS, schema=ColumnSet([]))), |
78 | 82 | HTTPQuerySettings(), |
79 | 83 | AttributionInfo( |
80 | 84 | get_app_id("blah"), |
@@ -220,3 +224,61 @@ def test_turbo(ch_query: Query) -> None: |
220 | 224 | and "avg(duration)" in res.data.result["data"][0] |
221 | 225 | ) |
222 | 226 | assert ch_query.get_from_clause().sampling_rate == snubasettings.TURBO_SAMPLE_RATE |
| 227 | + |
| 228 | + |
| 229 | +@pytest.mark.clickhouse_db |
| 230 | +@pytest.mark.redis_db |
| 231 | +def test_max_query_size_bytes(ch_query: Query) -> None: |
| 232 | + attinfo = AttributionInfo( |
| 233 | + get_app_id("blah"), {"tenant_type": "tenant_id"}, "blah", None, None, None |
| 234 | + ) |
| 235 | + settings = HTTPQuerySettings() |
| 236 | + timer = Timer("test") |
| 237 | + metadata = get_fake_metadata() |
| 238 | + |
| 239 | + state.set_config(MAX_QUERY_SIZE_BYTES_CONFIG, 1) |
| 240 | + |
| 241 | + res = ExecutionStage(attinfo, query_metadata=metadata).execute( |
| 242 | + QueryPipelineResult( |
| 243 | + data=ch_query, |
| 244 | + query_settings=settings, |
| 245 | + timer=timer, |
| 246 | + error=None, |
| 247 | + ) |
| 248 | + ) |
| 249 | + |
| 250 | + assert res.data is None |
| 251 | + assert isinstance(res.error, QueryException) |
| 252 | + assert "which is too long for ClickHouse to process" in res.error.message |
| 253 | + |
| 254 | + |
| 255 | +@pytest.mark.clickhouse_db |
| 256 | +@pytest.mark.redis_db |
| 257 | +def test_disable_max_query_size_check(ch_query: Query) -> None: |
| 258 | + attinfo = AttributionInfo( |
| 259 | + get_app_id("blah"), {"tenant_type": "tenant_id"}, "blah", None, None, None |
| 260 | + ) |
| 261 | + settings = HTTPQuerySettings() |
| 262 | + timer = Timer("test") |
| 263 | + metadata = get_fake_metadata() |
| 264 | + cluster_name = ( |
| 265 | + snubasettings.CLUSTERS[0]["cluster_name"] |
| 266 | + if "cluster_name" in snubasettings.CLUSTERS[0] |
| 267 | + else "test_cluster" |
| 268 | + ) |
| 269 | + |
| 270 | + # Lowering this should make the query too big... |
| 271 | + state.set_config(MAX_QUERY_SIZE_BYTES_CONFIG, 1) |
| 272 | + # Unless we disable the check for this cluster. |
| 273 | + state.set_config(DISABLE_MAX_QUERY_SIZE_CHECK_FOR_CLUSTERS_CONFIG, cluster_name) |
| 274 | + |
| 275 | + res = ExecutionStage(attinfo, query_metadata=metadata).execute( |
| 276 | + QueryPipelineResult( |
| 277 | + data=ch_query, |
| 278 | + query_settings=settings, |
| 279 | + timer=timer, |
| 280 | + error=None, |
| 281 | + ) |
| 282 | + ) |
| 283 | + |
| 284 | + assert res.data |
0 commit comments