ydb-dbapi 0.0.1b1__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.
- ydb_dbapi/__init__.py +16 -0
- ydb_dbapi/connections.py +392 -0
- ydb_dbapi/constants.py +218 -0
- ydb_dbapi/cursors.py +357 -0
- ydb_dbapi/errors.py +115 -0
- ydb_dbapi/utils.py +102 -0
- ydb_dbapi/version.py +1 -0
- ydb_dbapi-0.0.1b1.dist-info/LICENSE +201 -0
- ydb_dbapi-0.0.1b1.dist-info/METADATA +64 -0
- ydb_dbapi-0.0.1b1.dist-info/RECORD +11 -0
- ydb_dbapi-0.0.1b1.dist-info/WHEEL +4 -0
ydb_dbapi/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .connections import AsyncConnection
|
|
2
|
+
from .connections import Connection
|
|
3
|
+
from .connections import IsolationLevel
|
|
4
|
+
from .connections import async_connect
|
|
5
|
+
from .connections import connect
|
|
6
|
+
from .constants import *
|
|
7
|
+
from .cursors import AsyncCursor
|
|
8
|
+
from .cursors import Cursor
|
|
9
|
+
from .errors import *
|
|
10
|
+
from .version import VERSION
|
|
11
|
+
|
|
12
|
+
__version__ = VERSION
|
|
13
|
+
|
|
14
|
+
apilevel = "2.0"
|
|
15
|
+
threadsafety = 0
|
|
16
|
+
paramstyle = "pyformat"
|
ydb_dbapi/connections.py
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import posixpath
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import NamedTuple
|
|
6
|
+
|
|
7
|
+
import ydb
|
|
8
|
+
from ydb import QuerySessionPool as SessionPool
|
|
9
|
+
from ydb import QueryTxContext as TxContext
|
|
10
|
+
from ydb.aio import QuerySessionPool as AsyncSessionPool
|
|
11
|
+
from ydb.aio import QueryTxContext as AsyncTxContext
|
|
12
|
+
from ydb.retries import retry_operation_async
|
|
13
|
+
from ydb.retries import retry_operation_sync
|
|
14
|
+
|
|
15
|
+
from .cursors import AsyncCursor
|
|
16
|
+
from .cursors import Cursor
|
|
17
|
+
from .errors import InterfaceError
|
|
18
|
+
from .errors import InternalError
|
|
19
|
+
from .errors import NotSupportedError
|
|
20
|
+
from .utils import handle_ydb_errors
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class IsolationLevel(str, Enum):
|
|
24
|
+
SERIALIZABLE = "SERIALIZABLE"
|
|
25
|
+
ONLINE_READONLY = "ONLINE READONLY"
|
|
26
|
+
ONLINE_READONLY_INCONSISTENT = "ONLINE READONLY INCONSISTENT"
|
|
27
|
+
STALE_READONLY = "STALE READONLY"
|
|
28
|
+
SNAPSHOT_READONLY = "SNAPSHOT READONLY"
|
|
29
|
+
AUTOCOMMIT = "AUTOCOMMIT"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _IsolationSettings(NamedTuple):
|
|
33
|
+
ydb_mode: ydb.BaseQueryTxMode
|
|
34
|
+
interactive: bool
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_ydb_isolation_settings_map = {
|
|
38
|
+
IsolationLevel.AUTOCOMMIT: _IsolationSettings(
|
|
39
|
+
ydb.QuerySerializableReadWrite(), interactive=False
|
|
40
|
+
),
|
|
41
|
+
IsolationLevel.SERIALIZABLE: _IsolationSettings(
|
|
42
|
+
ydb.QuerySerializableReadWrite(), interactive=True
|
|
43
|
+
),
|
|
44
|
+
IsolationLevel.ONLINE_READONLY: _IsolationSettings(
|
|
45
|
+
ydb.QueryOnlineReadOnly(), interactive=True
|
|
46
|
+
),
|
|
47
|
+
IsolationLevel.ONLINE_READONLY_INCONSISTENT: _IsolationSettings(
|
|
48
|
+
ydb.QueryOnlineReadOnly().with_allow_inconsistent_reads(),
|
|
49
|
+
interactive=True,
|
|
50
|
+
),
|
|
51
|
+
IsolationLevel.STALE_READONLY: _IsolationSettings(
|
|
52
|
+
ydb.QueryStaleReadOnly(), interactive=True
|
|
53
|
+
),
|
|
54
|
+
IsolationLevel.SNAPSHOT_READONLY: _IsolationSettings(
|
|
55
|
+
ydb.QuerySnapshotReadOnly(), interactive=True
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class BaseConnection:
|
|
61
|
+
_driver_cls = ydb.Driver
|
|
62
|
+
_pool_cls = ydb.QuerySessionPool
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
host: str = "",
|
|
67
|
+
port: str = "",
|
|
68
|
+
database: str = "",
|
|
69
|
+
ydb_table_path_prefix: str = "",
|
|
70
|
+
credentials: ydb.AbstractCredentials | None = None,
|
|
71
|
+
ydb_session_pool: SessionPool | AsyncSessionPool | None = None,
|
|
72
|
+
**kwargs: dict,
|
|
73
|
+
) -> None:
|
|
74
|
+
self.endpoint = f"grpc://{host}:{port}"
|
|
75
|
+
self.database = database
|
|
76
|
+
self.credentials = credentials
|
|
77
|
+
self.table_path_prefix = ydb_table_path_prefix
|
|
78
|
+
|
|
79
|
+
self.connection_kwargs: dict = kwargs
|
|
80
|
+
|
|
81
|
+
self._tx_mode: ydb.BaseQueryTxMode = ydb.QuerySerializableReadWrite()
|
|
82
|
+
self._tx_context: TxContext | AsyncTxContext | None = None
|
|
83
|
+
self.interactive_transaction: bool = False
|
|
84
|
+
self._shared_session_pool: bool = False
|
|
85
|
+
|
|
86
|
+
if ydb_session_pool is not None:
|
|
87
|
+
self._shared_session_pool = True
|
|
88
|
+
self._session_pool = ydb_session_pool
|
|
89
|
+
self._driver = self._session_pool._driver
|
|
90
|
+
else:
|
|
91
|
+
driver_config = ydb.DriverConfig(
|
|
92
|
+
endpoint=self.endpoint,
|
|
93
|
+
database=self.database,
|
|
94
|
+
credentials=self.credentials,
|
|
95
|
+
)
|
|
96
|
+
self._driver = self._driver_cls(driver_config)
|
|
97
|
+
self._session_pool = self._pool_cls(self._driver, size=5)
|
|
98
|
+
|
|
99
|
+
self._session: ydb.QuerySession | ydb.aio.QuerySession | None = None
|
|
100
|
+
|
|
101
|
+
def set_isolation_level(self, isolation_level: IsolationLevel) -> None:
|
|
102
|
+
ydb_isolation_settings = _ydb_isolation_settings_map[isolation_level]
|
|
103
|
+
if self._tx_context and self._tx_context.tx_id:
|
|
104
|
+
raise InternalError(
|
|
105
|
+
"Failed to set transaction mode: transaction is already began"
|
|
106
|
+
)
|
|
107
|
+
self._tx_mode = ydb_isolation_settings.ydb_mode
|
|
108
|
+
self.interactive_transaction = ydb_isolation_settings.interactive
|
|
109
|
+
|
|
110
|
+
def get_isolation_level(self) -> str:
|
|
111
|
+
if self._tx_mode.name == ydb.QuerySerializableReadWrite().name:
|
|
112
|
+
if self.interactive_transaction:
|
|
113
|
+
return IsolationLevel.SERIALIZABLE
|
|
114
|
+
return IsolationLevel.AUTOCOMMIT
|
|
115
|
+
if self._tx_mode.name == ydb.QueryOnlineReadOnly().name:
|
|
116
|
+
if self._tx_mode.settings.allow_inconsistent_reads:
|
|
117
|
+
return IsolationLevel.ONLINE_READONLY_INCONSISTENT
|
|
118
|
+
return IsolationLevel.ONLINE_READONLY
|
|
119
|
+
if self._tx_mode.name == ydb.QueryStaleReadOnly().name:
|
|
120
|
+
return IsolationLevel.STALE_READONLY
|
|
121
|
+
if self._tx_mode.name == ydb.QuerySnapshotReadOnly().name:
|
|
122
|
+
return IsolationLevel.SNAPSHOT_READONLY
|
|
123
|
+
msg = f"{self._tx_mode.name} is not supported"
|
|
124
|
+
raise NotSupportedError(msg)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class Connection(BaseConnection):
|
|
128
|
+
_driver_cls = ydb.Driver
|
|
129
|
+
_pool_cls = ydb.QuerySessionPool
|
|
130
|
+
_cursor_cls = Cursor
|
|
131
|
+
|
|
132
|
+
def __init__(
|
|
133
|
+
self,
|
|
134
|
+
host: str = "",
|
|
135
|
+
port: str = "",
|
|
136
|
+
database: str = "",
|
|
137
|
+
ydb_table_path_prefix: str = "",
|
|
138
|
+
credentials: ydb.AbstractCredentials | None = None,
|
|
139
|
+
ydb_session_pool: SessionPool | AsyncSessionPool | None = None,
|
|
140
|
+
**kwargs: dict,
|
|
141
|
+
) -> None:
|
|
142
|
+
super().__init__(
|
|
143
|
+
host=host,
|
|
144
|
+
port=port,
|
|
145
|
+
database=database,
|
|
146
|
+
ydb_table_path_prefix=ydb_table_path_prefix,
|
|
147
|
+
credentials=credentials,
|
|
148
|
+
ydb_session_pool=ydb_session_pool,
|
|
149
|
+
**kwargs,
|
|
150
|
+
)
|
|
151
|
+
self._current_cursor: Cursor | None = None
|
|
152
|
+
|
|
153
|
+
def cursor(self) -> Cursor:
|
|
154
|
+
if self._session is None:
|
|
155
|
+
raise RuntimeError("Connection is not ready, use wait_ready.")
|
|
156
|
+
|
|
157
|
+
if self.interactive_transaction:
|
|
158
|
+
self._tx_context = self._session.transaction(self._tx_mode)
|
|
159
|
+
else:
|
|
160
|
+
self._tx_context = None
|
|
161
|
+
|
|
162
|
+
self._current_cursor = self._cursor_cls(
|
|
163
|
+
session=self._session,
|
|
164
|
+
tx_context=self._tx_context,
|
|
165
|
+
autocommit=(not self.interactive_transaction),
|
|
166
|
+
)
|
|
167
|
+
return self._current_cursor
|
|
168
|
+
|
|
169
|
+
def wait_ready(self, timeout: int = 10) -> None:
|
|
170
|
+
try:
|
|
171
|
+
self._driver.wait(timeout, fail_fast=True)
|
|
172
|
+
except ydb.Error as e:
|
|
173
|
+
raise InterfaceError(e.message, original_error=e) from e
|
|
174
|
+
except Exception as e:
|
|
175
|
+
self._driver.stop()
|
|
176
|
+
msg = (
|
|
177
|
+
"Failed to connect to YDB, details "
|
|
178
|
+
f"{self._driver.discovery_debug_details()}"
|
|
179
|
+
)
|
|
180
|
+
raise InterfaceError(msg) from e
|
|
181
|
+
|
|
182
|
+
self._session = self._session_pool.acquire()
|
|
183
|
+
|
|
184
|
+
def commit(self) -> None:
|
|
185
|
+
if self._tx_context and self._tx_context.tx_id:
|
|
186
|
+
self._tx_context.commit()
|
|
187
|
+
self._tx_context = None
|
|
188
|
+
|
|
189
|
+
def rollback(self) -> None:
|
|
190
|
+
if self._tx_context and self._tx_context.tx_id:
|
|
191
|
+
self._tx_context.rollback()
|
|
192
|
+
self._tx_context = None
|
|
193
|
+
|
|
194
|
+
def close(self) -> None:
|
|
195
|
+
self.rollback()
|
|
196
|
+
|
|
197
|
+
if self._current_cursor:
|
|
198
|
+
self._current_cursor.close()
|
|
199
|
+
|
|
200
|
+
if self._session:
|
|
201
|
+
self._session_pool.release(self._session)
|
|
202
|
+
|
|
203
|
+
if not self._shared_session_pool:
|
|
204
|
+
self._session_pool.stop()
|
|
205
|
+
self._driver.stop()
|
|
206
|
+
|
|
207
|
+
@handle_ydb_errors
|
|
208
|
+
def describe(self, table_path: str) -> ydb.TableSchemeEntry:
|
|
209
|
+
abs_table_path = posixpath.join(
|
|
210
|
+
self.database, self.table_path_prefix, table_path
|
|
211
|
+
)
|
|
212
|
+
return self._driver.table_client.describe_table(abs_table_path)
|
|
213
|
+
|
|
214
|
+
@handle_ydb_errors
|
|
215
|
+
def check_exists(self, table_path: str) -> bool:
|
|
216
|
+
abs_table_path = posixpath.join(
|
|
217
|
+
self.database, self.table_path_prefix, table_path
|
|
218
|
+
)
|
|
219
|
+
return self._check_path_exists(abs_table_path)
|
|
220
|
+
|
|
221
|
+
@handle_ydb_errors
|
|
222
|
+
def get_table_names(self) -> list[str]:
|
|
223
|
+
abs_dir_path = posixpath.join(self.database, self.table_path_prefix)
|
|
224
|
+
names = self._get_table_names(abs_dir_path)
|
|
225
|
+
return [posixpath.relpath(path, abs_dir_path) for path in names]
|
|
226
|
+
|
|
227
|
+
def _check_path_exists(self, table_path: str) -> bool:
|
|
228
|
+
try:
|
|
229
|
+
|
|
230
|
+
def callee() -> None:
|
|
231
|
+
self._driver.scheme_client.describe_path(table_path)
|
|
232
|
+
|
|
233
|
+
retry_operation_sync(callee)
|
|
234
|
+
except ydb.SchemeError:
|
|
235
|
+
return False
|
|
236
|
+
else:
|
|
237
|
+
return True
|
|
238
|
+
|
|
239
|
+
def _get_table_names(self, abs_dir_path: str) -> list[str]:
|
|
240
|
+
def callee() -> ydb.Directory:
|
|
241
|
+
return self._driver.scheme_client.list_directory(abs_dir_path)
|
|
242
|
+
|
|
243
|
+
directory = retry_operation_sync(callee)
|
|
244
|
+
result = []
|
|
245
|
+
for child in directory.children:
|
|
246
|
+
child_abs_path = posixpath.join(abs_dir_path, child.name)
|
|
247
|
+
if child.is_table():
|
|
248
|
+
result.append(child_abs_path)
|
|
249
|
+
elif child.is_directory() and not child.name.startswith("."):
|
|
250
|
+
result.extend(self.get_table_names(child_abs_path))
|
|
251
|
+
return result
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class AsyncConnection(BaseConnection):
|
|
255
|
+
_driver_cls = ydb.aio.Driver
|
|
256
|
+
_pool_cls = ydb.aio.QuerySessionPool
|
|
257
|
+
_cursor_cls = AsyncCursor
|
|
258
|
+
|
|
259
|
+
def __init__(
|
|
260
|
+
self,
|
|
261
|
+
host: str = "",
|
|
262
|
+
port: str = "",
|
|
263
|
+
database: str = "",
|
|
264
|
+
ydb_table_path_prefix: str = "",
|
|
265
|
+
credentials: ydb.AbstractCredentials | None = None,
|
|
266
|
+
ydb_session_pool: SessionPool | AsyncSessionPool | None = None,
|
|
267
|
+
**kwargs: dict,
|
|
268
|
+
) -> None:
|
|
269
|
+
super().__init__(
|
|
270
|
+
host=host,
|
|
271
|
+
port=port,
|
|
272
|
+
database=database,
|
|
273
|
+
ydb_table_path_prefix=ydb_table_path_prefix,
|
|
274
|
+
credentials=credentials,
|
|
275
|
+
ydb_session_pool=ydb_session_pool,
|
|
276
|
+
**kwargs,
|
|
277
|
+
)
|
|
278
|
+
self._current_cursor: AsyncCursor | None = None
|
|
279
|
+
|
|
280
|
+
def cursor(self) -> AsyncCursor:
|
|
281
|
+
if self._session is None:
|
|
282
|
+
raise RuntimeError("Connection is not ready, use wait_ready.")
|
|
283
|
+
|
|
284
|
+
if self.interactive_transaction:
|
|
285
|
+
self._tx_context = self._session.transaction(self._tx_mode)
|
|
286
|
+
else:
|
|
287
|
+
self._tx_context = None
|
|
288
|
+
|
|
289
|
+
self._current_cursor = self._cursor_cls(
|
|
290
|
+
session=self._session,
|
|
291
|
+
tx_context=self._tx_context,
|
|
292
|
+
autocommit=(not self.interactive_transaction),
|
|
293
|
+
)
|
|
294
|
+
return self._current_cursor
|
|
295
|
+
|
|
296
|
+
async def wait_ready(self, timeout: int = 10) -> None:
|
|
297
|
+
try:
|
|
298
|
+
await self._driver.wait(timeout, fail_fast=True)
|
|
299
|
+
except ydb.Error as e:
|
|
300
|
+
raise InterfaceError(e.message, original_error=e) from e
|
|
301
|
+
except Exception as e:
|
|
302
|
+
await self._driver.stop()
|
|
303
|
+
msg = (
|
|
304
|
+
"Failed to connect to YDB, details "
|
|
305
|
+
f"{self._driver.discovery_debug_details()}"
|
|
306
|
+
)
|
|
307
|
+
raise InterfaceError(msg) from e
|
|
308
|
+
|
|
309
|
+
self._session = await self._session_pool.acquire()
|
|
310
|
+
|
|
311
|
+
async def commit(self) -> None:
|
|
312
|
+
if self._tx_context and self._tx_context.tx_id:
|
|
313
|
+
await self._tx_context.commit()
|
|
314
|
+
self._tx_context = None
|
|
315
|
+
|
|
316
|
+
async def rollback(self) -> None:
|
|
317
|
+
if self._tx_context and self._tx_context.tx_id:
|
|
318
|
+
await self._tx_context.rollback()
|
|
319
|
+
self._tx_context = None
|
|
320
|
+
|
|
321
|
+
async def close(self) -> None:
|
|
322
|
+
await self.rollback()
|
|
323
|
+
|
|
324
|
+
if self._current_cursor:
|
|
325
|
+
await self._current_cursor.close()
|
|
326
|
+
|
|
327
|
+
if self._session:
|
|
328
|
+
await self._session_pool.release(self._session)
|
|
329
|
+
|
|
330
|
+
if not self._shared_session_pool:
|
|
331
|
+
await self._session_pool.stop()
|
|
332
|
+
await self._driver.stop()
|
|
333
|
+
|
|
334
|
+
@handle_ydb_errors
|
|
335
|
+
async def describe(self, table_path: str) -> ydb.TableSchemeEntry:
|
|
336
|
+
abs_table_path = posixpath.join(
|
|
337
|
+
self.database, self.table_path_prefix, table_path
|
|
338
|
+
)
|
|
339
|
+
return await self._driver.table_client.describe_table(abs_table_path)
|
|
340
|
+
|
|
341
|
+
@handle_ydb_errors
|
|
342
|
+
async def check_exists(self, table_path: str) -> bool:
|
|
343
|
+
abs_table_path = posixpath.join(
|
|
344
|
+
self.database, self.table_path_prefix, table_path
|
|
345
|
+
)
|
|
346
|
+
return await self._check_path_exists(abs_table_path)
|
|
347
|
+
|
|
348
|
+
@handle_ydb_errors
|
|
349
|
+
async def get_table_names(self) -> list[str]:
|
|
350
|
+
abs_dir_path = posixpath.join(self.database, self.table_path_prefix)
|
|
351
|
+
names = await self._get_table_names(abs_dir_path)
|
|
352
|
+
return [posixpath.relpath(path, abs_dir_path) for path in names]
|
|
353
|
+
|
|
354
|
+
async def _check_path_exists(self, table_path: str) -> bool:
|
|
355
|
+
try:
|
|
356
|
+
|
|
357
|
+
async def callee() -> None:
|
|
358
|
+
await self._driver.scheme_client.describe_path(table_path)
|
|
359
|
+
|
|
360
|
+
await retry_operation_async(callee)
|
|
361
|
+
except ydb.SchemeError:
|
|
362
|
+
return False
|
|
363
|
+
else:
|
|
364
|
+
return True
|
|
365
|
+
|
|
366
|
+
async def _get_table_names(self, abs_dir_path: str) -> list[str]:
|
|
367
|
+
async def callee() -> ydb.Directory:
|
|
368
|
+
return await self._driver.scheme_client.list_directory(
|
|
369
|
+
abs_dir_path
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
directory = await retry_operation_async(callee)
|
|
373
|
+
result = []
|
|
374
|
+
for child in directory.children:
|
|
375
|
+
child_abs_path = posixpath.join(abs_dir_path, child.name)
|
|
376
|
+
if child.is_table():
|
|
377
|
+
result.append(child_abs_path)
|
|
378
|
+
elif child.is_directory() and not child.name.startswith("."):
|
|
379
|
+
result.extend(self.get_table_names(child_abs_path))
|
|
380
|
+
return result
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def connect(*args: tuple, **kwargs: dict) -> Connection:
|
|
384
|
+
conn = Connection(*args, **kwargs) # type: ignore
|
|
385
|
+
conn.wait_ready()
|
|
386
|
+
return conn
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
async def async_connect(*args: tuple, **kwargs: dict) -> AsyncConnection:
|
|
390
|
+
conn = AsyncConnection(*args, **kwargs) # type: ignore
|
|
391
|
+
await conn.wait_ready()
|
|
392
|
+
return conn
|
ydb_dbapi/constants.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
YDB_KEYWORDS = {
|
|
2
|
+
"abort",
|
|
3
|
+
"action",
|
|
4
|
+
"add",
|
|
5
|
+
"after",
|
|
6
|
+
"all",
|
|
7
|
+
"alter",
|
|
8
|
+
"analyze",
|
|
9
|
+
"and",
|
|
10
|
+
"ansi",
|
|
11
|
+
"any",
|
|
12
|
+
"array",
|
|
13
|
+
"as",
|
|
14
|
+
"asc",
|
|
15
|
+
"assume",
|
|
16
|
+
"async",
|
|
17
|
+
"attach",
|
|
18
|
+
"autoincrement",
|
|
19
|
+
"before",
|
|
20
|
+
"begin",
|
|
21
|
+
"bernoulli",
|
|
22
|
+
"between",
|
|
23
|
+
"bitcast",
|
|
24
|
+
"by",
|
|
25
|
+
"cascade",
|
|
26
|
+
"case",
|
|
27
|
+
"cast",
|
|
28
|
+
"changefeed",
|
|
29
|
+
"check",
|
|
30
|
+
"collate",
|
|
31
|
+
"column",
|
|
32
|
+
"columns",
|
|
33
|
+
"commit",
|
|
34
|
+
"compact",
|
|
35
|
+
"conditional",
|
|
36
|
+
"conflict",
|
|
37
|
+
"constraint",
|
|
38
|
+
"consumer",
|
|
39
|
+
"cover",
|
|
40
|
+
"create",
|
|
41
|
+
"cross",
|
|
42
|
+
"cube",
|
|
43
|
+
"current",
|
|
44
|
+
"current_date",
|
|
45
|
+
"current_time",
|
|
46
|
+
"current_timestamp",
|
|
47
|
+
"data",
|
|
48
|
+
"database",
|
|
49
|
+
"decimal",
|
|
50
|
+
"declare",
|
|
51
|
+
"default",
|
|
52
|
+
"deferrable",
|
|
53
|
+
"deferred",
|
|
54
|
+
"define",
|
|
55
|
+
"delete",
|
|
56
|
+
"desc",
|
|
57
|
+
"detach",
|
|
58
|
+
"disable",
|
|
59
|
+
"discard",
|
|
60
|
+
"distinct",
|
|
61
|
+
"do",
|
|
62
|
+
"drop",
|
|
63
|
+
"each",
|
|
64
|
+
"else",
|
|
65
|
+
"empty",
|
|
66
|
+
"empty_action",
|
|
67
|
+
"encrypted",
|
|
68
|
+
"end",
|
|
69
|
+
"erase",
|
|
70
|
+
"error",
|
|
71
|
+
"escape",
|
|
72
|
+
"evaluate",
|
|
73
|
+
"except",
|
|
74
|
+
"exclude",
|
|
75
|
+
"exclusion",
|
|
76
|
+
"exclusive",
|
|
77
|
+
"exists",
|
|
78
|
+
"explain",
|
|
79
|
+
"export",
|
|
80
|
+
"external",
|
|
81
|
+
"fail",
|
|
82
|
+
"family",
|
|
83
|
+
"filter",
|
|
84
|
+
"flatten",
|
|
85
|
+
"following",
|
|
86
|
+
"for",
|
|
87
|
+
"foreign",
|
|
88
|
+
"from",
|
|
89
|
+
"full",
|
|
90
|
+
"function",
|
|
91
|
+
"glob",
|
|
92
|
+
"group",
|
|
93
|
+
"grouping",
|
|
94
|
+
"groups",
|
|
95
|
+
"hash",
|
|
96
|
+
"having",
|
|
97
|
+
"hop",
|
|
98
|
+
"if",
|
|
99
|
+
"ignore",
|
|
100
|
+
"ilike",
|
|
101
|
+
"immediate",
|
|
102
|
+
"import",
|
|
103
|
+
"in",
|
|
104
|
+
"index",
|
|
105
|
+
"indexed",
|
|
106
|
+
"inherits",
|
|
107
|
+
"initially",
|
|
108
|
+
"inner",
|
|
109
|
+
"insert",
|
|
110
|
+
"instead",
|
|
111
|
+
"intersect",
|
|
112
|
+
"into",
|
|
113
|
+
"is",
|
|
114
|
+
"isnull",
|
|
115
|
+
"join",
|
|
116
|
+
"json_exists",
|
|
117
|
+
"json_query",
|
|
118
|
+
"json_value",
|
|
119
|
+
"key",
|
|
120
|
+
"left",
|
|
121
|
+
"like",
|
|
122
|
+
"limit",
|
|
123
|
+
"local",
|
|
124
|
+
"match",
|
|
125
|
+
"natural",
|
|
126
|
+
"no",
|
|
127
|
+
"not",
|
|
128
|
+
"notnull",
|
|
129
|
+
"null",
|
|
130
|
+
"nulls",
|
|
131
|
+
"object",
|
|
132
|
+
"of",
|
|
133
|
+
"offset",
|
|
134
|
+
"on",
|
|
135
|
+
"only",
|
|
136
|
+
"or",
|
|
137
|
+
"order",
|
|
138
|
+
"others",
|
|
139
|
+
"outer",
|
|
140
|
+
"over",
|
|
141
|
+
"partition",
|
|
142
|
+
"passing",
|
|
143
|
+
"password",
|
|
144
|
+
"plan",
|
|
145
|
+
"pragma",
|
|
146
|
+
"preceding",
|
|
147
|
+
"presort",
|
|
148
|
+
"primary",
|
|
149
|
+
"process",
|
|
150
|
+
"raise",
|
|
151
|
+
"range",
|
|
152
|
+
"reduce",
|
|
153
|
+
"references",
|
|
154
|
+
"regexp",
|
|
155
|
+
"reindex",
|
|
156
|
+
"release",
|
|
157
|
+
"rename",
|
|
158
|
+
"replace",
|
|
159
|
+
"replication",
|
|
160
|
+
"reset",
|
|
161
|
+
"respect",
|
|
162
|
+
"restrict",
|
|
163
|
+
"result",
|
|
164
|
+
"return",
|
|
165
|
+
"returning",
|
|
166
|
+
"revert",
|
|
167
|
+
"right",
|
|
168
|
+
"rlike",
|
|
169
|
+
"rollback",
|
|
170
|
+
"rollup",
|
|
171
|
+
"row",
|
|
172
|
+
"rows",
|
|
173
|
+
"sample",
|
|
174
|
+
"savepoint",
|
|
175
|
+
"schema",
|
|
176
|
+
"select",
|
|
177
|
+
"semi",
|
|
178
|
+
"sets",
|
|
179
|
+
"source",
|
|
180
|
+
"stream",
|
|
181
|
+
"subquery",
|
|
182
|
+
"symbols",
|
|
183
|
+
"sync",
|
|
184
|
+
"system",
|
|
185
|
+
"table",
|
|
186
|
+
"tablesample",
|
|
187
|
+
"tablestore",
|
|
188
|
+
"temp",
|
|
189
|
+
"temporary",
|
|
190
|
+
"then",
|
|
191
|
+
"ties",
|
|
192
|
+
"to",
|
|
193
|
+
"topic",
|
|
194
|
+
"transaction",
|
|
195
|
+
"trigger",
|
|
196
|
+
"type",
|
|
197
|
+
"unbounded",
|
|
198
|
+
"unconditional",
|
|
199
|
+
"union",
|
|
200
|
+
"unique",
|
|
201
|
+
"unknown",
|
|
202
|
+
"update",
|
|
203
|
+
"upsert",
|
|
204
|
+
"use",
|
|
205
|
+
"user",
|
|
206
|
+
"using",
|
|
207
|
+
"vacuum",
|
|
208
|
+
"values",
|
|
209
|
+
"view",
|
|
210
|
+
"virtual",
|
|
211
|
+
"when",
|
|
212
|
+
"where",
|
|
213
|
+
"window",
|
|
214
|
+
"with",
|
|
215
|
+
"without",
|
|
216
|
+
"wrapper",
|
|
217
|
+
"xor",
|
|
218
|
+
}
|