Great Expectations 1.23.0 was published on 10 September 2026. SQLDatasource.get_execution_engine now returns the same SQLAlchemy execution engine on later calls, instead of building a new engine and connection pool for every validation. The tag also publishes an Oracle extra and changes three expectations that used to raise or disagree by backend.
The full release notes and downloads are on the GitHub release page.
The SQL execution engine stays cached ¶
Pull request 12148 fixes a cache that never matched. SQLDatasource.get_execution_engine saved its kwargs dict and then popped kwargs from that same object, so the next call never matched and every validation built a new SqlAlchemyExecutionEngine and pool. A few hundred validations against one PostgreSQL datasource can exhaust max_connections.
SQLServerDatasource.get_execution_engine also popped connection_string. That dialect holds a connection on the engine, so each discarded engine pinned one until collection. Both methods now cache a copy after the constructor returns, so a failed rebuild does not keep the previous engine. A configuration change still rebuilds the engine. SnowflakeDatasource.get_execution_engine still ignores the cache and reuses the SQLAlchemy engine only through get_engine().
The cached engine kept one inspector, so a column added later stayed invisible. The inspector now resets when a batch is fetched. create_temp_table defaults to false. When it is true, temporary objects on persisted connection dialects live for the process. This tag does not drop them.
Query asset SQL that failed before it ran ¶
Pull request 12124 fixes query SQL that ends in a line comment such as -- note. The subquery wrap put the closing parenthesis and alias on the same line, inside the comment. A newline is inserted first now. An unterminated block comment still fails.
Pull request 12162 stops Oracle from appending FROM DUAL. The wrapper selected only the text after SELECT, which has no FROM, so the wrapped query had two FROM clauses and failed with ORA-00907. Daily and monthly batch definitions failed on the partition probe, and the error looked like a bad column type. Both sites now submit the whole statement. PostgreSQL, MySQL, SQLite, and MSSQL keep the same SQL aside from one extra space after SELECT. Table assets were unaffected.
Expectations that raised or disagreed by backend ¶
Pull request 12145 makes ExpectColumnValueZScoresToBeLessThan pass on zero or undefined variance. (column - mean) divided by std_dev did not agree across engines. PostgreSQL and SQL Server raised. SQLite and MySQL returned null and succeeded. Pandas treated NaN as an outlier on every numeric row and raised ZeroDivisionError for object dtype. Spark was already safe. SQLAlchemy and pandas now pass a constant column with unexpected_count of 0.
Suites that used the pandas failure as a stuck column signal will start passing. ExpectColumnStdevToBeBetween with min_value above zero is the check for zero variance.
Pull request 12168 returns None from SQLite instead of raising when ExpectColumnStdevToBeBetween sees fewer than two values that are not null. SQLite has no stddev_samp. The math.sqrt shim threw OperationalError and omitted observed_value. success stays false.
Pull request 12180 stops KeyError from expect_column_values_to_be_unique on mixed case names. Since 1.20.0, asking for unexpected rows (COMPLETE, or unexpected_index_column_names set) missed on SQLAlchemy when the name was not already lower case. On Databricks, PostgreSQL, Snowflake, SQL Server, and Trino, table.columns returns CaseInsensitiveString keys that hash by the folded spelling. _column_by_name matches by equality and prefers the exact spelling.
Oracle extra, store encoding, and internal work ¶
Pull request 12091 publishes pip install 'great_expectations[oracle]'. The extra is floored at SQLAlchemy 2.0 in reqs/requirements-dev-oracle.txt, because oracle+oracledb does not exist on 1.4, which only has cx_oracle. Other SQL extras still allow 1.4.
Pull request 12125 sets encoding="utf-8" on TupleFilesystemStoreBackend reads and on project YAML in InlineStoreBackend and FileDataContext. The store wrote UTF-8 and read with the process locale. PEP 538 hides that on Unix. A Windows code page that is not UTF-8 does not. config_variables.yml is untouched.
Pull request 12126 moves documentation repository links to the fivetran organization. The release page for this tag already lives there.
The other entries are internal. They tighten types for metric values, render-content payloads, and metric keys, generalize the data source declaration past SQL, and pin the fluent datasource API with a per type CRUD suite. A dead match_on key is removed from the not-match-like-pattern-list metric. Further changes type check tests/, delete dead CI around check-actor-permissions, or bump browserslist, fast-uri, colord, svgo, and joi under docs/docusaurus. None of that changes a validation result.
Upgrade notes ¶
Constant columns, and pandas columns that contain infinity, can flip ExpectColumnValueZScoresToBeLessThan from a failure or an exception to success with unexpected_count of 0. Use ExpectColumnStdevToBeBetween with min_value above zero when a stuck column must fail.
On SQLite, ExpectColumnStdevToBeBetween over fewer than two values that are not null now returns observed_value of None and success of false, not OperationalError. Mixed case expect_column_values_to_be_unique returns a result instead of KeyError when unexpected rows are requested.
Oracle daily and monthly batch definitions on query assets work again. A trailing -- comment validates again. An unterminated /* comment still fails. SQL datasources other than Snowflake should hold fewer connections. With create_temp_table true, temporary objects can remain for the process lifetime. great_expectations[oracle] needs SQLAlchemy 2.0.
Where to get it ¶
- Release page:
https://github.com/fivetran/great_expectations/releases/tag/1.23.0 - Repository:
https://github.com/great-expectations/great_expectations - Tag:
1.23.0