sqlalchemy-cubrid 0.7.1__py3-none-any.whl
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.
- sqlalchemy_cubrid/__init__.py +85 -0
- sqlalchemy_cubrid/alembic_impl.py +145 -0
- sqlalchemy_cubrid/base.py +428 -0
- sqlalchemy_cubrid/compiler.py +515 -0
- sqlalchemy_cubrid/dialect.py +700 -0
- sqlalchemy_cubrid/dml.py +318 -0
- sqlalchemy_cubrid/py.typed +0 -0
- sqlalchemy_cubrid/pycubrid_dialect.py +124 -0
- sqlalchemy_cubrid/requirements.py +270 -0
- sqlalchemy_cubrid/trace.py +92 -0
- sqlalchemy_cubrid/types.py +349 -0
- sqlalchemy_cubrid-0.7.1.dist-info/METADATA +281 -0
- sqlalchemy_cubrid-0.7.1.dist-info/RECORD +18 -0
- sqlalchemy_cubrid-0.7.1.dist-info/WHEEL +5 -0
- sqlalchemy_cubrid-0.7.1.dist-info/entry_points.txt +7 -0
- sqlalchemy_cubrid-0.7.1.dist-info/licenses/AUTHORS +2 -0
- sqlalchemy_cubrid-0.7.1.dist-info/licenses/LICENSE +21 -0
- sqlalchemy_cubrid-0.7.1.dist-info/top_level.txt +1 -0
|
@@ -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.7.1"
|
|
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
|
+
)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# sqlalchemy_cubrid/alembic_impl.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
|
+
"""Alembic migration support for the CUBRID dialect.
|
|
9
|
+
|
|
10
|
+
This module provides the Alembic ``DefaultImpl`` subclass that enables
|
|
11
|
+
Alembic migrations against a CUBRID database. It is registered as an
|
|
12
|
+
entry-point under ``alembic.ddl`` so that Alembic auto-discovers it
|
|
13
|
+
when the target database URL uses the ``cubrid://`` scheme.
|
|
14
|
+
|
|
15
|
+
Usage::
|
|
16
|
+
|
|
17
|
+
# alembic.ini
|
|
18
|
+
[alembic]
|
|
19
|
+
sqlalchemy.url = cubrid://dba:password@localhost:33000/demodb
|
|
20
|
+
|
|
21
|
+
# That's it — Alembic will pick up the CUBRID implementation
|
|
22
|
+
# automatically via the ``alembic.ddl`` entry point.
|
|
23
|
+
|
|
24
|
+
CUBRID-specific notes
|
|
25
|
+
---------------------
|
|
26
|
+
* **DDL is auto-committed** — CUBRID implicitly commits every DDL
|
|
27
|
+
statement, so ``transactional_ddl`` is set to ``False``.
|
|
28
|
+
* **No ALTER COLUMN TYPE** — CUBRID does not support changing a
|
|
29
|
+
column's data type via ``ALTER TABLE … MODIFY``. Alembic's
|
|
30
|
+
``alter_column(type_=…)`` will raise. Use ``batch_alter_table``
|
|
31
|
+
(table recreate) as a workaround.
|
|
32
|
+
* **No RENAME COLUMN** — CUBRID ≤ 11.x does not support
|
|
33
|
+
``ALTER TABLE … RENAME COLUMN``. Alembic's ``alter_column(new_column_name=…)``
|
|
34
|
+
will raise. Use ``batch_alter_table`` (table recreate) as a
|
|
35
|
+
workaround.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
41
|
+
|
|
42
|
+
import sqlalchemy as sa
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
from alembic.ddl.impl import DefaultImpl
|
|
46
|
+
except ImportError: # pragma: no cover — optional dependency
|
|
47
|
+
raise ImportError(
|
|
48
|
+
"Alembic is required for migration support. Install it with: pip install sqlalchemy-cubrid[alembic]"
|
|
49
|
+
) from None
|
|
50
|
+
|
|
51
|
+
if TYPE_CHECKING:
|
|
52
|
+
from typing import Protocol
|
|
53
|
+
|
|
54
|
+
from sqlalchemy.sql.type_api import TypeEngine
|
|
55
|
+
|
|
56
|
+
class AutogenContextLike(Protocol):
|
|
57
|
+
imports: set[str]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CubridImpl(DefaultImpl):
|
|
61
|
+
"""Alembic migration implementation for CUBRID.
|
|
62
|
+
|
|
63
|
+
Registered via the ``alembic.ddl`` entry-point so Alembic
|
|
64
|
+
auto-discovers it for ``cubrid://`` URLs.
|
|
65
|
+
|
|
66
|
+
Attributes
|
|
67
|
+
----------
|
|
68
|
+
__dialect__ : str
|
|
69
|
+
``"cubrid"`` — matches the SQLAlchemy dialect name.
|
|
70
|
+
transactional_ddl : bool
|
|
71
|
+
``False`` — CUBRID implicitly commits DDL statements.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
__dialect__: str = "cubrid"
|
|
75
|
+
transactional_ddl: bool = False
|
|
76
|
+
|
|
77
|
+
_collection_type_names: set[str] = {"SET", "MULTISET", "SEQUENCE"}
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def _normalize_collection_value(value: object) -> str:
|
|
81
|
+
if isinstance(value, str):
|
|
82
|
+
return value.strip().lower()
|
|
83
|
+
if isinstance(value, sa.types.TypeEngine):
|
|
84
|
+
return value.__class__.__name__.lower()
|
|
85
|
+
return repr(value).strip().lower()
|
|
86
|
+
|
|
87
|
+
def render_type(
|
|
88
|
+
self, type_obj: TypeEngine[Any], autogen_context: AutogenContextLike
|
|
89
|
+
) -> str | Literal[False]:
|
|
90
|
+
if type(type_obj).__module__ != "sqlalchemy_cubrid.types":
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
type_name = type_obj.__class__.__name__
|
|
94
|
+
if type_name not in self._collection_type_names:
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
values = getattr(type_obj, "_ddl_values", ())
|
|
98
|
+
rendered_values: list[str] = []
|
|
99
|
+
|
|
100
|
+
for value in values:
|
|
101
|
+
if isinstance(value, str):
|
|
102
|
+
rendered_values.append(repr(value))
|
|
103
|
+
elif isinstance(value, sa.types.TypeEngine):
|
|
104
|
+
rendered_values.append(value.__class__.__name__)
|
|
105
|
+
else:
|
|
106
|
+
rendered_values.append(repr(value))
|
|
107
|
+
|
|
108
|
+
autogen_context.imports.add("from sqlalchemy_cubrid import types as cubrid_types")
|
|
109
|
+
args = ", ".join(rendered_values)
|
|
110
|
+
return f"cubrid_types.{type_name}({args})"
|
|
111
|
+
|
|
112
|
+
def compare_type(
|
|
113
|
+
self, inspector_column: sa.Column[Any], metadata_column: sa.Column[Any]
|
|
114
|
+
) -> bool:
|
|
115
|
+
inspector_type = inspector_column.type
|
|
116
|
+
metadata_type = metadata_column.type
|
|
117
|
+
|
|
118
|
+
inspector_name = inspector_type.__class__.__name__
|
|
119
|
+
metadata_name = metadata_type.__class__.__name__
|
|
120
|
+
|
|
121
|
+
is_inspector_collection = inspector_name in self._collection_type_names
|
|
122
|
+
is_metadata_collection = metadata_name in self._collection_type_names
|
|
123
|
+
|
|
124
|
+
if not is_inspector_collection and not is_metadata_collection:
|
|
125
|
+
return super().compare_type(inspector_column, metadata_column)
|
|
126
|
+
|
|
127
|
+
if is_inspector_collection != is_metadata_collection:
|
|
128
|
+
return True
|
|
129
|
+
|
|
130
|
+
if inspector_name != metadata_name:
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
inspector_values = [
|
|
134
|
+
self._normalize_collection_value(value)
|
|
135
|
+
for value in getattr(inspector_type, "_ddl_values", ())
|
|
136
|
+
]
|
|
137
|
+
metadata_values = [
|
|
138
|
+
self._normalize_collection_value(value)
|
|
139
|
+
for value in getattr(metadata_type, "_ddl_values", ())
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
if inspector_name == "SEQUENCE":
|
|
143
|
+
return inspector_values != metadata_values
|
|
144
|
+
|
|
145
|
+
return set(inspector_values) != set(metadata_values)
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# sqlalchemy_cubrid/base.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 identifier preparation, execution context, and reserved words."""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
from sqlalchemy.engine import default
|
|
15
|
+
from sqlalchemy.sql import compiler
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
AUTOCOMMIT_REGEXP = re.compile(
|
|
19
|
+
r"\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER|MERGE|TRUNCATE)", re.I | re.UNICODE
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# CUBRID Reserved words
|
|
23
|
+
# https://www.cubrid.org/manual/en/11.0/sql/keyword.html
|
|
24
|
+
RESERVED_WORDS = frozenset(
|
|
25
|
+
{
|
|
26
|
+
"absolute",
|
|
27
|
+
"action",
|
|
28
|
+
"add",
|
|
29
|
+
"add_months",
|
|
30
|
+
"after",
|
|
31
|
+
"all",
|
|
32
|
+
"allocate",
|
|
33
|
+
"alter",
|
|
34
|
+
"and",
|
|
35
|
+
"any",
|
|
36
|
+
"are",
|
|
37
|
+
"as",
|
|
38
|
+
"asc",
|
|
39
|
+
"assertion",
|
|
40
|
+
"at",
|
|
41
|
+
"attach",
|
|
42
|
+
"attribute",
|
|
43
|
+
"avg",
|
|
44
|
+
"before",
|
|
45
|
+
"between",
|
|
46
|
+
"bigint",
|
|
47
|
+
"bit",
|
|
48
|
+
"bit_length",
|
|
49
|
+
"blob",
|
|
50
|
+
"boolean",
|
|
51
|
+
"both",
|
|
52
|
+
"breadth",
|
|
53
|
+
"by",
|
|
54
|
+
"call",
|
|
55
|
+
"cascade",
|
|
56
|
+
"cascaded",
|
|
57
|
+
"case",
|
|
58
|
+
"cast",
|
|
59
|
+
"catalog",
|
|
60
|
+
"change",
|
|
61
|
+
"char",
|
|
62
|
+
"character",
|
|
63
|
+
"check",
|
|
64
|
+
"class",
|
|
65
|
+
"classes",
|
|
66
|
+
"clob",
|
|
67
|
+
"close",
|
|
68
|
+
"coalesce",
|
|
69
|
+
"collate",
|
|
70
|
+
"collation",
|
|
71
|
+
"column",
|
|
72
|
+
"commit",
|
|
73
|
+
"connect",
|
|
74
|
+
"connect_by_iscycle",
|
|
75
|
+
"connect_by_isleaf",
|
|
76
|
+
"connect_by_root",
|
|
77
|
+
"connection",
|
|
78
|
+
"constraint",
|
|
79
|
+
"constraints",
|
|
80
|
+
"continue",
|
|
81
|
+
"convert",
|
|
82
|
+
"corresponding",
|
|
83
|
+
"count",
|
|
84
|
+
"create",
|
|
85
|
+
"cross",
|
|
86
|
+
"current",
|
|
87
|
+
"current_date",
|
|
88
|
+
"current_datetime",
|
|
89
|
+
"current_time",
|
|
90
|
+
"current_timestamp",
|
|
91
|
+
"current_user",
|
|
92
|
+
"cursor",
|
|
93
|
+
"cycle",
|
|
94
|
+
"data",
|
|
95
|
+
"data_type",
|
|
96
|
+
"database",
|
|
97
|
+
"date",
|
|
98
|
+
"datetime",
|
|
99
|
+
"day",
|
|
100
|
+
"day_hour",
|
|
101
|
+
"day_millisecond",
|
|
102
|
+
"day_minute",
|
|
103
|
+
"day_second",
|
|
104
|
+
"deallocate",
|
|
105
|
+
"dec",
|
|
106
|
+
"decimal",
|
|
107
|
+
"declare",
|
|
108
|
+
"default",
|
|
109
|
+
"deferrable",
|
|
110
|
+
"deferred",
|
|
111
|
+
"delete",
|
|
112
|
+
"depth",
|
|
113
|
+
"desc",
|
|
114
|
+
"describe",
|
|
115
|
+
"descriptor",
|
|
116
|
+
"diagnostics",
|
|
117
|
+
"difference",
|
|
118
|
+
"disconnect",
|
|
119
|
+
"distinct",
|
|
120
|
+
"distinctrow",
|
|
121
|
+
"div",
|
|
122
|
+
"do",
|
|
123
|
+
"domain",
|
|
124
|
+
"double",
|
|
125
|
+
"duplicate",
|
|
126
|
+
"drop",
|
|
127
|
+
"each",
|
|
128
|
+
"else",
|
|
129
|
+
"elseif",
|
|
130
|
+
"end",
|
|
131
|
+
"equals",
|
|
132
|
+
"escape",
|
|
133
|
+
"evaluate",
|
|
134
|
+
"except",
|
|
135
|
+
"exception",
|
|
136
|
+
"exec",
|
|
137
|
+
"execute",
|
|
138
|
+
"exists",
|
|
139
|
+
"external",
|
|
140
|
+
"extract",
|
|
141
|
+
"false",
|
|
142
|
+
"fetch",
|
|
143
|
+
"file",
|
|
144
|
+
"first",
|
|
145
|
+
"float",
|
|
146
|
+
"for",
|
|
147
|
+
"foreign",
|
|
148
|
+
"found",
|
|
149
|
+
"from",
|
|
150
|
+
"full",
|
|
151
|
+
"function",
|
|
152
|
+
"general",
|
|
153
|
+
"get",
|
|
154
|
+
"global",
|
|
155
|
+
"go",
|
|
156
|
+
"goto",
|
|
157
|
+
"grant",
|
|
158
|
+
"group",
|
|
159
|
+
"having",
|
|
160
|
+
"hour",
|
|
161
|
+
"hour_millisecond",
|
|
162
|
+
"hour_minute",
|
|
163
|
+
"hour_second",
|
|
164
|
+
"identity",
|
|
165
|
+
"if",
|
|
166
|
+
"ignore",
|
|
167
|
+
"immediate",
|
|
168
|
+
"in",
|
|
169
|
+
"index",
|
|
170
|
+
"indicator",
|
|
171
|
+
"inherit",
|
|
172
|
+
"initially",
|
|
173
|
+
"inner",
|
|
174
|
+
"inout",
|
|
175
|
+
"input",
|
|
176
|
+
"insert",
|
|
177
|
+
"int",
|
|
178
|
+
"integer",
|
|
179
|
+
"intersect",
|
|
180
|
+
"intersection",
|
|
181
|
+
"interval",
|
|
182
|
+
"into",
|
|
183
|
+
"is",
|
|
184
|
+
"isolation",
|
|
185
|
+
"join",
|
|
186
|
+
"key",
|
|
187
|
+
"language",
|
|
188
|
+
"last",
|
|
189
|
+
"leading",
|
|
190
|
+
"leave",
|
|
191
|
+
"left",
|
|
192
|
+
"less",
|
|
193
|
+
"level",
|
|
194
|
+
"like",
|
|
195
|
+
"limit",
|
|
196
|
+
"list",
|
|
197
|
+
"local",
|
|
198
|
+
"local_transaction_id",
|
|
199
|
+
"localtime",
|
|
200
|
+
"localtimestamp",
|
|
201
|
+
"loop",
|
|
202
|
+
"lower",
|
|
203
|
+
"match",
|
|
204
|
+
"max",
|
|
205
|
+
"method",
|
|
206
|
+
"millisecond",
|
|
207
|
+
"min",
|
|
208
|
+
"minute",
|
|
209
|
+
"minute_millisecond",
|
|
210
|
+
"minute_second",
|
|
211
|
+
"mod",
|
|
212
|
+
"modify",
|
|
213
|
+
"module",
|
|
214
|
+
"month",
|
|
215
|
+
"multiset",
|
|
216
|
+
"multiset_of",
|
|
217
|
+
"na",
|
|
218
|
+
"names",
|
|
219
|
+
"national",
|
|
220
|
+
"natural",
|
|
221
|
+
"nchar",
|
|
222
|
+
"next",
|
|
223
|
+
"no",
|
|
224
|
+
"none",
|
|
225
|
+
"not",
|
|
226
|
+
"null",
|
|
227
|
+
"nullif",
|
|
228
|
+
"numeric",
|
|
229
|
+
"object",
|
|
230
|
+
"octet_length",
|
|
231
|
+
"of",
|
|
232
|
+
"off",
|
|
233
|
+
"on",
|
|
234
|
+
"only",
|
|
235
|
+
"open",
|
|
236
|
+
"optimization",
|
|
237
|
+
"option",
|
|
238
|
+
"or",
|
|
239
|
+
"order",
|
|
240
|
+
"out",
|
|
241
|
+
"outer",
|
|
242
|
+
"output",
|
|
243
|
+
"overlaps",
|
|
244
|
+
"parameters",
|
|
245
|
+
"partial",
|
|
246
|
+
"position",
|
|
247
|
+
"precision",
|
|
248
|
+
"prepare",
|
|
249
|
+
"preserve",
|
|
250
|
+
"primary",
|
|
251
|
+
"prior",
|
|
252
|
+
"privileges",
|
|
253
|
+
"procedure",
|
|
254
|
+
"query",
|
|
255
|
+
"read",
|
|
256
|
+
"real",
|
|
257
|
+
"recursive",
|
|
258
|
+
"ref",
|
|
259
|
+
"references",
|
|
260
|
+
"referencing",
|
|
261
|
+
"relative",
|
|
262
|
+
"rename",
|
|
263
|
+
"replace",
|
|
264
|
+
"resignal",
|
|
265
|
+
"restrict",
|
|
266
|
+
"return",
|
|
267
|
+
"returns",
|
|
268
|
+
"revoke",
|
|
269
|
+
"right",
|
|
270
|
+
"role",
|
|
271
|
+
"rollback",
|
|
272
|
+
"rollup",
|
|
273
|
+
"routine",
|
|
274
|
+
"row",
|
|
275
|
+
"rownum",
|
|
276
|
+
"rows",
|
|
277
|
+
"savepoint",
|
|
278
|
+
"schema",
|
|
279
|
+
"scope",
|
|
280
|
+
"scroll",
|
|
281
|
+
"search",
|
|
282
|
+
"second",
|
|
283
|
+
"second_millisecond",
|
|
284
|
+
"section",
|
|
285
|
+
"select",
|
|
286
|
+
"sensitive",
|
|
287
|
+
"sequence",
|
|
288
|
+
"sequence_of",
|
|
289
|
+
"serializable",
|
|
290
|
+
"session",
|
|
291
|
+
"session_user",
|
|
292
|
+
"set",
|
|
293
|
+
"set_of",
|
|
294
|
+
"seteq",
|
|
295
|
+
"shared",
|
|
296
|
+
"siblings",
|
|
297
|
+
"signal",
|
|
298
|
+
"similar",
|
|
299
|
+
"size",
|
|
300
|
+
"smallint",
|
|
301
|
+
"some",
|
|
302
|
+
"sql",
|
|
303
|
+
"sqlcode",
|
|
304
|
+
"sqlerror",
|
|
305
|
+
"sqlexception",
|
|
306
|
+
"sqlstate",
|
|
307
|
+
"sqlwarning",
|
|
308
|
+
"statistics",
|
|
309
|
+
"string",
|
|
310
|
+
"subclass",
|
|
311
|
+
"subset",
|
|
312
|
+
"subseteq",
|
|
313
|
+
"substring",
|
|
314
|
+
"sum",
|
|
315
|
+
"superclass",
|
|
316
|
+
"superset",
|
|
317
|
+
"superseteq",
|
|
318
|
+
"sys_connect_by_path",
|
|
319
|
+
"sys_date",
|
|
320
|
+
"sys_datetime",
|
|
321
|
+
"sys_time",
|
|
322
|
+
"sys_timestamp",
|
|
323
|
+
"sysdate",
|
|
324
|
+
"sysdatetime",
|
|
325
|
+
"system_user",
|
|
326
|
+
"systime",
|
|
327
|
+
"table",
|
|
328
|
+
"temporary",
|
|
329
|
+
"then",
|
|
330
|
+
"time",
|
|
331
|
+
"timestamp",
|
|
332
|
+
"timezone_hour",
|
|
333
|
+
"timezone_minute",
|
|
334
|
+
"to",
|
|
335
|
+
"trailing",
|
|
336
|
+
"transaction",
|
|
337
|
+
"translate",
|
|
338
|
+
"translation",
|
|
339
|
+
"trigger",
|
|
340
|
+
"trim",
|
|
341
|
+
"true",
|
|
342
|
+
"truncate",
|
|
343
|
+
"under",
|
|
344
|
+
"union",
|
|
345
|
+
"unique",
|
|
346
|
+
"unknown",
|
|
347
|
+
"update",
|
|
348
|
+
"upper",
|
|
349
|
+
"usage",
|
|
350
|
+
"use",
|
|
351
|
+
"user",
|
|
352
|
+
"using",
|
|
353
|
+
"utime",
|
|
354
|
+
"value",
|
|
355
|
+
"values",
|
|
356
|
+
"varchar",
|
|
357
|
+
"variable",
|
|
358
|
+
"varying",
|
|
359
|
+
"vclass",
|
|
360
|
+
"view",
|
|
361
|
+
"when",
|
|
362
|
+
"whenever",
|
|
363
|
+
"where",
|
|
364
|
+
"while",
|
|
365
|
+
"with",
|
|
366
|
+
"without",
|
|
367
|
+
"work",
|
|
368
|
+
"write",
|
|
369
|
+
"xor",
|
|
370
|
+
"year",
|
|
371
|
+
"year_month",
|
|
372
|
+
"zone",
|
|
373
|
+
}
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
class CubridIdentifierPreparer(compiler.IdentifierPreparer):
|
|
378
|
+
"""Quoting logic for CUBRID identifiers."""
|
|
379
|
+
|
|
380
|
+
reserved_words = RESERVED_WORDS
|
|
381
|
+
|
|
382
|
+
def __init__(
|
|
383
|
+
self,
|
|
384
|
+
dialect,
|
|
385
|
+
initial_quote='"',
|
|
386
|
+
final_quote=None,
|
|
387
|
+
escape_quote='"',
|
|
388
|
+
omit_schema=False,
|
|
389
|
+
):
|
|
390
|
+
super().__init__(dialect, initial_quote, final_quote, escape_quote, omit_schema)
|
|
391
|
+
|
|
392
|
+
def _quote_free_identifiers(self, *ids):
|
|
393
|
+
"""Unilaterally identifier-quote any number of strings."""
|
|
394
|
+
return tuple(self.quote_identifier(i) for i in ids if i is not None)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class CubridExecutionContext(default.DefaultExecutionContext):
|
|
398
|
+
"""Execution context for CUBRID connections."""
|
|
399
|
+
|
|
400
|
+
def should_autocommit_text(self, statement):
|
|
401
|
+
return AUTOCOMMIT_REGEXP.match(statement)
|
|
402
|
+
|
|
403
|
+
def get_lastrowid(self):
|
|
404
|
+
"""Return the last inserted row ID.
|
|
405
|
+
|
|
406
|
+
CUBRID's Python driver does not expose ``cursor.lastrowid``.
|
|
407
|
+
Instead, the connection object provides ``get_last_insert_id()``.
|
|
408
|
+
We also fall back to ``SELECT LAST_INSERT_ID()`` if the method
|
|
409
|
+
is unavailable.
|
|
410
|
+
"""
|
|
411
|
+
try:
|
|
412
|
+
# CUBRID Python driver exposes this on the raw connection
|
|
413
|
+
raw_conn = self.root_connection.connection.dbapi_connection
|
|
414
|
+
if hasattr(raw_conn, "get_last_insert_id"):
|
|
415
|
+
return raw_conn.get_last_insert_id()
|
|
416
|
+
except Exception: # nosec B110 — fallback to SQL when driver lacks method
|
|
417
|
+
pass
|
|
418
|
+
|
|
419
|
+
# Fallback: use SQL function
|
|
420
|
+
cursor = self.create_server_side_cursor()
|
|
421
|
+
try:
|
|
422
|
+
cursor.execute("SELECT LAST_INSERT_ID()")
|
|
423
|
+
row = cursor.fetchone()
|
|
424
|
+
if row:
|
|
425
|
+
return int(row[0])
|
|
426
|
+
finally:
|
|
427
|
+
cursor.close()
|
|
428
|
+
return None
|