Skip to main content

Unified Relational DB abstraction layer — clean adapters for 9+ databases

Project description

dd-db

Unified Relational DB abstraction layer for Python.

Connect to any relational database and get a pandas DataFrame back — with a consistent API for schema inspection, connection management, and query timing.

Supported Databases

Adapter Class Extra
SQLite (stdlib) SQLiteDB (none)
DuckDB DuckDB duckdb
PostgreSQL PostgresDB postgres
MySQL / MariaDB MySQLDB mysql
Snowflake SnowflakeDB snowflake
Google BigQuery BigQueryDB bigquery
ClickHouse ClickHouseDB clickhouse
SQL Server MSSQLDB mssql
Oracle OracleDB oracle

Install

pip install dd-db                   # SQLite only (stdlib, zero extra deps)
pip install "dd-db[duckdb]"         # + DuckDB
pip install "dd-db[postgres]"       # + PostgreSQL
pip install "dd-db[all]"            # all adapters
pip install "dd-db[dev]"            # dev tools + DuckDB

Quick Start

from dd_db import SQLiteDB

with SQLiteDB(":memory:") as db:
    db.run_query("CREATE TABLE t (id INT, name TEXT)")
    db.run_query("INSERT INTO t VALUES (1, 'Alice')")
    db.run_query("INSERT INTO t VALUES (2, 'Bob')")

    # SELECT returns a pandas DataFrame
    df = db.run_query("SELECT * FROM t")
    print(df)
    #    id   name
    # 0   1  Alice
    # 1   2    Bob

    # Parameterised queries
    row = db.run_query("SELECT * FROM t WHERE id = :id", params={"id": 1})

    # Schema inspection
    print(db.list_tables())          # ['t']
    print(db.describe("t"))          # DataFrame with column/type/pk columns
    schema = db.get_schema("t")      # TableSchema Pydantic model
    print(schema.row_count)          # 2

    # Timed query
    df, meta = db.timed_query("SELECT * FROM t")
    print(meta.execution_time_ms)    # e.g. 0.42

API Reference

Core methods (all adapters)

Method Returns Description
run_query(sql, params?) DataFrame Execute SQL; SELECT → rows, DML → {rows_affected}
list_tables(schema?) list[str] Table names
tables(schema?) DataFrame Table names as DataFrame
get_schema(table, schema?) TableSchema Typed column metadata
describe(table, schema?) DataFrame Human-readable column info
test_connection() bool Health check
connection_info() ConnectionInfo Loggable summary (no passwords)
timed_query(sql, params?) (DataFrame, QueryResult) Query + execution metadata
connect() None Open connection
disconnect() None Close connection

Context manager

with SQLiteDB("mydb.sqlite") as db:
    ...
# connection closed automatically

Pydantic models

from dd_db import TableSchema, ColumnInfo, QueryResult, ConnectionInfo
  • ColumnInfoname, data_type, nullable, default, primary_key
  • TableSchematable_name, schema_name, columns, row_count, full_name
  • QueryResultsql, rows_returned, columns, execution_time_ms, success, error
  • ConnectionInfoadapter, host, port, database, username

Examples

DuckDB analytics

DuckDB uses $name for named parameters (not :name):

from dd_db import DuckDB

with DuckDB() as db:
    df = db.run_query("""
        SELECT region, SUM(amount) AS total
        FROM sales
        GROUP BY region
        ORDER BY total DESC
    """)
    print(df)

    # Parameterised — DuckDB uses $name style
    row = db.run_query(
        "SELECT * FROM sales WHERE region = $region AND amount > $min",
        params={"region": "North", "min": 1000.0},
    )

PostgreSQL

from dd_db import PostgresDB

with PostgresDB(host="localhost", database="mydb", user="me", password="pw") as db:
    df = db.run_query("SELECT * FROM orders WHERE status = :status",
                      params={"status": "pending"})

Snowflake

from dd_db import SnowflakeDB

with SnowflakeDB(account="xy12345", user="me", password="pw",
                 database="ANALYTICS", schema="PUBLIC",
                 warehouse="COMPUTE_WH") as db:
    df = db.run_query("SELECT TOP 100 * FROM my_table")

Parameter style by adapter

Each adapter translates params dict to its driver's native style:

Adapter SQL placeholder Example
SQLiteDB :name WHERE id = :id
PostgresDB :name WHERE id = :id
DuckDB $name WHERE id = $id
MySQLDB %(name)s WHERE id = %(id)s
SnowflakeDB %(name)s WHERE id = %(id)s
BigQueryDB @name WHERE id = @id
MSSQLDB ? (positional) WHERE id = ?
OracleDB :name WHERE id = :id
ClickHouseDB {name:type} WHERE id = {id:Int32}

Cookbooks

See cookbook/ for runnable examples:

  • 01_sqlite_basics.py — full walkthrough with SQLite (no install needed)
  • 02_duckdb_basics.py — analytics with DuckDB, including DataFrame joins

Running Tests

pip install -e ".[dev]"
python -m pytest

Tests use :memory: SQLite — no external server required.

Design

See docs/DESIGN.md for:

  • Why synchronous-first?
  • Why DataFrame return type everywhere?
  • Relationship to vanna.ai
  • How to add a new adapter

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

dd_db-0.1.1.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

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

dd_db-0.1.1-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

Details for the file dd_db-0.1.1.tar.gz.

File metadata

  • Download URL: dd_db-0.1.1.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for dd_db-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b807282a0eb6568ff84b264c9b85c5d454027bba754f9bb9682a1245ebd83f66
MD5 368e1a50a558c1cc42bbe1fa62c5c349
BLAKE2b-256 0856f236c7c210a6204e614e42991eb6829e2c7c605dd5d0c7404e006d0dec39

See more details on using hashes here.

File details

Details for the file dd_db-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: dd_db-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 26.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for dd_db-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 57ac11466fd35382fb23282e90a8377747f8aa9b7c5b9ca49bf0ef9390c55326
MD5 70dd28bdc15a9f039e627fe79c17a916
BLAKE2b-256 46b2235388ecb717136630307b219de1c0be822a84db772e81340aa30805c061

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