Skip to content

PRD: pycubrid — Pure Python DB-API 2.0 Driver for CUBRID

1. Overview

Project: pycubrid Current Version: see PyPI (pycubrid.__version__) Status: Production-ready Repository: github.com/cubrid-lab/pycubrid License: MIT

1.1 Problem Statement

CUBRID's existing Python driver (CUBRIDdb) is a C-extension module with significant limitations:

  • Requires C compiler and CUBRID C libraries to install
  • Platform compatibility issues (fails on many Linux distributions, macOS ARM)
  • No official wheels — users must compile from source
  • Not PEP 249 compliant — missing standard exception hierarchy, type objects
  • No type hints, no PEP 561 marker
  • Abandoned maintenance — last meaningful update years ago

Modern Python developers expect:

  • pip install that just works — no C build dependencies
  • Full PEP 249 (DB-API 2.0) compliance
  • Type annotations for IDE support
  • Context managers for resource cleanup
  • Comprehensive test coverage

1.2 What Was Built

A complete pure Python implementation of the CUBRID CAS protocol:

  • Full PEP 249 (DB-API 2.0) compliance — standard exception hierarchy, type objects, cursor interface
  • Pure Python — no C extensions, no compilation, works everywhere Python runs
  • Direct CAS protocol — speaks CUBRID's binary protocol natively over TCP
  • Offline and live test suites (test tree) with a CI-enforced 95% coverage floor (measured results)
  • PEP 561 typed package — py.typed marker for modern IDE and static analysis
  • LOB support — CLOB and BLOB handling via create_lob()
  • Prepared statements — server-side statement preparation and execution (planned; current implementation uses driver-side parameter binding)
  • Batch operations — executemany() and executemany_batch() for bulk inserts
  • CI/CD — Python 3.11–3.15 support, with representative offline and live-endpoint lanes per change and a full Python × CUBRID matrix on release

1.3 Success Criteria — Status

Criterion Target Achieved
Pure Python (no C extensions) ✅ ✅ pip install pycubrid
PEP 249 (DB-API 2.0) compliant ✅ ✅ Full API compliance
Offline tests (no live DB) ✅ ✅ make test; coverage floor enforced on full runs
LOB (CLOB/BLOB) support ✅ ✅ create_lob(), read/write
Prepared statements ✅ ✅ cursor.execute(sql, params) — driver-side parameter binding via ? placeholders (see PARAMETER_BINDING.md)
CI/CD with version matrix ✅ ✅ Py 3.11–3.15 representative offline and live lanes; full 5 × 4 matrix on release
Publishable to PyPI ✅ ✅ Released by merging a reviewed release PR (RELEASING.md)
≥ 95% code coverage ✅ ✅ CI-enforced floor; measured results
Comprehensive documentation ✅ ✅ Guides under docs/ in English and Korean + README
PEP 561 typed package ✅ ✅ py.typed marker

2. Technical Architecture

2.1 Module Structure

graph TD
    root[pycubrid/ - main package]
    init["__init__.py - Public API connect(), types, exceptions, __version__"]
    connection[connection.py - Connection class connect/commit/rollback/cursor/LOB]
    cursor[cursor.py - Cursor class execute/fetch/executemany/callproc/iterator]
    types[types.py - DB-API 2.0 type objects and constructors]
    exceptions[exceptions.py - PEP 249 exception hierarchy]
    constants[constants.py - CAS function codes, data types, protocol constants]
    protocol["protocol.py - CAS wire protocol packet classes (20 packet types)"]
    packet[packet.py - Low-level packet reader/writer]
    lob[lob.py - LOB support]
    typed[py.typed - PEP 561 marker]

    root --> init
    root --> connection
    root --> cursor
    root --> types
    root --> exceptions
    root --> constants
    root --> protocol
    root --> packet
    root --> lob
    root --> typed

2.2 Dependency Matrix

Package Version Purpose
Python ≥ 3.11 Runtime
pytest ≥ 7.0 Testing (dev)
ruff ≥ 0.4 Lint + format (dev)

Standard library only — pycubrid needs no runtime dependencies except tzdata on Windows, which supplies the IANA time zone database that zoneinfo needs for TZ types (#413).

2.3 PEP 249 Compliance

Attribute Value
apilevel "2.0"
threadsafety 1 (connections cannot be shared between threads)
paramstyle "qmark" (positional parameters ?)

Full standard exception hierarchy: Warning, Error, InterfaceError, DatabaseError, OperationalError, IntegrityError, InternalError, ProgrammingError, NotSupportedError

Standard type objects: STRING, BINARY, NUMBER, DATETIME, ROWID

Standard constructors: Date(), Time(), Timestamp(), Binary(), DateFromTicks(), TimeFromTicks(), TimestampFromTicks()


3. Implemented Features

3.1 Connection Management

  • connect() factory function with keyword arguments
  • Auto-commit control via connection.autocommit property
  • Context manager support (with statement)
  • Server version detection via connection.get_server_version()
  • connection.close() for explicit cleanup
  • connection.ping() for native CAS health checks
  • Async connection API via pycubrid.aio.connect()

3.2 Cursor Operations

  • execute(sql, params?) — execute with optional parameters
  • executemany(sql, seq_of_params) — batch execute
  • executemany_batch(sql, seq_of_params) — optimized batch insert
  • fetchone() / fetchmany(size) / fetchall() — result retrieval
  • execute(sql, params) — qmark-style parameterized queries bound CLIENT-SIDE; SQL is fully rendered before being sent to CAS (see PARAMETER_BINDING.md)
  • callproc(procname, params) — stored procedure calls
  • nextset() — DB-API compatibility method (returns None)
  • Iterator protocol — for row in cursor
  • Context manager — with conn.cursor() as cur
  • description attribute — column metadata after execute

3.3 LOB Support

  • connection.create_lob(lob_type) — create CLOB (type=24) or BLOB (type=23)
  • Read/write large text and binary data
  • Insert strings/bytes directly into CLOB/BLOB columns

3.4 Schema Introspection

  • connection.get_schema_info() — tables, columns, indexes, constraints

3.5 Async API (shipped in 1.1.0)

  • pycubrid.aio.connect() — async module-level constructor
  • AsyncConnection — connect, commit, rollback, close, cursor, set_autocommit
  • AsyncCursor — async execute, executemany, fetchone, fetchmany, fetchall, nextset

3.6 CAS Protocol

Direct implementation of CUBRID's Client Application Server (CAS) binary protocol:

  • 20 packet types covering all database operations
  • Two-step connection: broker handshake → CAS session
  • Big-endian binary codec for all data types
  • Server-side cursor with lazy fetch for large result sets

4. Test Coverage

4.1 Test Matrix

Test File Coverage Area
test_connection.py Connection, authentication, auto-commit, context manager
test_cursor.py Execute, fetch, executemany, callproc, iterator, description
test_types.py Type objects, constructors, date/time conversion
test_exceptions.py Exception hierarchy, error codes
test_protocol.py Packet building, parsing, CAS function codes
test_packet.py Binary reader/writer, data type encoding
test_lob.py LOB creation, read, write
test_constants.py Protocol constants, data type codes
test_integration.py Live DB tests (Docker)
Totals Not pinned here: run make test, and see the test tree and measured coverage

4.2 CI Matrix

Lane Python CUBRID
Ordinary PR smoke (offline) 3.12 —
Main, weekly, high-risk PR (offline) 3.11, 3.15 —
Full compatibility matrix (explicit dispatch and every release) 3.11, 3.12, 3.13, 3.14, 3.15 10.2, 11.0, 11.2, 11.4 (5 × 4)

See CI execution policy for the per-event live endpoints.


5. Known Limitations

Limitations imposed by CUBRID or design choices:

Feature Status Reason
Async TLS ✅ Implemented in v1.4.0; uses CUBRID's STARTTLS-style upgrade — plaintext CUBRS handshake then loop.start_tls() (with ssl_handshake_timeout) before OPEN_DATABASE (#154). Default context requires TLS 1.2 minimum.
Connection pooling ❌ Not in scope; use SQLAlchemy's pool or external pooler
Thread safety level 2+ ❌ CUBRID CAS sessions are connection-bound
LOB streaming ⚠️ LOB data loaded fully into memory
Timezone-aware parsing ⚠️ Supported for TZ types; behavior depends on server-supplied zone tokens
Async LOB helper ⚠️ No dedicated async Lob helper yet

6. Documentation

Document Content
README.md Landing page with Quick Start
docs/CONNECTION.md Connection strings, configuration
docs/TYPES.md Type mapping, CUBRID-specific types
docs/API_REFERENCE.md Complete API documentation
docs/PROTOCOL.md CAS wire protocol reference
docs/DEVELOPMENT.md Dev setup, testing, Docker, CI/CD
docs/EXAMPLES.md Practical usage examples
CHANGELOG.md Release history
CONTRIBUTING.md Contribution guidelines

7. Roadmap

Delivered Milestones

Release Highlights
1.0.0 Stable sync DB-API surface, LOB support, schema APIs, test/CI baseline
1.1.0 Native pycubrid.aio async API shipped
1.2.0 ping(), JSON decoding, collection decoding, nextset(), richer errors
1.3.0 Sync TLS support, refreshed CI/docs baseline

Forward-looking Priorities

Item Description Priority
LOB ergonomics Higher-level helpers for reading fetched LOB handles Medium
Statement caching Reuse prepared statements for repeated workloads Medium
CUBRID 12.x validation Expand CI and docs for newer server versions Medium

8. Architecture Decisions

8.1 Why Pure Python (no C extensions)

The C-extension driver (CUBRIDdb) required users to have CUBRID C libraries installed, which was a significant barrier — especially on macOS, ARM Linux, and containerized environments. A pure Python implementation eliminates all build dependencies and makes pip install pycubrid work everywhere.

8.2 Why Direct CAS Protocol

Rather than wrapping the C library or using ODBC, pycubrid implements CUBRID's CAS (Client Application Server) binary protocol directly over TCP. This provides:

  • Zero native dependencies
  • Full control over connection lifecycle
  • Ability to implement features the C driver lacks (e.g., proper LOB handling)

8.3 Why PEP 249 Strict Compliance

DB-API 2.0 is the standard Python database interface. Strict compliance means:

  • Any code written for sqlite3, psycopg2, or mysql-connector works with minimal changes
  • SQLAlchemy and other ORMs can use pycubrid as a drop-in driver
  • Standard exception handling patterns work out of the box

9. Ecosystem Integration

pycubrid is the foundational driver in the cubrid-lab Python ecosystem:

graph TD
    pycubrid["pycubrid (DB-API 2.0 driver)"]
    sqlalchemy["sqlalchemy-cubrid (SQLAlchemy 2.0 dialect)"]
    cookbook["cubrid-cookbook (runnable examples)"]
    fastapi[FastAPI examples]
    django[Django examples]
    flask[Flask examples]
    pandas[Pandas examples]
    streamlit[Streamlit examples]
    celery[Celery examples]

    pycubrid --> sqlalchemy
    sqlalchemy --> cookbook
    cookbook --> fastapi
    cookbook --> django
    cookbook --> flask
    cookbook --> pandas
    cookbook --> streamlit
    cookbook --> celery

10. Example-first Design Philosophy

Why Example-first

CUBRID's ecosystem is small compared to PostgreSQL or MySQL. For a small-ecosystem project, the entry barrier must be minimized — users should be able to copy-paste working code within 30 seconds of reading the documentation.

Because the ecosystem is still small, the project provides extensive examples and cookbook-style documentation to lower the adoption barrier.

Hello World

pip install pycubrid
import pycubrid

conn = pycubrid.connect(
    host="localhost",
    port=33000,
    database="demodb",
    user="dba",
    password="",
)

cur = conn.cursor()
cur.execute("SELECT 1 + 1")
print(cur.fetchone())  # (2,)

cur.close()
conn.close()

This code connects to a CUBRID database, runs a query, and prints the result. No ORM setup, no configuration files, no boilerplate.

AI Agent Discoverability

Modern developers increasingly rely on AI coding assistants — Claude Code, OpenCode, Cursor, GitHub Copilot, Devin, and others. These agents read README files, PRDs, documentation, and example code to decide which libraries to recommend.

More examples in documentation = higher probability of AI recommendation.

By embedding working code directly in the PRD, README, and docs, we ensure that AI agents can discover, learn, and recommend pycubrid accurately.

Cookbook Integration

The cubrid-cookbook repository provides production-ready, runnable examples for pycubrid:

Example Description
01_connect.py Basic connection and query
02_crud.py Create, read, update, delete operations
03_transactions.py Transaction management with commit/rollback
04_prepared.py Parameterized queries (driver-side binding) for repeated execution
05_error_handling.py Error handling with PEP 249 exception hierarchy
06_lob.py LOB (CLOB/BLOB) operations

Inspiration from Successful Projects

Projects that succeeded partly through example-heavy documentation:

Project What They Did
FastAPI Every endpoint documented with runnable examples; became the fastest-growing Python web framework
LangChain Cookbook-first approach drove explosive adoption in the AI space
SQLAlchemy Extensive ORM cookbook and tutorial; de facto Python ORM for 15+ years
Pandas "10 Minutes to pandas" and cookbook lowered entry barrier for data science

pycubrid follows the same philosophy: examples are not supplementary — they are the primary documentation.


Last updated: October 2026. Figures that change with each release are linked, not copied. The async API is available since v1.1.0.