sqlite-utils icon indicating copy to clipboard operation
sqlite-utils copied to clipboard

Release 4.0a0 - and eventually 4.0

Open simonw opened this issue 6 months ago • 4 comments

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

simonw avatar May 09 '25 03:05 simonw

8 commits since last release: https://github.com/simonw/sqlite-utils/compare/3.38...8e7d018fa2582e90433c242168994e4b8f504ed8

simonw avatar May 09 '25 03:05 simonw

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?

simonw avatar May 09 '25 06:05 simonw

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

simonw avatar May 09 '25 06:05 simonw

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

simonw avatar May 09 '25 06:05 simonw