uql-orm 0.81.0 → 0.82.0
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 +3 -3
- package/dist/browser/querier/httpQuerier.d.ts +2 -2
- package/dist/browser/querier/httpQuerier.js +2 -1
- package/dist/browser/type/clientQuerier.d.ts +2 -2
- package/dist/browser/uql-browser.min.js +2 -2
- package/dist/browser/uql-browser.min.js.map +9 -8
- package/dist/bunSql/bunSql.util.js +2 -1
- package/dist/dialect/abstractSqlDialect.d.ts +15 -5
- package/dist/dialect/abstractSqlDialect.js +109 -40
- package/dist/dialect/operators.d.ts +7 -1
- package/dist/dialect/operators.js +13 -1
- package/dist/entity/metadata/definition.d.ts +1 -2
- package/dist/entity/metadata/definition.js +37 -39
- package/dist/http/handler.js +5 -4
- package/dist/http/query.d.ts +1 -1
- package/dist/http/query.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/migrate/acquireQuerierForMigrations.js +2 -1
- package/dist/migrate/assertCliConfig.js +7 -6
- package/dist/migrate/bin.js +0 -0
- package/dist/migrate/builder/expressions.js +2 -1
- package/dist/migrate/cli-config.js +5 -4
- package/dist/migrate/ddl/indexDdl.js +4 -3
- package/dist/migrate/ddl/mysqlIndexDdl.js +5 -4
- package/dist/migrate/ddl/pgIndexDdl.js +2 -1
- package/dist/migrate/ddl/sqliteIndexDdl.js +2 -1
- package/dist/migrate/ddl/tableDdl.js +2 -1
- package/dist/migrate/generator/mongoCommand.js +2 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js +6 -5
- package/dist/migrate/indexPredicate.js +2 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +2 -1
- package/dist/migrate/introspection/mongoIntrospector.js +2 -1
- package/dist/migrate/migrationTarget.js +2 -1
- package/dist/migrate/migrator.js +2 -1
- package/dist/migrate/schemaGenerator.js +5 -4
- package/dist/migrate/triggerSql.d.ts +1 -1
- package/dist/migrate/triggerSql.js +77 -61
- package/dist/mongo/mongoDialect.d.ts +1 -3
- package/dist/mongo/mongoDialect.js +9 -14
- package/dist/mongo/mongodbQuerier.js +3 -7
- package/dist/querier/abstractQuerier.d.ts +9 -4
- package/dist/querier/abstractQuerier.js +26 -19
- package/dist/querier/abstractQuerierPool.d.ts +3 -3
- package/dist/querier/abstractSqlQuerier.d.ts +2 -2
- package/dist/querier/abstractSqlQuerier.js +1 -1
- package/dist/querier/abstractSqlQuerierPool.d.ts +2 -2
- package/dist/querier/queryError.d.ts +2 -2
- package/dist/schema/schemaASTBuilder.js +2 -1
- package/dist/type/dialect.d.ts +23 -1
- package/dist/type/entity.d.ts +15 -11
- package/dist/type/logger.d.ts +2 -2
- package/dist/type/querier.d.ts +3 -3
- package/dist/type/query.d.ts +3 -13
- package/dist/type/queryAggregate.d.ts +4 -10
- package/dist/type/queryRaw.d.ts +17 -3
- package/dist/type/queryRaw.js +2 -1
- package/dist/type/queryWhere.d.ts +7 -7
- package/dist/type/universalQuerier.d.ts +3 -3
- package/dist/type/vector.d.ts +2 -1
- package/dist/type/vector.js +2 -1
- package/dist/util/dialect.util.d.ts +13 -5
- package/dist/util/dialect.util.js +28 -20
- package/dist/util/field.util.d.ts +4 -4
- package/dist/util/field.util.js +10 -2
- package/dist/util/hook.util.d.ts +1 -1
- package/dist/util/hook.util.js +8 -1
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/util/logger.d.ts +3 -3
- package/dist/util/object.util.js +3 -2
- package/dist/util/raw.d.ts +6 -7
- package/dist/util/raw.js +10 -12
- package/dist/util/sqlLiteral.js +3 -2
- package/dist/util/triggerWrite.d.ts +15 -0
- package/dist/util/triggerWrite.js +20 -0
- package/package.json +1 -1
- package/skills/uql-orm/SKILL.md +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isMongoQuerier, isSqlQuerier, } from '../type/index.js';
|
|
2
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
2
3
|
/**
|
|
3
4
|
* Querier used for schema migrations and the migration journal.
|
|
4
5
|
*
|
|
@@ -34,7 +35,7 @@ export function withMongoQuerierForMigrations(pool, requiredBy, task) {
|
|
|
34
35
|
function withQuerierOfKind(pool, isKind, error, task) {
|
|
35
36
|
return withQuerierForMigrations(pool, (querier) => {
|
|
36
37
|
if (!isKind(querier)) {
|
|
37
|
-
throw new
|
|
38
|
+
throw new UqlUsageError(error);
|
|
38
39
|
}
|
|
39
40
|
return task(querier);
|
|
40
41
|
});
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
1
2
|
/**
|
|
2
3
|
* Validates shape required for the migrations CLI (real `QuerierPool`, not config stubs).
|
|
3
4
|
*/
|
|
4
5
|
export function assertCliConfig(config) {
|
|
5
6
|
if (config === null || typeof config !== 'object') {
|
|
6
|
-
throw new
|
|
7
|
+
throw new UqlUsageError('Config must be a non-null object');
|
|
7
8
|
}
|
|
8
9
|
const c = config;
|
|
9
10
|
const pool = c['pool'];
|
|
10
11
|
if (pool === null || typeof pool !== 'object') {
|
|
11
|
-
throw new
|
|
12
|
+
throw new UqlUsageError('Config.pool is required and must be an object');
|
|
12
13
|
}
|
|
13
14
|
const p = pool;
|
|
14
15
|
for (const key of ['getQuerier', 'transaction', 'withQuerier']) {
|
|
15
16
|
if (typeof p[key] !== 'function') {
|
|
16
|
-
throw new
|
|
17
|
+
throw new UqlUsageError(`Config.pool.${key} must be a function`);
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
if (p['end'] !== undefined && typeof p['end'] !== 'function') {
|
|
20
|
-
throw new
|
|
21
|
+
throw new UqlUsageError('Config.pool.end must be a function when provided');
|
|
21
22
|
}
|
|
22
23
|
const dialect = p['dialect'];
|
|
23
24
|
if (dialect === null || typeof dialect !== 'object') {
|
|
24
|
-
throw new
|
|
25
|
+
throw new UqlUsageError('Config.pool.dialect is required and must be an object');
|
|
25
26
|
}
|
|
26
27
|
const dialectName = dialect['dialectName'];
|
|
27
28
|
if (typeof dialectName !== 'string') {
|
|
28
|
-
throw new
|
|
29
|
+
throw new UqlUsageError('Config.pool.dialect.dialectName must be a string');
|
|
29
30
|
}
|
|
30
31
|
}
|
package/dist/migrate/bin.js
CHANGED
|
File without changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
1
2
|
const ANSI = {
|
|
2
3
|
now: 'CURRENT_TIMESTAMP',
|
|
3
4
|
currentDate: 'CURRENT_DATE',
|
|
@@ -129,7 +130,7 @@ function expressionSql(expression, dialect) {
|
|
|
129
130
|
const { expressions } = DIALECT_DEFAULTS[dialect.dialectName];
|
|
130
131
|
const sql = expression.kind === 'raw' ? expression.sql : expressions[expression.kind];
|
|
131
132
|
if (sql == null) {
|
|
132
|
-
throw new
|
|
133
|
+
throw new UqlUsageError(`${dialect.dialectName} has no '${expression.kind}' default; pass expr.raw(...) with SQL this engine accepts`);
|
|
133
134
|
}
|
|
134
135
|
return sql;
|
|
135
136
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
4
5
|
/**
|
|
5
6
|
* Loads the config with a plain `import()`, leaving TypeScript to the runtime: uql bundles no transpiler,
|
|
6
7
|
* since only the project knows its decorator spec. Node's type stripping handles no decorators.
|
|
7
8
|
*/
|
|
8
9
|
async function importConfig(path) {
|
|
9
10
|
const mod = (await import(pathToFileURL(path).href).catch((cause) => {
|
|
10
|
-
throw new
|
|
11
|
+
throw new UqlUsageError(`Could not import ${path}: ${cause?.message}\n` +
|
|
11
12
|
'If it reaches entity classes, their decorators need a runtime that transforms TypeScript, not ' +
|
|
12
13
|
'just one that strips its types. Run the CLI with `bun`, or with `node --import tsx` ' +
|
|
13
14
|
'(`npm i -D tsx`). A JavaScript config, or passing the config inline, needs neither.', { cause });
|
|
@@ -21,14 +22,14 @@ export async function loadConfig(customPath) {
|
|
|
21
22
|
.then(() => true)
|
|
22
23
|
.catch(() => false);
|
|
23
24
|
if (!exists) {
|
|
24
|
-
throw new
|
|
25
|
+
throw new UqlUsageError(`Could not find uql configuration file at ${customPath}`);
|
|
25
26
|
}
|
|
26
27
|
try {
|
|
27
28
|
const config = await importConfig(fullPath);
|
|
28
29
|
return config;
|
|
29
30
|
}
|
|
30
31
|
catch (error) {
|
|
31
|
-
throw new
|
|
32
|
+
throw new UqlUsageError(`Could not load configuration file at ${customPath}: ${error.message}`);
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
const configPaths = ['uql.config.ts', 'uql.config.js', 'uql.config.mjs', '.uqlrc.ts', '.uqlrc.js'];
|
|
@@ -42,5 +43,5 @@ export async function loadConfig(customPath) {
|
|
|
42
43
|
return config;
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
throw new
|
|
46
|
+
throw new UqlUsageError('Could not find uql configuration file. Create a uql.config.ts or uql.config.js file in your project root.');
|
|
46
47
|
}
|
|
@@ -2,6 +2,7 @@ import { jsonTypeMode } from '../../dialect/jsonSql.js';
|
|
|
2
2
|
import { INDEX_TYPES } from '../../schema/types.js';
|
|
3
3
|
import { INDEX_FEATURE_LABELS, } from '../../type/index.js';
|
|
4
4
|
import { fulltextConfig, getKeys } from '../../util/index.js';
|
|
5
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
5
6
|
/**
|
|
6
7
|
* What in an index asks for each feature. A `Record` over the feature union rather than a list, so a
|
|
7
8
|
* feature added to {@link INDEX_FEATURE_LABELS} cannot reach a dialect without the test that decides
|
|
@@ -20,14 +21,14 @@ const INDEX_FEATURE_PROBES = {
|
|
|
20
21
|
/** Refuses an index of a type `types` lacks, `hints` naming what to declare instead. */
|
|
21
22
|
export function assertIndexType(index, types, dialectName, hints = new Map()) {
|
|
22
23
|
if (index.type && !types.has(index.type)) {
|
|
23
|
-
throw new
|
|
24
|
+
throw new UqlUsageError(`${dialectName} has no ${index.type} index (index "${index.name}")` + (hints.get(index.type) ?? ''));
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
/** Refuses an index asking for a feature `features` lacks. */
|
|
27
28
|
export function assertIndexFeatures(index, features, dialectName) {
|
|
28
29
|
for (const feature of getKeys(INDEX_FEATURE_PROBES)) {
|
|
29
30
|
if (INDEX_FEATURE_PROBES[feature](index) && !features.has(feature)) {
|
|
30
|
-
throw new
|
|
31
|
+
throw new UqlUsageError(`${dialectName} does not support ${INDEX_FEATURE_LABELS[feature]} (index "${index.name}")`);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -122,7 +123,7 @@ export class IndexDdl {
|
|
|
122
123
|
* every other dialect refuses `jsonArray` in {@link assertIndexFeatures} and never reaches this.
|
|
123
124
|
*/
|
|
124
125
|
jsonArrayIndexExpr(_escapedColumn, _json) {
|
|
125
|
-
throw new
|
|
126
|
+
throw new UqlUsageError(`${this.dialect.dialectName} has no multi-valued index`);
|
|
126
127
|
}
|
|
127
128
|
/** Postgres-wire dialects put a vector or user-declared operator class here. */
|
|
128
129
|
indexColumnOpsClass(_entry, _index) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsonTypeMode } from '../../dialect/jsonSql.js';
|
|
2
2
|
import { indexDistance, isVectorIndexType, unsupportedVectorMetric, VECTOR_INDEX_TYPES } from '../../type/vector.js';
|
|
3
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
3
4
|
import { IndexDdl } from './indexDdl.js';
|
|
4
5
|
/**
|
|
5
6
|
* A full-text index is its own keyword here (`CREATE FULLTEXT INDEX ... (cols)`); `USING fulltext` is
|
|
@@ -38,14 +39,14 @@ export class MySqlIndexDdl extends MysqlLikeIndexDdl {
|
|
|
38
39
|
jsonPathIndexExpr(escapedColumn, json) {
|
|
39
40
|
const mode = jsonTypeMode(json.type);
|
|
40
41
|
if (mode === 'json') {
|
|
41
|
-
throw new
|
|
42
|
+
throw new UqlUsageError(`mysql cannot index the boolean JSON path '${json.path}', which compares as JSON`);
|
|
42
43
|
}
|
|
43
44
|
const expr = super.jsonPathIndexExpr(escapedColumn, json);
|
|
44
45
|
if (mode === 'numeric') {
|
|
45
46
|
return expr;
|
|
46
47
|
}
|
|
47
48
|
if (!json.length) {
|
|
48
|
-
throw new
|
|
49
|
+
throw new UqlUsageError(`a MySQL index over the string JSON path '${json.path}' needs a length`);
|
|
49
50
|
}
|
|
50
51
|
return `CAST(${expr} AS CHAR(${json.length}) CHARACTER SET utf8mb4) COLLATE utf8mb4_bin`;
|
|
51
52
|
}
|
|
@@ -132,13 +133,13 @@ function arrayCastType(json) {
|
|
|
132
133
|
const type = json.type;
|
|
133
134
|
const cast = ARRAY_CASTS.get(typeof type === 'string' ? type.toLowerCase() : type);
|
|
134
135
|
if (!cast) {
|
|
135
|
-
throw new
|
|
136
|
+
throw new UqlUsageError(`mysql has no array cast for ${typeof type === 'string' ? type : type.name} elements`);
|
|
136
137
|
}
|
|
137
138
|
if (cast !== 'CHAR' && cast !== 'BINARY') {
|
|
138
139
|
return cast;
|
|
139
140
|
}
|
|
140
141
|
if (!json.length) {
|
|
141
|
-
throw new
|
|
142
|
+
throw new UqlUsageError(`a multi-valued index over ${cast === 'CHAR' ? 'string' : 'binary'} elements needs a length`);
|
|
142
143
|
}
|
|
143
144
|
return `${cast}(${json.length})`;
|
|
144
145
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { indexDistance, unsupportedVectorMetric } from '../../type/vector.js';
|
|
2
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
2
3
|
import { IndexDdl } from './indexDdl.js';
|
|
3
4
|
/** `CREATE INDEX ... USING hnsw ("embedding" vector_cosine_ops) WITH (m = ...)`, pgvector's form. */
|
|
4
5
|
export class PgIndexDdl extends IndexDdl {
|
|
@@ -49,7 +50,7 @@ export class PgIndexDdl extends IndexDdl {
|
|
|
49
50
|
const opsClass = `${vectorType}_${metric}_ops`;
|
|
50
51
|
// IVFFlat has neither a sparsevec nor an L1 operator class; HNSW has all of them (pgvector 0.8.2).
|
|
51
52
|
if (index.type === 'ivfflat' && (vectorType === 'sparsevec' || distance === 'l1')) {
|
|
52
|
-
throw new
|
|
53
|
+
throw new UqlUsageError(`ivfflat has no ${opsClass} operator class (index "${index.name}"); use hnsw`);
|
|
53
54
|
}
|
|
54
55
|
return ` ${opsClass}`;
|
|
55
56
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { indexDistance, isVectorIndexType, unsupportedVectorMetric } from '../../type/vector.js';
|
|
2
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
2
3
|
import { IndexDdl } from './indexDdl.js';
|
|
3
4
|
/**
|
|
4
5
|
* SQLite's `CREATE INDEX`, which names no index type. A vector index is libSQL's DiskANN where the dialect
|
|
@@ -31,7 +32,7 @@ export class SqliteIndexDdl extends IndexDdl {
|
|
|
31
32
|
}
|
|
32
33
|
// Its tables are named after the index, unquoted: any other name fails with "unable to initialize diskann".
|
|
33
34
|
if (!/^\w+$/.test(index.name) || index.entries.length !== 1) {
|
|
34
|
-
throw new
|
|
35
|
+
throw new UqlUsageError(`libSQL names a vector index only by letters, digits and underscores, over one column (index "${index.name}")`);
|
|
35
36
|
}
|
|
36
37
|
return metric;
|
|
37
38
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
1
2
|
import { formatDefaultValue, sameDefault } from '../builder/expressions.js';
|
|
2
3
|
/**
|
|
3
4
|
* A column's type with the size it was read back with, unless its spelling already carries one:
|
|
@@ -39,7 +40,7 @@ export class TableDdl {
|
|
|
39
40
|
*/
|
|
40
41
|
alterColumn(table, column, definition, from) {
|
|
41
42
|
if (this.dialect.alterColumnSyntax === 'none') {
|
|
42
|
-
throw new
|
|
43
|
+
throw new UqlUsageError(`${this.dialect}: Cannot alter column "${column.name}" - you must recreate the table. ` +
|
|
43
44
|
`This database does not support ALTER COLUMN.`);
|
|
44
45
|
}
|
|
45
46
|
const target = this.dialect.escapeId(table);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
1
2
|
export function serializeMongoCommand(command) {
|
|
2
3
|
return JSON.stringify(command);
|
|
3
4
|
}
|
|
@@ -9,7 +10,7 @@ function parseMongoCommand(statement) {
|
|
|
9
10
|
return JSON.parse(statement);
|
|
10
11
|
}
|
|
11
12
|
function unsupportedMongoCommand(statement) {
|
|
12
|
-
return new
|
|
13
|
+
return new UqlUsageError(`unsupported MongoDB migration command: ${statement}`);
|
|
13
14
|
}
|
|
14
15
|
/** Execute one emitted command. */
|
|
15
16
|
export function runMongoCommand(db, statement) {
|
|
@@ -6,6 +6,7 @@ import { QueryRaw, } from '../../type/index.js';
|
|
|
6
6
|
import { indexDistance, unsupportedVectorMetric } from '../../type/vector.js';
|
|
7
7
|
import { declaredIndexes, declaredIndexName, renderIndexColumn } from '../../util/ddlExpression.util.js';
|
|
8
8
|
import { fulltextConfig, fulltextWeights } from '../../util/dialect.util.js';
|
|
9
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
9
10
|
import { assertIndexFeatures, assertIndexType } from '../ddl/indexDdl.js';
|
|
10
11
|
import { assertIndexPredicate, refusedIndexPredicate } from '../indexPredicate.js';
|
|
11
12
|
import { sides } from '../schemaChange.js';
|
|
@@ -30,7 +31,7 @@ export class MongoSchemaGenerator extends MongoDialect {
|
|
|
30
31
|
}
|
|
31
32
|
/** A collection has no SQL to render a check, a computed column or an index expression into. */
|
|
32
33
|
compileDdl() {
|
|
33
|
-
throw new
|
|
34
|
+
throw new UqlUsageError('mongodb has no SQL to render a check, a computed column or an index expression into');
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
36
37
|
* A document store has no cross-collection constraint, so unlike the SQL generator there is nothing to
|
|
@@ -84,7 +85,7 @@ export class MongoSchemaGenerator extends MongoDialect {
|
|
|
84
85
|
*/
|
|
85
86
|
compileIndexPredicate(where, entity, indexName) {
|
|
86
87
|
if (where instanceof QueryRaw) {
|
|
87
|
-
throw new
|
|
88
|
+
throw new UqlUsageError(`mongodb does not support partial indexes from a SQL predicate (index "${indexName}")`);
|
|
88
89
|
}
|
|
89
90
|
assertIndexPredicate(where, this.dialectName, indexName);
|
|
90
91
|
const filter = this.renderFilter(entity, where);
|
|
@@ -160,7 +161,7 @@ export class MongoSchemaGenerator extends MongoDialect {
|
|
|
160
161
|
assertIndexFeatures(index, new Set(), this.dialectName);
|
|
161
162
|
const [vector, ...filters] = index.entries;
|
|
162
163
|
if (!vector || index.dimensions === undefined) {
|
|
163
|
-
throw new
|
|
164
|
+
throw new UqlUsageError(`an Atlas vector search index states its field's dimensions (index "${index.name}")`);
|
|
164
165
|
}
|
|
165
166
|
const distance = indexDistance(index);
|
|
166
167
|
const similarity = ATLAS_SIMILARITY[distance];
|
|
@@ -192,7 +193,7 @@ export class MongoSchemaGenerator extends MongoDialect {
|
|
|
192
193
|
case 'createTable': {
|
|
193
194
|
const { name, columns, indexes } = operation.table;
|
|
194
195
|
if (columns.length) {
|
|
195
|
-
throw new
|
|
196
|
+
throw new UqlUsageError(`mongodb does not support columns in a migration (collection "${name}")`);
|
|
196
197
|
}
|
|
197
198
|
return [
|
|
198
199
|
serializeMongoCommand({ action: 'createCollection', name }),
|
|
@@ -208,7 +209,7 @@ export class MongoSchemaGenerator extends MongoDialect {
|
|
|
208
209
|
case 'dropIndex':
|
|
209
210
|
return [this.generateDropIndex(operation.tableName, operation.indexName)];
|
|
210
211
|
default:
|
|
211
|
-
throw new
|
|
212
|
+
throw new UqlUsageError(`mongodb does not support ${operation.type} in a migration`);
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
diffSchema(entity, currentTable) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { QueryRaw } from '../type/queryRaw.js';
|
|
2
2
|
import { isOperatorObject } from '../util/object.util.js';
|
|
3
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
3
4
|
/**
|
|
4
5
|
* The `$where` a partial index takes, on the engines where that is less than a query's: SQL Server's
|
|
5
6
|
* `CREATE INDEX` `<filter_predicate>` (comparisons and `IN` on plain columns, joined by `AND`), and
|
|
@@ -30,7 +31,7 @@ export function assertIndexPredicate(where, dialectName, indexName) {
|
|
|
30
31
|
}
|
|
31
32
|
/** What refusing any part of a partial index's predicate reports. */
|
|
32
33
|
export function refusedIndexPredicate(dialectName, part, indexName) {
|
|
33
|
-
return new
|
|
34
|
+
return new UqlUsageError(`${dialectName} does not support ${part} in a partial index predicate (index "${indexName}")`);
|
|
34
35
|
}
|
|
35
36
|
/** The first part of `where` outside `grammar`, depth-first; a `raw` clause is left alone. */
|
|
36
37
|
function refusedOperator(where, grammar) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FOREIGN_KEY_ACTIONS } from '../../schema/types.js';
|
|
2
2
|
import { isSqlQuerier } from '../../type/index.js';
|
|
3
3
|
import { isOwnedName } from '../../util/sql.util.js';
|
|
4
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
4
5
|
import { BaseSqlIntrospector } from './baseSqlIntrospector.js';
|
|
5
6
|
/** A SQL introspector: an engine states its catalogue queries (`get*Query`) and how their rows map (`map*Result`). */
|
|
6
7
|
export class AbstractSqlSchemaIntrospector extends BaseSqlIntrospector {
|
|
@@ -73,7 +74,7 @@ export class AbstractSqlSchemaIntrospector extends BaseSqlIntrospector {
|
|
|
73
74
|
withSqlQuerier(task) {
|
|
74
75
|
return this.pool.withQuerier((querier) => {
|
|
75
76
|
if (!isSqlQuerier(querier)) {
|
|
76
|
-
throw new
|
|
77
|
+
throw new UqlUsageError(`${this.constructor.name} requires a SQL-based querier`);
|
|
77
78
|
}
|
|
78
79
|
return task(querier);
|
|
79
80
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { textConfigOf } from '../../mongo/textLanguage.js';
|
|
2
2
|
import { createTableNode, SchemaAST } from '../../schema/schemaAST.js';
|
|
3
3
|
import { isMongoQuerier, } from '../../type/index.js';
|
|
4
|
+
import { UqlUsageError } from '../../util/uqlError.js';
|
|
4
5
|
/** What a server without Atlas Search answers a search index command with. */
|
|
5
6
|
const SEARCH_NOT_ENABLED = 31082;
|
|
6
7
|
/**
|
|
@@ -80,7 +81,7 @@ export class MongoSchemaIntrospector {
|
|
|
80
81
|
withDb(task) {
|
|
81
82
|
return this.pool.withQuerier((querier) => {
|
|
82
83
|
if (!isMongoQuerier(querier)) {
|
|
83
|
-
throw new
|
|
84
|
+
throw new UqlUsageError('MongoSchemaIntrospector requires a MongoDB querier');
|
|
84
85
|
}
|
|
85
86
|
return task(querier.db);
|
|
86
87
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isMongoQuerier, isSqlQuerier, } from '../type/index.js';
|
|
2
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
2
3
|
import { withMongoQuerierForMigrations, withSqlQuerierForMigrations } from './acquireQuerierForMigrations.js';
|
|
3
4
|
import { MigrationBuilder } from './builder/migrationBuilder.js';
|
|
4
5
|
import { migrationSource } from './codegen/migrationFile.js';
|
|
@@ -46,5 +47,5 @@ export async function migrationBuilderFor(querier) {
|
|
|
46
47
|
if (isMongoQuerier(querier)) {
|
|
47
48
|
return new MigrationBuilder(await mongoSchemaGenerator(), mongoSession(querier).run);
|
|
48
49
|
}
|
|
49
|
-
throw new
|
|
50
|
+
throw new UqlUsageError('A migration builder needs a SQL or a MongoDB querier');
|
|
50
51
|
}
|
package/dist/migrate/migrator.js
CHANGED
|
@@ -5,6 +5,7 @@ import { getEntities, getMeta } from '../entity/index.js';
|
|
|
5
5
|
import { SchemaAST } from '../schema/index.js';
|
|
6
6
|
import { hasTriggers } from '../util/field.util.js';
|
|
7
7
|
import { LoggerWrapper } from '../util/index.js';
|
|
8
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
8
9
|
import { buildMigrationModule } from './codegen/migrationFile.js';
|
|
9
10
|
import { introspectorFor } from './introspection/registry.js';
|
|
10
11
|
import { migrationBuilderFor, migrationTargetFor } from './migrationTarget.js';
|
|
@@ -96,7 +97,7 @@ export class Migrator {
|
|
|
96
97
|
if (options.to) {
|
|
97
98
|
const toIndex = selected.findIndex((m) => m.name === options.to);
|
|
98
99
|
if (toIndex === -1) {
|
|
99
|
-
throw new
|
|
100
|
+
throw new UqlUsageError(`Migration '${options.to}' not found`);
|
|
100
101
|
}
|
|
101
102
|
selected = selected.slice(0, toIndex + 1);
|
|
102
103
|
}
|
|
@@ -5,6 +5,7 @@ import { buildSchemaAST } from '../schema/schemaASTBuilder.js';
|
|
|
5
5
|
import { diffRelationshipNodes, diffTable } from '../schema/schemaASTDiffer.js';
|
|
6
6
|
import { isAutoIncrement, qualifyName } from '../util/index.js';
|
|
7
7
|
import { derivedCheckName, derivedForeignKeyName, derivedPrimaryKeyName, isOwnedName } from '../util/sql.util.js';
|
|
8
|
+
import { UqlUsageError } from '../util/uqlError.js';
|
|
8
9
|
import { sameDefault } from './builder/expressions.js';
|
|
9
10
|
import { splitSqlStatements } from './builder/splitSqlStatements.js';
|
|
10
11
|
import { indexDdlFor, tableDdlFor } from './ddl/index.js';
|
|
@@ -536,7 +537,7 @@ export class SqlSchemaGenerator {
|
|
|
536
537
|
}
|
|
537
538
|
generateAddForeignKeySql(tableName, foreignKey) {
|
|
538
539
|
if (!this.features.foreignKeyAlter) {
|
|
539
|
-
throw new
|
|
540
|
+
throw new UqlUsageError(`Dialect ${this.dialect} does not support adding foreign keys to existing tables`);
|
|
540
541
|
}
|
|
541
542
|
const constraint = this.foreignKeyConstraint(tableName, foreignKey, this.escapeId(foreignKey.references.table));
|
|
542
543
|
return `ALTER TABLE ${this.escapeId(tableName)} ADD ${constraint};`;
|
|
@@ -566,7 +567,7 @@ export class SqlSchemaGenerator {
|
|
|
566
567
|
return `ALTER TABLE ${table} DROP PRIMARY KEY;`;
|
|
567
568
|
}
|
|
568
569
|
if (!constraintName) {
|
|
569
|
-
throw new
|
|
570
|
+
throw new UqlUsageError(`Cannot drop the primary key of "${tableName}": ${this.dialect} names the constraint, and ` +
|
|
570
571
|
'introspection did not report a name for it.');
|
|
571
572
|
}
|
|
572
573
|
return `ALTER TABLE ${table} DROP CONSTRAINT ${this.escapeId(constraintName)};`;
|
|
@@ -579,7 +580,7 @@ export class SqlSchemaGenerator {
|
|
|
579
580
|
if (!column.generatedAs || this.features.generatedColumnAdd) {
|
|
580
581
|
return;
|
|
581
582
|
}
|
|
582
|
-
throw new
|
|
583
|
+
throw new UqlUsageError(`${this.dialect}: Cannot add the computed column "${column.name}" to the existing table ` +
|
|
583
584
|
`"${tableName}" - this database only accepts one in a CREATE TABLE. Drop \`stored\` to have the ` +
|
|
584
585
|
'expression spliced into each statement instead, or recreate the table in a written migration.');
|
|
585
586
|
}
|
|
@@ -587,7 +588,7 @@ export class SqlSchemaGenerator {
|
|
|
587
588
|
if (this.features.primaryKeyAlter) {
|
|
588
589
|
return;
|
|
589
590
|
}
|
|
590
|
-
throw new
|
|
591
|
+
throw new UqlUsageError(`${this.dialect}: Cannot change the primary key of "${tableName}" - this database has no ALTER ` +
|
|
591
592
|
'for it. Recreate the table in a written migration.');
|
|
592
593
|
}
|
|
593
594
|
}
|
|
@@ -21,4 +21,4 @@ export declare function dropTrigger<E>(dialect: AbstractSqlDialect, meta: Entity
|
|
|
21
21
|
* column. Generated rather than authored, so unlike an authored body it renders on every engine from
|
|
22
22
|
* one declaration - and not at all on the MySQL family, whose columns stamp themselves.
|
|
23
23
|
*/
|
|
24
|
-
export declare function stampTriggers<E>(dialect: AbstractSqlDialect, meta: EntityMeta<E>): EntityTriggerMeta<E>[];
|
|
24
|
+
export declare function stampTriggers<E extends object>(dialect: AbstractSqlDialect, meta: EntityMeta<E>): EntityTriggerMeta<E>[];
|