[BUG] LIKE-pattern Expectations never evaluate on Oracle or SingleStore — the dialect allow-list omits both, and the fallback crashes with AttributeError
What's wrong
The four LIKE-pattern Expectations — ExpectColumnValuesToMatchLikePattern, ExpectColumnValuesToNotMatchLikePattern, ExpectColumnValuesToMatchLikePatternList, ExpectColumnValuesToNotMatchLikePatternList — never evaluate on Oracle or SingleStore. Every call returns an exception instead of a verdict, although both databases evaluate LIKE natively and every other supported SQL dialect gets a result.
All four metrics ask get_dialect_like_pattern_expression (great_expectations/expectations/metrics/util.py:950-1046) for the SQL. That helper is an allow-list: it sets dialect_supported = True for twelve named dialects, then emits plain column.like(<pattern>) — no dialect-specific translation — and returns None for anything else. Oracle and SingleStore are simply not on the list. The metrics then fall into an "unsupported dialect" branch which, in three of the four modules, crashes while building its own warning (column_values_match_like_pattern.py:29: _dialect.name on a module object that has no .name), so what the user sees is an AttributeError about a SQLAlchemy module rather than anything about LIKE.
Impact
- Crashes:
success: Falsewithexception_infopopulated, for every LIKE-pattern Expectation on Oracle or SingleStore, regardless of data. The four Expectations are unusable on these two backends. - The error text —
module 'sqlalchemy.dialects.oracle' has no attribute 'name'— points at SQLAlchemy, not at GX or at LIKE support, so users cannot tell what went wrong. - Present since the helper was introduced in
0.13.0, through1.23.0. - Workaround: none within these Expectations.
ExpectColumnValuesToMatchRegexworks on Oracle (a branch for it was added in #12103); SingleStore has no equivalent.
Reproduction
Reproduced on 1.23.0 (673082d4b), Python 3.11, against the repository's own Oracle (assets/docker/oracle) and SingleStore (assets/docker/singlestore) containers.
Add to tests/integration/data_sources_and_expectations/expectations/test_expect_column_values_to_match_like_pattern.py (import OracleDatasourceTestConfig and SingleStoreDatasourceTestConfig alongside the module's other configs):
@parameterize_batch_for_data_sources(
data_source_configs=[OracleDatasourceTestConfig(), SingleStoreDatasourceTestConfig()],
data=DATA,
)
def test_like_pattern_evaluates_on_oracle_and_singlestore(batch_for_datasource: Batch) -> None:
"""Both dialects support LIKE natively, so the expectation must evaluate rather than raise.
Every value in PREFIXED_PATTERNS starts with "foo", so ``foo%`` matches all three and the
expectation must succeed. Today neither dialect is in the LIKE-pattern allow-list, and the
unsupported-dialect fallback crashes with an ``AttributeError`` before it can raise the
``NotImplementedError`` it intends to, so the result carries an exception instead of a verdict.
"""
result = batch_for_datasource.validate(
gxe.ExpectColumnValuesToMatchLikePattern(column=PREFIXED_PATTERNS, like_pattern="foo%")
)
assert result.success, result.exception_infopytest tests/integration/data_sources_and_expectations/expectations/test_expect_column_values_to_match_like_pattern.py::test_like_pattern_evaluates_on_oracle_and_singlestore -m "oracle or singlestore"Observed:
FAILED ...::test_like_pattern_evaluates_on_oracle_and_singlestore[oracle]
MetricResolutionError: module 'sqlalchemy.dialects.oracle' has no attribute 'name'
FAILED ...::test_like_pattern_evaluates_on_oracle_and_singlestore[singlestore]
MetricResolutionError: module 'sqlalchemy_singlestoredb' has no attribute 'name'
exception_info: {"...column_values.match_like_pattern.condition...": {"raised_exception": true, ...}}Expected:
2 passed # success=True on both; "foo%" matches foo_abc, foo_def, foo_ghiRequirements
- When any of the four LIKE-pattern Expectations runs against an Oracle or SingleStore data source, it must evaluate
LIKEand return a verdict — the samesuccessandunexpected_countthat PostgreSQL, MySQL and SQLite return for the same data and pattern. - Results on the twelve dialects already in the allow-list must be unchanged.
- When a dialect genuinely has no LIKE translation, the result must carry a clean, descriptive exception that names the dialect (the
NotImplementedErrorthe code intends), not anAttributeErrorraised while formatting the message. - The public signatures and parameters of the four Expectations must not change.
- Each of the four LIKE-pattern test modules under
tests/integration/data_sources_and_expectations/expectations/must run Oracle and SingleStore in its success and failure cases, so neither dialect can drop out of the list unnoticed.
Out of scope: the regex Expectations (Snowflake's anchoring is #12213; ClickHouse's regexp_like call is a separate defect); Oracle's type-name resolution in ExpectColumnValuesToBeOfType (separate defect, same "dialect module is not a complete namespace" mistake); the LIKE escape-character feature request (#12153); inverting the allow-list to admit every SQLAlchemy dialect — a wider change touching dialects with no test coverage here.
Context
- Fix shape, verified: with two base-class checks added inside the helper's existing
if hasattr(dialect, "dialect"):block —issubclass(dialect.dialect, sa.dialects.oracle.base.OracleDialect)andissubclass(dialect.dialect, sa.dialects.mysql.base.MySQLDialect)— the test above passes on both dialects with no other change. Plaincolumn.likeis all either needs. - Why the existing MySQL check misses SingleStore:
sqlalchemy_singlestoredb.dialectisSingleStoreDBDialect, whose MRO includesMySQLDialect, but the allow-list compares againstsa.dialects.mysql.dialect, which is the default-driver subclass (MySQLDialect_mysqldb), not the base — soissubclassisFalse. Compare against.base.<Name>Dialect. The regex helper's Oracle branch atutil.py:137uses the same default-driver comparison; it happens to work there because theoracledbdialect subclasses thecx_oracleone. - The fallback crash:
column_condition_partial.py:182-192binds_dialecttoexecution_engine.dialect_module— a module object.column_values_match_like_pattern.py:29,..._not_match_like_pattern.py:29and..._not_match_like_pattern_list.py:36format_dialect.nameand crash;..._match_like_pattern_list.py:39formats_dialect.dialect.nameand raises the intendedNotImplementedError. Aligning the three with the fourth satisfies requirement 3; moving the raise into the helper would be cleaner still. - Ruled out: a data or fixture problem — the same fixture and pattern pass on every allow-listed dialect the module already runs; the same two dialects pass the rest of the integration suite. Not verified: the three sibling metrics under the probe above (same helper, same list, so the same fix — but they need their own cases, hence requirement 5); whether the
MySQLDialectbase check admits any dialect that should stay out (MariaDB and friends also derive from it and also supportLIKE). - Also recorded in
tests/integration/data_sources_and_expectations/data_source_backlog.md("Fifteen candidates were measured…"): these four cases are the only failures keeping SingleStore out of the gallery tier, and four of Oracle's six.
Source: fivetran/great_expectations