# Bazoola
[](https://github.com/ddoroshev/bazoola/actions/workflows/ci.yml)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
A lightweight, file-based database implementation in Python designed for educational purposes and simple applications.
## Overview
Bazoola is a minimal database system that stores data in text files with fixed-width fields. It supports basic database operations like CRUD (Create, Read, Update, Delete), schema validation, foreign key relationships, and simple querying capabilities.
## Features
- **File-based storage**: Data is stored in human-readable text files with fixed-width fields
- **Schema definition**: Define table schemas with typed fields
- **Primary keys**: Automatic ID generation (manual ID assignment validates uniqueness but doesn't support custom sequences)
- **Foreign keys**: Support for relationships between tables
- **Indexing**: ID-based indexing for fast lookups
- **Joins**: Support for joining related tables
- **Querying**: Find records by field values, substrings, or custom conditions
- **Free space management**: Reuses deleted record space
## Installation
### Install as a package
```bash
# Install directly from GitHub
pip install git+https://github.com/ddoroshev/bazoola.git
```
### Development setup
```bash
# Clone the repository
git clone https://github.com/ddoroshev/bazoola.git
cd bazoola
# Install dependencies using Poetry
poetry install
```
## Quick Start
```python
from bazoola import DB, Table, Schema, Field, PK, FK, CHAR, INT, Join
# Define table schemas
class TableAuthors(Table):
name = "authors"
schema = Schema([
Field("id", PK()),
Field("name", CHAR(20)),
])
class TableBooks(Table):
name = "books"
schema = Schema([
Field("id", PK()),
Field("title", CHAR(20)),
Field("author_id", FK("authors")),
Field("year", INT(null=True)),
])
# Create database instance
db = DB([TableAuthors, TableBooks])
# Insert data
author = db.insert("authors", {"name": "John Doe"})
book = db.insert("books", {
"title": "My Book",
"author_id": author["id"],
"year": 2024
})
# Query with joins
book_with_author = db.find_by_id(
"books",
book["id"],
joins=[Join("author_id", "author", "authors")]
)
print(book_with_author)
# Output: {'id': 1, 'title': 'My Book', 'author_id': 1, 'year': 2024, 'author': {'id': 1, 'name': 'John Doe'}}
# Close the database
db.close()
```
## Field Types
- **PK()**: Primary key field (auto-incrementing integer)
- **INT(null=False)**: Integer field
- **CHAR(size, null=False)**: Fixed-size character field
- **FK(table_name, null=False)**: Foreign key field
## API Reference
### Database Operations
```python
# Insert a record
row = db.insert("table_name", {"field": "value"})
# Find by ID
row = db.find_by_id("table_name", id)
# Find all records
rows = db.find_all("table_name")
# Find by field value
rows = db.find_by("table_name", "field_name", value)
# Find by substring
rows = db.find_by_substr("table_name", "field_name", "substr")
# Update a record
row = db.update_by_id("table_name", id, {"field": "new_value"})
# Delete a record
db.delete_by_id("table_name", id)
# Delete by substring match
db.delete_by_substr("table_name", "field_name", "substr")
# Truncate table
db.truncate("table_name", cascade=False)
```
### Advanced Queries
```python
from db import GT, LT
# Find with conditions
rows = db.find_by_cond("books", GT(year=2020))
rows = db.find_by_cond("books", LT(year=2000))
# Query with joins
rows = db.find_all("books", joins=[
Join("author_id", "author", "authors")
])
# Inverse joins (one-to-many)
from db import InverseJoin
author = db.find_by_id("authors", 1, joins=[
InverseJoin("author_id", "books", "books")
])
```
## File Structure
Bazoola creates the following files for each table:
- `{table_name}.dat` - Main data file
- `{table_name}__seqnum.dat` - Sequence number for auto-increment
- `{table_name}__id.idx.dat` - Primary key index
- `{table_name}__free.dat` - Free rownum stack for space reuse
## Configuration
Set the `TABLE_BASE_DIR` environment variable to specify where database files should be stored:
```bash
export TABLE_BASE_DIR=/path/to/data/directory
```
## Testing
```bash
# Run tests
poetry run pytest
# Run tests with coverage
poetry run pytest --cov
# Type checking
poetry run mypy .
# Linting
poetry run ruff check .
```
## Limitations
- No multi-threading support
- No transactions or rollback support
- Limited query optimization
- Fixed-size fields only
- No SQL interface (by design)
## License
This project is licensed under the MIT License - see the LICENSE file for details.
Raw data
{
"_id": null,
"home_page": "https://github.com/ddoroshev/bazoola",
"name": "bazoola",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "database, file-based, educational, lightweight",
"author": "Dima Doroshev",
"author_email": "github@doroshev.com",
"download_url": "https://files.pythonhosted.org/packages/46/0b/8372d7ea3cc1c8f32ae8321a642bd76a3c09a639d355f63d2b2f798f85c2/bazoola-0.0.1.tar.gz",
"platform": null,
"description": "# Bazoola\n\n[](https://github.com/ddoroshev/bazoola/actions/workflows/ci.yml)\n[](https://www.python.org/downloads/)\n[](https://opensource.org/licenses/MIT)\n\nA lightweight, file-based database implementation in Python designed for educational purposes and simple applications.\n\n## Overview\n\nBazoola is a minimal database system that stores data in text files with fixed-width fields. It supports basic database operations like CRUD (Create, Read, Update, Delete), schema validation, foreign key relationships, and simple querying capabilities.\n\n## Features\n\n- **File-based storage**: Data is stored in human-readable text files with fixed-width fields\n- **Schema definition**: Define table schemas with typed fields\n- **Primary keys**: Automatic ID generation (manual ID assignment validates uniqueness but doesn't support custom sequences)\n- **Foreign keys**: Support for relationships between tables\n- **Indexing**: ID-based indexing for fast lookups\n- **Joins**: Support for joining related tables\n- **Querying**: Find records by field values, substrings, or custom conditions\n- **Free space management**: Reuses deleted record space\n\n## Installation\n\n### Install as a package\n\n```bash\n# Install directly from GitHub\npip install git+https://github.com/ddoroshev/bazoola.git\n```\n\n### Development setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/ddoroshev/bazoola.git\ncd bazoola\n\n# Install dependencies using Poetry\npoetry install\n```\n\n## Quick Start\n\n```python\nfrom bazoola import DB, Table, Schema, Field, PK, FK, CHAR, INT, Join\n\n# Define table schemas\nclass TableAuthors(Table):\n name = \"authors\"\n schema = Schema([\n Field(\"id\", PK()),\n Field(\"name\", CHAR(20)),\n ])\n\nclass TableBooks(Table):\n name = \"books\"\n schema = Schema([\n Field(\"id\", PK()),\n Field(\"title\", CHAR(20)),\n Field(\"author_id\", FK(\"authors\")),\n Field(\"year\", INT(null=True)),\n ])\n\n# Create database instance\ndb = DB([TableAuthors, TableBooks])\n\n# Insert data\nauthor = db.insert(\"authors\", {\"name\": \"John Doe\"})\nbook = db.insert(\"books\", {\n \"title\": \"My Book\",\n \"author_id\": author[\"id\"],\n \"year\": 2024\n})\n\n# Query with joins\nbook_with_author = db.find_by_id(\n \"books\",\n book[\"id\"],\n joins=[Join(\"author_id\", \"author\", \"authors\")]\n)\nprint(book_with_author)\n# Output: {'id': 1, 'title': 'My Book', 'author_id': 1, 'year': 2024, 'author': {'id': 1, 'name': 'John Doe'}}\n\n# Close the database\ndb.close()\n```\n\n## Field Types\n\n- **PK()**: Primary key field (auto-incrementing integer)\n- **INT(null=False)**: Integer field\n- **CHAR(size, null=False)**: Fixed-size character field\n- **FK(table_name, null=False)**: Foreign key field\n\n## API Reference\n\n### Database Operations\n\n```python\n# Insert a record\nrow = db.insert(\"table_name\", {\"field\": \"value\"})\n\n# Find by ID\nrow = db.find_by_id(\"table_name\", id)\n\n# Find all records\nrows = db.find_all(\"table_name\")\n\n# Find by field value\nrows = db.find_by(\"table_name\", \"field_name\", value)\n\n# Find by substring\nrows = db.find_by_substr(\"table_name\", \"field_name\", \"substr\")\n\n# Update a record\nrow = db.update_by_id(\"table_name\", id, {\"field\": \"new_value\"})\n\n# Delete a record\ndb.delete_by_id(\"table_name\", id)\n\n# Delete by substring match\ndb.delete_by_substr(\"table_name\", \"field_name\", \"substr\")\n\n# Truncate table\ndb.truncate(\"table_name\", cascade=False)\n```\n\n### Advanced Queries\n\n```python\nfrom db import GT, LT\n\n# Find with conditions\nrows = db.find_by_cond(\"books\", GT(year=2020))\nrows = db.find_by_cond(\"books\", LT(year=2000))\n\n# Query with joins\nrows = db.find_all(\"books\", joins=[\n Join(\"author_id\", \"author\", \"authors\")\n])\n\n# Inverse joins (one-to-many)\nfrom db import InverseJoin\nauthor = db.find_by_id(\"authors\", 1, joins=[\n InverseJoin(\"author_id\", \"books\", \"books\")\n])\n```\n\n## File Structure\n\nBazoola creates the following files for each table:\n- `{table_name}.dat` - Main data file\n- `{table_name}__seqnum.dat` - Sequence number for auto-increment\n- `{table_name}__id.idx.dat` - Primary key index\n- `{table_name}__free.dat` - Free rownum stack for space reuse\n\n## Configuration\n\nSet the `TABLE_BASE_DIR` environment variable to specify where database files should be stored:\n\n```bash\nexport TABLE_BASE_DIR=/path/to/data/directory\n```\n\n## Testing\n\n```bash\n# Run tests\npoetry run pytest\n\n# Run tests with coverage\npoetry run pytest --cov\n\n# Type checking\npoetry run mypy .\n\n# Linting\npoetry run ruff check .\n```\n\n## Limitations\n\n- No multi-threading support\n- No transactions or rollback support\n- Limited query optimization\n- Fixed-size fields only\n- No SQL interface (by design)\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A lightweight, file-based database implementation in Python",
"version": "0.0.1",
"project_urls": {
"Documentation": "https://github.com/ddoroshev/bazoola#readme",
"Homepage": "https://github.com/ddoroshev/bazoola",
"Repository": "https://github.com/ddoroshev/bazoola"
},
"split_keywords": [
"database",
" file-based",
" educational",
" lightweight"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "836eabc17bb8cf67e5445df8f057df1f59fd7ef5a17c9d9ef4d17a08a602c9eb",
"md5": "82a45b9b90ed9389f1b59dc91d811740",
"sha256": "737f8b00a4968e177da7b27a4467a15a147ead175b4d990f5c19be1659eef4b6"
},
"downloads": -1,
"filename": "bazoola-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "82a45b9b90ed9389f1b59dc91d811740",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 8731,
"upload_time": "2025-07-14T15:02:09",
"upload_time_iso_8601": "2025-07-14T15:02:09.562324Z",
"url": "https://files.pythonhosted.org/packages/83/6e/abc17bb8cf67e5445df8f057df1f59fd7ef5a17c9d9ef4d17a08a602c9eb/bazoola-0.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "460b8372d7ea3cc1c8f32ae8321a642bd76a3c09a639d355f63d2b2f798f85c2",
"md5": "48ef97f5412e8aec1fc7c3978b9993a0",
"sha256": "4d400bb677c5fe8cbba8327043c2b99257a177491120defc51716ae1bcd69f86"
},
"downloads": -1,
"filename": "bazoola-0.0.1.tar.gz",
"has_sig": false,
"md5_digest": "48ef97f5412e8aec1fc7c3978b9993a0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 10034,
"upload_time": "2025-07-14T15:02:11",
"upload_time_iso_8601": "2025-07-14T15:02:11.633865Z",
"url": "https://files.pythonhosted.org/packages/46/0b/8372d7ea3cc1c8f32ae8321a642bd76a3c09a639d355f63d2b2f798f85c2/bazoola-0.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-14 15:02:11",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ddoroshev",
"github_project": "bazoola",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "bazoola"
}