Pure Python DB-API 2.0 driver for CUBRID database
Project description
pycubrid
Pure Python DB-API 2.0 driver for the CUBRID database — no C extensions, no compilation, implements the PEP 249 (DB-API 2.0) interface.
🇰🇷 한국어 · 🇺🇸 English · 🇨🇳 中文 · 🇮🇳 हिन्दी · 🇩🇪 Deutsch · 🇷🇺 Русский
Status: Beta. The core public API follows semantic versioning; minor releases may add features and bug fixes while the project remains under active development.
Why pycubrid?
CUBRID is a high-performance open-source relational database, widely adopted in
Korean public-sector and enterprise applications. The existing C-extension driver
(CUBRIDdb) had build dependencies and platform compatibility issues.
pycubrid solves these problems:
- Pure Python implementation — no C build dependencies, install with
pip installonly - Implements PEP 249 (DB-API 2.0) — standard exception hierarchy, type objects, cursor interface
- 666 offline tests with 97%+ code coverage — no database required to run them
- Native asyncio support — async/await API via
pycubrid.aiofor high-concurrency applications - PEP 561 typed package —
py.typedmarker for modern IDE and static analysis support - Direct CUBRID CAS protocol implementation — no additional middleware required
- LOB (CLOB/BLOB) support — handle large text and binary data
Requirements
- Python 3.10+
- CUBRID database server 10.2+
Installation
pip install pycubrid
Quick Start
Basic Connection
import pycubrid
conn = pycubrid.connect(
host="localhost",
port=33000,
database="testdb",
user="dba",
password="",
)
cur = conn.cursor()
cur.execute("SELECT 1 + 1")
print(cur.fetchone()) # (2,)
cur.close()
conn.close()
Context Manager
import pycubrid
with pycubrid.connect(host="localhost", port=33000, database="testdb", user="dba") as conn:
with conn.cursor() as cur:
cur.execute("CREATE TABLE IF NOT EXISTS cookbook_users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100))")
cur.execute("INSERT INTO cookbook_users (name) VALUES (?)", ("Alice",))
conn.commit()
cur.execute("SELECT * FROM cookbook_users")
for row in cur:
print(row)
Async
import asyncio
import pycubrid.aio
async def main():
conn = await pycubrid.aio.connect(
host="localhost", port=33000, database="testdb", user="dba"
)
cur = await conn.cursor()
await cur.execute("SELECT 1 + 1")
print(await cur.fetchone()) # (2,)
await cur.close()
await conn.close()
asyncio.run(main())
Parameter Binding
# qmark style (question marks)
cur.execute("SELECT * FROM users WHERE name = ? AND age > ?", ("Alice", 25))
# Batch insert with executemany
data = [("Alice", 30), ("Bob", 25), ("Charlie", 35)]
cur.executemany("INSERT INTO users (name, age) VALUES (?, ?)", data)
conn.commit()
Parameterized Queries
sql = "SELECT * FROM users WHERE department = ?"
cur.execute(sql, ("Engineering",))
engineers = cur.fetchall()
cur.execute(sql, ("Marketing",))
marketers = cur.fetchall()
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()
Features
- Pure Python — no C extensions, no compilation, works everywhere Python runs
- Complete DB-API 2.0 —
connect(),Cursor,fetchone/many/all,executemany,callproc - Parameterized queries —
cursor.execute(sql, params)with server-sidePREPARE_AND_EXECUTE - Batch operations —
executemany()andexecutemany_batch()for bulk inserts - LOB support —
create_lob(), read/write CLOB and BLOB columns - Schema introspection —
get_schema_info()for tables, columns, indexes, constraints - Auto-commit control —
connection.autocommitproperty for transaction management - Server version detection —
connection.get_server_version()returns version string (e.g.,"11.2.0.0378") - Iterator protocol — iterate over cursor results with
for row in cursor - Context managers —
withstatements for both connections and cursors - Async support —
pycubrid.aio.connect()withAsyncConnectionandAsyncCursorfor asyncio event loops
Supported CUBRID Versions
The project targets CUBRID 11.x series and is validated in CI against:
- 11.2
- 11.4
SQLAlchemy Integration
pycubrid works as a driver for sqlalchemy-cubrid — the SQLAlchemy 2.0 dialect for CUBRID:
pip install "sqlalchemy-cubrid[pycubrid]"
from sqlalchemy import create_engine, text
engine = create_engine("cubrid+pycubrid://dba@localhost:33000/testdb")
with engine.connect() as conn:
result = conn.execute(text("SELECT 1"))
print(result.scalar())
SQLAlchemy features (ORM, Core, Alembic migrations, schema reflection) are accessible through the pycubrid driver when used with sqlalchemy-cubrid.
Documentation
| Guide | Description |
|---|---|
| Connection | Connection strings, URL format, configuration |
| Type Mapping | Full type mapping, CUBRID-specific types, collection types |
| API Reference | Complete API documentation — modules, classes, functions |
| Protocol | CAS wire protocol reference |
| Development | Dev setup, testing, Docker, coverage, CI/CD |
| Examples | Practical usage examples with code |
| Troubleshooting | Connection errors, query problems, LOB handling, debugging |
Compatibility
| Python 3.10 | Python 3.11 | Python 3.12 | Python 3.13 | |
|---|---|---|---|---|
| Offline Tests | ✅ | ✅ | ✅ | ✅ |
| CUBRID 11.4 | ✅ | -- | ✅ | -- |
| CUBRID 11.2 | ✅ | -- | ✅ | -- |
Architecture
graph TD
app[Application]
pycubrid[pycubrid Connection/Cursor]
cas[CAS Protocol]
server[CUBRID Server]
app --> pycubrid
pycubrid --> cas
cas --> server
graph TD
root[pycubrid/]
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 (18 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
root --> aio
aio[aio/ - AsyncConnection, AsyncCursor, async connect()]
FAQ
How do I connect to CUBRID with Python?
import pycubrid
conn = pycubrid.connect(host="localhost", port=33000, database="testdb", user="dba")
How do I install pycubrid?
pip install pycubrid — no C extensions or build tools required.
What parameter style does pycubrid use?
Question mark (qmark) style: cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
Does pycubrid work with SQLAlchemy?
Yes. Install pip install "sqlalchemy-cubrid[pycubrid]" and use the connection URL cubrid+pycubrid://dba@localhost:33000/testdb.
What Python versions are supported?
Python 3.10, 3.11, 3.12, and 3.13.
Does pycubrid support LOBs (CLOB/BLOB)?
Yes. Insert strings/bytes directly into CLOB/BLOB columns. For reading, LOB columns return data that can be accessed through the cursor.
Is pycubrid thread-safe?
pycubrid has threadsafety = 1, meaning connections cannot be shared between threads. Create a separate connection per thread.
What CUBRID versions are supported?
CUBRID 10.2, 11.0, 11.2, and 11.4 are tested in CI.
Does pycubrid support async/await?
Yes. Use pycubrid.aio.connect() for native asyncio support. The async API mirrors the sync API — AsyncConnection and AsyncCursor provide the same methods with await.
Related Projects
- sqlalchemy-cubrid — SQLAlchemy 2.0 dialect for CUBRID
- cubrid-python-cookbook — Production-ready Python examples for CUBRID
Roadmap
See ROADMAP.md for this project's direction and next milestones.
For the ecosystem-wide view, see the CUBRID Labs Ecosystem Roadmap and Project Board.
Contributing
See CONTRIBUTING.md for guidelines and docs/DEVELOPMENT.md for development setup.
Security
Report vulnerabilities via email — see SECURITY.md. Do not open public issues for security concerns.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycubrid-1.2.0.tar.gz.
File metadata
- Download URL: pycubrid-1.2.0.tar.gz
- Upload date:
- Size: 84.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96d74e766dc45f84a323c5999bfa5779e4dabcb125de7c45fd8532f019757efa
|
|
| MD5 |
79e418629ef4c2e87c2608fbc0e66215
|
|
| BLAKE2b-256 |
eef9a18b728576e610fa4b65a9195bea1454c1ca44e36d5928cd0391ed72ed73
|
Provenance
The following attestation bundles were made for pycubrid-1.2.0.tar.gz:
Publisher:
publish-pypi.yml on cubrid-labs/pycubrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycubrid-1.2.0.tar.gz -
Subject digest:
96d74e766dc45f84a323c5999bfa5779e4dabcb125de7c45fd8532f019757efa - Sigstore transparency entry: 1340587429
- Sigstore integration time:
-
Permalink:
cubrid-labs/pycubrid@5f6e255a203db1bc37837cd9c26d621e4754396b -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/cubrid-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@5f6e255a203db1bc37837cd9c26d621e4754396b -
Trigger Event:
push
-
Statement type:
File details
Details for the file pycubrid-1.2.0-py3-none-any.whl.
File metadata
- Download URL: pycubrid-1.2.0-py3-none-any.whl
- Upload date:
- Size: 42.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1ac5fad8a0b5fbc9d1dbe007b781dcb91be813a2f84b1dcabc1d95f64645347
|
|
| MD5 |
c2e3adfbeb5ff693d331d4067f5e3c2d
|
|
| BLAKE2b-256 |
592fa60eb7067941f073bf450ae5581a3d29ef51e317e01f208d1d20f4d08ce1
|
Provenance
The following attestation bundles were made for pycubrid-1.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on cubrid-labs/pycubrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycubrid-1.2.0-py3-none-any.whl -
Subject digest:
e1ac5fad8a0b5fbc9d1dbe007b781dcb91be813a2f84b1dcabc1d95f64645347 - Sigstore transparency entry: 1340587432
- Sigstore integration time:
-
Permalink:
cubrid-labs/pycubrid@5f6e255a203db1bc37837cd9c26d621e4754396b -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/cubrid-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@5f6e255a203db1bc37837cd9c26d621e4754396b -
Trigger Event:
push
-
Statement type: