sqlite-utils
sqlite-utils copied to clipboard
Release 4.0a0 - and eventually 4.0
The change here breaks backwards compatibility a tiny bit:
- #652
I'm going to ship it as a 4.0 alpha first to exercise it a bit more.
If I'm doing a 4.0 there may be other backwards-incompatible changes I want to sneak in too.
Backwards incompatible changes
- [x] https://github.com/simonw/sqlite-utils/issues/652
- [x] https://github.com/simonw/sqlite-utils/issues/657
Other changes for 4.0 (not necessarily backwards incompatible)
- [ ] https://github.com/simonw/sqlite-utils/issues/655
8 commits since last release: https://github.com/simonw/sqlite-utils/compare/3.38...8e7d018fa2582e90433c242168994e4b8f504ed8
The absolute most disruptive change I could make is to switch style away from [table_name] to "table_name" in CREATE TABLE statements - which would be aesthetically more pleasing but would also break EVERY test suite out there that checks for the schema after creating tables.
I think it may be worth it though. This is the only chance to do that.
Might even be possible to create a codemod kind of thing to help people update their tests?
So many tests like this one would have to be updated: https://github.com/simonw/sqlite-utils/blob/094b010fd870e9fe9f020d4df200d4de7f27209b/tests/test_create.py#L52-L61
Here's how to get a list of SQLite reserved words directly from SQLite using ctypes: https://claude.ai/share/69d7fead-9d2c-4083-b00a-b9a389fc2660
import ctypes
import os
import sys
import platform
from ctypes.util import find_library
def get_keywords():
"""Get all SQLite keywords as a set using ctypes."""
# Find and load the SQLite library
if platform.system() == 'Windows':
sqlite_lib_path = find_library('sqlite3')
elif platform.system() == 'Darwin': # macOS
# Common paths on macOS
possible_paths = [
'/usr/lib/libsqlite3.dylib',
'/usr/local/lib/libsqlite3.dylib',
'/opt/homebrew/lib/libsqlite3.dylib' # Homebrew on Apple Silicon
]
sqlite_lib_path = next((path for path in possible_paths if os.path.exists(path)),
find_library('sqlite3'))
else: # Linux and others
sqlite_lib_path = find_library('sqlite3')
if not sqlite_lib_path:
raise RuntimeError("Could not find SQLite library")
sqlite_lib = ctypes.CDLL(sqlite_lib_path)
# Define function prototypes
sqlite_lib.sqlite3_keyword_count.argtypes = []
sqlite_lib.sqlite3_keyword_count.restype = ctypes.c_int
sqlite_lib.sqlite3_keyword_name.argtypes = [ctypes.c_int,
ctypes.POINTER(ctypes.c_char_p),
ctypes.POINTER(ctypes.c_int)]
sqlite_lib.sqlite3_keyword_name.restype = ctypes.c_int
# Create the result set
keywords = set()
# Get the keyword count
count = sqlite_lib.sqlite3_keyword_count()
# Get each keyword
name_ptr = ctypes.c_char_p()
size_ptr = ctypes.c_int()
for i in range(count):
result = sqlite_lib.sqlite3_keyword_name(i, ctypes.byref(name_ptr), ctypes.byref(size_ptr))
if result != 0: # SQLITE_OK is 0
raise Exception(f"SQLite error: {result}")
# Extract the string from the pointer with the correct size
keyword = name_ptr.value[:size_ptr.value].decode('utf-8')
keywords.add(keyword)
return keywords
Adapted from this code in APSW: https://github.com/rogerbinns/apsw/blob/d5a23bc6b00adfbefa5c549f258927adf0170180/src/apsw.c#L1343-L1372