Skip to main content

Cute sqlite3 wrapper for sql tables

Project description

Sql-Engine

My Sql-Engine is a cute little wrapper for sqlite3 table manipulations without any third party dependencies.

Features

Abstracts SQL queries into tiny little methods like, insert, insert_many, upsert, and not so little and tiny query builders a-la select, delete, update, etc. Sql-Engine also provides bulk insertion and transaction methods, like insert_many and select.fetchmany_iterator. Methods can be executed in transaction mode thanks to transaction context manager.

Sql-Engine implements Jupyter integration and dynamic schema building. You can easily instantiate existing database table and view it in cute little html representation.

from sqlengine import schema

table = schema.table_from_database("temp/chinook.db", "Album")
table
Album
AlbumIdTitleArtistId
1For Those About To Rock We Salute You1
2Balls to the Wall2
3Restless and Wild2
4Let There Be Rock1
5Big Ones3
6Jagged Little Pill4
7Facelift5
8Warner 25 Anos6
9Plays Metallica By Four Cellos7
10Audioslave8
... more rows ...

Note that GitHub's html rendering is simplified.


You can preview select statements before fetching data to your variables.

table = schema.table_from_database("temp/chinook.db", "Invoice")

table.select("InvoiceId", "CustomerId", "BillingAddress", "BillingCountry", "Total")\
    .where\
        .gte("Total", 2.0)\
    .then\
        .order_by("CustomerId")\
        .limit(10)
Invoice
InvoiceIdCustomerIdBillingAddressBillingCountryTotal
981Av. Brigadeiro Faria Lima, 2170Brazil3.98
1211Av. Brigadeiro Faria Lima, 2170Brazil3.96
1431Av. Brigadeiro Faria Lima, 2170Brazil5.94
3271Av. Brigadeiro Faria Lima, 2170Brazil13.86
3821Av. Brigadeiro Faria Lima, 2170Brazil8.91
122Theodor-Heuss-Straße 34Germany13.86
672Theodor-Heuss-Straße 34Germany8.91
2192Theodor-Heuss-Straße 34Germany3.96
2412Theodor-Heuss-Straße 34Germany5.94
9931498 rue BélangerCanada3.98

Purpose

It's a tiny little modern ORM-like that lets you prototype your databases locally with great flexibility. Also, it can be used in production apps to store and retrieve data, because all select, update, delete queries are parametrized. But it does not restrict you from using your own queries which might not be paramerized with methods like select.custom() and where.custom().

And last (but not least) is data inspection. If you need to quickly inspect existing .db file but don't want to install yet another heavy ORM with a lot of unused dependencies, you might look into Sql-Engine, as it uses only native python modules.

Installation

To install sqlengine, you can use pip:

pip install sqlengine-lite

Env

You may set environment variable for logging. By default it's WARNING.

SQL_ENGINE_LOG_LEVEL=INFO

Quick Start

All you have to do to create your own cute little table is to inherit SqlTableMixin class or to create your own schema and declare desired properties of your table's columns. They are:

Name of the table that will be used in queries. If omitted in inherited class declaration, then it will take the class name.

__tablename__ : Optional[str]

Column names of the table

__columns__ : list[str] 

Column types of the table

__types__ : list[SqlType | str] 

List of primary keys

__primary__ : list[str] 

Table Declaration

More details at Declaration.

from sqlengine import SqlTableMixin, Primary

# Helper constants for column names
ID = "ID"
Name = "Name"
Occupation = "Occupation"
Salary = "Salary"


class Employees(SqlTableMixin):

    ID         : Primary[int]
    Name       : str
    Occupation : str
    Salary     : float

    # You may overwrite your insert methods for type consistency
    def insert(self, id : int, name : str, occupation : str, salary : float) -> None:
        return super().insert(id, name, occupation, salary)
    
    def upsert(self, id : int, name : str, occupation : str, salary : float) -> None:
        return super().upsert(id, name, occupation, salary)

Instantiation

More details at Instantiation.

# Create an instance of the table class 
# with provided path to create or connect to
# `force_drop=True` to overwrite existing table if exists

table = Employees("temp/data.db", force_drop=True)

Row insertion

# Insert one row

table.insert(1, "John Doe", "Software Engineer", 75000.0)
# Bulk insert multiple rows

employees_data = [
    (2, "Jane Smith", "Data Scientist", 80000.0),
    (3, "Alice Johnson", "Product Manager", 90000.0),
    (4, "Bob Brown", "Project Manager", 78000.0),
    (5, "Charlie Davis", "UI/UX Designer", 65000.0),
    (6, "David Wilson", "DevOps Engineer", 82000.0),
    (7, "Eve Taylor", "Customer Support", 45000.0),
    (8, "Frank White", "Quality Assurance", 53000.0),
    (9, "Grace Hall", "Marketing Manager", 68000.0),
    (10, "Henry Lee", "Technical Writer", 52000.0)
]

table.insert_many(employees_data)
# Upsert one row

table.upsert(1, "Jane Doe", "Data Scientist", 80000.0)

Jupyter view

# Inspect tables in Jupyter Notebook

table
Employees
IDNameOccupationSalary
1Jane DoeData Scientist80000.0
2Jane SmithData Scientist80000.0
3Alice JohnsonProduct Manager90000.0
4Bob BrownProject Manager78000.0
5Charlie DavisUI/UX Designer65000.0
6David WilsonDevOps Engineer82000.0
7Eve TaylorCustomer Support45000.0
8Frank WhiteQuality Assurance53000.0
9Grace HallMarketing Manager68000.0
10Henry LeeTechnical Writer52000.0

Select Query

More details at Statements.

# Query select and fetch

table.select.where.between(ID, 3, 5).then.fetchall()

# ->
# [(3, 'Alice Johnson', 'Product Manager', 90000.0),
#  (4, 'Bob Brown', 'Project Manager', 78000.0),
#  (5, 'Charlie Davis', 'UI/UX Designer', 65000.0)]
# Inspect query select in Jupyter

table.select(Name, Salary).where.lt(Salary, 70_000)
Employees
NameSalary
Charlie Davis65000.0
Eve Taylor45000.0
Frank White53000.0
Grace Hall68000.0
Henry Lee52000.0

Update Query

# equal to ...update.set(Salary, 50_000)...
table.update(Salary, 50_000).where.eq(Name, "Eve Taylor").then.execute()

Delete Query

table.delete.where.eq(ID, 5).then.execute()

Transaction

More details at Transaction.

# Operate within a transaction

with table.transaction():
    for row in employees_data:
        table.upsert(*row)

Get Item

More details at Syntax Sugar.

# Fetch row by primary key

table[9]

# -> (9, 'Grace Hall', 'Marketing Manager', 68000.0)
# Fetch slice by integer primary key

table[4:10:2]

# -> 
# [(4, 'Bob Brown', 'Project Manager', 78000.0),
#  (6, 'David Wilson', 'DevOps Engineer', 82000.0),
#  (8, 'Frank White', 'Quality Assurance', 53000.0)]

Custom Types

More details at Custom Types.

from datetime import datetime
from sqlengine import SqlTableMixin, Primary

class DateTime(datetime):
    
    def to_sql(self) -> str:
        return self.strftime("%Y-%m-%d %H:%M")

    @classmethod
    def from_sql(cls, sql : bytes):
        return cls.fromisoformat(sql.decode('utf-8'))
    
    def __repr__(self):
        return f"DateTime({self.time})"


class ReservationIndex(SqlTableMixin):

    user_id : Primary[int]
    room_id : Primary[str]
    time_at : Primary[DateTime]
    user_name : str | None


table = ReservationIndex("temp/data.db")

table.insert(1, "loft_1", DateTime.now(), None)
table
ReservationIndex
user_idroom_idtime_atuser_name
1loft_12026-05-29 21:29:00None

Csv Converter

# Save table to csv
from sqlengine.utils import to_csv

to_csv(table, "temp/table.csv")
# Save query result to csv

to_csv(table.select.where.gt(Salary, 70_000), "temp/query.csv")

Full Documentation

For detailed usage, API reference, and advanced examples, see the full documentation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqlengine_lite-2.2.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlengine_lite-2.2.0-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file sqlengine_lite-2.2.0.tar.gz.

File metadata

  • Download URL: sqlengine_lite-2.2.0.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sqlengine_lite-2.2.0.tar.gz
Algorithm Hash digest
SHA256 ca09c4f7cacb8cf37b5dcdda831312cc1e3afb8d916d32bfac1b08d4412e6674
MD5 6da112e0a6493b335b1ae613d0d25017
BLAKE2b-256 6f8dada38442d5a8834c8a62736fec50ef56613869aaa2d5d83b5be95eee6073

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlengine_lite-2.2.0.tar.gz:

Publisher: publish.yml on suffermuffin/SQL-Engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sqlengine_lite-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: sqlengine_lite-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sqlengine_lite-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 09859c6610fc90f855c3d272c2c4bbfe0c026f705867ab330998369f6fd56219
MD5 77249bc63ac4913aadf7a70a3bb927f3
BLAKE2b-256 c5ff91056669c783330ae2d7b9b82b3a05e8f92315539c3b394b84c50f2ecee1

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlengine_lite-2.2.0-py3-none-any.whl:

Publisher: publish.yml on suffermuffin/SQL-Engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page