From af49b1660964b4a3d3d429ec8cf04825a0cf4a98 Mon Sep 17 00:00:00 2001 From: Pavlo Mishchenko Date: Mon, 19 Aug 2024 17:09:53 +0300 Subject: [PATCH 1/6] Add client_found_rows option to connect() --- singlestoredb/config.py | 7 +++++++ singlestoredb/connection.py | 1 + singlestoredb/mysql/connection.py | 3 +++ singlestoredb/tests/test_connection.py | 13 +++++++++++++ 4 files changed, 24 insertions(+) diff --git a/singlestoredb/config.py b/singlestoredb/config.py index 1dd120dfa..80bb292f9 100644 --- a/singlestoredb/config.py +++ b/singlestoredb/config.py @@ -103,6 +103,13 @@ environ='SINGLESTOREDB_MULTI_STATEMENTS', ) +register_option( + 'client_found_rows', 'bool', check_bool, False, + 'Should affected_rows in OK_PACKET indicate the ' + 'number of matched rows instead of changed?', + environ='SINGLESTOREDB_CLIENT_FOUND_ROWS', +) + register_option( 'ssl_key', 'str', check_str, None, 'File containing SSL key', diff --git a/singlestoredb/connection.py b/singlestoredb/connection.py index 663f9ec97..d840fbd23 100644 --- a/singlestoredb/connection.py +++ b/singlestoredb/connection.py @@ -1298,6 +1298,7 @@ def connect( program_name: Optional[str] = None, conn_attrs: Optional[Dict[str, str]] = None, multi_statements: Optional[bool] = None, + client_found_rows: Optional[bool] = None, connect_timeout: Optional[int] = None, nan_as_null: Optional[bool] = None, inf_as_null: Optional[bool] = None, diff --git a/singlestoredb/mysql/connection.py b/singlestoredb/mysql/connection.py index b388ee4b1..928685a05 100644 --- a/singlestoredb/mysql/connection.py +++ b/singlestoredb/mysql/connection.py @@ -347,6 +347,7 @@ def __init__( # noqa: C901 driver=None, # internal use conn_attrs=None, multi_statements=None, + client_found_rows=None, nan_as_null=None, inf_as_null=None, encoding_errors='strict', @@ -380,6 +381,8 @@ def __init__( # noqa: C901 client_flag |= CLIENT.LOCAL_FILES if multi_statements: client_flag |= CLIENT.MULTI_STATEMENTS + if client_found_rows: + client_flag |= CLIENT.FOUND_ROWS if read_default_group and not read_default_file: if sys.platform.startswith('win'): diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 75f9c5f96..1b59d3314 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2776,6 +2776,19 @@ def test_multi_statements(self): self.assertEqual([(2,)], list(cur)) self.assertIsNone(cur.nextset()) + def test_client_found_rows(self): + if self.conn.driver not in ['http', 'https']: + with s2.connect(database=type(self).dbname, client_found_rows=True) as conn: + with conn.cursor() as cur: + cur.execute("CREATE TABLE test_client_found_rows (id BIGINT \ + PRIMARY KEY, s TEXT DEFAULT 'def');") + cur.execute('INSERT INTO test_client_found_rows (id) \ + VALUES (1), (2), (3);') + cur.execute("UPDATE test_client_found_rows SET s = 'def' \ + WHERE id = 1;") + self.assertEqual(1, conn.affected_rows()) + cur.execute('DROP TABLE test_client_found_rows;') + def test_connect_timeout(self): with s2.connect(database=type(self).dbname, connect_timeout=8) as conn: with conn.cursor() as cur: From d188242f38faca00c6d9d4703af65a73daddce62 Mon Sep 17 00:00:00 2001 From: Pavlo Mishchenko Date: Mon, 19 Aug 2024 23:02:17 +0300 Subject: [PATCH 2/6] Add uuid to test table name --- singlestoredb/tests/test_connection.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 1b59d3314..464d410b5 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2778,16 +2778,34 @@ def test_multi_statements(self): def test_client_found_rows(self): if self.conn.driver not in ['http', 'https']: + with s2.connect(database=type(self).dbname, client_found_rows=False) as conn: + with conn.cursor() as cur: + table_name = f'test_client_found_rows_{uuid.uuid4()}' + cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ + PRIMARY KEY, s TEXT DEFAULT 'def');") + cur.execute(f'INSERT INTO {table_name} (id) \ + VALUES (1), (2), (3);') + cur.execute(f"UPDATE {table_name} SET s = 'def' \ + WHERE id = 1;") + # UPDATE statement above is not changing any rows, + # so affected_rows is 0 if client_found_rows is False (default) + self.assertEqual(0, conn.affected_rows()) + cur.execute(f'DROP TABLE {table_name};') + with s2.connect(database=type(self).dbname, client_found_rows=True) as conn: with conn.cursor() as cur: - cur.execute("CREATE TABLE test_client_found_rows (id BIGINT \ + table_name = f'test_client_found_rows_{uuid.uuid4()}' + cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ PRIMARY KEY, s TEXT DEFAULT 'def');") - cur.execute('INSERT INTO test_client_found_rows (id) \ + cur.execute(f'INSERT INTO {table_name} (id) \ VALUES (1), (2), (3);') - cur.execute("UPDATE test_client_found_rows SET s = 'def' \ + cur.execute(f"UPDATE {table_name} SET s = 'def' \ WHERE id = 1;") + # UPDATE statement above is not changing any rows, + # but affected_rows is 1 as 1 row is subject to update, and + # this is what affected_rows return when client_found_rows is True self.assertEqual(1, conn.affected_rows()) - cur.execute('DROP TABLE test_client_found_rows;') + cur.execute(f'DROP TABLE {table_name};') def test_connect_timeout(self): with s2.connect(database=type(self).dbname, connect_timeout=8) as conn: From b6194b8c77db016e14b417b181f755ff6f939ba0 Mon Sep 17 00:00:00 2001 From: Kevin D Smith Date: Tue, 20 Aug 2024 09:08:50 -0500 Subject: [PATCH 3/6] Update test_connection.py --- singlestoredb/tests/test_connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 464d410b5..0606a5bb9 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2780,7 +2780,7 @@ def test_client_found_rows(self): if self.conn.driver not in ['http', 'https']: with s2.connect(database=type(self).dbname, client_found_rows=False) as conn: with conn.cursor() as cur: - table_name = f'test_client_found_rows_{uuid.uuid4()}' + table_name = f'test_client_found_rows_{uuid.uuid4()}'.replace('-', '_') cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ PRIMARY KEY, s TEXT DEFAULT 'def');") cur.execute(f'INSERT INTO {table_name} (id) \ From e006024f8ce7627dbc6b2196c280f10dbb5d1677 Mon Sep 17 00:00:00 2001 From: Kevin D Smith Date: Tue, 20 Aug 2024 09:34:31 -0500 Subject: [PATCH 4/6] Update test_connection.py --- singlestoredb/tests/test_connection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 0606a5bb9..03b31e07e 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2780,7 +2780,8 @@ def test_client_found_rows(self): if self.conn.driver not in ['http', 'https']: with s2.connect(database=type(self).dbname, client_found_rows=False) as conn: with conn.cursor() as cur: - table_name = f'test_client_found_rows_{uuid.uuid4()}'.replace('-', '_') + tag = uuid.uuid4().replace('-', '_') + table_name = f'test_client_found_rows_{tag}' cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ PRIMARY KEY, s TEXT DEFAULT 'def');") cur.execute(f'INSERT INTO {table_name} (id) \ From a1678601f812de03aee1c0aa8d5492e4b17ebe64 Mon Sep 17 00:00:00 2001 From: Kevin D Smith Date: Tue, 20 Aug 2024 10:22:35 -0500 Subject: [PATCH 5/6] Update test_connection.py --- singlestoredb/tests/test_connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 03b31e07e..73318b675 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2780,7 +2780,7 @@ def test_client_found_rows(self): if self.conn.driver not in ['http', 'https']: with s2.connect(database=type(self).dbname, client_found_rows=False) as conn: with conn.cursor() as cur: - tag = uuid.uuid4().replace('-', '_') + tag = str(uuid.uuid4()).replace('-', '_') table_name = f'test_client_found_rows_{tag}' cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ PRIMARY KEY, s TEXT DEFAULT 'def');") From 6524cc0eb26616a2c054bd2489946b22bd2557f0 Mon Sep 17 00:00:00 2001 From: Kevin D Smith Date: Tue, 20 Aug 2024 10:58:31 -0500 Subject: [PATCH 6/6] Update test_connection.py --- singlestoredb/tests/test_connection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/singlestoredb/tests/test_connection.py b/singlestoredb/tests/test_connection.py index 73318b675..c0e73e815 100755 --- a/singlestoredb/tests/test_connection.py +++ b/singlestoredb/tests/test_connection.py @@ -2795,7 +2795,8 @@ def test_client_found_rows(self): with s2.connect(database=type(self).dbname, client_found_rows=True) as conn: with conn.cursor() as cur: - table_name = f'test_client_found_rows_{uuid.uuid4()}' + tag = str(uuid.uuid4()).replace('-', '_') + table_name = f'test_client_found_rows_{tag}' cur.execute(f"CREATE TABLE {table_name} (id BIGINT \ PRIMARY KEY, s TEXT DEFAULT 'def');") cur.execute(f'INSERT INTO {table_name} (id) \