42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Small, portable SQLite bind batches for image-index lookups.
|
|
|
|
Older SQLite builds (including some bundled Python distributions) allow only
|
|
999 bound parameters per statement. Keep every variable-length IN query below
|
|
that limit, even when a gallery holds tens of thousands of images.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterator, Sequence
|
|
import sqlite3
|
|
from typing import TypeVar
|
|
|
|
|
|
T = TypeVar("T")
|
|
SQLITE_BIND_BATCH_SIZE = 900
|
|
|
|
|
|
def iter_sqlite_batches(values: Sequence[T], batch_size: int = SQLITE_BIND_BATCH_SIZE) -> Iterator[Sequence[T]]:
|
|
if batch_size < 1 or batch_size > SQLITE_BIND_BATCH_SIZE:
|
|
raise ValueError(f"batch_size must be between 1 and {SQLITE_BIND_BATCH_SIZE}")
|
|
for start in range(0, len(values), batch_size):
|
|
yield values[start:start + batch_size]
|
|
class ClosingConnection(sqlite3.Connection):
|
|
"""sqlite3's default context commits but leaves the handle open on Windows."""
|
|
def __exit__(self, *args):
|
|
try:
|
|
return super().__exit__(*args)
|
|
finally:
|
|
self.close()
|
|
|
|
|
|
class BorrowedReadConnection:
|
|
"""The request owns this read-only handle; nested helpers must not close it."""
|
|
def __init__(self, connection):
|
|
self.connection = connection
|
|
|
|
def __enter__(self):
|
|
return self.connection
|
|
|
|
def __exit__(self, *args):
|
|
return False
|