Commit Graph
5 Commits
Author SHA1 Message Date
Superset Dev 75044575a1 fix(testcontainers): avoid table-qualified columns in mongodb pagination test
The previous fix (positional row access) only masked the symptom.
Root cause: SQLAlchemy always qualifies a Table-bound column as
"pilot_pagination.id" once there's a FROM clause, but pymongosql's
projection builder takes that qualified text completely literally as a
MongoDB field path -- {"pilot_pagination.id": 1} reads a *nested* field
under a top-level "pilot_pagination" key, which doesn't exist on these
flat documents, silently projecting None for every row instead of
raising (confirmed via pymongosql/sql/query_handler.py's
_extract_field_and_alias, which uses the raw expression text verbatim
as the Mongo field key regardless of any AS alias).

A bare column()/table() pair (not bound to each other via a real Table
object) compiles to an unqualified "id" reference, which resolves
correctly, while still exercising the dialect's own LIMIT/OFFSET
compilation through a real Core select() -- this test's actual intent.
2026-08-28 10:47:11 -07:00
Superset Dev 4028ff1e05 fix(testcontainers): use positional row access in mongodb pagination test
text() has no static column metadata of its own -- the row's key comes
entirely from whatever pymongosql's DBAPI cursor reports for the raw
compiled SQL string, which turned out to be the qualified
"pilot_pagination.id" (matching the SELECT list's column reference), not
the bare "id" that attribute access expected. Reproduced by compiling the
exact statement offline and inspecting text()'s (empty) column metadata;
confirmed the AttributeError on real CI runs of this branch and #43640.
2026-08-28 10:38:11 -07:00
rusackasandClaude Opus 4.8 67a193f1d9 fix(testcontainers): stop third-party dialect entry points from leaking global compiler state
sqlalchemy-monetdb mutates SQLAlchemy's shared, process-global
compiler.OPERATORS mapping in place on import instead of subclassing it
(OPERATORS = compiler.OPERATORS; OPERATORS[operators.ne] = " <> "). Once
Superset's own get_available_engine_specs() enumerates the "monetdb"
sqlalchemy.dialects entry point to build the "available databases" list
(which happens on every app boot, not just when MonetDB is actually
used), that changes `!=` rendering to `<>` for every dialect for the
rest of the process -- breaking test_where_operators identically across
the test-mysql/test-postgres/test-sqlite CI jobs, since installing the
monetdb extra now pulls sqlalchemy-monetdb into their shared dev
requirements.

Snapshot/restore sqlalchemy.sql.compiler.OPERATORS around each
third-party dialect entry point load so a misbehaving connector can't
leak global compiler state just because it was enumerated here.

Also fix the new mongodb testcontainers pagination test: pymongosql's
SQL-to-Mongo AST parser reads LIMIT/OFFSET off the compiled SQL text
ahead of parameter substitution, so a bound `LIMIT ?`/`OFFSET ?`
placeholder is silently dropped. Compile with literal_binds=True instead,
matching how Superset actually issues chart/SQL Lab queries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 05:56:24 -07:00
rusackasandClaude Opus 4.8 cd2638e27c fix(testcontainers): address bot + reviewer feedback on db2 baseline, mariadb host, mongodb pagination test, weak type assertions, monetdb readiness, and CI path coverage
- drop `db2` from the `testcontainers[...]` extra in development.in/.txt:
  it transitively pulls `ibm-db-sa`/`ibm-db` into the baseline dev lockfile,
  which has no Linux arm64 wheel and breaks the multi-platform dev Docker
  image build; the db2 CI leg already installs it on demand separately.
- mariadb: preserve a remote Docker daemon's real host, only rewrite the
  literal "localhost" case to 127.0.0.1.
- testcontainers.yml: widen pull_request paths to superset/db_engine_specs/**,
  pyproject.toml, and the requirements manifests so a driver/lockfile-only
  change can't bypass this coverage.
- mongodb: use Core `select(...).limit().offset()` instead of a literal SQL
  string, so the pagination test actually exercises the dialect's own
  compilation.
- monetdb/mongodb/yugabytedb: assert generic_type/sqla_type on the mapped
  column spec, not just that a spec was returned.
- monetdb: wait for the exposed port (not just a log line that predates
  `monetdbd start -n`) before considering the container ready.
- timescaledb: pin the image to a specific tag instead of the mutable
  `latest-pg16`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 02:35:46 -07:00
Superset Dev 1333ed12c7 feat(ci): expand testcontainers coverage to mariadb, timescaledb, yugabytedb, monetdb, mongodb
Adds five more dialects to the testcontainers suite, stacked on top of the
7-dialect pilot in feat/testcontainers-nightly-pilot: mariadb, timescaledb,
yugabytedb, monetdb, mongodb.

mariadb, timescaledb, and yugabytedb are all wire-compatible with an
existing base dialect (MySQL and Postgres respectively), so they reuse
testcontainers' MySqlContainer/PostgresContainer classes pointed at a
different image rather than needing new container-class wiring.
yugabytedb specifically cannot reuse PostgresContainer's built-in
readiness check, though: that execs `psql`, which the yugabyte image
doesn't ship (only its own `ysqlsh`) -- uses a generic DockerContainer
instead, started via `yugabyted start` and waiting on its own final
startup log line.

monetdb has no native testcontainers module; uses a generic DockerContainer
with the documented MDB_* environment variables. Publishes an amd64-only
image (confirmed running under Rosetta/QEMU emulation on Apple Silicon,
unlike CrateDB's harder x86-64-v3 CPU requirement).

mongodb needed a different data-setup approach, like elasticsearch before
it: documents get inserted via the native pymongo driver, not SQL INSERT,
since MongoDB is schemaless and Superset talks to it through pymongosql
(a SQL-to-MongoDB translation layer requiring a `?mode=superset` query
param). Two real bugs surfaced writing this one: testcontainers'
MongoDbContainer.get_connection_url() has no database path or query
string at all, so naively appending "&mode=superset" glued directly onto
the port number instead of starting a query string; and the root user
MongoDbContainer creates lives in the `admin` database, so connecting
with a different default database in the URL requires authSource=admin
or authentication fails outright. Confirmed pymongosql supports OFFSET
(maps to MongoDB's native `skip`), unlike Elasticsearch's SQL layer.

mariadb could not be verified locally in this environment: mysqlclient
(MySQLdb) has a pre-existing, unrelated native-library linking issue
against this machine's Homebrew-installed libmysqlclient. CI installs it
via apt on Linux, where this does not occur -- same accepted pattern
already used for crate/mssql/db2 in the base branch.
2026-08-27 22:44:32 -07:00