Skip to main content

A schema-flexible, zero-abstraction SQLite interface supporting Relational tables, JSON tables, Full-Text Search, and Semantic Search.

Project description

sqless

English | 中文版

A schema-flexible, zero-abstraction SQLite interface supporting Relational tables, JSON tables, Full-Text Search, and Semantic Search.

:@sqless


Why sqless is special

  • Schema-free – automatically adjusts the table schema to fit the input data structure.
  • High-performance – executes SQL directly, close to raw SQLite speed, faster than many ORMs.
  • Multi-file sharding – store data across multiple SQLite files easily.
  • SQL-safe – semantic parsing, parameter binding, and identifier validation prevent SQL injection.
  • Multi-table type – supports Relational, JSON, Full-Text Search (FTS), and Vector tables.

⚡ Performance Test

  • Unit: Seconds (lower is better).
  • Percentages indicate the performance difference compared to other libraries.
    • : How much faster sqless is than the library (i.e., how much slower the library is).
    • : How much slower sqless is than raw SQLite (i.e., the overhead of sqless).
Name Init Write Update Read Category
sqlalchemy 0.022 (↑12%) 5.572 (↑94%) 3.218 (↑99%) 58.345 (↑97%) Static schema
dataset 0.030 (↑33%) 10.337 (↑97%) 1.290 (↑98%) 46.209 (↑96%) Flex schema
pony 0.030 (↑34%) 2.221 (↑84%) 0.679 (↑96%) 10.283 (↑84%) Static schema
sqless 0.020 0.359 0.030 1.676 Flex schema
raw sqlite 0.013 (↓51%) 0.260 (↓38%) 0.023 (↓32%) 1.406 (↓19%) Static schema

See benchmark/cmp_with_other_orms.py for details.


🚀 Quick Start

import sqless

db = sqless.DB("your.db")
table = db['users']

table.upsert({
    'U1': {'name': 'Tom', 'age': 14},
    'U2': {'name': 'Jerry', 'age': 12},
})

for item in table.iter('age < 15'):
    print(item)

table['U1']['age'] = 15   # ❌ does NOT update database
table['U1'] = {'age':15}  # ✅ updates database
print(table['U1']) # {'key': 'U1', 'name': 'Tom', 'age': 15}

🧠 Table Types

Table type is determined by prefix:

Type Prefix Features
Relational none low-flexible schema, partial updates
JSON json_ high-flexible schema, full replacement
FTS fts_ full-text search
Vector vec_ semantic search

🔹 Relational Table

table = db['users']
table['U1'] = {'name': 'Tom', 'age': 14}
table['U1'] = {'age': 15}
print(table['U1']) # {'key': 'U1', 'name': 'Tom', 'age': 15}
  • Partial updates: updating one field does not affect others.

See examples/hello-sqless.py for details.


🔹 JSON Table

table = db['json_users']
table['U1'] = {'name': 'Tom', 'age': 14}
table['U1'] = {'age': 15}
print(table['U1']) # {'age': 15}
  • Full replacement: writing field A will overwrite old fields.

See examples/json-table-example.py for details.


🔹 FTS Table (Full-Text Search)

table = db['fts_docs']

table.upsert({
    "A": "SQLite supports full text search"
})

results = table.search('"SQLite"')

See examples/fts-table-example.py for details.


🔹 Vector Table (Semantic Search)

Requirements:

  1. pip install sqless[vec]
  2. Set SILICON_API_KEY environment variable (uses BAAI/bge-m3 embedding model).
  3. Register for SiliconFlow free API if needed: https://cloud.siliconflow.cn/i/szt2CkYN

Usage:

table = db['vec_docs']

table.upsert({
    "A": "Deep learning is part of machine learning"
})

results = table.search("large language model", k=2)

See examples/vec-table-example.py for details.


📁 Multi-file DB

dbs = sqless.DBS(folder="db_folder")

table = dbs["app-Asia-users"]
table.upsert({...})

Mapping rule:

app-Asia-users
↓
app-Asia.sqlite / users

See examples/multi-files-sqless.py for details.


🗂 DB Operations

dir(db)
db.list_tables()
del db['users']
db.close()

See examples/hello-sqless.py for details.


Safe WHERE Expressions

sqless supports safe, parameterized WHERE parsing:

  • Logical operators: AND, OR, NOT
  • Comparison operators: =, ==, !=, <, >, <=, >=, like, ilike, is, in
  • Parentheses: ( and )
  • Sorting: ORDER BY <column> [ASC|DESC]
  • SQL injection safe: forbidden characters ; -- /* */ blocked
  • Values automatically bound with ? placeholders

Example

# Filter age in [10,12,14] or name like 'Tom%', order by age ascending
where_str = "age in [10,12,14] OR name like 'Tom%' order by age asc"
success, sql, params = parse_where(where_str)
print(sql)    # where age in (?,?,?) or name like ? order by age asc
print(params) # [10, 12, 14, 'Tom%']

Notes:

  • in requires a list value: [10,12,14]
  • is null works, e.g., age is null
  • Column names must be valid identifiers (letters, digits, underscores, Chinese characters; cannot start with a digit)
  • Complex SQL functions or subqueries are not supported

🧭 Use Cases

  • Local database tools
  • Data analysis
  • Lightweight services
  • AI applications (RAG / semantic search)

🔄 Migration / Changes

New in this version:

  • vec_ table (semantic search)
  • fts_ table (full-text search)
  • json_ table (high-flexible schema)

Default table type remains Relational (low-flexible schema).


🔹 Legacy Server (Deprecated)

sqless --host 127.0.0.1 --port 12239 --secret xxx
  • Auto creates directories: www/, db/, fs/
  • Access via: http://127.0.0.1:12239/index.html

⚠️ Will be removed in future versions. Current version still compatible.

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

sqless-3.1.1.tar.gz (26.8 kB view details)

Uploaded Source

Built Distribution

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

sqless-3.1.1-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file sqless-3.1.1.tar.gz.

File metadata

  • Download URL: sqless-3.1.1.tar.gz
  • Upload date:
  • Size: 26.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for sqless-3.1.1.tar.gz
Algorithm Hash digest
SHA256 9603f76b73f28d405e57657891c5075052a04e2a432d5b2cc96ef2fa423f5494
MD5 5b562ab295c360f0b24ee317109d7f05
BLAKE2b-256 7f02354bde3b554f3eda3bc2c559bc2dbf0566e884ea36865c6c92cd09e41415

See more details on using hashes here.

File details

Details for the file sqless-3.1.1-py3-none-any.whl.

File metadata

  • Download URL: sqless-3.1.1-py3-none-any.whl
  • Upload date:
  • Size: 28.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for sqless-3.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9dc9316403e17b68c03284cee7d36dca04bad55f1c9d2cc5d830b9176e8ebbf1
MD5 d500e8bf4bfedc0a445e7df332dfe906
BLAKE2b-256 287de67f4393b5ddb38160e9a6fc838a5470aea979aaa2555823210c5262ac51

See more details on using hashes here.

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