sqlalchemy-cubrid 0.0.1.dev1__tar.gz → 0.8.0__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.8.0/AUTHORS +2 -0
  2. sqlalchemy_cubrid-0.8.0/PKG-INFO +260 -0
  3. sqlalchemy_cubrid-0.8.0/README.md +211 -0
  4. sqlalchemy_cubrid-0.8.0/pyproject.toml +109 -0
  5. sqlalchemy_cubrid-0.8.0/setup.cfg +4 -0
  6. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/__init__.py +85 -0
  7. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/alembic_impl.py +145 -0
  8. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.8.0}/sqlalchemy_cubrid/base.py +44 -39
  9. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/compiler.py +515 -0
  10. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/dialect.py +700 -0
  11. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/dml.py +318 -0
  12. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/py.typed +0 -0
  13. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/pycubrid_dialect.py +124 -0
  14. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/requirements.py +270 -0
  15. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/trace.py +92 -0
  16. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid/types.py +349 -0
  17. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid.egg-info/PKG-INFO +260 -0
  18. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid.egg-info/SOURCES.txt +32 -0
  19. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid.egg-info/entry_points.txt +7 -0
  20. sqlalchemy_cubrid-0.8.0/sqlalchemy_cubrid.egg-info/requires.txt +20 -0
  21. sqlalchemy_cubrid-0.8.0/test/test_alembic.py +261 -0
  22. sqlalchemy_cubrid-0.8.0/test/test_base.py +145 -0
  23. sqlalchemy_cubrid-0.8.0/test/test_compiler.py +1695 -0
  24. sqlalchemy_cubrid-0.8.0/test/test_dialect_offline.py +799 -0
  25. sqlalchemy_cubrid-0.8.0/test/test_dialects.py +79 -0
  26. sqlalchemy_cubrid-0.8.0/test/test_integration.py +581 -0
  27. sqlalchemy_cubrid-0.8.0/test/test_pycubrid_dialect.py +299 -0
  28. sqlalchemy_cubrid-0.8.0/test/test_requirements.py +133 -0
  29. sqlalchemy_cubrid-0.8.0/test/test_suite.py +13 -0
  30. sqlalchemy_cubrid-0.8.0/test/test_trace.py +197 -0
  31. sqlalchemy_cubrid-0.8.0/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.8.0}/LICENSE +0 -0
  46. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.8.0}/sqlalchemy_cubrid.egg-info/dependency_links.txt +0 -0
  47. {sqlalchemy_cubrid-0.0.1.dev1 → sqlalchemy_cubrid-0.8.0}/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,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlalchemy-cubrid
3
+ Version: 0.8.0
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.8; 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
+ <!-- BADGES:END -->
64
+
65
+ ---
66
+
67
+ ## Why sqlalchemy-cubrid?
68
+
69
+ CUBRID is a high-performance open-source relational database, widely adopted in
70
+ Korean public-sector and enterprise applications. Until now, there was no
71
+ production-ready SQLAlchemy dialect that supports the modern 2.0 API.
72
+
73
+ **sqlalchemy-cubrid** bridges that gap:
74
+
75
+ - Full SQLAlchemy 2.0 dialect with **statement caching** and **PEP 561 typing**
76
+ - **426 offline tests** with **99%+ code coverage** — no database required to run them
77
+ - Tested against **4 CUBRID versions** (10.2, 11.0, 11.2, 11.4) across **Python 3.10 -- 3.13**
78
+ - CUBRID-specific DML constructs: `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`
79
+ - Alembic migration support out of the box
80
+ - **Two driver options** — C-extension (`cubrid://`) or pure Python (`cubrid+pycubrid://`)
81
+
82
+ ## Architecture
83
+
84
+ ```mermaid
85
+ flowchart TD
86
+ app["Application"] --> sa["SQLAlchemy Core/ORM"]
87
+ sa --> dialect["CubridDialect"]
88
+ dialect --> pycubrid["pycubrid driver"]
89
+ dialect --> cext["CUBRIDdb driver"]
90
+ pycubrid --> server["CUBRID Server"]
91
+ cext --> server
92
+ ```
93
+
94
+ ```mermaid
95
+ flowchart TD
96
+ expr["SQL Expression"] --> compiler["CubridSQLCompiler"] --> sql["SQL String"]
97
+ ```
98
+
99
+ ## Requirements
100
+
101
+ - Python 3.10+
102
+ - SQLAlchemy 2.0 – 2.1
103
+ - [CUBRID-Python](https://github.com/CUBRID/cubrid-python) (C-extension) **or** [pycubrid](https://github.com/sqlalchemy-cubrid/pycubrid) (pure Python)
104
+
105
+ ## Installation
106
+
107
+ ```bash
108
+ pip install sqlalchemy-cubrid
109
+ ```
110
+
111
+ With the pure Python driver (no C build needed):
112
+
113
+ ```bash
114
+ pip install "sqlalchemy-cubrid[pycubrid]"
115
+ ```
116
+
117
+ With Alembic support:
118
+
119
+ ```bash
120
+ pip install "sqlalchemy-cubrid[alembic]"
121
+ ```
122
+
123
+ ## Quick Start
124
+
125
+ ### Core (Connection-Level)
126
+
127
+ ```python
128
+ from sqlalchemy import create_engine, text
129
+
130
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
131
+
132
+ with engine.connect() as conn:
133
+ result = conn.execute(text("SELECT 1"))
134
+ print(result.scalar())
135
+ ```
136
+
137
+ ### ORM (Session-Level)
138
+
139
+ ```python
140
+ from sqlalchemy import create_engine, String
141
+ from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
142
+
143
+
144
+ class Base(DeclarativeBase):
145
+ pass
146
+
147
+
148
+ class User(Base):
149
+ __tablename__ = "users"
150
+
151
+ id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
152
+ name: Mapped[str] = mapped_column(String(100))
153
+ email: Mapped[str] = mapped_column(String(200), unique=True)
154
+
155
+
156
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
157
+ Base.metadata.create_all(engine)
158
+
159
+ with Session(engine) as session:
160
+ user = User(name="Alice", email="alice@example.com")
161
+ session.add(user)
162
+ session.commit()
163
+ ```
164
+
165
+ ## Features
166
+
167
+ - Complete type system -- numeric, string, date/time, bit, LOB, and collection types
168
+ - SQL compilation -- SELECT, JOIN, CAST, LIMIT/OFFSET, subqueries, CTEs, window functions
169
+ - DML extensions -- `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`, `FOR UPDATE`, `TRUNCATE`
170
+ - DDL support -- `COMMENT`, `IF NOT EXISTS` / `IF EXISTS`, `AUTO_INCREMENT`
171
+ - Schema reflection -- tables, views, columns, PKs, FKs, indexes, unique constraints, comments
172
+ - Alembic migrations via `CubridImpl` (auto-discovered entry point)
173
+ - All 6 CUBRID isolation levels (dual-granularity: class-level + instance-level)
174
+
175
+ ## Documentation
176
+
177
+ | Guide | Description |
178
+ |---|---|
179
+ | [Connection](docs/CONNECTION.md) | Connection strings, URL format, driver setup, pool tuning |
180
+ | [Type Mapping](docs/TYPES.md) | Full type mapping, CUBRID-specific types, collection types |
181
+ | [DML Extensions](docs/DML_EXTENSIONS.md) | ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, query trace |
182
+ | [Isolation Levels](docs/ISOLATION_LEVELS.md) | All 6 CUBRID isolation levels, configuration |
183
+ | [Alembic Migrations](docs/ALEMBIC.md) | Setup, configuration, limitations, batch workarounds |
184
+ | [Feature Support](docs/FEATURE_SUPPORT.md) | Comparison with MySQL, PostgreSQL, SQLite |
185
+ | [ORM Cookbook](docs/ORM_COOKBOOK.md) | Practical ORM examples, relationships, queries |
186
+ | [Development](docs/DEVELOPMENT.md) | Dev setup, testing, Docker, coverage, CI/CD |
187
+ | [Driver Compatibility](docs/DRIVER_COMPAT.md) | CUBRID-Python driver versions and known issues |
188
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues, error solutions, debugging techniques |
189
+
190
+ ## Compatibility
191
+
192
+ | | Python 3.10 | Python 3.11 | Python 3.12 | Python 3.13 |
193
+ |---|:---:|:---:|:---:|:---:|
194
+ | **Offline Tests** | ✅ | ✅ | ✅ | ✅ |
195
+ | **CUBRID 11.4** | ✅ | -- | ✅ | -- |
196
+ | **CUBRID 11.2** | ✅ | -- | ✅ | -- |
197
+ | **CUBRID 11.0** | ✅ | -- | ✅ | -- |
198
+ | **CUBRID 10.2** | ✅ | -- | ✅ | -- |
199
+
200
+ ## FAQ
201
+
202
+ ### How do I connect to CUBRID with SQLAlchemy?
203
+
204
+ ```python
205
+ from sqlalchemy import create_engine
206
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
207
+ ```
208
+
209
+ For the pure Python driver (no C build needed): `create_engine("cubrid+pycubrid://dba@localhost:33000/demodb")`
210
+
211
+ ### Does sqlalchemy-cubrid support SQLAlchemy 2.0?
212
+
213
+ 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.
214
+
215
+ ### Does sqlalchemy-cubrid support Alembic migrations?
216
+
217
+ 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.
218
+
219
+ ### What Python versions are supported?
220
+
221
+ Python 3.10, 3.11, 3.12, and 3.13.
222
+
223
+ ### Does CUBRID support RETURNING clauses?
224
+
225
+ No. CUBRID does not support `INSERT ... RETURNING` or `UPDATE ... RETURNING`. Use `cursor.lastrowid` or `SELECT LAST_INSERT_ID()` instead.
226
+
227
+ ### How do I use ON DUPLICATE KEY UPDATE with CUBRID?
228
+
229
+ ```python
230
+ from sqlalchemy_cubrid import insert
231
+ stmt = insert(users).values(name="Alice").on_duplicate_key_update(name="Alice Updated")
232
+ ```
233
+
234
+ ### What's the difference between `cubrid://` and `cubrid+pycubrid://`?
235
+
236
+ `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.
237
+
238
+
239
+ ## Related Projects
240
+
241
+ - [pycubrid](https://github.com/cubrid-labs/pycubrid) — Pure Python DB-API 2.0 driver for CUBRID
242
+ - [cubrid-python-cookbook](https://github.com/cubrid-labs/cubrid-python-cookbook) — Production-ready Python examples for CUBRID
243
+
244
+ ## Roadmap
245
+
246
+ See [`ROADMAP.md`](ROADMAP.md) for this project's direction and next milestones.
247
+
248
+ 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).
249
+
250
+ ## Contributing
251
+
252
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for development setup.
253
+
254
+ ## Security
255
+
256
+ Report vulnerabilities via email -- see [SECURITY.md](SECURITY.md). Do not open public issues for security concerns.
257
+
258
+ ## License
259
+
260
+ MIT -- see [LICENSE](LICENSE).
@@ -0,0 +1,211 @@
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
+ <!-- BADGES:END -->
15
+
16
+ ---
17
+
18
+ ## Why sqlalchemy-cubrid?
19
+
20
+ CUBRID is a high-performance open-source relational database, widely adopted in
21
+ Korean public-sector and enterprise applications. Until now, there was no
22
+ production-ready SQLAlchemy dialect that supports the modern 2.0 API.
23
+
24
+ **sqlalchemy-cubrid** bridges that gap:
25
+
26
+ - Full SQLAlchemy 2.0 dialect with **statement caching** and **PEP 561 typing**
27
+ - **426 offline tests** with **99%+ code coverage** — no database required to run them
28
+ - Tested against **4 CUBRID versions** (10.2, 11.0, 11.2, 11.4) across **Python 3.10 -- 3.13**
29
+ - CUBRID-specific DML constructs: `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`
30
+ - Alembic migration support out of the box
31
+ - **Two driver options** — C-extension (`cubrid://`) or pure Python (`cubrid+pycubrid://`)
32
+
33
+ ## Architecture
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ app["Application"] --> sa["SQLAlchemy Core/ORM"]
38
+ sa --> dialect["CubridDialect"]
39
+ dialect --> pycubrid["pycubrid driver"]
40
+ dialect --> cext["CUBRIDdb driver"]
41
+ pycubrid --> server["CUBRID Server"]
42
+ cext --> server
43
+ ```
44
+
45
+ ```mermaid
46
+ flowchart TD
47
+ expr["SQL Expression"] --> compiler["CubridSQLCompiler"] --> sql["SQL String"]
48
+ ```
49
+
50
+ ## Requirements
51
+
52
+ - Python 3.10+
53
+ - SQLAlchemy 2.0 – 2.1
54
+ - [CUBRID-Python](https://github.com/CUBRID/cubrid-python) (C-extension) **or** [pycubrid](https://github.com/sqlalchemy-cubrid/pycubrid) (pure Python)
55
+
56
+ ## Installation
57
+
58
+ ```bash
59
+ pip install sqlalchemy-cubrid
60
+ ```
61
+
62
+ With the pure Python driver (no C build needed):
63
+
64
+ ```bash
65
+ pip install "sqlalchemy-cubrid[pycubrid]"
66
+ ```
67
+
68
+ With Alembic support:
69
+
70
+ ```bash
71
+ pip install "sqlalchemy-cubrid[alembic]"
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ### Core (Connection-Level)
77
+
78
+ ```python
79
+ from sqlalchemy import create_engine, text
80
+
81
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
82
+
83
+ with engine.connect() as conn:
84
+ result = conn.execute(text("SELECT 1"))
85
+ print(result.scalar())
86
+ ```
87
+
88
+ ### ORM (Session-Level)
89
+
90
+ ```python
91
+ from sqlalchemy import create_engine, String
92
+ from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
93
+
94
+
95
+ class Base(DeclarativeBase):
96
+ pass
97
+
98
+
99
+ class User(Base):
100
+ __tablename__ = "users"
101
+
102
+ id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
103
+ name: Mapped[str] = mapped_column(String(100))
104
+ email: Mapped[str] = mapped_column(String(200), unique=True)
105
+
106
+
107
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
108
+ Base.metadata.create_all(engine)
109
+
110
+ with Session(engine) as session:
111
+ user = User(name="Alice", email="alice@example.com")
112
+ session.add(user)
113
+ session.commit()
114
+ ```
115
+
116
+ ## Features
117
+
118
+ - Complete type system -- numeric, string, date/time, bit, LOB, and collection types
119
+ - SQL compilation -- SELECT, JOIN, CAST, LIMIT/OFFSET, subqueries, CTEs, window functions
120
+ - DML extensions -- `ON DUPLICATE KEY UPDATE`, `MERGE`, `REPLACE INTO`, `FOR UPDATE`, `TRUNCATE`
121
+ - DDL support -- `COMMENT`, `IF NOT EXISTS` / `IF EXISTS`, `AUTO_INCREMENT`
122
+ - Schema reflection -- tables, views, columns, PKs, FKs, indexes, unique constraints, comments
123
+ - Alembic migrations via `CubridImpl` (auto-discovered entry point)
124
+ - All 6 CUBRID isolation levels (dual-granularity: class-level + instance-level)
125
+
126
+ ## Documentation
127
+
128
+ | Guide | Description |
129
+ |---|---|
130
+ | [Connection](docs/CONNECTION.md) | Connection strings, URL format, driver setup, pool tuning |
131
+ | [Type Mapping](docs/TYPES.md) | Full type mapping, CUBRID-specific types, collection types |
132
+ | [DML Extensions](docs/DML_EXTENSIONS.md) | ON DUPLICATE KEY UPDATE, MERGE, REPLACE INTO, query trace |
133
+ | [Isolation Levels](docs/ISOLATION_LEVELS.md) | All 6 CUBRID isolation levels, configuration |
134
+ | [Alembic Migrations](docs/ALEMBIC.md) | Setup, configuration, limitations, batch workarounds |
135
+ | [Feature Support](docs/FEATURE_SUPPORT.md) | Comparison with MySQL, PostgreSQL, SQLite |
136
+ | [ORM Cookbook](docs/ORM_COOKBOOK.md) | Practical ORM examples, relationships, queries |
137
+ | [Development](docs/DEVELOPMENT.md) | Dev setup, testing, Docker, coverage, CI/CD |
138
+ | [Driver Compatibility](docs/DRIVER_COMPAT.md) | CUBRID-Python driver versions and known issues |
139
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues, error solutions, debugging techniques |
140
+
141
+ ## Compatibility
142
+
143
+ | | Python 3.10 | Python 3.11 | Python 3.12 | Python 3.13 |
144
+ |---|:---:|:---:|:---:|:---:|
145
+ | **Offline Tests** | ✅ | ✅ | ✅ | ✅ |
146
+ | **CUBRID 11.4** | ✅ | -- | ✅ | -- |
147
+ | **CUBRID 11.2** | ✅ | -- | ✅ | -- |
148
+ | **CUBRID 11.0** | ✅ | -- | ✅ | -- |
149
+ | **CUBRID 10.2** | ✅ | -- | ✅ | -- |
150
+
151
+ ## FAQ
152
+
153
+ ### How do I connect to CUBRID with SQLAlchemy?
154
+
155
+ ```python
156
+ from sqlalchemy import create_engine
157
+ engine = create_engine("cubrid://dba:password@localhost:33000/demodb")
158
+ ```
159
+
160
+ For the pure Python driver (no C build needed): `create_engine("cubrid+pycubrid://dba@localhost:33000/demodb")`
161
+
162
+ ### Does sqlalchemy-cubrid support SQLAlchemy 2.0?
163
+
164
+ 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.
165
+
166
+ ### Does sqlalchemy-cubrid support Alembic migrations?
167
+
168
+ 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.
169
+
170
+ ### What Python versions are supported?
171
+
172
+ Python 3.10, 3.11, 3.12, and 3.13.
173
+
174
+ ### Does CUBRID support RETURNING clauses?
175
+
176
+ No. CUBRID does not support `INSERT ... RETURNING` or `UPDATE ... RETURNING`. Use `cursor.lastrowid` or `SELECT LAST_INSERT_ID()` instead.
177
+
178
+ ### How do I use ON DUPLICATE KEY UPDATE with CUBRID?
179
+
180
+ ```python
181
+ from sqlalchemy_cubrid import insert
182
+ stmt = insert(users).values(name="Alice").on_duplicate_key_update(name="Alice Updated")
183
+ ```
184
+
185
+ ### What's the difference between `cubrid://` and `cubrid+pycubrid://`?
186
+
187
+ `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.
188
+
189
+
190
+ ## Related Projects
191
+
192
+ - [pycubrid](https://github.com/cubrid-labs/pycubrid) — Pure Python DB-API 2.0 driver for CUBRID
193
+ - [cubrid-python-cookbook](https://github.com/cubrid-labs/cubrid-python-cookbook) — Production-ready Python examples for CUBRID
194
+
195
+ ## Roadmap
196
+
197
+ See [`ROADMAP.md`](ROADMAP.md) for this project's direction and next milestones.
198
+
199
+ 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).
200
+
201
+ ## Contributing
202
+
203
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for development setup.
204
+
205
+ ## Security
206
+
207
+ Report vulnerabilities via email -- see [SECURITY.md](SECURITY.md). Do not open public issues for security concerns.
208
+
209
+ ## License
210
+
211
+ 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.8.0"
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.8",
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
+
@@ -0,0 +1,85 @@
1
+ # sqlalchemy_cubrid/__init__.py
2
+ # Copyright (C) 2021-2026 by sqlalchemy-cubrid authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of sqlalchemy-cubrid and is released under
6
+ # the MIT License: http://www.opensource.org/licenses/mit-license.php
7
+
8
+ """CUBRID dialect for SQLAlchemy.
9
+
10
+ Each dialect provides the full set of typenames supported by that backend
11
+ with its ``__all__`` collection.
12
+
13
+ See: https://docs.sqlalchemy.org/en/20/core/type_basics.html#vendor-specific-types
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from .types import (
19
+ BIGINT,
20
+ BIT,
21
+ BLOB,
22
+ CHAR,
23
+ CLOB,
24
+ DECIMAL,
25
+ DOUBLE,
26
+ DOUBLE_PRECISION,
27
+ FLOAT,
28
+ MONETARY,
29
+ MULTISET,
30
+ NCHAR,
31
+ NUMERIC,
32
+ NVARCHAR,
33
+ OBJECT,
34
+ REAL,
35
+ SEQUENCE,
36
+ SET,
37
+ SMALLINT,
38
+ STRING,
39
+ VARCHAR,
40
+ )
41
+ from .dml import insert, merge, replace
42
+ from .trace import trace_query
43
+
44
+ from sqlalchemy.sql.sqltypes import (
45
+ DATE,
46
+ DATETIME,
47
+ INTEGER,
48
+ TIME,
49
+ TIMESTAMP,
50
+ )
51
+
52
+ __version__ = "0.8.0"
53
+
54
+ __all__ = (
55
+ "insert",
56
+ "merge",
57
+ "replace",
58
+ "trace_query",
59
+ "SMALLINT",
60
+ "INTEGER",
61
+ "BIGINT",
62
+ "NUMERIC",
63
+ "DECIMAL",
64
+ "FLOAT",
65
+ "REAL",
66
+ "DOUBLE",
67
+ "DOUBLE_PRECISION",
68
+ "MONETARY",
69
+ "DATE",
70
+ "TIME",
71
+ "TIMESTAMP",
72
+ "DATETIME",
73
+ "BIT",
74
+ "CHAR",
75
+ "VARCHAR",
76
+ "NCHAR",
77
+ "NVARCHAR",
78
+ "STRING",
79
+ "BLOB",
80
+ "CLOB",
81
+ "SET",
82
+ "MULTISET",
83
+ "SEQUENCE",
84
+ "OBJECT",
85
+ )