Skip to content

SqliterDB

The main entry point for all database operations. Manages SQLite connections, table creation, CRUD operations, caching, and transactions.

from sqliter import SqliterDB

Source: sqliter/sqliter.py

See also: Guide -- Connecting, Guide -- Properties, Guide -- Tables, Guide -- Data Operations, Guide -- Caching, Guide -- Transactions


Class Attribute

MEMORY_DB

Constant for in-memory database filename.

MEMORY_DB = ":memory:"

Constructor

def __init__(
    self,
    db_filename: str | None = None,
    *,
    memory: bool = False,
    auto_commit: bool = True,
    debug: bool = False,
    logger: logging.Logger | None = None,
    reset: bool = False,
    return_local_time: bool = True,
    cache_enabled: bool = False,
    cache_max_size: int = 1000,
    cache_ttl: int | None = None,
    cache_max_memory_mb: int | None = None,
) -> None:

Parameters:

ParameterTypeDefaultDescription
db_filenamestr | NoneNonePath to the SQLite database file
memoryboolFalseIf True, create an in-memory database
auto_commitboolTrueAuto-commit after each operation
debugboolFalseEnable SQL debug logging
loggerLogger | NoneNoneCustom logger for debug output
resetboolFalseDrop all tables on initialization
return_local_timeboolTrueReturn local time for datetime fields
cache_enabledboolFalseEnable query result caching
cache_max_sizeint1000Max cached queries per table (LRU)
cache_ttlint | NoneNoneTime-to-live for cache entries (seconds)
cache_max_memory_mbint | NoneNoneMax memory for cache (MB)

Raises:

  • ValueError -- If no filename is provided for a non-memory database, if cache_max_size <= 0, if cache_ttl < 0, or if cache_max_memory_mb <= 0.

Example:

# File-based database
db = SqliterDB("myapp.db")

# In-memory database
db = SqliterDB(memory=True)

# With caching enabled
db = SqliterDB(
    "myapp.db",
    cache_enabled=True,
    cache_ttl=300,
    cache_max_memory_mb=50,
)

Properties

filename

Returns the database filename, or None if using an in-memory database.

TypeDescription
str | NoneFile path or None for in-memory

is_memory

Returns True if the database is in-memory.

TypeDescription
boolTrue for :memory: databases

is_autocommit

Returns True if auto-commit is enabled.

TypeDescription
boolCurrent auto-commit setting

is_connected

Returns True if a database connection is currently open.

TypeDescription
boolConnection status

table_names

Returns a list of all table names in the database. Temporarily connects if not already connected and restores the connection state afterward.

TypeDescription
list[str]All user table names (excludes sqlite_ system tables)

Example:

db = SqliterDB("myapp.db")
print(db.table_names)  # ["users", "posts", ...]

Connection Methods

connect()

Establish a connection to the SQLite database. Enables foreign key constraint enforcement via PRAGMA foreign_keys = ON.

def connect(self) -> sqlite3.Connection:

Returns:

sqlite3.Connection -- The SQLite connection object.

Raises:

close()

Close the database connection. Commits pending changes if auto_commit is True. Clears the query cache and resets cache statistics.

def close(self) -> None:

commit()

Explicitly commit the current transaction.

def commit(self) -> None:

Table Methods

create_table()

Create a database table based on a model class. Handles column definitions, primary keys, foreign key constraints, and indexes.

def create_table(
    self,
    model_class: type[BaseDBModel],
    *,
    exists_ok: bool = True,
    force: bool = False,
) -> None:

Parameters:

ParameterTypeDefaultDescription
model_classtype[BaseDBModel]requiredThe model class defining the table
exists_okboolTrueIf True, do not raise if table exists
forceboolFalseIf True, drop and recreate the table

Raises:

Example:

db.create_table(User)
db.create_table(User, force=True)  # Drop and recreate

drop_table()

Drop the table associated with a model class.

def drop_table(
    self,
    model_class: type[BaseDBModel],
) -> None:

Parameters:

ParameterTypeDefaultDescription
model_classtype[BaseDBModel]requiredThe model class whose table to drop

Raises:


CRUD Methods

insert()

Insert a new record into the database. Sets created_at and updated_at timestamps automatically.

def insert(
    self,
    model_instance: T,
    *,
    timestamp_override: bool = False,
) -> T:

Parameters:

ParameterTypeDefaultDescription
model_instanceTrequiredThe model instance to insert
timestamp_overrideboolFalseIf True, respect provided non-zero timestamp values

Returns:

T -- A new model instance with pk set to the inserted row's ID.

Raises:

Example:

user = User(name="Alice", email="[email protected]")
saved = db.insert(user)
print(saved.pk)  # e.g. 1

bulk_insert()

Insert multiple records of the same model type in a single transaction. More efficient than calling insert() in a loop.

def bulk_insert(
    self,
    instances: Sequence[T],
    *,
    timestamp_override: bool = False,
) -> list[T]:

Parameters:

ParameterTypeDefaultDescription
instancesSequence[T]requiredThe model instances to insert
timestamp_overrideboolFalseIf True, respect provided non-zero timestamp values

Returns:

list[T] -- New model instances with pk set for each inserted row. Returns [] for an empty input sequence.

Raises:

Behavior:

  • All records are inserted within a single transaction. If any record fails, the entire batch is rolled back.
  • When called inside a with db: context manager, the commit is deferred to context exit.
  • Cache is invalidated once after all records are inserted.

Example:

users = [
    User(name="Alice", email="[email protected]"),
    User(name="Bob", email="[email protected]"),
]
saved = db.bulk_insert(users)
print(saved[0].pk, saved[1].pk)  # e.g. 1, 2

get()

Retrieve a single record by its primary key.

def get(
    self,
    model_class: type[T],
    primary_key_value: int,
    *,
    bypass_cache: bool = False,
    cache_ttl: int | None = None,
) -> T | None:

Parameters:

ParameterTypeDefaultDescription
model_classtype[T]requiredThe model class
primary_key_valueintrequiredThe primary key value
bypass_cacheboolFalseSkip cache read/write for this lookup
cache_ttlint | NoneNoneOptional TTL override for this specific lookup

Returns:

T | None -- The model instance if found, None otherwise.

Raises:

  • RecordFetchError -- If there is an error fetching the record.
  • ValueError -- If cache_ttl is negative.

Example:

user = db.get(User, 1)
if user:
    print(user.name)

Caching:

When cache_enabled=True, get() uses the query cache. Use bypass_cache=True to force a fresh lookup, or cache_ttl to override the global cache TTL for this call.

update()

Update an existing record. The model instance must have a valid pk. Automatically sets updated_at to the current time.

def update(
    self,
    model_instance: BaseDBModel,
) -> None:

Parameters:

ParameterTypeDefaultDescription
model_instanceBaseDBModelrequiredThe model instance to update

Raises:

Example:

user = db.get(User, 1)
user.name = "Bob"
db.update(user)

delete()

Delete a record by its primary key.

def delete(
    self,
    model_class: type[BaseDBModel],
    primary_key_value: int | str,
) -> None:

Parameters:

ParameterTypeDefaultDescription
model_classtype[BaseDBModel]requiredThe model class
primary_key_valueint | strrequiredThe primary key of the record to delete

Raises:

Example:

db.delete(User, 1)

select()

Create a QueryBuilder for constructing queries with filters, ordering, pagination, and more.

def select(
    self,
    model_class: type[T],
    fields: list[str] | None = None,
    exclude: list[str] | None = None,
) -> QueryBuilder[T]:

Parameters:

ParameterTypeDefaultDescription
model_classtype[T]requiredThe model class to query
fieldslist[str] | NoneNoneFields to include
excludelist[str] | NoneNoneFields to exclude

Returns:

QueryBuilder[T] -- A query builder for method chaining.

Example:

# Simple query
users = db.select(User).fetch_all()

# With filters and ordering
users = (
    db.select(User)
    .filter(active=True)
    .order("name")
    .limit(10)
    .fetch_all()
)

# Exclude fields
users = db.select(User, exclude=["password_hash"]).fetch_all()

Cache Methods

get_cache_stats()

Get cache performance statistics.

def get_cache_stats(self) -> dict[str, int | float]:

Returns:

dict[str, int | float] -- Dictionary with keys:

KeyTypeDescription
hitsintNumber of cache hits
missesintNumber of cache misses
totalintTotal cache lookups
hit_ratefloatHit rate as percentage (0--100)

Example:

stats = db.get_cache_stats()
print(f"Hit rate: {stats['hit_rate']}%")

clear_cache()

Clear all cached query results. Cache statistics (hits/misses) are preserved.

def clear_cache(self) -> None:

Context Manager

SqliterDB can be used as a context manager for transaction management. Within a with block, auto-commit is suppressed and all operations are wrapped in a single transaction.

def __enter__(self) -> Self:
def __exit__(
    self,
    exc_type: type[BaseException] | None,
    exc_value: BaseException | None,
    traceback: TracebackType | None,
) -> None:

Behavior:

  • __enter__: Opens a connection and begins a transaction.
  • __exit__ (no exception): Commits the transaction and closes the connection.
  • __exit__ (exception raised): Rolls back the transaction and closes the connection.
  • Cache is cleared on exit in both cases.

Example:

db = SqliterDB("myapp.db")

with db:
    db.create_table(User)
    db.insert(User(name="Alice"))
    db.insert(User(name="Bob"))
    # Both inserts are committed together on exit

# If an exception occurs, both inserts are rolled back

See also: Guide -- Transactions