confluent-sql 0.5.1__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/CHANGELOG.md +6 -1
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/PKG-INFO +1 -1
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/pyproject.toml +1 -1
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/statement.py +35 -4
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/test_fetch.py +128 -1
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_statement_unit.py +38 -3
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/uv.lock +1 -1
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/.github/CODEOWNERS +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/.gitignore +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/.semaphore/publish_to_pypi.yml +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/.semaphore/semaphore.yml +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/ARCHITECTURE.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/CLAUDE.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/DBAPI_EXTENSIONS.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/LICENSE.txt +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/Makefile +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/README.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/STREAMING.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/TYPES.md +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/byoidc_bearer_token_example.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/errors.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/simple_append_only_streaming_query_example.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/snapshot_mode_tuple_cursor_simple_example.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/statement_properties_example.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/tableflow_lifecycle_example.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/service.yml +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/__init__.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/__version__.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/auth.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/changelog_compressor.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/connection.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/connectors.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/cursor.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/exceptions.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/execution_mode.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/polling.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/result_readers.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/retry.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/statement_properties.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/tableflow.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/src/confluent_sql/types.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/__init__.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/conftest.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/conftest.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/test_connection.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/test_connector.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/test_cursor.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/integration/test_tableflow.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/conftest.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_auth_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_changelog_compressor_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_changelog_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connection_byoidc_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connection_connector_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connection_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connection_unit_properties.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connectors_connection_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_connectors_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_cursor_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_execution_mode_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_polling_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_result_readers_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_retry_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_statement_properties_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_tableflow_connection_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_tableflow_unit.py +0 -0
- {confluent_sql-0.5.1 → confluent_sql-0.5.2}/tests/unit/test_types_unit.py +0 -0
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this dbapi driver will be documented in this file.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 0.5.2, 2026-08-26
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `Statement.is_pure_ddl` / `_PURE_DDL_KINDS` now include `CREATE_MATERIALIZED_TABLE`, `CREATE_OR_ALTER_MATERIALIZED_TABLE`, `ALTER_MATERIALIZED_TABLE` (the bare, query-evolving form), and `DROP_MATERIALIZED_TABLE`.
|
|
10
|
+
- Previously these kinds weren't classified as pure or impure DDL, so in **streaming** execution mode, `Statement.can_fetch_results` fell through to the "ready when RUNNING" branch used for CTAS -- meaning a streaming-mode `Cursor.execute()` (and therefore `Connection.execute_streaming_ddl()`) on one of these statements could in principle return control as soon as the statement was RUNNING rather than waiting for it to reach a terminal phase, the same way `execute_streaming_ddl()` correctly waits out a genuinely perpetual CTAS job's RUNNING phase. Snapshot execution mode (the default, and what `execute_snapshot_ddl()` always uses) was unaffected -- it already waits for a terminal phase regardless of `is_pure_ddl`.
|
|
6
11
|
|
|
7
12
|
## 0.5.1, 2026-08-25
|
|
8
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: confluent-sql
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: DB-API v2 compliant driver for Confluent Cloud Flink SQL
|
|
5
5
|
Project-URL: Repository, https://github.com/confluentinc/confluent-sql
|
|
6
6
|
Project-URL: Documentation, https://github.com/confluentinc/confluent-sql?tab=readme-ov-file#confluent-sql
|
|
@@ -170,12 +170,30 @@ class Statement:
|
|
|
170
170
|
"""Represents a Confluent SQL statement, including its metadata, spec, status,
|
|
171
171
|
and parsed traits such as schema, sql kind, etc."""
|
|
172
172
|
|
|
173
|
-
# SQL kinds that represent pure DDL statements (create/modify schema objects)
|
|
173
|
+
# SQL kinds that represent pure DDL statements (create/modify schema objects) which should
|
|
174
|
+
# be waiting for a terminal state before the created/modified objects are usable.
|
|
174
175
|
_PURE_DDL_KINDS = frozenset(
|
|
175
|
-
{
|
|
176
|
+
{
|
|
177
|
+
"CREATE_TABLE",
|
|
178
|
+
"DROP_TABLE",
|
|
179
|
+
"CREATE_VIEW",
|
|
180
|
+
"DROP_VIEW",
|
|
181
|
+
"ALTER_TABLE",
|
|
182
|
+
# The four MATERIALIZED_TABLE kinds stretch "pure" a little: unlike the other
|
|
183
|
+
# members, CREATE_MATERIALIZED_TABLE, CREATE_OR_ALTER_MATERIALIZED_TABLE, and
|
|
184
|
+
# ALTER_MATERIALIZED_TABLE (a query-evolving ALTER, not just a metadata-only one)
|
|
185
|
+
# also kick off (or redeploy) a persistent background refresh job that keeps running
|
|
186
|
+
# long after this statement settles. But they still will reliably reach terminal
|
|
187
|
+
# COMPLETED (or FAILED) phase independent of the background job, which is the one
|
|
188
|
+
# thing this property actually gates.
|
|
189
|
+
"CREATE_MATERIALIZED_TABLE",
|
|
190
|
+
"CREATE_OR_ALTER_MATERIALIZED_TABLE",
|
|
191
|
+
"ALTER_MATERIALIZED_TABLE",
|
|
192
|
+
"DROP_MATERIALIZED_TABLE",
|
|
193
|
+
}
|
|
176
194
|
)
|
|
177
195
|
|
|
178
|
-
# SQL kinds that represent impure DDL (produce no result set but
|
|
196
|
+
# SQL kinds that represent impure DDL (produce no result set but will remain in RUNNING phase)
|
|
179
197
|
_IMPURE_DDL_KINDS = frozenset({"CREATE_TABLE_AS"})
|
|
180
198
|
|
|
181
199
|
# From the cursor that created this statement ...
|
|
@@ -336,9 +354,22 @@ class Statement:
|
|
|
336
354
|
Pure DDL statements need to complete fully before the created/modified objects
|
|
337
355
|
are ready for use, unlike streaming queries or CTAS which are ready when RUNNING.
|
|
338
356
|
|
|
357
|
+
"Pure" is stretched a little to also cover CREATE_MATERIALIZED_TABLE,
|
|
358
|
+
CREATE_OR_ALTER_MATERIALIZED_TABLE, and ALTER_MATERIALIZED_TABLE (the query-evolving
|
|
359
|
+
form -- see CREATE_OR_ALTER_MATERIALIZED_TABLE): their completion additionally kicks off
|
|
360
|
+
(or redeploys) a persistent background refresh job that keeps running long after the
|
|
361
|
+
statement settles, which isn't true of the other members. They earn the label anyway
|
|
362
|
+
because they satisfy the one thing this property actually gates: the statement's own
|
|
363
|
+
phase reliably reaches a terminal phase before the created/altered object is usable,
|
|
364
|
+
rather than lingering in RUNNING the way CTAS does (see _PURE_DDL_KINDS for the
|
|
365
|
+
confirming detail). DROP_MATERIALIZED_TABLE needs no such stretch -- like the other
|
|
366
|
+
DROP_* kinds, it's a one-shot action with no background job of its own.
|
|
367
|
+
|
|
339
368
|
Returns:
|
|
340
369
|
True if the statement is one of: CREATE_TABLE, DROP_TABLE, CREATE_VIEW,
|
|
341
|
-
DROP_VIEW, ALTER_TABLE
|
|
370
|
+
DROP_VIEW, ALTER_TABLE, CREATE_MATERIALIZED_TABLE,
|
|
371
|
+
CREATE_OR_ALTER_MATERIALIZED_TABLE, ALTER_MATERIALIZED_TABLE,
|
|
372
|
+
DROP_MATERIALIZED_TABLE. False otherwise.
|
|
342
373
|
"""
|
|
343
374
|
return self.sql_kind in self._PURE_DDL_KINDS
|
|
344
375
|
|
|
@@ -9,7 +9,7 @@ from typing import NamedTuple
|
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
|
-
from confluent_sql import Connection, SqlNone, YearMonthInterval
|
|
12
|
+
from confluent_sql import Connection, OperationalError, SqlNone, YearMonthInterval
|
|
13
13
|
from confluent_sql.execution_mode import ExecutionMode
|
|
14
14
|
|
|
15
15
|
|
|
@@ -678,6 +678,133 @@ class TestExecuteDDL:
|
|
|
678
678
|
assert statement.schema is None, "CTAS schema should be None"
|
|
679
679
|
assert statement.is_deleted, "Snapshot DDL statement should be auto-deleted"
|
|
680
680
|
|
|
681
|
+
def test_execute_streaming_ddl_create_materialized_table_completes(
|
|
682
|
+
self, connection: Connection, auto_dropped_table_name: str
|
|
683
|
+
):
|
|
684
|
+
"""Prove that CREATE MATERIALIZED TABLE, submitted via execute_streaming_ddl(), waits
|
|
685
|
+
for the statement to reach COMPLETED rather than returning as soon as it's RUNNING --
|
|
686
|
+
unlike CTAS, whose backing job runs forever, a materialized table's own CREATE statement
|
|
687
|
+
settles once its background refresh job is started (see statement.py's is_pure_ddl)."""
|
|
688
|
+
try:
|
|
689
|
+
statement_text = f"""
|
|
690
|
+
CREATE MATERIALIZED TABLE `{auto_dropped_table_name}`
|
|
691
|
+
AS SELECT * FROM `sample_data_stock_trades` WHERE quantity > 100
|
|
692
|
+
"""
|
|
693
|
+
|
|
694
|
+
statement = connection.execute_streaming_ddl(statement_text)
|
|
695
|
+
|
|
696
|
+
# execute_streaming_ddl's closing_cursor auto-deletes a terminal statement on exit,
|
|
697
|
+
# which flips Statement.phase to DELETED (it overrides the underlying phase once
|
|
698
|
+
# deleted -- see Statement.phase) -- so we can't read back "COMPLETED" directly here.
|
|
699
|
+
# is_deleted only follows from a *deletable* terminal phase (COMPLETED/FAILED/
|
|
700
|
+
# STOPPED); FAILED would have raised OperationalError out of execute_streaming_ddl
|
|
701
|
+
# instead of returning, and nothing here ever requested a STOPPED, so reaching this
|
|
702
|
+
# line with is_deleted true and no exception raised is exactly the proof that the
|
|
703
|
+
# statement settled to COMPLETED.
|
|
704
|
+
assert not statement.is_running
|
|
705
|
+
assert statement.is_deleted
|
|
706
|
+
|
|
707
|
+
# The table should be immediately queryable.
|
|
708
|
+
with connection.closing_cursor(as_dict=True) as cursor:
|
|
709
|
+
cursor.execute(f"SELECT COUNT(*) AS row_count FROM `{auto_dropped_table_name}`")
|
|
710
|
+
results = cursor.fetchone()
|
|
711
|
+
assert results is not None
|
|
712
|
+
finally:
|
|
713
|
+
with suppress(Exception):
|
|
714
|
+
connection.execute_snapshot_ddl(
|
|
715
|
+
f"DROP MATERIALIZED TABLE IF EXISTS `{auto_dropped_table_name}`"
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
def test_execute_streaming_ddl_create_or_alter_materialized_table_completes(
|
|
719
|
+
self, connection: Connection, auto_dropped_table_name: str
|
|
720
|
+
):
|
|
721
|
+
"""Prove that CREATE OR ALTER MATERIALIZED TABLE, and a bare (query-evolving) ALTER
|
|
722
|
+
MATERIALIZED TABLE, both also wait for COMPLETED, same as a first-time CREATE
|
|
723
|
+
MATERIALIZED TABLE. Each step respells the filter predicate (>100, then >=100, then >50)
|
|
724
|
+
to exercise a genuine redefinition of an already-existing materialized table."""
|
|
725
|
+
|
|
726
|
+
def show_create_ddl_text(table_name: str) -> str:
|
|
727
|
+
# SHOW CREATE MATERIALIZED TABLE is a plain bounded single-row query, so a default
|
|
728
|
+
# (snapshot mode) cursor is all it needs.
|
|
729
|
+
with connection.closing_cursor(as_dict=True) as cursor:
|
|
730
|
+
cursor.execute(f"SHOW CREATE MATERIALIZED TABLE `{table_name}`")
|
|
731
|
+
row = cursor.fetchone()
|
|
732
|
+
assert row is not None
|
|
733
|
+
return row["SHOW CREATE MATERIALIZED TABLE"] # type: ignore[index]
|
|
734
|
+
|
|
735
|
+
try:
|
|
736
|
+
create_statement_text = f"""
|
|
737
|
+
CREATE MATERIALIZED TABLE `{auto_dropped_table_name}`
|
|
738
|
+
AS SELECT * FROM `sample_data_stock_trades` WHERE quantity > 100
|
|
739
|
+
"""
|
|
740
|
+
created = connection.execute_streaming_ddl(create_statement_text)
|
|
741
|
+
assert not created.is_running
|
|
742
|
+
assert created.is_deleted # see the sibling CREATE test for why this implies COMPLETED
|
|
743
|
+
|
|
744
|
+
create_or_alter_statement_text = f"""
|
|
745
|
+
CREATE OR ALTER MATERIALIZED TABLE `{auto_dropped_table_name}`
|
|
746
|
+
AS SELECT * FROM `sample_data_stock_trades` WHERE quantity >= 100
|
|
747
|
+
"""
|
|
748
|
+
create_or_altered = connection.execute_streaming_ddl(create_or_alter_statement_text)
|
|
749
|
+
|
|
750
|
+
assert not create_or_altered.is_running
|
|
751
|
+
assert create_or_altered.is_deleted
|
|
752
|
+
|
|
753
|
+
# Prove the redefinition actually took effect.
|
|
754
|
+
assert ">= 100" in show_create_ddl_text(auto_dropped_table_name)
|
|
755
|
+
|
|
756
|
+
# A bare ALTER (no CREATE OR prefix) with a new AS SELECT is query evolution too --
|
|
757
|
+
# same completion semantics, since ALTER_MATERIALIZED_TABLE is also pure DDL.
|
|
758
|
+
bare_alter_statement_text = f"""
|
|
759
|
+
ALTER MATERIALIZED TABLE `{auto_dropped_table_name}`
|
|
760
|
+
AS SELECT * FROM `sample_data_stock_trades` WHERE quantity > 50
|
|
761
|
+
"""
|
|
762
|
+
bare_altered = connection.execute_streaming_ddl(bare_alter_statement_text)
|
|
763
|
+
|
|
764
|
+
assert not bare_altered.is_running
|
|
765
|
+
assert bare_altered.is_deleted
|
|
766
|
+
|
|
767
|
+
assert "> 50" in show_create_ddl_text(auto_dropped_table_name)
|
|
768
|
+
finally:
|
|
769
|
+
with suppress(Exception):
|
|
770
|
+
connection.execute_snapshot_ddl(
|
|
771
|
+
f"DROP MATERIALIZED TABLE IF EXISTS `{auto_dropped_table_name}`"
|
|
772
|
+
)
|
|
773
|
+
|
|
774
|
+
def test_execute_snapshot_ddl_drop_materialized_table_completes(
|
|
775
|
+
self, connection: Connection, auto_dropped_table_name: str
|
|
776
|
+
):
|
|
777
|
+
"""Prove that DROP MATERIALIZED TABLE, submitted via execute_snapshot_ddl(), completes
|
|
778
|
+
(it's pure DDL, like the other DROP_* kinds -- see statement.py's _PURE_DDL_KINDS)."""
|
|
779
|
+
try:
|
|
780
|
+
create_statement_text = f"""
|
|
781
|
+
CREATE MATERIALIZED TABLE `{auto_dropped_table_name}`
|
|
782
|
+
AS SELECT * FROM `sample_data_stock_trades` WHERE quantity > 100
|
|
783
|
+
"""
|
|
784
|
+
connection.execute_streaming_ddl(create_statement_text)
|
|
785
|
+
|
|
786
|
+
drop_statement = connection.execute_snapshot_ddl(
|
|
787
|
+
f"DROP MATERIALIZED TABLE `{auto_dropped_table_name}`"
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
# is_deleted implies COMPLETED here, not just some other deletable terminal phase --
|
|
791
|
+
# see the CREATE test above for why.
|
|
792
|
+
assert not drop_statement.is_running
|
|
793
|
+
assert drop_statement.is_deleted
|
|
794
|
+
|
|
795
|
+
# The table should be gone: selecting from it should now fail with the backend's
|
|
796
|
+
# missing-object diagnostic, not just some unrelated failure.
|
|
797
|
+
with (
|
|
798
|
+
pytest.raises(OperationalError, match="does not exist"),
|
|
799
|
+
connection.closing_cursor() as cursor,
|
|
800
|
+
):
|
|
801
|
+
cursor.execute(f"SELECT * FROM `{auto_dropped_table_name}`")
|
|
802
|
+
finally:
|
|
803
|
+
with suppress(Exception):
|
|
804
|
+
connection.execute_snapshot_ddl(
|
|
805
|
+
f"DROP MATERIALIZED TABLE IF EXISTS `{auto_dropped_table_name}`"
|
|
806
|
+
)
|
|
807
|
+
|
|
681
808
|
|
|
682
809
|
@pytest.mark.integration
|
|
683
810
|
class TestArrayStatements:
|
|
@@ -440,6 +440,10 @@ class TestStatementProperties:
|
|
|
440
440
|
("CREATE_VIEW", True),
|
|
441
441
|
("DROP_VIEW", True),
|
|
442
442
|
("ALTER_TABLE", True),
|
|
443
|
+
("CREATE_MATERIALIZED_TABLE", True),
|
|
444
|
+
("CREATE_OR_ALTER_MATERIALIZED_TABLE", True),
|
|
445
|
+
("ALTER_MATERIALIZED_TABLE", True),
|
|
446
|
+
("DROP_MATERIALIZED_TABLE", True),
|
|
443
447
|
("SELECT", False),
|
|
444
448
|
("INSERT", False),
|
|
445
449
|
("UPDATE", False),
|
|
@@ -980,32 +984,63 @@ class TestStatementCanFetchResults:
|
|
|
980
984
|
statement = Statement.from_response(mock_connection, statement_json)
|
|
981
985
|
assert statement.can_fetch_results(ExecutionMode.STREAMING_QUERY)
|
|
982
986
|
|
|
987
|
+
@pytest.mark.parametrize(
|
|
988
|
+
"sql_kind",
|
|
989
|
+
[
|
|
990
|
+
"CREATE_TABLE",
|
|
991
|
+
"CREATE_MATERIALIZED_TABLE",
|
|
992
|
+
"CREATE_OR_ALTER_MATERIALIZED_TABLE",
|
|
993
|
+
"ALTER_MATERIALIZED_TABLE",
|
|
994
|
+
"DROP_MATERIALIZED_TABLE",
|
|
995
|
+
],
|
|
996
|
+
)
|
|
983
997
|
@pytest.mark.parametrize("phase", ["PENDING", "RUNNING"])
|
|
984
998
|
def test_streaming_ddl_pure_ddl_not_ready(
|
|
985
999
|
self,
|
|
986
1000
|
mock_connection: Connection,
|
|
987
1001
|
statement_response_factory: StatementResponseFactory,
|
|
988
1002
|
phase: str,
|
|
1003
|
+
sql_kind: str,
|
|
989
1004
|
):
|
|
990
|
-
"""In streaming DDL mode, pure DDL must wait for terminal state.
|
|
1005
|
+
"""In streaming DDL mode, pure DDL must wait for terminal state.
|
|
1006
|
+
|
|
1007
|
+
The three MATERIALIZED_TABLE kinds are included alongside CREATE_TABLE here: even though
|
|
1008
|
+
CREATE_MATERIALIZED_TABLE, CREATE_OR_ALTER_MATERIALIZED_TABLE, and
|
|
1009
|
+
ALTER_MATERIALIZED_TABLE all kick off (or redeploy) a persistent background refresh job
|
|
1010
|
+
on completion, each statement's own phase reliably reaches a terminal phase once that job
|
|
1011
|
+
is started (confirmed against a real environment -- unlike CTAS, which the Flink API
|
|
1012
|
+
traits currently mis-report as perpetually RUNNING, see is_bounded's Jan 2026 bug note),
|
|
1013
|
+
so they belong in the same "must wait for terminal" bucket as the other pure DDL kinds.
|
|
1014
|
+
"""
|
|
991
1015
|
statement_json = statement_response_factory(
|
|
992
1016
|
phase=phase,
|
|
993
|
-
sql_kind=
|
|
1017
|
+
sql_kind=sql_kind,
|
|
994
1018
|
)
|
|
995
1019
|
statement = Statement.from_response(mock_connection, statement_json)
|
|
996
1020
|
assert not statement.can_fetch_results(ExecutionMode.STREAMING_DDL)
|
|
997
1021
|
|
|
1022
|
+
@pytest.mark.parametrize(
|
|
1023
|
+
"sql_kind",
|
|
1024
|
+
[
|
|
1025
|
+
"CREATE_TABLE",
|
|
1026
|
+
"CREATE_MATERIALIZED_TABLE",
|
|
1027
|
+
"CREATE_OR_ALTER_MATERIALIZED_TABLE",
|
|
1028
|
+
"ALTER_MATERIALIZED_TABLE",
|
|
1029
|
+
"DROP_MATERIALIZED_TABLE",
|
|
1030
|
+
],
|
|
1031
|
+
)
|
|
998
1032
|
@pytest.mark.parametrize("phase", ["COMPLETED", "STOPPED", "FAILED"])
|
|
999
1033
|
def test_streaming_ddl_pure_ddl_ready(
|
|
1000
1034
|
self,
|
|
1001
1035
|
mock_connection: Connection,
|
|
1002
1036
|
statement_response_factory: StatementResponseFactory,
|
|
1003
1037
|
phase: str,
|
|
1038
|
+
sql_kind: str,
|
|
1004
1039
|
):
|
|
1005
1040
|
"""In streaming DDL mode, pure DDL is ready in terminal states."""
|
|
1006
1041
|
statement_json = statement_response_factory(
|
|
1007
1042
|
phase=phase,
|
|
1008
|
-
sql_kind=
|
|
1043
|
+
sql_kind=sql_kind,
|
|
1009
1044
|
)
|
|
1010
1045
|
statement = Statement.from_response(mock_connection, statement_json)
|
|
1011
1046
|
assert statement.can_fetch_results(ExecutionMode.STREAMING_DDL)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/simple_append_only_streaming_query_example.py
RENAMED
|
File without changes
|
{confluent_sql-0.5.1 → confluent_sql-0.5.2}/examples/snapshot_mode_tuple_cursor_simple_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|