mirror of
https://github.com/apache/superset.git
synced 2026-09-06 07:21:35 +00:00
Stacked on feat/testcontainers-more-dialects. All four extras already existed in pyproject.toml, so this only wires up tests -- no new optional-dependency groups needed. - postgres/mysql: straight copies of the timescaledb/mariadb pattern respectively, pointed at vanilla images instead of a fork/extension. - clickhouse: connects over the container's HTTP port (8123), matching clickhouse-connect (Superset's driver), not the native TCP port (9000) the container's own docstring example uses. ClickHouse has no real primary-key concept and clickhouse-connect's DDL compiler rejects CREATE TABLE without an explicit engine, so _pagination.py gained an optional extra_table_args hook to pass MergeTree(order_by=...). Also works around a pre-existing quirk in db_engine_specs/clickhouse.py: its module-level type-formatting setup dereferences current_app.config, so importing it outside a Flask app context raises RuntimeError -- tests/unit_tests/db_engine_specs/test_clickhouse.py already works around this with per-test local imports, but that suite also benefits from an autouse app_context fixture this suite doesn't have, so this test pushes one explicitly around the one-time import. - starrocks: no dedicated testcontainers module, so a generic DockerContainer against the official allin1-ubuntu image (FE+BE in one container). Not verified locally (multiple-GB image, skipped to keep local Docker load low per session guidance); the fixture retries its first connection since the query port can accept TCP before StarRocks' query engine is fully initialized.
69 lines
2.9 KiB
Python
69 lines
2.9 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
"""
|
|
Shared body for the "paginated query returns correct rows in order" test
|
|
that db_engine_specs.{cockroachdb,crate,db2,mssql,oracle,trino}'s
|
|
testcontainers suites each run against their own real instance: a plain
|
|
SQLAlchemy Core LIMIT/OFFSET query, compiled and executed for real. Mocked
|
|
tests cannot catch a dialect compiling this incorrectly (see
|
|
apache/superset#42899, where Trino emitted OFFSET before LIMIT) -- only
|
|
real execution can.
|
|
|
|
Each call site keeps its own test function (and dialect-specific docstring)
|
|
so failures still report against the right module; this only factors out
|
|
the identical table setup/assert body, via an optional post-insert hook for
|
|
dialects (CrateDB) that need one, and an optional extra-table-args hook for
|
|
dialects (ClickHouse) whose CREATE TABLE requires a schema item a plain
|
|
Column/primary key can't express.
|
|
"""
|
|
|
|
from collections.abc import Callable
|
|
from typing import Any
|
|
|
|
from sqlalchemy import Column, insert, Integer, MetaData, select, Table as SATable
|
|
from sqlalchemy.engine import Connection, Engine
|
|
|
|
|
|
def assert_paginated_query_returns_correct_rows_in_order(
|
|
engine: Engine,
|
|
after_insert: Callable[[Connection], None] | None = None,
|
|
extra_table_args: tuple[Any, ...] = (),
|
|
) -> None:
|
|
metadata = MetaData()
|
|
t = SATable(
|
|
"pilot_pagination",
|
|
metadata,
|
|
# autoincrement=False: a single-column integer primary key otherwise
|
|
# implicitly becomes AUTO_INCREMENT on MySQL/MariaDB. That column
|
|
# type treats an explicit 0 as NULL by default (NO_AUTO_VALUE_ON_ZERO
|
|
# is off), so the id=0 row below would silently get auto-assigned 1,
|
|
# colliding with the explicit id=1 row in the same batch insert.
|
|
Column("id", Integer, primary_key=True, autoincrement=False),
|
|
*extra_table_args,
|
|
)
|
|
metadata.create_all(engine)
|
|
with engine.begin() as conn:
|
|
conn.execute(insert(t), [{"id": i} for i in range(10)])
|
|
if after_insert is not None:
|
|
after_insert(conn)
|
|
|
|
with engine.connect() as conn:
|
|
stmt = select(t.c.id).order_by(t.c.id).limit(3).offset(4)
|
|
rows = conn.execute(stmt).fetchall()
|
|
|
|
assert [row.id for row in rows] == [4, 5, 6]
|