umbot-ydb-adapter 1.0.0 → 1.0.1
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.
- package/README.md +9 -3
- package/dist/YdbAdapter.d.ts +5 -4
- package/dist/YdbAdapter.js +13 -6
- package/dist/yql.d.ts +3 -3
- package/dist/yql.js +6 -6
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -181,7 +181,7 @@ Yandex Lockbox.
|
|
|
181
181
|
| `SoundTokens` | `soundToken` | `idx_platform_path` по `(platform, path)` |
|
|
182
182
|
|
|
183
183
|
Все колонки — `Utf8`, колонки ключа — `NOT NULL`. Индексы синхронные (`GLOBAL SYNC`): токен, сохранённый через
|
|
184
|
-
`
|
|
184
|
+
`INSERT`, сразу находится поиском по пути. YDB использует вторичный индекс только при явном `VIEW`, поэтому адаптер
|
|
185
185
|
сам добавляет `VIEW idx_platform_path` в поиск токена по `(platform, path)`.
|
|
186
186
|
|
|
187
187
|
Если таблица уже есть, адаптер добавляет недостающие колонки и индексы, но не меняет и не удаляет существующие.
|
|
@@ -210,6 +210,10 @@ new YdbAdapter({
|
|
|
210
210
|
Типы колонок: `Utf8`, `Int64`, `Double`, `Bool`. Значения приводятся к типу колонки: число `42` в колонке `Utf8`
|
|
211
211
|
запишется строкой `'42'`.
|
|
212
212
|
|
|
213
|
+
Таблицы можно описать и общей для всех адаптеров опцией umbot `appConfig.dbTables` (umbot 3.1.6+): адаптер создаст
|
|
214
|
+
их так же, но все колонки получат тип `Utf8` — в `IDbTableSchema` есть только строковые поля. Если таблица с тем же
|
|
215
|
+
именем есть и в `tables`, используется описание из `tables`.
|
|
216
|
+
|
|
213
217
|
Для таблиц, не описанных в `tables` (созданных миграцией или вручную), тип значения берётся из правил модели
|
|
214
218
|
(`rules()`), а если правила нет — из самого значения:
|
|
215
219
|
|
|
@@ -255,8 +259,10 @@ const stats = await new UsersData(appContext).query(async (sql) => {
|
|
|
255
259
|
|
|
256
260
|
## Поведение и ограничения
|
|
257
261
|
|
|
258
|
-
- **Вставка — `
|
|
259
|
-
|
|
262
|
+
- **Вставка — `INSERT`.** `add()` с занятым ключом возвращает `false` и не перезаписывает запись, как у SQL-адаптеров;
|
|
263
|
+
для изменения записи используйте `update()` или `save()`. SDK повторяет вставку после временной ошибки сети: если
|
|
264
|
+
первая попытка всё же записала строку, повтор получит «ключ занят», и `add()` вернёт `false` (с ошибкой в логе),
|
|
265
|
+
хотя запись сохранена.
|
|
260
266
|
- **Запись — в Serializable-транзакции**: так YDB требует для таблиц со вторичными индексами.
|
|
261
267
|
- **`UPDATE` не меняет колонки ключа**: YDB этого не позволяет, а модель umbot передаёт `platform` и в данных, и в
|
|
262
268
|
условии.
|
package/dist/YdbAdapter.d.ts
CHANGED
|
@@ -119,7 +119,7 @@ export declare class YdbAdapter extends BaseDbAdapter<IYdbDbInfo> {
|
|
|
119
119
|
* Сначала выполняется один запрос-проверка (`SELECT ... LIMIT 0` по всем таблицам и индексам).
|
|
120
120
|
* Если схема уже готова — на этом всё: в Cloud Functions метод вызывается на каждом холодном
|
|
121
121
|
* старте, и DDL на каждый старт стоил бы заметного времени.
|
|
122
|
-
* @param tables Описание таблиц
|
|
122
|
+
* @param tables Описание таблиц от umbot: `DB_TABLES_SCHEMA` и `appConfig.dbTables`
|
|
123
123
|
* @returns true, если схема готова
|
|
124
124
|
*/
|
|
125
125
|
ensureSchema(tables: readonly IDbTableSchema[]): Promise<boolean>;
|
|
@@ -135,10 +135,11 @@ export declare class YdbAdapter extends BaseDbAdapter<IYdbDbInfo> {
|
|
|
135
135
|
*/
|
|
136
136
|
_select(selectData: IQuery, where: IQueryData | null, isOne: boolean): Promise<IModelRes>;
|
|
137
137
|
/**
|
|
138
|
-
* Добавляет запись (
|
|
139
|
-
*
|
|
138
|
+
* Добавляет запись (INSERT). Занятый ключ YDB отклоняет — вернётся false, запись не
|
|
139
|
+
* перезаписывается (как у SQL-адаптеров). SDK повторяет запрос после временной ошибки сети;
|
|
140
|
+
* если первая попытка всё же записала строку, повтор получит «ключ занят» и вернёт false.
|
|
140
141
|
* @param insertData Запрос с данными в `data`
|
|
141
|
-
* @returns true при
|
|
142
|
+
* @returns true при успехе, false — ключ занят или ошибка базы (в логе)
|
|
142
143
|
*/
|
|
143
144
|
_insert(insertData: IQuery): Promise<boolean>;
|
|
144
145
|
/**
|
package/dist/YdbAdapter.js
CHANGED
|
@@ -157,13 +157,19 @@ class YdbAdapter extends plugins_1.BaseDbAdapter {
|
|
|
157
157
|
* Сначала выполняется один запрос-проверка (`SELECT ... LIMIT 0` по всем таблицам и индексам).
|
|
158
158
|
* Если схема уже готова — на этом всё: в Cloud Functions метод вызывается на каждом холодном
|
|
159
159
|
* старте, и DDL на каждый старт стоил бы заметного времени.
|
|
160
|
-
* @param tables Описание таблиц
|
|
160
|
+
* @param tables Описание таблиц от umbot: `DB_TABLES_SCHEMA` и `appConfig.dbTables`
|
|
161
161
|
* @returns true, если схема готова
|
|
162
162
|
*/
|
|
163
163
|
async ensureSchema(tables) {
|
|
164
164
|
let infos;
|
|
165
165
|
try {
|
|
166
|
-
|
|
166
|
+
// Одноимённая таблица из опции tables (с типами колонок) заменяет описание от umbot
|
|
167
|
+
// (appConfig.dbTables, все колонки Utf8) — иначе таблица создалась бы с колонками Utf8.
|
|
168
|
+
const byName = new Map();
|
|
169
|
+
for (const info of [...tables.map(yql_1.tableInfoFromSchema), ...this.#customTables()]) {
|
|
170
|
+
byName.set(info.tableName, info);
|
|
171
|
+
}
|
|
172
|
+
infos = [...byName.values()];
|
|
167
173
|
}
|
|
168
174
|
catch (error) {
|
|
169
175
|
this._saveLog('ensureSchema: некорректное описание таблицы', error);
|
|
@@ -291,14 +297,15 @@ class YdbAdapter extends plugins_1.BaseDbAdapter {
|
|
|
291
297
|
}
|
|
292
298
|
}
|
|
293
299
|
/**
|
|
294
|
-
* Добавляет запись (
|
|
295
|
-
*
|
|
300
|
+
* Добавляет запись (INSERT). Занятый ключ YDB отклоняет — вернётся false, запись не
|
|
301
|
+
* перезаписывается (как у SQL-адаптеров). SDK повторяет запрос после временной ошибки сети;
|
|
302
|
+
* если первая попытка всё же записала строку, повтор получит «ключ занят» и вернёт false.
|
|
296
303
|
* @param insertData Запрос с данными в `data`
|
|
297
|
-
* @returns true при
|
|
304
|
+
* @returns true при успехе, false — ключ занят или ошибка базы (в логе)
|
|
298
305
|
*/
|
|
299
306
|
async _insert(insertData) {
|
|
300
307
|
try {
|
|
301
|
-
const statement = (0, yql_1.
|
|
308
|
+
const statement = (0, yql_1.buildInsert)(insertData.tableName, insertData.data ?? {}, this.#context(insertData));
|
|
302
309
|
await this.#execute(statement, { write: true });
|
|
303
310
|
return true;
|
|
304
311
|
}
|
package/dist/yql.d.ts
CHANGED
|
@@ -124,14 +124,14 @@ export declare function chooseIndex(table: IYdbTableInfo | undefined, where: IQu
|
|
|
124
124
|
*/
|
|
125
125
|
export declare function buildSelect(tableName: string, where: IQueryData | null, isOne: boolean, ctx: IYqlContext): IYqlStatement;
|
|
126
126
|
/**
|
|
127
|
-
* Собирает
|
|
128
|
-
* null записывается как NULL.
|
|
127
|
+
* Собирает INSERT одной записи: занятый ключ YDB отклоняет, запись не перезаписывается.
|
|
128
|
+
* Поля со значением undefined пропускаются, null записывается как NULL.
|
|
129
129
|
* @param tableName Имя таблицы
|
|
130
130
|
* @param data Данные записи
|
|
131
131
|
* @param ctx Контекст запроса
|
|
132
132
|
* @returns Запрос
|
|
133
133
|
*/
|
|
134
|
-
export declare function
|
|
134
|
+
export declare function buildInsert(tableName: string, data: IQueryData, ctx: IYqlContext): IYqlStatement;
|
|
135
135
|
/**
|
|
136
136
|
* Собирает UPDATE. Колонки первичного ключа из SET убираются: YDB не меняет ключ
|
|
137
137
|
* записи, а модель umbot передаёт `uniqueKeys` и в данных, и в условии.
|
package/dist/yql.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.quoteTable = quoteTable;
|
|
|
7
7
|
exports.quoteColumn = quoteColumn;
|
|
8
8
|
exports.chooseIndex = chooseIndex;
|
|
9
9
|
exports.buildSelect = buildSelect;
|
|
10
|
-
exports.
|
|
10
|
+
exports.buildInsert = buildInsert;
|
|
11
11
|
exports.buildUpdate = buildUpdate;
|
|
12
12
|
exports.buildDelete = buildDelete;
|
|
13
13
|
exports.buildCreateTable = buildCreateTable;
|
|
@@ -397,14 +397,14 @@ function buildSelect(tableName, where, isOne, ctx) {
|
|
|
397
397
|
return { text, params: params.params };
|
|
398
398
|
}
|
|
399
399
|
/**
|
|
400
|
-
* Собирает
|
|
401
|
-
* null записывается как NULL.
|
|
400
|
+
* Собирает INSERT одной записи: занятый ключ YDB отклоняет, запись не перезаписывается.
|
|
401
|
+
* Поля со значением undefined пропускаются, null записывается как NULL.
|
|
402
402
|
* @param tableName Имя таблицы
|
|
403
403
|
* @param data Данные записи
|
|
404
404
|
* @param ctx Контекст запроса
|
|
405
405
|
* @returns Запрос
|
|
406
406
|
*/
|
|
407
|
-
function
|
|
407
|
+
function buildInsert(tableName, data, ctx) {
|
|
408
408
|
const params = new YqlParams();
|
|
409
409
|
const columns = [];
|
|
410
410
|
const values = [];
|
|
@@ -424,7 +424,7 @@ function buildUpsert(tableName, data, ctx) {
|
|
|
424
424
|
if (!columns.length) {
|
|
425
425
|
throw new YqlBuildError(`Нет данных для записи в таблицу "${tableName}".`);
|
|
426
426
|
}
|
|
427
|
-
const text = `
|
|
427
|
+
const text = `INSERT INTO ${quoteTable(tableName)} (${columns.join(', ')}) VALUES (${values.join(', ')})`;
|
|
428
428
|
return { text, params: params.params };
|
|
429
429
|
}
|
|
430
430
|
/**
|
|
@@ -478,7 +478,7 @@ function buildDelete(tableName, where, ctx) {
|
|
|
478
478
|
}
|
|
479
479
|
/**
|
|
480
480
|
* Описание вторичного индекса для CREATE TABLE / ALTER TABLE.
|
|
481
|
-
* Индекс синхронный: запись, только что сохранённая через
|
|
481
|
+
* Индекс синхронный: запись, только что сохранённая через INSERT или UPDATE, сразу видна в поиске по индексу.
|
|
482
482
|
*/
|
|
483
483
|
function indexDefinition(index) {
|
|
484
484
|
return `INDEX ${quoteColumn(index.name)} GLOBAL SYNC ON (${index.fields.map(quoteColumn).join(', ')})`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "umbot-ydb-adapter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "YDB (Yandex Database) adapter for the umbot framework: storage for Alice skills and chat bots in Yandex Cloud Functions without a separate database server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"umbot",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"database",
|
|
16
16
|
"db-adapter",
|
|
17
17
|
"typescript",
|
|
18
|
-
"bot-framework"
|
|
18
|
+
"bot-framework",
|
|
19
|
+
"smartapp"
|
|
19
20
|
],
|
|
20
21
|
"author": {
|
|
21
22
|
"name": "Maxim-M",
|
|
@@ -79,7 +80,7 @@
|
|
|
79
80
|
"ts-jest": "^29.4.9",
|
|
80
81
|
"typescript": "^5.9.3",
|
|
81
82
|
"typescript-eslint": "^8.60.0",
|
|
82
|
-
"umbot": "^3.1.
|
|
83
|
+
"umbot": "^3.1.6"
|
|
83
84
|
},
|
|
84
85
|
"funding": {
|
|
85
86
|
"type": "individual",
|