|
1 | 1 | import os |
2 | 2 | import sqlite3 |
| 3 | +import time |
3 | 4 |
|
4 | 5 | import pytest |
5 | 6 |
|
| 7 | +import sqlitecloud |
6 | 8 | from sqlitecloud.datatypes import SQLiteCloudException |
| 9 | +from tests.conftest import get_sqlitecloud_dbapi2_connection |
7 | 10 |
|
8 | 11 |
|
9 | 12 | class TestSQLite3FeatureParity: |
10 | 13 | @pytest.fixture() |
11 | 14 | def sqlite3_connection(self): |
| 15 | + yield next(self.get_sqlite3_connection()) |
| 16 | + |
| 17 | + def get_sqlite3_connection(self): |
| 18 | + # set isolation_level=None to enable autocommit |
| 19 | + # and to be aligned with the behavior of SQLite Cloud |
12 | 20 | connection = sqlite3.connect( |
13 | | - os.path.join(os.path.dirname(__file__), "../assets/chinook.sqlite") |
| 21 | + os.path.join(os.path.dirname(__file__), "../assets/chinook.sqlite"), |
| 22 | + isolation_level=None, |
14 | 23 | ) |
15 | 24 | yield connection |
16 | 25 | connection.close() |
@@ -243,3 +252,73 @@ def test_fetchall(self, sqlitecloud_dbapi2_connection, sqlite3_connection): |
243 | 252 | assert sqlitecloud_results == sqlite3_results |
244 | 253 | assert len(sqlitecloud_results) == 0 |
245 | 254 | assert len(sqlite3_results) == 0 |
| 255 | + |
| 256 | + def test_autocommit_mode_enabled_by_default( |
| 257 | + self, sqlitecloud_dbapi2_connection, sqlite3_connection |
| 258 | + ): |
| 259 | + seed = str(int(time.time())) |
| 260 | + |
| 261 | + connections = [ |
| 262 | + (sqlitecloud_dbapi2_connection, next(get_sqlitecloud_dbapi2_connection())), |
| 263 | + (sqlite3_connection, next(self.get_sqlite3_connection())), |
| 264 | + ] |
| 265 | + |
| 266 | + for (connection, control_connection) in connections: |
| 267 | + connection.execute( |
| 268 | + "INSERT INTO albums (Title, ArtistId) VALUES (? , 1);", |
| 269 | + (f"Test {seed}",), |
| 270 | + ) |
| 271 | + |
| 272 | + cursor2 = control_connection.execute( |
| 273 | + "SELECT * FROM albums WHERE Title = ?", (f"Test {seed}",) |
| 274 | + ) |
| 275 | + assert cursor2.fetchone() is not None |
| 276 | + |
| 277 | + def test_explicit_transaction_to_commit( |
| 278 | + self, |
| 279 | + sqlitecloud_dbapi2_connection: sqlitecloud.Connection, |
| 280 | + sqlite3_connection: sqlite3.Connection, |
| 281 | + ): |
| 282 | + seed = str(int(time.time())) |
| 283 | + |
| 284 | + connections = [ |
| 285 | + (sqlitecloud_dbapi2_connection, next(get_sqlitecloud_dbapi2_connection())), |
| 286 | + (sqlite3_connection, next(self.get_sqlite3_connection())), |
| 287 | + ] |
| 288 | + |
| 289 | + for (connection, control_connection) in connections: |
| 290 | + cursor1 = connection.execute("BEGIN;") |
| 291 | + cursor1.execute( |
| 292 | + "INSERT INTO albums (Title, ArtistId) VALUES (?, 1);", (f"Test {seed}",) |
| 293 | + ) |
| 294 | + |
| 295 | + cursor2 = control_connection.execute( |
| 296 | + "SELECT * FROM albums WHERE Title = ?", (f"Test {seed}",) |
| 297 | + ) |
| 298 | + assert cursor2.fetchone() is None |
| 299 | + |
| 300 | + connection.commit() |
| 301 | + |
| 302 | + cursor2.execute("SELECT * FROM albums WHERE Title = ?", (f"Test {seed}",)) |
| 303 | + assert cursor2.fetchone() is not None |
| 304 | + |
| 305 | + def test_explicit_transaction_to_rollback( |
| 306 | + self, |
| 307 | + sqlitecloud_dbapi2_connection: sqlitecloud.Connection, |
| 308 | + sqlite3_connection: sqlite3.Connection, |
| 309 | + ): |
| 310 | + seed = str(int(time.time())) |
| 311 | + |
| 312 | + for connection in [sqlitecloud_dbapi2_connection, sqlite3_connection]: |
| 313 | + cursor1 = connection.execute("BEGIN;") |
| 314 | + cursor1.execute( |
| 315 | + "INSERT INTO albums (Title, ArtistId) VALUES (?, 1);", (f"Test {seed}",) |
| 316 | + ) |
| 317 | + |
| 318 | + cursor1.execute("SELECT * FROM albums WHERE Title = ?", (f"Test {seed}",)) |
| 319 | + assert cursor1.fetchone() is not None |
| 320 | + |
| 321 | + connection.rollback() |
| 322 | + |
| 323 | + cursor1.execute("SELECT * FROM albums WHERE Title = ?", (f"Test {seed}",)) |
| 324 | + assert cursor1.fetchone() is None |
0 commit comments