Commit Graph
52 Commits
Author SHA1 Message Date
Jiseok CHOI dbd3a0a6b3 sqlite3: add SQLITE_DBCONFIG constants, setconfig() and getconfig() (#8535)
* sqlite3: add SQLITE_DBCONFIG constants, setconfig() and getconfig()

Implement Connection.setconfig() and Connection.getconfig() using
sqlite3_db_config(), and export all SQLITE_DBCONFIG_* integer
constants to the module.

Fixes test_connection_config in test_dbapi.py.

Assisted-by: GitHub Copilot:claude-sonnet-4-6

* sqlite3: fix setconfig to propagate actual SQLite error

When sqlite3_db_config() returns a non-OK result, propagate the actual
SQLite error instead of replacing it with a generic 'Unable to set
config' message, to match CPython's set_error_from_db() behavior.

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-08-16 20:13:10 +09:00
Jiseok CHOI e19b622174 sqlite3: pass None for NULL authorizer args instead of crashing (#8534)
* sqlite3: pass None for NULL authorizer args instead of crashing

CPython's authorizer callback receives NULL for arg1/arg2/db_name/access
when not applicable (e.g. SQLITE_READ on a table gives NULL for the
database name in some versions). Previously RustPython passed these
pointers to ptr_to_str which would crash or produce an error.

Now ptr_to_str_or_none is used: NULL pointers become Python None, which
matches CPython behavior and allows test_table_access and
test_column_access to pass.

Assisted-by: GitHub Copilot:claude-sonnet-4-6

* fix(sqlite3): avoid reentrant deadlock in Statement::new

sqlite3_prepare_v2 can synchronously invoke the authorizer callback,
which may call back into Connection methods (e.g. set_authorizer)
that require the same db lock. Holding db_lock across the prepare()
call caused a self-deadlock when a callback re-entered the connection.

Release the lock after sql_limit check and copy the raw handle before
calling prepare(), so FFI calls that can trigger Python re-entrancy
happen outside the lock scope.

Fixes hang in test_authorizer_concurrent_mutation_in_call
2026-08-15 21:05:33 +09:00
Jiseok CHOI a142de9abc sqlite3: add Connection exception attributes and fix autocommit ValueError (#8533)
Add DB-API 2.0 optional extension: expose exception classes as attributes
on Connection objects (Warning, Error, InterfaceError, DatabaseError,
DataError, OperationalError, IntegrityError, InternalError,
ProgrammingError, NotSupportedError).

Also fix autocommit validation to raise ValueError (not TypeError) when
an unsupported type is passed.

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-08-15 21:05:12 +09:00
Jiseok CHOI 7cda53b946 sqlite3: validate narg before creating functions/aggregates (#8532)
CPython 3.14 added check_num_params() which raises ProgrammingError when
narg/n_arg/num_params is out of range (-1..=SQLITE_LIMIT_FUNCTION_ARG).
RustPython passed invalid values directly to SQLite, resulting in an
OperationalError instead.

Add check_num_params() helper and call it in create_function(),
create_aggregate(), and create_window_function().

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-08-15 21:04:45 +09:00
Chanho Lee 4d890b33db Fix sqlite autocommit cursor transactions (#8419)
Assisted-by: Codex:gpt-5.6-sol
2026-08-01 11:28:59 +09:00
Chanho Lee 15e7b2027e Fix sqlite autocommit lifecycle (#8387)
* fix: open disabled sqlite autocommit transactions

Assisted-by: Codex:gpt-5.6-sol

* fix: reopen disabled sqlite transactions after commit

Assisted-by: Codex:gpt-5.6-sol

* fix: reopen disabled sqlite transactions after rollback

Assisted-by: Codex:gpt-5.6-sol

* fix: roll back disabled sqlite connections on close

Assisted-by: Codex:gpt-5.6-sol
2026-07-27 21:42:19 +09:00
Jiseok CHOI 375051ddf8 sqlite3: raise ProgrammingError when named param receives sequence (#8363)
CPython raises ProgrammingError with "Binding N is a named parameter"
when a query uses named placeholders (, , ) but
the caller passes a sequence instead of a mapping.

RustPython's bind_parameters_sequence() did not check whether each
binding slot is a named parameter, so no error was raised.

Fix: call sqlite3_bind_parameter_name() for each slot in
bind_parameters_sequence(). If the first byte of the returned name is
not '?' (i.e. it is a named placeholder), raise ProgrammingError before
attempting to bind.

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-07-26 13:02:25 +09:00
Jiseok CHOI 64352495d7 sqlite3: allow Row construction with cursor having no description (#8364)
Row(cursor, data) raised ValueError when cursor.description was None.
CPython allows this case and returns an empty key list.

- Use empty tuple when description is None instead of raising
- Include the key name in the IndexError when a string key is not found

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-07-25 19:55:36 +09:00
Jiseok CHOI 2082675d96 sqlite3: fix closed connection error message to match CPython (#8362)
When a Connection is explicitly closed via con.close(), subsequent
operations (cursor(), commit(), rollback(), create_function(), etc.)
should raise ProgrammingError with 'Cannot operate on a closed database.'
to match CPython behaviour.

Previously, _db_lock() always returned 'Base Connection.__init__ not
called.' when self.db was None, without distinguishing between a
connection that was never initialised (subclass before __init__) and
one that was initialised and then explicitly closed.

Fix: inspect the initialized atomic flag — if True but db is None,
the connection was closed; if False, it was never initialised.

Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-07-25 19:54:59 +09:00
Jiseok CHOI a218e4ce99 sqlite3: fix isolation_level TypeError message to match CPython (#8313)
Assisted-by: GitHub Copilot:claude-sonnet-4-6
2026-07-19 13:56:02 +09:00
Shahar Naveh d93dd2a781 Update test_sqlite3 to 3.14.6 (#8172) 2026-06-30 23:49:27 +09:00
Jiseok CHOIandJeong, YunWon 913f8c86f7 sqlite3: fix Blob.__setitem__ value range validation (#7981)
* sqlite3: fix Blob.__setitem__ value range validation

Previously, assigning an out-of-range integer (negative or > 255) or an
integer too large for i64 (e.g. 2**65) to a Blob index raised OverflowError
instead of ValueError.

Mirror CPython's ass_subscript_index logic:
- Convert the value via to_i64(), treating any overflow as -1
- Validate the result is in [0, 255], raising ValueError("byte must be in range(0, 256)") otherwise
- Separate deletion error messages: "item deletion" for index, "slice deletion" for slice

* sqlite3: fix Blob.__setitem__ negative-step slice write

In the step != 1 branch of Blob.ass_subscript, the loop used
  i_in_temp += step as usize
where step is isize. For negative steps (e.g. step = -2),
  (-2isize) as usize = 18446744073709551614
causing an out-of-bounds panic whenever slice_len >= 2.

Fix: use SaturatedSliceIter (already used by the read path) to iterate
over the correct absolute blob indices, then map each index back to a
temp buffer offset via abs_idx - range_start.

Also fix a Clippy lint: replace
  val < 0 || val > 255
with the idiomatic
  !(0..=255).contains(&val)

Add a regression test in extra_tests/snippets/stdlib_sqlite.py that
exercises blob[9:0:-2] (negative step, slice_len=5).

* fix: guard blob negative-step snippet from CPython 3.11 bug

* style: add blank line after import sys in stdlib_sqlite snippet (ruff)

* Update extra_tests/snippets/stdlib_sqlite.py

---------

Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com>
2026-05-27 16:40:05 +09:00
Jiseok CHOI ccad9c168a Fix sqlite3 Cursor.fetchmany to not fetch rows when size=0 (#7425) 2026-03-14 15:49:55 +09:00
Jiseok CHOI 828f960110 sqlite3: add Cursor.row_factory pygetset and fix Connection.cursor() propagation (#7278)
Add #[pygetset] getter/setter for Cursor.row_factory so that Python-level
attribute access reads/writes the Rust struct field instead of the
instance dict.

Fix Connection.cursor() to only propagate the connection's row_factory
to the cursor when the connection's row_factory is not None, matching
CPython behavior. Previously it unconditionally overwrote the cursor's
row_factory, discarding any factory set by a cursor subclass __init__.
2026-03-01 10:44:50 +09:00
Jiseok CHOI a6b06c80fd sqlite3: handle int type in Connection.timeout parameter (#7237) 2026-02-28 10:38:30 +09:00
Jiseok CHOI 3f86af32f3 sqlite3: reject negative fetchmany values (#7240) 2026-02-27 21:03:40 +09:00
Jiseok CHOI 0d1e0d48e8 sqlite3: reject negative arraysize values (#7238) 2026-02-27 20:59:15 +09:00
Jiseok CHOI 00440b179a Update sqlite3 and the tests to CPython 3.14.2 (#6787)
* Update sqlite3, dbm.sqlite3 and tests to CPython 3.14.2

* Add skip decorators for failing sqlite3 tests

Skip tests that fail due to unimplemented features or behavior differences:
- _iterdump not implemented (test_dump.py)
- Unraisable exception handling not implemented (test_hooks.py, test_userfunctions.py)
- Keyword-only arguments not supported for various methods
- Autocommit behavior differences (test_transactions.py)
- TransactionTests skipped due to timeout parameter type issue
- Various error message differences (test_dbapi.py)
- SQLITE_DBCONFIG constants not implemented
- Row and Connection signature inspection issues

All tests now pass with 95 skipped out of 493 total tests.

* Change @unittest.skip to @unittest.expectedFailure per code review

- Convert @unittest.skip decorators to @unittest.expectedFailure for tests that fail without panic/hang
- Keep @unittest.skip only for TransactionTests class (setUp fails with timeout=0 int type)

* fixup
2026-01-19 02:45:47 +09:00
Jiseok CHOI 050db4725f sqlite3: fix Connection.cursor() factory argument handling (#6783)
Fix test_is_instance in CursorFactoryTests by properly handling the
factory argument in Connection.cursor() method. Now the factory can
be passed as both positional and keyword argument, and returns the
correct subclass type instead of always returning PyRef<Cursor>.

- Use FromArgs derive macro with CursorArgs struct for argument parsing
- Return PyObjectRef instead of PyRef<Cursor> to allow subclasses
- Use fast_issubclass to validate returned cursor is a Cursor subclass
- Properly differentiate between 'no argument' and 'None passed'
2026-01-18 23:37:47 +09:00
Terry Tianlin LuanandJeong, YunWon 609dbb1439 Downgraded skips in tests (#6716)
* Downgraded skips in tests

* Fixed failing tests

* Fixed test_ftplib + test_socket + test_ssl + test_threaded_import failures

* Removed comments about which tests are run in which environment

* Addressed PR comments

* Annotated skips on failing tests

* Removed unneeded tests

* Removed unneeded sys import from test_ftplib

* Added annotation to test_ftplib

* Readded skipIf to test_cleanup_with_symlink_modes with a more general ENV_POLLUTING_TESTS_WINDOWS

* Addressed PR comments

* Made changes to minimize diff in PR

* Apply suggestion from @youknowone

---------

Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com>
2026-01-15 21:43:22 +09:00
Jeong, YunWon 527111bc98 PyWrapperDescrObject and rewrite toggle_slot (#6536)
* SlotFunc

* slotdef

* unify slots

* remove unsed slots
2025-12-28 11:44:36 +09:00
Jiseok CHOI a14dd5921d fix(sqlite): Raise ProgrammingError when operating on a closed cursor (#6339) 2025-12-08 00:14:31 +09:00
Jiseok CHOI a9469a20d5 Fix sqlite connection reinitialization (#6288)
* Fix sqlite connection reinitialization

* Align sqlite connection reinit with CPython

* Enable sqlite test_connection_bad_reinit

* Fix sqlite reinit flag without threading

* Use stronger memory ordering for initialized flag synchronization
2025-11-22 22:13:06 +09:00
Jiseok CHOI 567fb4dec0 fix(sqlite): raise ProgrammingError when operating on a blob with a closed connection, (#6286)
Fixed #6285
2025-11-22 20:42:24 +09:00
Jiseok CHOI 2faa05dcfb Fix sqlite Connection initialization check (#6199)
* Fix sqlite3 Connection initialization check

Add proper __init__ validation for sqlite3.Connection to ensure base class
__init__ is called before using connection methods. This fixes the
test_connection_constructor_call_check test case.

Changes:
- Modified Connection.py_new to detect subclassing
- For base Connection class, initialization happens immediately in py_new
- For subclassed Connection, db is initialized as None
- Added __init__ method that performs actual database initialization
- Updated _db_lock error message to match CPython: 'Base Connection.__init__ not called.'

This ensures CPython compatibility where attempting to use a Connection
subclass instance without calling the base __init__ raises ProgrammingError.

* use Initializer trait
2025-10-21 11:11:31 +09:00
Jiseok CHOI 25a464eeae Fix sqlite3 Cursor initialization check (#6198)
Add proper __init__ validation for sqlite3.Cursor to ensure base class
__init__ is called before using cursor methods. This fixes the
test_cursor_constructor_call_check test case.

Changes:
- Modified Cursor to initialize with inner=None in py_new
- Added explicit __init__ method that sets up CursorInner
- Updated close() method to check for uninitialized state
- Changed error message to match CPython: 'Base Cursor.__init__ not called.'

This ensures CPython compatibility where attempting to use a Cursor
instance without calling the base __init__ raises ProgrammingError.
2025-10-21 09:33:55 +09:00
Jiseok CHOI a2b194a6f8 sqlite3: Support 'size' keyword argument in Cursor::fetchmany 2025-09-01 15:23:04 +09:00
Jiseok CHOI e909e32f31 sqlite: Fix missing ProgrammingError for parameter mismatch (#6104) 2025-08-21 13:19:38 +09:00
Jiseok CHOI a58d582001 Implement unsupported ops for sqlite3.Blob (#6066) 2025-08-05 17:53:06 +09:00
Jiseok CHOI b2d6594bd9 Prevent direct instantiation of sqlite3.{Statement,Blob} 2025-08-01 13:39:45 +09:00
Jiseok CHOI 1e6da5f430 sqlite: Align Connection.__call__ error handling with CPython (#6042) 2025-07-30 14:05:17 +09:00
Jiseok CHOI d8f1d188c3 stdlib(sqlite): Raise ProgrammingError in closed Blob context manager (#6041) 2025-07-27 21:47:05 +09:00
Jiseok CHOI 38ca076cb5 feat(stdlib/sqlite): Implement slice assignment for Blob (#6039) 2025-07-27 10:43:11 +09:00
Jiseok CHOI fb9147736d stdlib(sqlite3): Raise ProgrammingError for missing named parameter (#6036) 2025-07-25 19:02:56 +09:00
Jiseok CHOI bcf56279ec Raise UnicodeEncodeError for surrogates in sqlite.executescript (#6024) 2025-07-25 10:45:33 +09:00
Jiseok CHOI 57bdf35ee6 Enforce valid UTF-8 encoding for sqlite collation names (#6015)
* Make public `PyStr::ensure_valid_utf8`

* Enforce valid UTF-8 encoding for sqlite collation names
2025-07-21 23:42:47 +09:00
Jiseok CHOI bbe98ddd86 Construct detailed message on text decode failure (#6014) 2025-07-21 22:33:09 +09:00
Jiseok CHOI 6f80ac0edd Align SQL comment parsing with CPython (#5996) 2025-07-20 10:51:42 +09:00
Jiseok CHOI f8d03fd680 Correctly implement isolation_level setter to handle deletion (#5983) 2025-07-18 23:08:51 +09:00
Jiseok CHOI 5957f5d31a Fix off-by-one error in SQL length limit check (#5982) 2025-07-16 01:53:20 +09:00
Jiseok CHOI f465af3a7c Reject SQL queries containing null characters (#5981) 2025-07-16 01:52:28 +09:00
Jiseok CHOI 6d2152cafe Correctly handle None for protocol in adapt(..) (#5979) 2025-07-16 01:49:53 +09:00
Jiseok CHOI ed433837b3 Introduce PyUtf8Str and fix(sqlite): validate surrogates in SQL statements (#5969)
* fix(sqlite): validate surrogates in SQL statements

* Add `PyUtf8Str` wrapper for safe conversion
2025-07-15 00:54:42 +09:00
Jiseok CHOI 5ab64b7002 fix(sqlite): align adaptation protocol with CPython (#5964) 2025-07-14 14:22:52 +09:00
Jiseok CHOI d42e8f0042 fix(sqlite): produce correct error for surrogate characters (#5962) 2025-07-14 14:21:36 +09:00
Jiseok CHOI 3a6a766a03 fix(sqlite): implement PARSE_COLNAMES column name parsing (#5923) 2025-07-10 00:18:40 +09:00
Jiseok CHOI e6fdef43dc fix(sqlite): autocommit mode transaction handling to match CPython (#5918) 2025-07-09 20:13:26 +09:00
Jiseok CHOI 341341520e Fix SQLite large integer overflow error handling (#5916) 2025-07-09 17:14:45 +09:00
Ashwin Naren b81ae9b954 More cspell fixes (#5670) 2025-04-11 09:37:20 +09:00
Noa a86126419c Fix remaining tests 2025-03-25 19:05:12 -05:00