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.5.0.tar.gz (27.6 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.5.0-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for sqless-3.5.0.tar.gz
Algorithm Hash digest
SHA256 79e9c8cdd1bdcc6a691846236f22e42595356121b5b4a6645e000697524f9296
MD5 e023d5c67b85a26347592044b44ac75c
BLAKE2b-256 4579c76bd61eace42d99e06baa1460b47e6e5f3e24e2af7d0f5982cb1eec85dc

See more details on using hashes here.

File details

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

File metadata

  • Download URL: sqless-3.5.0-py3-none-any.whl
  • Upload date:
  • Size: 29.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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 23c4010ff546345afa82180488dbd867ffb8487b8188a97dd715961c76983734
MD5 241e86fb08ca6a6691028a6ad83b2bb3
BLAKE2b-256 57a13c01bca32427c63dee19d37826023c22f709797bf21b2915820122925a35

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