Skip to main content

sqlalchemy-cubrid

SQLAlchemy 2.0–2.2 dialect for the CUBRID database — Python ORM, schema reflection, Alembic migrations, and type mapping for SQLAlchemy and CUBRID-specific types.

🇰🇷 한국어 · 🇺🇸 English · 🇨🇳 中文 · 🇮🇳 हिन्दी · 🇩🇪 Deutsch · 🇷🇺 Русский

PyPI version python version ci workflow integration-full workflow coverage license GitHub stars docs


Status: Production/Stablesqlalchemy-cubrid is a maintained SQLAlchemy dialect for CUBRID supporting SQLAlchemy 2.0–2.2 and CUBRID 10.2–11.4.

Why sqlalchemy-cubrid?

CUBRID is a high-performance open-source relational database, widely adopted in Korean public-sector and enterprise applications. Until now, there was no actively maintained SQLAlchemy dialect that supports the modern 2.0–2.2 API.

sqlalchemy-cubrid bridges that gap:

  • Full SQLAlchemy 2.0–2.2 dialect with statement caching and PEP 561 typing
  • Extensive offline test suite with high code coverage (CI badge above) — no database required to run them
  • Concurrency stress testsQueuePool sync threaded + asyncio.gather workloads validated against live CUBRID
  • SQLAlchemy 2.2-ready compat shim — private API access wrapped in _compat.py; dependency pin now >=2.0,<2.3 covering SA 2.0, 2.1, and the upcoming 2.2 release line
  • Tested against 4 CUBRID versions (10.2, 11.0, 11.2, 11.4) across Python 3.10 -- 3.14
  • CUBRID-specific DML constructs: ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO
  • Alembic migration support out of the box
  • Three driver options — C-extension (cubrid://), pure Python (cubrid+pycubrid://), or async pure Python (cubrid+aiopycubrid://)

Support Status

  • Status: Production/Stable PyPI version
  • Supported matrix: SQLAlchemy >=2.0,<2.3, CUBRID 10.2, 11.0, 11.2, 11.4, Python 3.103.14
  • Integration CI exercises Python 3.10 and 3.14 against all four CUBRID versions on every PR; intermediate versions (3.11–3.13) are supported and validated via the offline test suite
  • SQLAlchemy 2.2 remains canary-only until explicitly added to the supported matrix
  • See Known Limitations for behavior boundaries and unsupported features

Architecture

flowchart TD
    app["Application"] --> sa["SQLAlchemy Core/ORM"]
    sa --> dialect["CubridDialect"]
    dialect --> pycubrid["pycubrid driver"]
    dialect --> cext["CUBRIDdb driver"]
    dialect --> aio["pycubrid.aio async driver"]
    pycubrid --> server["CUBRID Server"]
    cext --> server
    aio --> server
flowchart TD
    expr["SQL Expression"] --> compiler["CubridSQLCompiler"] --> sql["SQL String"]

Requirements

Installation

pip install sqlalchemy-cubrid

With the pure Python driver (no C build needed):

pip install "sqlalchemy-cubrid[pycubrid]"

With Alembic support:

pip install "sqlalchemy-cubrid[alembic]"

Quick Start

Core (Connection-Level)

from sqlalchemy import create_engine, text

engine = create_engine("cubrid://dba:password@localhost:33000/demodb")

with engine.connect() as conn:
    result = conn.execute(text("SELECT 1"))
    print(result.scalar())

ORM (Session-Level)

from sqlalchemy import create_engine, String
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(100))
    email: Mapped[str] = mapped_column(String(200), unique=True)


engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
Base.metadata.create_all(engine)

with Session(engine) as session:
    user = User(name="Alice", email="alice@example.com")
    session.add(user)
    session.commit()

Async

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy import text

engine = create_async_engine("cubrid+aiopycubrid://dba:password@localhost:33000/demodb")

async with AsyncSession(engine) as session:
    result = await session.execute(text("SELECT 1"))
    print(result.scalar())

Async insert with PK retrieval

CUBRID has no RETURNING clause. For ORM inserts, call await session.flush() inside the transaction block to populate the auto-increment PK on the object before commit:

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(100))

engine = create_async_engine("cubrid+aiopycubrid://dba:password@localhost:33000/demodb")

async with AsyncSession(engine) as session:
    async with session.begin():
        user = User(name="Alice")
        session.add(user)
        await session.flush()  # populates user.id without committing
        print(f"Inserted id={user.id}")

For raw Core inserts where you need the auto-increment PK, run SELECT LAST_INSERT_ID() after the statement (see Known Limitations).

Features

  • Type mapping for SQLAlchemy standard and CUBRID-specific types — numeric, string, date/time, bit, LOB, collection, and JSON types
  • SQL compilation -- SELECT, JOIN, CAST, LIMIT/OFFSET, subqueries, CTEs, window functions
  • DML extensions -- ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, FOR UPDATE, TRUNCATE
  • DDL support -- COMMENT, IF NOT EXISTS / IF EXISTS, AUTO_INCREMENT
  • Schema reflection -- tables, views, columns, PKs, FKs, indexes, unique constraints, comments
  • Alembic migrations via CubridImpl (auto-discovered entry point)
  • All 6 CUBRID isolation levels (dual-granularity: class-level + instance-level)
  • Async support — create_async_engine("cubrid+aiopycubrid://...") via pycubrid.aio

Known Limitations

  • No RETURNINGINSERT/UPDATE/DELETE ... RETURNING not supported; for ORM use await session.flush() to populate id on the object (see Async Quick Start), or for Core use cursor.lastrowid / SELECT LAST_INSERT_ID() after the statement
  • No sequences — CUBRID uses AUTO_INCREMENT only
  • No multi-schema — single schema per database
  • DDL auto-commits — migrations are not transactional (transactional_ddl = False); use Alembic batch migrations and test rollback scenarios manually
  • SQLAlchemy 2.0–2.2 only — pinned to <2.3; SA 2.2 is forward-supported via shims and a --pre canary CI job (details)
  • Async requires pycubrid >= 1.3.2,<2.0 — the cubrid+aiopycubrid:// driver needs the async-capable pycubrid package line currently supported by this project
  • CARDINALITY() brokenfunc.cardinality() raises CompileError with workaround guidance; the CUBRID server has a known bug
  • Reserved words auto-quoted — Column names matching CUBRID reserved words (day, count, value, etc.) are automatically double-quoted in DDL; see reserved word list
  • Timezone type fidelity — CUBRID TIMESTAMPTZ is reflected as TIMESTAMP; timezone offset is preserved in the stored value but the dialect does not distinguish TZ vs LTZ semantics at the SQLAlchemy type level. In practice this means datetime objects round-trip correctly but explicit TZ/LTZ type introspection is not available

Documentation

Guide Description
Connection Connection strings, URL format, driver setup, pool tuning
Type Mapping Full type mapping, CUBRID-specific types, collection types
DML Extensions ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, query trace
Isolation Levels All 6 CUBRID isolation levels, configuration
Alembic Migrations Setup, configuration, limitations, batch workarounds
Feature Support Comparison with MySQL, PostgreSQL, SQLite
ORM Cookbook Practical ORM examples, relationships, queries
Development Dev setup, testing, Docker, coverage, CI/CD
Driver Compatibility CUBRID-Python driver versions and known issues
Troubleshooting Common issues, error solutions, debugging techniques
Async Connection Async engine setup with cubrid+aiopycubrid://

Compatibility Matrix

Component Supported versions
Python 3.10, 3.11, 3.12, 3.13, 3.14
CUBRID 10.2, 11.0, 11.2, 11.4
SQLAlchemy 2.0–2.2
Alembic >=1.7
pycubrid (sync) >=1.3.2,<2.0
pycubrid (async) >=1.3.2,<2.0

FAQ

How do I connect to CUBRID with SQLAlchemy?

from sqlalchemy import create_engine
engine = create_engine("cubrid://dba:password@localhost:33000/demodb")

For the pure Python driver (no C build needed): create_engine("cubrid+pycubrid://dba@localhost:33000/demodb")

Does sqlalchemy-cubrid support SQLAlchemy 2.0–2.2?

Yes. sqlalchemy-cubrid is built for SQLAlchemy 2.0–2.2 and supports the 2.0-style API including Session.execute(), typed Mapped[] columns, and statement caching.

Does sqlalchemy-cubrid support Alembic migrations?

Yes. Install with pip install "sqlalchemy-cubrid[alembic]". The dialect auto-registers via entry point. Note that CUBRID auto-commits DDL, so migrations are not transactional.

What Python versions are supported?

Python 3.10, 3.11, 3.12, 3.13, and 3.14.

Does CUBRID support RETURNING clauses?

No. CUBRID does not support INSERT ... RETURNING or UPDATE ... RETURNING. Use cursor.lastrowid or SELECT LAST_INSERT_ID() instead.

How do I use ON DUPLICATE KEY UPDATE with CUBRID?

from sqlalchemy_cubrid import insert
stmt = insert(users).values(name="Alice").on_duplicate_key_update(name="Alice Updated")

What's the difference between cubrid:// and cubrid+pycubrid://?

cubrid:// uses the C-extension driver (CUBRIDdb) which requires compilation. cubrid+pycubrid:// uses the pure Python driver which installs with pip alone — no build tools needed. cubrid+aiopycubrid:// uses the async variant of the pure Python driver for use with create_async_engine and AsyncSession.

Does sqlalchemy-cubrid support async?

Yes. Use create_async_engine("cubrid+aiopycubrid://...") with the pycubrid async driver. Requires pycubrid>=1.3.2,<2.0. Both pycubrid dialects use native Connection.ping(False) / AsyncConnection.ping(False) for pool_pre_ping, and all Core and ORM features work with AsyncSession.

Related Projects

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqlalchemy_cubrid-1.6.0.tar.gz (95.6 kB view details)

Uploaded Source

Built Distribution

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

sqlalchemy_cubrid-1.6.0-py3-none-any.whl (45.7 kB view details)

Uploaded Python 3

File details

Details for the file sqlalchemy_cubrid-1.6.0.tar.gz.

File metadata

  • Download URL: sqlalchemy_cubrid-1.6.0.tar.gz
  • Upload date:
  • Size: 95.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sqlalchemy_cubrid-1.6.0.tar.gz
Algorithm Hash digest
SHA256 0eb2859ec68a79beecf6ec1a2088001457f558590d9b12ba9184ea1a9189ab48
MD5 5163b26d376a0b7aac60fe652991f747
BLAKE2b-256 9fbc9d9d971a550df4f1a14b1b6b428c55e98e653f667df547e4f4c7376e8d42

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlalchemy_cubrid-1.6.0.tar.gz:

Publisher: publish-pypi.yml on cubrid-lab/sqlalchemy-cubrid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sqlalchemy_cubrid-1.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sqlalchemy_cubrid-1.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a06f01d86a0f32c00fae064a466edf504f2e9699c2aebbb909af0d2199947ec4
MD5 2318c384c4e56aaf884be79e9cb40094
BLAKE2b-256 11848f9948d324c7465fbe8296d1a122811a96dbc5216420c72a3369d1be7ab1

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlalchemy_cubrid-1.6.0-py3-none-any.whl:

Publisher: publish-pypi.yml on cubrid-lab/sqlalchemy-cubrid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.6.0 This release

2 files

1.5.1

2 files

1.5.0

2 files

1.4.3

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

0.8.0

2 files

0.7.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page