"""Phase 3 integration tests — DDL + DML. Tests CREATE TEMP TABLE, INSERT, UPDATE, DELETE end-to-end with row counts verified via subsequent SELECTs. """ from __future__ import annotations import pytest import informix_db from tests.conftest import ConnParams pytestmark = pytest.mark.integration def _connect(conn_params: ConnParams) -> informix_db.Connection: return informix_db.connect( host=conn_params.host, port=conn_params.port, user=conn_params.user, password=conn_params.password, database=conn_params.database, server=conn_params.server, connect_timeout=10.0, read_timeout=10.0, ) def test_create_temp_table(conn_params: ConnParams) -> None: """DDL: CREATE TEMP TABLE returns rowcount=0 and no description.""" with _connect(conn_params) as conn: cur = conn.cursor() cur.execute("CREATE TEMP TABLE t_phase3_a (id INTEGER, name VARCHAR(50))") assert cur.description is None assert cur.rowcount == 0 def test_insert_then_select_persists(conn_params: ConnParams) -> None: """DML: INSERT actually persists; SELECT returns inserted rows.""" with _connect(conn_params) as conn: cur = conn.cursor() cur.execute("CREATE TEMP TABLE t_phase3_b (id INTEGER, name VARCHAR(50))") cur.execute("INSERT INTO t_phase3_b VALUES (1, 'alpha')") assert cur.rowcount == 1 cur.execute("INSERT INTO t_phase3_b VALUES (2, 'beta')") assert cur.rowcount == 1 cur.execute("INSERT INTO t_phase3_b VALUES (3, 'gamma')") assert cur.rowcount == 1 cur.execute("SELECT id, name FROM t_phase3_b ORDER BY id") rows = cur.fetchall() assert rows == [(1, "alpha"), (2, "beta"), (3, "gamma")] def test_update_with_where(conn_params: ConnParams) -> None: """UPDATE with WHERE clause changes rowcount-many rows.""" with _connect(conn_params) as conn: cur = conn.cursor() cur.execute("CREATE TEMP TABLE t_phase3_c (id INTEGER, name VARCHAR(50))") cur.execute("INSERT INTO t_phase3_c VALUES (1, 'old')") cur.execute("INSERT INTO t_phase3_c VALUES (2, 'old')") cur.execute("INSERT INTO t_phase3_c VALUES (3, 'old')") cur.execute("UPDATE t_phase3_c SET name = 'new' WHERE id = 2") # rowcount semantics: at least the affected row count # (Phase 3.x will refine — for now we check the SELECT) cur.execute("SELECT id, name FROM t_phase3_c ORDER BY id") rows = cur.fetchall() assert rows == [(1, "old"), (2, "new"), (3, "old")] def test_delete_with_where(conn_params: ConnParams) -> None: """DELETE with WHERE removes the matched row.""" with _connect(conn_params) as conn: cur = conn.cursor() cur.execute("CREATE TEMP TABLE t_phase3_d (id INTEGER, name VARCHAR(50))") cur.execute("INSERT INTO t_phase3_d VALUES (1, 'keep')") cur.execute("INSERT INTO t_phase3_d VALUES (2, 'delete')") cur.execute("INSERT INTO t_phase3_d VALUES (3, 'keep')") cur.execute("DELETE FROM t_phase3_d WHERE id = 2") cur.execute("SELECT id, name FROM t_phase3_d ORDER BY id") rows = cur.fetchall() assert rows == [(1, "keep"), (3, "keep")] def test_full_dml_cycle_in_one_connection(conn_params: ConnParams) -> None: """Mix DDL, multiple DML, and SELECT on one connection — proves session state.""" with _connect(conn_params) as conn: cur = conn.cursor() cur.execute("CREATE TEMP TABLE t_phase3_e (id INTEGER, val INTEGER)") for i in range(1, 6): cur.execute(f"INSERT INTO t_phase3_e VALUES ({i}, {i * 10})") cur.execute("SELECT val FROM t_phase3_e WHERE id > 2 ORDER BY id") rows = cur.fetchall() assert rows == [(30,), (40,), (50,)] cur.execute("DELETE FROM t_phase3_e WHERE id <= 2") cur.execute("SELECT id FROM t_phase3_e ORDER BY id") rows = cur.fetchall() assert rows == [(3,), (4,), (5,)] def test_commit_rollback_in_unlogged_db_raises(conn_params: ConnParams) -> None: """commit() and rollback() fail with OperationalError in sysmaster (no logging). Confirms the commit/rollback wire machinery works — it sends the right PDU and parses the SQ_ERR response. To actually test transactions, point integration at a logged database (e.g. ``stores_demo``). """ with ( _connect(conn_params) as conn, pytest.raises(informix_db.OperationalError, match="-255"), ): conn.commit()