sqlalchemy-cubrid 0.0.1.dev1__tar.gz → 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. sqlalchemy_cubrid-0.7.1/AUTHORS +2 -0
  2. sqlalchemy_cubrid-0.7.1/PKG-INFO +281 -0
  3. sqlalchemy_cubrid-0.7.1/README.md +232 -0
  4. sqlalchemy_cubrid-0.7.1/pyproject.toml +109 -0
  5. sqlalchemy_cubrid-0.7.1/setup.cfg +4 -0
  6. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/__init__.py +85 -0
  7. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/alembic_impl.py +145 -0
  8. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.7.1}/sqlalchemy_cubrid/base.py +44 -39
  9. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/compiler.py +515 -0
  10. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/dialect.py +700 -0
  11. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/dml.py +318 -0
  12. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/py.typed +0 -0
  13. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/pycubrid_dialect.py +124 -0
  14. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/requirements.py +270 -0
  15. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/trace.py +92 -0
  16. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid/types.py +349 -0
  17. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid.egg-info/PKG-INFO +281 -0
  18. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid.egg-info/SOURCES.txt +32 -0
  19. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid.egg-info/entry_points.txt +7 -0
  20. sqlalchemy_cubrid-0.7.1/sqlalchemy_cubrid.egg-info/requires.txt +20 -0
  21. sqlalchemy_cubrid-0.7.1/test/test_alembic.py +261 -0
  22. sqlalchemy_cubrid-0.7.1/test/test_base.py +145 -0
  23. sqlalchemy_cubrid-0.7.1/test/test_compiler.py +1695 -0
  24. sqlalchemy_cubrid-0.7.1/test/test_dialect_offline.py +799 -0
  25. sqlalchemy_cubrid-0.7.1/test/test_dialects.py +79 -0
  26. sqlalchemy_cubrid-0.7.1/test/test_integration.py +581 -0
  27. sqlalchemy_cubrid-0.7.1/test/test_pycubrid_dialect.py +299 -0
  28. sqlalchemy_cubrid-0.7.1/test/test_requirements.py +133 -0
  29. sqlalchemy_cubrid-0.7.1/test/test_suite.py +13 -0
  30. sqlalchemy_cubrid-0.7.1/test/test_trace.py +197 -0
  31. sqlalchemy_cubrid-0.7.1/test/test_types.py +272 -0
  32. sqlalchemy_cubrid-0.0.1.dev1/PKG-INFO +0 -15
  33. sqlalchemy_cubrid-0.0.1.dev1/README.md +0 -2
  34. sqlalchemy_cubrid-0.0.1.dev1/pyproject.toml +0 -3
  35. sqlalchemy_cubrid-0.0.1.dev1/setup.cfg +0 -19
  36. sqlalchemy_cubrid-0.0.1.dev1/setup.py +0 -31
  37. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid/__init__.py +0 -12
  38. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid/compiler.py +0 -38
  39. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid/dialect.py +0 -62
  40. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid/types.py +0 -26
  41. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid.egg-info/PKG-INFO +0 -15
  42. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid.egg-info/SOURCES.txt +0 -16
  43. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid.egg-info/entry_points.txt +0 -2
  44. sqlalchemy_cubrid-0.0.1.dev1/sqlalchemy_cubrid.egg-info/requires.txt +0 -2
  45. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.7.1}/LICENSE +0 -0
  46. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.7.1}/sqlalchemy_cubrid.egg-info/dependency_links.txt +0 -0
  47. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.7.1}/sqlalchemy_cubrid.egg-info/top_level.txt +0 -0
@@ -0,0 +1,2 @@
1
+ Yeongseon Choe <yeongseon.choe@gmail.com>
2
+ Gyeongjun Paik <paikend@gmail.com>
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlalchemy-cubrid
3
+ Version: 0.7.1
4
+ Summary: CUBRID dialect for SQLAlchemy
5
+ Author-email: Yeongseon Choe <yeongseon.choe@gmail.com>, Gyeongjun Paik <paikend@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/cubrid-labs/sqlalchemy-cubrid
8
+ Project-URL: Repository, https://github.com/cubrid-labs/sqlalchemy-cubrid
9
+ Project-URL: Documentation, https://github.com/cubrid-labs/sqlalchemy-cubrid/tree/main/docs
10
+ Project-URL: Changelog, https://github.com/cubrid-labs/sqlalchemy-cubrid/blob/main/CHANGELOG.md
11
+ Project-URL: Issues, https://github.com/cubrid-labs/sqlalchemy-cubrid/issues
12
+ Keywords: SQLAlchemy,CUBRID,dialect
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Programming Language :: SQL
26
+ Classifier: Topic :: Database
27
+ Classifier: Topic :: Database :: Front-Ends
28
+ Requires-Python: >=3.10
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ License-File: AUTHORS
32
+ Requires-Dist: sqlalchemy<2.2,>=2.0
33
+ Provides-Extra: cubrid
34
+ Requires-Dist: CUBRID-Python; extra == "cubrid"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest>=7.0; extra == "dev"
37
+ Requires-Dist: pytest-cov; extra == "dev"
38
+ Requires-Dist: ruff==0.15.6; extra == "dev"
39
+ Requires-Dist: mypy==1.19.1; extra == "dev"
40
+ Requires-Dist: bandit[toml]==1.9.4; extra == "dev"
41
+ Requires-Dist: pre-commit; extra == "dev"
42
+ Requires-Dist: tox; extra == "dev"
43
+ Requires-Dist: alembic>=1.7; extra == "dev"
44
+ Provides-Extra: alembic
45
+ Requires-Dist: alembic>=1.7; extra == "alembic"
46
+ Provides-Extra: pycubrid
47
+ Requires-Dist: pycubrid>=0.6.0; extra == "pycubrid"
48
+ Dynamic: license-file
49
+
50
+ # sqlalchemy-cubrid
51
+
52
+ **SQLAlchemy 2.0 dialect for the CUBRID database** — Python ORM, schema reflection, Alembic migrations, and full type system support.
53
+
54
+ [🇰🇷 한국어](docs/README.ko.md) · [🇺🇸 English](README.md) · [🇨🇳 中文](docs/README.zh.md) · [🇮🇳 हिन्दी](docs/README.hi.md) · [🇩🇪 Deutsch](docs/README.de.md) · [🇷🇺 Русский](docs/README.ru.md)
55
+
56
+ <!-- BADGES:START -->
57
+ [![PyPI version](https://img.shields.io/pypi/v/sqlalchemy-cubrid)](https://pypi.org/project/sqlalchemy-cubrid)
58
+ [![python version](https://img.shields.io/pypi/pyversions/sqlalchemy-cubrid)](https://www.python.org)
59
+ [![ci workflow](https://github.com/cubrid-labs/sqlalchemy-cubrid/actions/workflows/ci.yml/badge.svg)](https://github.com/cubrid-labs/sqlalchemy-cubrid/actions/workflows/ci.yml)
60
+ [![coverage](https://codecov.io/gh/cubrid-labs/sqlalchemy-cubrid/branch/main/graph/badge.svg)](https://codecov.io/gh/cubrid-labs/sqlalchemy-cubrid)
61
+ [![license](https://img.shields.io/github/license/cubrid-labs/sqlalchemy-cubrid)](https://github.com/cubrid-labs/sqlalchemy-cubrid/blob/main/LICENSE)
62
+ [![GitHub stars](https://img.shields.io/github/stars/cubrid-labs/sqlalchemy-cubrid)](https://github.com/cubrid-labs/sqlalchemy-cubrid)
63
+ ![dev version](https://img.shields.io/badge/dev-v0.8.0--dev-orange)
64
+ ![status](https://img.shields.io/badge/status-stable-brightgreen)
65
+ <!-- BADGES:END -->
66
+
67
+ ---
68
+
69
+ ## Why sqlalchemy-cubrid?
70
+
71
+ CUBRID is a high-performance open-source relational database, widely adopted in
72
+ Korean public-sector and enterprise applications. Until now, there was no
73
+ production-ready SQLAlchemy dialect that supports the modern 2.0 API.
74
+
75
+ **sqlalchemy-cubrid** bridges that gap:
76
+
77
+ - Full SQLAlchemy 2.0 dialect with **statement caching** and **PEP 561 typing**
78
+ - **426 offline tests** with **99%+ code coverage** — no database required to run them
79
+ - Tested against **4 CUBRID versions** (10.2, 11.0, 11.2, 11.4) across **Python 3.10 -- 3.13**
80
+ - CUBRID-specific DML constructs: `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`
81
+ - Alembic migration support out of the box
82
+ - **Two driver options** — C-extension (`cubrid://`) or pure Python (`cubrid+pycubrid://`)
83
+
84
+ ## Architecture
85
+
86
+ ```mermaid
87
+ flowchart TD
88
+ app["Application"] --> sa["SQLAlchemy Core/ORM"]
89
+ sa --> dialect["CubridDialect"]
90
+ dialect --> pycubrid["pycubrid driver"]
91
+ dialect --> cext["CUBRIDdb driver"]
92
+ pycubrid --> server["CUBRID Server"]
93
+ cext --> server
94
+ ```
95
+
96
+ ```mermaid
97
+ flowchart TD
98
+ expr["SQL Expression"] --> compiler["CubridSQLCompiler"] --> sql["SQL String"]
99
+ ```
100
+
101
+ ## Requirements
102
+
103
+ - Python 3.10+
104
+ - SQLAlchemy 2.0 – 2.1
105
+ - [CUBRID-Python](https://github.com/CUBRID/cubrid-python) (C-extension) **or** [pycubrid](https://github.com/sqlalchemy-cubrid/pycubrid) (pure Python)
106
+
107
+ ## Installation
108
+
109
+ ```bash
110
+ pip install sqlalchemy-cubrid
111
+ ```
112
+
113
+ With the pure Python driver (no C build needed):
114
+
115
+ ```bash
116
+ pip install "sqlalchemy-cubrid[pycubrid]"
117
+ ```
118
+
119
+ With Alembic support:
120
+
121
+ ```bash
122
+ pip install "sqlalchemy-cubrid[alembic]"
123
+ ```
124
+
125
+ ## Quick Start
126
+
127
+ ### Core (Connection-Level)
128
+
129
+ ```python
130
+ from sqlalchemy import create_engine, text
131
+
132
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
133
+
134
+ with engine.connect() as conn:
135
+ result = conn.execute(text("SELECT 1"))
136
+ print(result.scalar())
137
+ ```
138
+
139
+ ### ORM (Session-Level)
140
+
141
+ ```python
142
+ from sqlalchemy import create_engine, String
143
+ from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
144
+
145
+
146
+ class Base(DeclarativeBase):
147
+ pass
148
+
149
+
150
+ class User(Base):
151
+ __tablename__ = "users"
152
+
153
+ id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
154
+ name: Mapped[str] = mapped_column(String(100))
155
+ email: Mapped[str] = mapped_column(String(200), unique=True)
156
+
157
+
158
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
159
+ Base.metadata.create_all(engine)
160
+
161
+ with Session(engine) as session:
162
+ user = User(name="Alice", email="alice@example.com")
163
+ session.add(user)
164
+ session.commit()
165
+ ```
166
+
167
+ ## Features
168
+
169
+ - Complete type system -- numeric, string, date/time, bit, LOB, and collection types
170
+ - SQL compilation -- SELECT, JOIN, CAST, LIMIT/OFFSET, subqueries, CTEs, window functions
171
+ - DML extensions -- `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`, `FOR UPDATE`, `TRUNCATE`
172
+ - DDL support -- `COMMENT`, `IF NOT EXISTS` / `IF EXISTS`, `AUTO_INCREMENT`
173
+ - Schema reflection -- tables, views, columns, PKs, FKs, indexes, unique constraints, comments
174
+ - Alembic migrations via `CubridImpl` (auto-discovered entry point)
175
+ - All 6 CUBRID isolation levels (dual-granularity: class-level + instance-level)
176
+
177
+ ## Documentation
178
+
179
+ | Guide | Description |
180
+ |---|---|
181
+ | [Connection](docs/CONNECTION.md) | Connection strings, URL format, driver setup, pool tuning |
182
+ | [Type Mapping](docs/TYPES.md) | Full type mapping, CUBRID-specific types, collection types |
183
+ | [DML Extensions](docs/DML_EXTENSIONS.md) | ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, query trace |
184
+ | [Isolation Levels](docs/ISOLATION_LEVELS.md) | All 6 CUBRID isolation levels, configuration |
185
+ | [Alembic Migrations](docs/ALEMBIC.md) | Setup, configuration, limitations, batch workarounds |
186
+ | [Feature Support](docs/FEATURE_SUPPORT.md) | Comparison with MySQL, PostgreSQL, SQLite |
187
+ | [ORM Cookbook](docs/ORM_COOKBOOK.md) | Practical ORM examples, relationships, queries |
188
+ | [Development](docs/DEVELOPMENT.md) | Dev setup, testing, Docker, coverage, CI/CD |
189
+ | [Driver Compatibility](docs/DRIVER_COMPAT.md) | CUBRID-Python driver versions and known issues |
190
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues, error solutions, debugging techniques |
191
+
192
+ ## Compatibility
193
+
194
+ | | Python 3.10 | Python 3.11 | Python 3.12 | Python 3.13 |
195
+ |---|:---:|:---:|:---:|:---:|
196
+ | **Offline Tests** | ✅ | ✅ | ✅ | ✅ |
197
+ | **CUBRID 11.4** | ✅ | -- | ✅ | -- |
198
+ | **CUBRID 11.2** | ✅ | -- | ✅ | -- |
199
+ | **CUBRID 11.0** | ✅ | -- | ✅ | -- |
200
+ | **CUBRID 10.2** | ✅ | -- | ✅ | -- |
201
+
202
+ ## FAQ
203
+
204
+ ### How do I connect to CUBRID with SQLAlchemy?
205
+
206
+ ```python
207
+ from sqlalchemy import create_engine
208
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
209
+ ```
210
+
211
+ For the pure Python driver (no C build needed): `create_engine("cubrid+pycubrid://dba@localhost:33000/demodb")`
212
+
213
+ ### Does sqlalchemy-cubrid support SQLAlchemy 2.0?
214
+
215
+ Yes. sqlalchemy-cubrid is built for SQLAlchemy 2.0+ and supports the new 2.0-style API including `Session.execute()`, typed `Mapped[]` columns, and statement caching.
216
+
217
+ ### Does sqlalchemy-cubrid support Alembic migrations?
218
+
219
+ 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.
220
+
221
+ ### What Python versions are supported?
222
+
223
+ Python 3.10, 3.11, 3.12, and 3.13.
224
+
225
+ ### Does CUBRID support RETURNING clauses?
226
+
227
+ No. CUBRID does not support `INSERT ... RETURNING` or `UPDATE ... RETURNING`. Use `cursor.lastrowid` or `SELECT LAST_INSERT_ID()` instead.
228
+
229
+ ### How do I use ON DUPLICATE KEY UPDATE with CUBRID?
230
+
231
+ ```python
232
+ from sqlalchemy_cubrid import insert
233
+ stmt = insert(users).values(name="Alice").on_duplicate_key_update(name="Alice Updated")
234
+ ```
235
+
236
+ ### What's the difference between `cubrid://` and `cubrid+pycubrid://`?
237
+
238
+ `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.
239
+
240
+
241
+ ## Benchmark
242
+
243
+ Performance benchmarks comparing CUBRID (via pycubrid) against MySQL (via PyMySQL) are tracked in the [cubrid-benchmark](https://github.com/cubrid-labs/cubrid-benchmark) suite.
244
+
245
+ [![Benchmark](https://github.com/cubrid-labs/cubrid-benchmark/actions/workflows/bench.yml/badge.svg)](https://cubrid-labs.github.io/cubrid-benchmark/)
246
+
247
+ - **Tier 0** — Functional smoke tests (connect + CRUD)
248
+ - **Tier 1** — Driver throughput: 10K INSERT/SELECT, 1K UPDATE/DELETE
249
+ - Same schema, same seed data, same CI hardware per run
250
+ - Results published to [GitHub Pages dashboard](https://cubrid-labs.github.io/cubrid-benchmark/)
251
+
252
+
253
+ ## Related Projects
254
+
255
+ - [pycubrid](https://github.com/cubrid-labs/pycubrid) — Pure Python DB-API 2.0 driver for CUBRID
256
+ - [cubrid-client](https://github.com/cubrid-labs/cubrid-client) — Native TypeScript client for CUBRID (CAS protocol)
257
+ - [drizzle-cubrid](https://github.com/cubrid-labs/drizzle-cubrid) — Drizzle ORM dialect for CUBRID
258
+ - [cubrid-go](https://github.com/cubrid-labs/cubrid-go) — Pure Go database/sql driver for CUBRID
259
+ - [gorm-cubrid](https://github.com/cubrid-labs/gorm-cubrid) — GORM dialect for CUBRID
260
+ - [cubrid-rs](https://github.com/cubrid-labs/cubrid-rs) — Native Rust database driver for CUBRID (sync + async, pure Rust)
261
+ - [sea-orm-cubrid](https://github.com/cubrid-labs/sea-orm-cubrid) — SeaORM backend for CUBRID
262
+ - [cubrid-cookbook](https://github.com/cubrid-labs/cubrid-cookbook) — Production-ready examples for all CUBRID drivers
263
+ - [cubrid-benchmark](https://github.com/cubrid-labs/cubrid-benchmark) — Multi-language benchmark suite for CUBRID
264
+
265
+ ## Roadmap
266
+
267
+ See [`ROADMAP.md`](ROADMAP.md) for this project's direction and next milestones.
268
+
269
+ For the ecosystem-wide view, see the [CUBRID Labs Ecosystem Roadmap](https://github.com/cubrid-labs/.github/blob/main/ROADMAP.md) and [Project Board](https://github.com/orgs/cubrid-labs/projects/2).
270
+
271
+ ## Contributing
272
+
273
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for development setup.
274
+
275
+ ## Security
276
+
277
+ Report vulnerabilities via email -- see [SECURITY.md](SECURITY.md). Do not open public issues for security concerns.
278
+
279
+ ## License
280
+
281
+ MIT -- see [LICENSE](LICENSE).
@@ -0,0 +1,232 @@
1
+ # sqlalchemy-cubrid
2
+
3
+ **SQLAlchemy 2.0 dialect for the CUBRID database** — Python ORM, schema reflection, Alembic migrations, and full type system support.
4
+
5
+ [🇰🇷 한국어](docs/README.ko.md) · [🇺🇸 English](README.md) · [🇨🇳 中文](docs/README.zh.md) · [🇮🇳 हिन्दी](docs/README.hi.md) · [🇩🇪 Deutsch](docs/README.de.md) · [🇷🇺 Русский](docs/README.ru.md)
6
+
7
+ <!-- BADGES:START -->
8
+ [![PyPI version](https://img.shields.io/pypi/v/sqlalchemy-cubrid)](https://pypi.org/project/sqlalchemy-cubrid)
9
+ [![python version](https://img.shields.io/pypi/pyversions/sqlalchemy-cubrid)](https://www.python.org)
10
+ [![ci workflow](https://github.com/cubrid-labs/sqlalchemy-cubrid/actions/workflows/ci.yml/badge.svg)](https://github.com/cubrid-labs/sqlalchemy-cubrid/actions/workflows/ci.yml)
11
+ [![coverage](https://codecov.io/gh/cubrid-labs/sqlalchemy-cubrid/branch/main/graph/badge.svg)](https://codecov.io/gh/cubrid-labs/sqlalchemy-cubrid)
12
+ [![license](https://img.shields.io/github/license/cubrid-labs/sqlalchemy-cubrid)](https://github.com/cubrid-labs/sqlalchemy-cubrid/blob/main/LICENSE)
13
+ [![GitHub stars](https://img.shields.io/github/stars/cubrid-labs/sqlalchemy-cubrid)](https://github.com/cubrid-labs/sqlalchemy-cubrid)
14
+ ![dev version](https://img.shields.io/badge/dev-v0.8.0--dev-orange)
15
+ ![status](https://img.shields.io/badge/status-stable-brightgreen)
16
+ <!-- BADGES:END -->
17
+
18
+ ---
19
+
20
+ ## Why sqlalchemy-cubrid?
21
+
22
+ CUBRID is a high-performance open-source relational database, widely adopted in
23
+ Korean public-sector and enterprise applications. Until now, there was no
24
+ production-ready SQLAlchemy dialect that supports the modern 2.0 API.
25
+
26
+ **sqlalchemy-cubrid** bridges that gap:
27
+
28
+ - Full SQLAlchemy 2.0 dialect with **statement caching** and **PEP 561 typing**
29
+ - **426 offline tests** with **99%+ code coverage** — no database required to run them
30
+ - Tested against **4 CUBRID versions** (10.2, 11.0, 11.2, 11.4) across **Python 3.10 -- 3.13**
31
+ - CUBRID-specific DML constructs: `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`
32
+ - Alembic migration support out of the box
33
+ - **Two driver options** — C-extension (`cubrid://`) or pure Python (`cubrid+pycubrid://`)
34
+
35
+ ## Architecture
36
+
37
+ ```mermaid
38
+ flowchart TD
39
+ app["Application"] --> sa["SQLAlchemy Core/ORM"]
40
+ sa --> dialect["CubridDialect"]
41
+ dialect --> pycubrid["pycubrid driver"]
42
+ dialect --> cext["CUBRIDdb driver"]
43
+ pycubrid --> server["CUBRID Server"]
44
+ cext --> server
45
+ ```
46
+
47
+ ```mermaid
48
+ flowchart TD
49
+ expr["SQL Expression"] --> compiler["CubridSQLCompiler"] --> sql["SQL String"]
50
+ ```
51
+
52
+ ## Requirements
53
+
54
+ - Python 3.10+
55
+ - SQLAlchemy 2.0 – 2.1
56
+ - [CUBRID-Python](https://github.com/CUBRID/cubrid-python) (C-extension) **or** [pycubrid](https://github.com/sqlalchemy-cubrid/pycubrid) (pure Python)
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ pip install sqlalchemy-cubrid
62
+ ```
63
+
64
+ With the pure Python driver (no C build needed):
65
+
66
+ ```bash
67
+ pip install "sqlalchemy-cubrid[pycubrid]"
68
+ ```
69
+
70
+ With Alembic support:
71
+
72
+ ```bash
73
+ pip install "sqlalchemy-cubrid[alembic]"
74
+ ```
75
+
76
+ ## Quick Start
77
+
78
+ ### Core (Connection-Level)
79
+
80
+ ```python
81
+ from sqlalchemy import create_engine, text
82
+
83
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
84
+
85
+ with engine.connect() as conn:
86
+ result = conn.execute(text("SELECT 1"))
87
+ print(result.scalar())
88
+ ```
89
+
90
+ ### ORM (Session-Level)
91
+
92
+ ```python
93
+ from sqlalchemy import create_engine, String
94
+ from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
95
+
96
+
97
+ class Base(DeclarativeBase):
98
+ pass
99
+
100
+
101
+ class User(Base):
102
+ __tablename__ = "users"
103
+
104
+ id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
105
+ name: Mapped[str] = mapped_column(String(100))
106
+ email: Mapped[str] = mapped_column(String(200), unique=True)
107
+
108
+
109
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
110
+ Base.metadata.create_all(engine)
111
+
112
+ with Session(engine) as session:
113
+ user = User(name="Alice", email="alice@example.com")
114
+ session.add(user)
115
+ session.commit()
116
+ ```
117
+
118
+ ## Features
119
+
120
+ - Complete type system -- numeric, string, date/time, bit, LOB, and collection types
121
+ - SQL compilation -- SELECT, JOIN, CAST, LIMIT/OFFSET, subqueries, CTEs, window functions
122
+ - DML extensions -- `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`, `FOR UPDATE`, `TRUNCATE`
123
+ - DDL support -- `COMMENT`, `IF NOT EXISTS` / `IF EXISTS`, `AUTO_INCREMENT`
124
+ - Schema reflection -- tables, views, columns, PKs, FKs, indexes, unique constraints, comments
125
+ - Alembic migrations via `CubridImpl` (auto-discovered entry point)
126
+ - All 6 CUBRID isolation levels (dual-granularity: class-level + instance-level)
127
+
128
+ ## Documentation
129
+
130
+ | Guide | Description |
131
+ |---|---|
132
+ | [Connection](docs/CONNECTION.md) | Connection strings, URL format, driver setup, pool tuning |
133
+ | [Type Mapping](docs/TYPES.md) | Full type mapping, CUBRID-specific types, collection types |
134
+ | [DML Extensions](docs/DML_EXTENSIONS.md) | ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, query trace |
135
+ | [Isolation Levels](docs/ISOLATION_LEVELS.md) | All 6 CUBRID isolation levels, configuration |
136
+ | [Alembic Migrations](docs/ALEMBIC.md) | Setup, configuration, limitations, batch workarounds |
137
+ | [Feature Support](docs/FEATURE_SUPPORT.md) | Comparison with MySQL, PostgreSQL, SQLite |
138
+ | [ORM Cookbook](docs/ORM_COOKBOOK.md) | Practical ORM examples, relationships, queries |
139
+ | [Development](docs/DEVELOPMENT.md) | Dev setup, testing, Docker, coverage, CI/CD |
140
+ | [Driver Compatibility](docs/DRIVER_COMPAT.md) | CUBRID-Python driver versions and known issues |
141
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues, error solutions, debugging techniques |
142
+
143
+ ## Compatibility
144
+
145
+ | | Python 3.10 | Python 3.11 | Python 3.12 | Python 3.13 |
146
+ |---|:---:|:---:|:---:|:---:|
147
+ | **Offline Tests** | ✅ | ✅ | ✅ | ✅ |
148
+ | **CUBRID 11.4** | ✅ | -- | ✅ | -- |
149
+ | **CUBRID 11.2** | ✅ | -- | ✅ | -- |
150
+ | **CUBRID 11.0** | ✅ | -- | ✅ | -- |
151
+ | **CUBRID 10.2** | ✅ | -- | ✅ | -- |
152
+
153
+ ## FAQ
154
+
155
+ ### How do I connect to CUBRID with SQLAlchemy?
156
+
157
+ ```python
158
+ from sqlalchemy import create_engine
159
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
160
+ ```
161
+
162
+ For the pure Python driver (no C build needed): `create_engine("cubrid+pycubrid://dba@localhost:33000/demodb")`
163
+
164
+ ### Does sqlalchemy-cubrid support SQLAlchemy 2.0?
165
+
166
+ Yes. sqlalchemy-cubrid is built for SQLAlchemy 2.0+ and supports the new 2.0-style API including `Session.execute()`, typed `Mapped[]` columns, and statement caching.
167
+
168
+ ### Does sqlalchemy-cubrid support Alembic migrations?
169
+
170
+ 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.
171
+
172
+ ### What Python versions are supported?
173
+
174
+ Python 3.10, 3.11, 3.12, and 3.13.
175
+
176
+ ### Does CUBRID support RETURNING clauses?
177
+
178
+ No. CUBRID does not support `INSERT ... RETURNING` or `UPDATE ... RETURNING`. Use `cursor.lastrowid` or `SELECT LAST_INSERT_ID()` instead.
179
+
180
+ ### How do I use ON DUPLICATE KEY UPDATE with CUBRID?
181
+
182
+ ```python
183
+ from sqlalchemy_cubrid import insert
184
+ stmt = insert(users).values(name="Alice").on_duplicate_key_update(name="Alice Updated")
185
+ ```
186
+
187
+ ### What's the difference between `cubrid://` and `cubrid+pycubrid://`?
188
+
189
+ `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.
190
+
191
+
192
+ ## Benchmark
193
+
194
+ Performance benchmarks comparing CUBRID (via pycubrid) against MySQL (via PyMySQL) are tracked in the [cubrid-benchmark](https://github.com/cubrid-labs/cubrid-benchmark) suite.
195
+
196
+ [![Benchmark](https://github.com/cubrid-labs/cubrid-benchmark/actions/workflows/bench.yml/badge.svg)](https://cubrid-labs.github.io/cubrid-benchmark/)
197
+
198
+ - **Tier 0** — Functional smoke tests (connect + CRUD)
199
+ - **Tier 1** — Driver throughput: 10K INSERT/SELECT, 1K UPDATE/DELETE
200
+ - Same schema, same seed data, same CI hardware per run
201
+ - Results published to [GitHub Pages dashboard](https://cubrid-labs.github.io/cubrid-benchmark/)
202
+
203
+
204
+ ## Related Projects
205
+
206
+ - [pycubrid](https://github.com/cubrid-labs/pycubrid) — Pure Python DB-API 2.0 driver for CUBRID
207
+ - [cubrid-client](https://github.com/cubrid-labs/cubrid-client) — Native TypeScript client for CUBRID (CAS protocol)
208
+ - [drizzle-cubrid](https://github.com/cubrid-labs/drizzle-cubrid) — Drizzle ORM dialect for CUBRID
209
+ - [cubrid-go](https://github.com/cubrid-labs/cubrid-go) — Pure Go database/sql driver for CUBRID
210
+ - [gorm-cubrid](https://github.com/cubrid-labs/gorm-cubrid) — GORM dialect for CUBRID
211
+ - [cubrid-rs](https://github.com/cubrid-labs/cubrid-rs) — Native Rust database driver for CUBRID (sync + async, pure Rust)
212
+ - [sea-orm-cubrid](https://github.com/cubrid-labs/sea-orm-cubrid) — SeaORM backend for CUBRID
213
+ - [cubrid-cookbook](https://github.com/cubrid-labs/cubrid-cookbook) — Production-ready examples for all CUBRID drivers
214
+ - [cubrid-benchmark](https://github.com/cubrid-labs/cubrid-benchmark) — Multi-language benchmark suite for CUBRID
215
+
216
+ ## Roadmap
217
+
218
+ See [`ROADMAP.md`](ROADMAP.md) for this project's direction and next milestones.
219
+
220
+ For the ecosystem-wide view, see the [CUBRID Labs Ecosystem Roadmap](https://github.com/cubrid-labs/.github/blob/main/ROADMAP.md) and [Project Board](https://github.com/orgs/cubrid-labs/projects/2).
221
+
222
+ ## Contributing
223
+
224
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for development setup.
225
+
226
+ ## Security
227
+
228
+ Report vulnerabilities via email -- see [SECURITY.md](SECURITY.md). Do not open public issues for security concerns.
229
+
230
+ ## License
231
+
232
+ MIT -- see [LICENSE](LICENSE).
@@ -0,0 +1,109 @@
1
+ [build-system]
2
+ requires = ["setuptools>=65.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sqlalchemy-cubrid"
7
+ version = "0.7.1"
8
+ description = "CUBRID dialect for SQLAlchemy"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "Yeongseon Choe", email = "yeongseon.choe@gmail.com"},
14
+ {name = "Gyeongjun Paik", email = "paikend@gmail.com"},
15
+ ]
16
+ keywords = ["SQLAlchemy", "CUBRID", "dialect"]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3 :: Only",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
30
+ "Programming Language :: SQL",
31
+ "Topic :: Database",
32
+ "Topic :: Database :: Front-Ends",
33
+ ]
34
+ dependencies = [
35
+ "sqlalchemy>=2.0,<2.2",
36
+ ]
37
+
38
+ [project.optional-dependencies]
39
+ cubrid = [
40
+ "CUBRID-Python",
41
+ ]
42
+ dev = [
43
+ "pytest>=7.0",
44
+ "pytest-cov",
45
+ "ruff==0.15.6",
46
+ "mypy==1.19.1",
47
+ "bandit[toml]==1.9.4",
48
+ "pre-commit",
49
+ "tox",
50
+ "alembic>=1.7",
51
+ ]
52
+ alembic = [
53
+ "alembic>=1.7",
54
+ ]
55
+ pycubrid = [
56
+ "pycubrid>=0.6.0",
57
+ ]
58
+
59
+ [project.urls]
60
+ Homepage = "https://github.com/cubrid-labs/sqlalchemy-cubrid"
61
+ Repository = "https://github.com/cubrid-labs/sqlalchemy-cubrid"
62
+ Documentation = "https://github.com/cubrid-labs/sqlalchemy-cubrid/tree/main/docs"
63
+ Changelog = "https://github.com/cubrid-labs/sqlalchemy-cubrid/blob/main/CHANGELOG.md"
64
+ Issues = "https://github.com/cubrid-labs/sqlalchemy-cubrid/issues"
65
+
66
+ [project.entry-points."sqlalchemy.dialects"]
67
+ cubrid = "sqlalchemy_cubrid.dialect:CubridDialect"
68
+ "cubrid.cubrid" = "sqlalchemy_cubrid.dialect:CubridDialect"
69
+ "cubrid.pycubrid" = "sqlalchemy_cubrid.pycubrid_dialect:PyCubridDialect"
70
+
71
+ [project.entry-points."alembic.ddl"]
72
+ cubrid = "sqlalchemy_cubrid.alembic_impl:CubridImpl"
73
+
74
+ [tool.setuptools]
75
+ packages = ["sqlalchemy_cubrid"]
76
+ include-package-data = true
77
+
78
+ [tool.ruff]
79
+ line-length = 100
80
+ target-version = "py310"
81
+
82
+ [tool.ruff.lint.isort]
83
+ known-first-party = ["sqlalchemy_cubrid"]
84
+
85
+ [tool.mypy]
86
+ python_version = "3.10"
87
+ strict = true
88
+ warn_return_any = true
89
+ warn_unused_configs = true
90
+
91
+ [[tool.mypy.overrides]]
92
+ module = "test.*"
93
+ ignore_errors = true
94
+
95
+ [tool.bandit]
96
+ exclude_dirs = ["test"]
97
+ skips = ["B101"]
98
+
99
+ [tool.coverage.run]
100
+ source = ["sqlalchemy_cubrid"]
101
+
102
+ [tool.coverage.report]
103
+ show_missing = true
104
+ fail_under = 95
105
+
106
+ [tool.pytest.ini_options]
107
+ testpaths = ["test"]
108
+ addopts = "--tb native -v -r fxX --maxfail=25 -p no:warnings"
109
+ python_files = "test/*test_*.py"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+