Skip to main content

FastAPI SQL Query Engine

Project description

🚀 DBAnu - FastAPI SQL Query Engine

Transform SQL queries into production-ready REST APIs in seconds.

DBAnu eliminates the boilerplate of creating database APIs. With just a few lines of code, expose any SQL query as a fully-featured FastAPI endpoint with built-in filtering, pagination, authentication, and middleware support.

✨ Why DBAnu?

The Problem

Building database APIs involves repetitive work:

  • Writing the same CRUD endpoints
  • Implementing pagination logic
  • Adding authentication checks
  • Creating filtering systems
  • Handling database connections

The Solution

DBAnu turns this:

# Traditional approach - 50+ lines
@app.get("/api/books")
async def get_books(author: str = None, limit: int = 100, offset: int = 0):
    # Validate inputs, build WHERE clause, handle pagination...
    # ...and much more boilerplate

Into this:

# DBAnu approach - 3 lines
serve_select(
    app=app,
    query_engine=query_engine,
    path="/api/books",
    select_query="SELECT * FROM books LIMIT ? OFFSET ?"
)

🎯 Key Features

🚀 Instant API Generation

Turn any SQL query into a REST endpoint in seconds

🔄 Multi-Database Union Queries

Combine results from SQLite, PostgreSQL, MySQL in a single API call

🛡️ Type-Safe Everything

Pydantic-powered validation for filters, responses, and middleware

🔧 Powerful Middleware System

Intercept and modify queries, add logging, authentication, and more

📊 Smart Pagination

Built-in pagination with priority-based union pagination across databases

🚀 Quick Start

Installation

pip install dbanu

From Zero to API in 60 Seconds

from fastapi import FastAPI
from dbanu import serve_select, SQLiteQueryEngine

app = FastAPI()

# Create a SQLite query engine
query_engine = SQLiteQueryEngine()

# 🎉 Create your first API endpoint
serve_select(
    app=app,
    query_engine=query_engine,
    path="/api/books",
    select_query="SELECT id, title, author FROM books LIMIT ? OFFSET ?",
    count_query="SELECT COUNT(*) FROM books"
)

That's it! You now have a fully functional API with:

  • ✅ Automatic pagination (limit and offset parameters)
  • ✅ Total count for frontend pagination
  • ✅ Proper error handling
  • ✅ FastAPI documentation at /docs

📚 Usage Examples

Basic Query Endpoint

from fastapi import FastAPI
from dbanu import serve_select, SQLiteQueryEngine

app = FastAPI()
query_engine = SQLiteQueryEngine()

# Simple books endpoint
serve_select(
    app=app,
    query_engine=query_engine,
    path="/api/books",
    select_query="SELECT * FROM books LIMIT ? OFFSET ?",
    count_query="SELECT COUNT(*) FROM books"
)

Usage:

GET /api/books?limit=10&offset=0

Advanced Filtering

from pydantic import BaseModel
from dbanu import serve_select, SQLiteQueryEngine

app = FastAPI()

# Define your filter model
class BookFilter(BaseModel):
    author: str | None = None
    min_year: int | None = None

query_engine = SQLiteQueryEngine()

serve_select(
    app=app,
    query_engine=query_engine,
    path="/api/books",
    filter_model=BookFilter,
    select_query=(
        "SELECT id, title, author, year FROM books "
        "WHERE (author = ? OR ? IS NULL) "
        "AND (year >= ? OR ? IS NULL) "
        "LIMIT ? OFFSET ?"
    ),
    select_param=lambda filters, limit, offset: [
        filters.author, filters.author,
        filters.min_year, filters.min_year,
        limit, offset
    ]
)

Usage:

# Get books by Stephen King published after 2000
GET /api/books?author=Stephen%20King&min_year=2000&limit=10&offset=0

Multi-Database Union Queries

Query multiple databases simultaneously and get unified results!

from fastapi import FastAPI
from dbanu import serve_union, SelectSource, SQLiteQueryEngine, PostgreSQLQueryEngine

app = FastAPI()

# Create engines for different databases
sqlite_engine = SQLiteQueryEngine(db_path="./classic_literature.db")
pgsql_engine = PostgreSQLQueryEngine(
    host="localhost", database="fantasy_books", 
    user="user", password="password"
)

# Combine all databases in one endpoint
serve_union(
    app=app,
    sources={
        "classics": SelectSource(
            query_engine=sqlite_engine,
            select_query="SELECT *, 'classic' as genre FROM books LIMIT ? OFFSET ?"
        ),
        "fantasy": SelectSource(
            query_engine=pgsql_engine,
            select_query="SELECT *, 'fantasy' as genre FROM books LIMIT %s OFFSET %s"
        ),
    },
    path="/api/all-books"
)

Usage:

# Get books from ALL databases in one call
GET /api/all-books?limit=20&offset=0

# Control source priority
GET /api/all-books?limit=20&offset=0&priority=fantasy,classics

Enterprise-Grade with Middleware

from fastapi import Depends, FastAPI, HTTPException
from dbanu import serve_select, SQLiteQueryEngine, QueryContext

app = FastAPI()
query_engine = SQLiteQueryEngine()

# Authentication dependency
async def get_current_user():
    return {"user_id": 1, "username": "demo_user", "role": "admin"}

# Middleware: Logging
def logging_middleware(context: QueryContext, next_handler):
    user_info = context.dependency_results.get("get_current_user", {})
    username = user_info.get("username", "anonymous")
    print(f"📝 Request from {username}: {context.filters.model_dump()}")
    return next_handler()

# Middleware: Authorization
def authorization_middleware(context: QueryContext, next_handler):
    current_user = context.dependency_results.get("get_current_user")
    if not current_user:
        raise HTTPException(status_code=401, detail="Authentication required")
    
    # Role-based access control
    if current_user.get("role") not in ["admin", "editor"]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    return next_handler()

# Create the secure endpoint
serve_select(
    app=app,
    query_engine=query_engine,
    path="/api/secure/books",
    dependencies=[Depends(get_current_user)],
    middlewares=[logging_middleware, authorization_middleware],
    select_query="SELECT id, title, author FROM books LIMIT ? OFFSET ?"
)

🏗️ Database Engines

SQLite

from dbanu import SQLiteQueryEngine
query_engine = SQLiteQueryEngine(db_path="./database.db")

PostgreSQL

from dbanu import PostgreSQLQueryEngine
query_engine = PostgreSQLQueryEngine(
    host="localhost",
    database="mydb",
    user="user",
    password="password"
)

MySQL

from dbanu import MySQLQueryEngine
query_engine = MySQLQueryEngine(
    host="localhost",
    database="mydb",
    user="user",
    password="password"
)

🚀 Running the Example

Quick Demo

  1. Start the demo environment:
cd example
docker-compose up -d
  1. Run the example server:
python -m example.server
  1. Explore the APIs:
    • Visit http://localhost:8000/docs
    • Test different endpoints:
      • /api/v1/sqlite/books - Classic literature
      • /api/v1/pgsql/books - Fantasy books
      • /api/v1/mysql/books - Science fiction
      • /api/v1/all/books - All books combined!

🧪 Testing

# Install test dependencies
pip install pytest pytest-asyncio

# Run all tests
pytest tests/ -v

📖 API Reference

serve_select Parameters

  • app: FastAPI application instance
  • query_engine: Database query engine (SQLite, PostgreSQL, or MySQL)
  • select_query: SQL SELECT query string
  • select_param: Function to generate query parameters from filters
  • count_query: Optional SQL COUNT query for pagination
  • path: API endpoint path (default: "/get")
  • filter_model: Pydantic model for filtering
  • data_model: Pydantic model for response data
  • dependencies: List of FastAPI dependencies
  • middlewares: List of middleware functions that receive QueryContext

serve_union Parameters

  • app: FastAPI application instance
  • sources: Dictionary of SelectSource objects for each database
  • path: API endpoint path (default: "/get")
  • filter_model: Pydantic model for filtering (applies to all sources)
  • data_model: Pydantic model for response data
  • dependencies: List of FastAPI dependencies
  • middlewares: List of middleware functions

📄 License

MIT

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

dbanu-0.0.8.tar.gz (11.1 kB view details)

Uploaded Source

Built Distribution

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

dbanu-0.0.8-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file dbanu-0.0.8.tar.gz.

File metadata

  • Download URL: dbanu-0.0.8.tar.gz
  • Upload date:
  • Size: 11.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.11.9 Linux/5.15.153.1-microsoft-standard-WSL2

File hashes

Hashes for dbanu-0.0.8.tar.gz
Algorithm Hash digest
SHA256 ea9ec6bbb7ee8540f38638adee24ae3d81fbda6d67cd24a6ce45716bc6fdcea9
MD5 1b5e005b0ae54fe35999a8ba60ee6f42
BLAKE2b-256 b97712bd1d24ac16b72a1e7b7093d30a5ab73f1539007b087d1aa5bdb2216b6e

See more details on using hashes here.

File details

Details for the file dbanu-0.0.8-py3-none-any.whl.

File metadata

  • Download URL: dbanu-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.11.9 Linux/5.15.153.1-microsoft-standard-WSL2

File hashes

Hashes for dbanu-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 2ce17f6d49ab57c846cd53f7432f6736b4e78e7f87ca4a7a9944265590634355
MD5 8c4dfcdf7e8692d5ca481b9b0697469a
BLAKE2b-256 ff6f0eaada8b92252c55b952fee006bda5df27576f1d35315d57792a6a2fdcc4

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