@uql/core 3.12.1 → 3.13.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/CHANGELOG.md +35 -7
- package/dist/browser/querier/httpQuerier.d.ts +2 -2
- package/dist/browser/querier/httpQuerier.d.ts.map +1 -1
- package/dist/browser/querier/httpQuerier.js.map +1 -1
- package/dist/browser/type/clientQuerier.d.ts +12 -3
- package/dist/browser/type/clientQuerier.d.ts.map +1 -1
- package/dist/dialect/abstractSqlDialect.d.ts +38 -5
- package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
- package/dist/dialect/abstractSqlDialect.js +144 -95
- package/dist/dialect/abstractSqlDialect.js.map +1 -1
- package/dist/maria/mariadbQuerier.d.ts +1 -5
- package/dist/maria/mariadbQuerier.d.ts.map +1 -1
- package/dist/maria/mariadbQuerier.js +2 -2
- package/dist/maria/mariadbQuerier.js.map +1 -1
- package/dist/migrate/cli.d.ts +4 -4
- package/dist/migrate/cli.d.ts.map +1 -1
- package/dist/migrate/cli.js.map +1 -1
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -2
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts.map +1 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js.map +1 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +7 -7
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts.map +1 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js.map +1 -1
- package/dist/migrate/introspection/mongoIntrospector.js +1 -1
- package/dist/migrate/introspection/mongoIntrospector.js.map +1 -1
- package/dist/migrate/introspection/postgresIntrospector.d.ts +2 -2
- package/dist/migrate/introspection/postgresIntrospector.d.ts.map +1 -1
- package/dist/migrate/introspection/postgresIntrospector.js +0 -1
- package/dist/migrate/introspection/postgresIntrospector.js.map +1 -1
- package/dist/migrate/storage/databaseStorage.js.map +1 -1
- package/dist/mongo/mongoDialect.d.ts +2 -2
- package/dist/mongo/mongoDialect.d.ts.map +1 -1
- package/dist/mongo/mongoDialect.js +3 -6
- package/dist/mongo/mongoDialect.js.map +1 -1
- package/dist/mongo/mongodbQuerier.d.ts +2 -2
- package/dist/mongo/mongodbQuerier.d.ts.map +1 -1
- package/dist/mongo/mongodbQuerier.js +3 -3
- package/dist/mongo/mongodbQuerier.js.map +1 -1
- package/dist/mysql/mysql2Querier.d.ts +1 -1
- package/dist/mysql/mysql2Querier.d.ts.map +1 -1
- package/dist/mysql/mysql2Querier.js +6 -5
- package/dist/mysql/mysql2Querier.js.map +1 -1
- package/dist/neon/neonQuerier.d.ts +1 -5
- package/dist/neon/neonQuerier.d.ts.map +1 -1
- package/dist/neon/neonQuerier.js +2 -3
- package/dist/neon/neonQuerier.js.map +1 -1
- package/dist/postgres/pgQuerier.d.ts +3 -7
- package/dist/postgres/pgQuerier.d.ts.map +1 -1
- package/dist/postgres/pgQuerier.js +3 -3
- package/dist/postgres/pgQuerier.js.map +1 -1
- package/dist/postgres/postgresDialect.d.ts +2 -1
- package/dist/postgres/postgresDialect.d.ts.map +1 -1
- package/dist/postgres/postgresDialect.js +14 -1
- package/dist/postgres/postgresDialect.js.map +1 -1
- package/dist/querier/abstractQuerier.d.ts +5 -5
- package/dist/querier/abstractQuerier.d.ts.map +1 -1
- package/dist/querier/abstractQuerier.js.map +1 -1
- package/dist/querier/abstractSqlQuerier.d.ts +2 -2
- package/dist/querier/abstractSqlQuerier.d.ts.map +1 -1
- package/dist/querier/abstractSqlQuerier.js.map +1 -1
- package/dist/sqlite/sqliteDialect.d.ts +2 -1
- package/dist/sqlite/sqliteDialect.d.ts.map +1 -1
- package/dist/sqlite/sqliteDialect.js +13 -0
- package/dist/sqlite/sqliteDialect.js.map +1 -1
- package/dist/type/entity.d.ts +35 -2
- package/dist/type/entity.d.ts.map +1 -1
- package/dist/type/querier.d.ts +3 -3
- package/dist/type/querier.d.ts.map +1 -1
- package/dist/type/query.d.ts +27 -45
- package/dist/type/query.d.ts.map +1 -1
- package/dist/type/query.js +6 -4
- package/dist/type/query.js.map +1 -1
- package/dist/type/universalQuerier.d.ts +17 -17
- package/dist/type/universalQuerier.d.ts.map +1 -1
- package/dist/type/utility.d.ts +8 -1
- package/dist/type/utility.d.ts.map +1 -1
- package/dist/util/dialect.util.d.ts +3 -3
- package/dist/util/dialect.util.d.ts.map +1 -1
- package/dist/util/dialect.util.js +4 -15
- package/dist/util/dialect.util.js.map +1 -1
- package/dist/util/sql.util.d.ts +9 -1
- package/dist/util/sql.util.d.ts.map +1 -1
- package/dist/util/sql.util.js +10 -0
- package/dist/util/sql.util.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,17 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [3.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Bug Fixes
|
|
10
|
-
|
|
11
|
-
* Make JSONB `$ne` operator null-safe by using `IS DISTINCT FROM` / `IS NOT` and refine query map type definitions. ([2bb2023](https://github.com/rogerpadilla/uql/commit/2bb202310d5a1a7fa2bc0ff7948c892afa4ba4f2))
|
|
6
|
+
## [3.13.1](https://github.com/rogerpadilla/uql/compare/@uql/core@3.13.0...@uql/core@3.13.1) (2026-03-07)
|
|
12
7
|
|
|
13
8
|
|
|
14
9
|
### Features
|
|
15
10
|
|
|
16
|
-
*
|
|
11
|
+
* refactor `QueryRaw` to a class, add JSON `$merge`/`$unset` operators, and enable JSON dot-notation sorting. ([3f6f31a](https://github.com/rogerpadilla/uql/commit/3f6f31a9f3f2f9fcc038d4974121df2d0f8e6260))
|
|
17
12
|
|
|
18
13
|
|
|
19
14
|
|
|
@@ -25,6 +20,39 @@ All notable changes to this project will be documented in this file. Please add
|
|
|
25
20
|
|
|
26
21
|
date format is [yyyy-mm-dd]
|
|
27
22
|
|
|
23
|
+
## [3.13.1] - 2026-03-07
|
|
24
|
+
### Type Safety
|
|
25
|
+
- **Fully Typed Querier Returns**: Remaining querier methods now return proper types instead of `unknown`, enabling IDE autocompletion and compile-time validation on query results for all methods.
|
|
26
|
+
- **Semantic `RawRow` Type**: Introduced `RawRow` as a reusable semantic alias for raw database result rows, replacing scattered `Record<string, unknown>` and `any` across queriers, introspection, and SQL utilities.
|
|
27
|
+
- **Typed MySQL Driver**: Replaced `any` in MySQL2 querier with proper `ResultSetHeader` type from the driver.
|
|
28
|
+
- **Smarter `$select` Validation**: Field and relation selections are now validated simultaneously, catching invalid property names at compile time.
|
|
29
|
+
- **Stricter Null Comparisons**: `null` is now only accepted in `$eq` and `$ne` operators — invalid comparisons like `$gt: null` are caught at compile time.
|
|
30
|
+
- **Typed `defaultValue`**: Entity field defaults are now type-checked instead of accepting `any`.
|
|
31
|
+
|
|
32
|
+
### API Surface & DX
|
|
33
|
+
- **Cleaner Querier Interfaces**: `ClientQuerier` and `UniversalQuerier` are now properly separated with documented contracts, preventing confusing type mismatches.
|
|
34
|
+
- **Reduced Public API**: Removed unused/redundant type exports (`QuerySearchOne`, `QueryConflictPathsMap`), making the API surface smaller and easier to navigate.
|
|
35
|
+
- **Improved JSDoc**: Added cross-references between related operators (`$not` root vs field) for better discoverability.
|
|
36
|
+
|
|
37
|
+
### Refactoring
|
|
38
|
+
- **DRY Relation Iteration**: Consolidated duplicated relation iteration logic into `forEachJoinableRelation`, eliminating ~35 duplicated lines.
|
|
39
|
+
- **DRY `compareJsonPath`**: Simplified from 6 parameters to 3, removing redundant internal calls.
|
|
40
|
+
- **DRY `extractInsertResult`**: Shared utility for INSERT result ID extraction across all RETURNING-based drivers (pg, neon, maria), eliminating duplicated logic.
|
|
41
|
+
- **Eliminated Type Casts**: Replaced `Record<string, unknown>` casts with proper type guards across the dialect layer.
|
|
42
|
+
- **Typo Fix**: Renamed `buldQueryWhereAsMap` → `buildQueryWhereAsMap`.
|
|
43
|
+
|
|
44
|
+
## [3.13.0] - 2026-03-07
|
|
45
|
+
### New Features
|
|
46
|
+
- **`QueryRaw` Class Refactoring**: Replaced the opaque type + type-guard pattern with a proper `class` using `Symbol`-keyed properties (`RAW_VALUE`, `RAW_ALIAS`). Enables `instanceof QueryRaw` checks, eliminates autocomplete pollution, and prevents accidental structural matches.
|
|
47
|
+
- **JSON `$merge`/`$unset` Operators**: Restored type-safe partial update of JSONB fields via `$merge` (shallow merge) and `$unset` (key removal) in `update()` payloads. Works across PostgreSQL (`||`/`-`), MySQL (`JSON_MERGE_PATCH`/`JSON_REMOVE`), and SQLite (`json_patch`/`json_remove`).
|
|
48
|
+
```ts
|
|
49
|
+
await querier.updateMany(Company, { $where: { id: 1 } }, {
|
|
50
|
+
kind: { $merge: { theme: 'dark' }, $unset: ['deprecated'] },
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
- **JSON Dot-Notation Sorting**: `$sort` now supports JSONB dot-notation paths (e.g. `{ 'kind.priority': 'desc' }`), sharing the `resolveJsonDotPath` helper with `$where` for DRY consistency.
|
|
54
|
+
|
|
55
|
+
|
|
28
56
|
## [3.12.1] - 2026-03-05
|
|
29
57
|
### Bug Fixes
|
|
30
58
|
- **Null-Safe JSONB `$ne`**: JSONB dot-notation `$ne` now uses null-safe operators (`IS DISTINCT FROM` on PostgreSQL, `IS NOT` on SQLite) so that absent keys (which return SQL `NULL`) are correctly included in results. Previously, `{ 'settings.isArchived': { $ne: true } }` would silently exclude rows where the key didn't exist.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IdKey, IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type } from '../../type/index.js';
|
|
1
|
+
import type { IdKey, IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type, UpdatePayload } from '../../type/index.js';
|
|
2
2
|
import type { ClientQuerier, RequestFindOptions, RequestOptions, RequestSuccessResponse } from '../type/index.js';
|
|
3
3
|
export declare class HttpQuerier implements ClientQuerier {
|
|
4
4
|
readonly basePath: string;
|
|
@@ -9,7 +9,7 @@ export declare class HttpQuerier implements ClientQuerier {
|
|
|
9
9
|
findManyAndCount<E>(entity: Type<E>, q: Query<E>, opts?: RequestFindOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
10
10
|
count<E>(entity: Type<E>, q: QuerySearch<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
11
11
|
insertOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<any>>;
|
|
12
|
-
updateOneById<E>(entity: Type<E>, id: IdValue<E>, payload: E
|
|
12
|
+
updateOneById<E>(entity: Type<E>, id: IdValue<E>, payload: UpdatePayload<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
13
13
|
saveOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<any>> | Promise<{
|
|
14
14
|
data: NonNullable<E[IdKey<E>]>;
|
|
15
15
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/querier/httpQuerier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"httpQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/querier/httpQuerier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,OAAO,EACP,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,aAAa,EACd,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAGlH,qBAAa,WAAY,YAAW,aAAa;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM;IAErC,WAAW,CAAC,CAAC,EACX,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAMjD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAMlH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,kBAAkB;IAUnE,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,kBAAkB;IAI3E,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc;IAMlE,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc;IAK/D,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc;IAKlG,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc;;;IAU7D,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,GAAE,YAAY,GAAG,cAAmB;IAM1F,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,GAAE,YAAY,GAAG,cAAmB;IAM1F,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;CAG/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpQuerier.js","sourceRoot":"","sources":["../../../src/browser/querier/httpQuerier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"httpQuerier.js","sourceRoot":"","sources":["../../../src/browser/querier/httpQuerier.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type,
|
|
1
|
+
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type, UpdatePayload } from '../../type/index.js';
|
|
2
2
|
import type { RequestOptions, RequestSuccessResponse } from './request.js';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Client-side querier — mirrors {@link UniversalQuerier} method names and semantics but with two structural differences:
|
|
5
|
+
* 1. Every return type is wrapped in `RequestSuccessResponse<T>` (adds `data`/`count` envelope).
|
|
6
|
+
* 2. Every method accepts an extra `opts?: RequestOptions` parameter.
|
|
7
|
+
*
|
|
8
|
+
* These differences prevent clean `extends UniversalQuerier` — TypeScript does not support
|
|
9
|
+
* higher-kinded type wrappers, so the interfaces are kept in sync by convention.
|
|
10
|
+
* @see UniversalQuerier for the server-side contract with direct return types.
|
|
11
|
+
*/
|
|
12
|
+
export interface ClientQuerier {
|
|
4
13
|
findOneById<E>(entity: Type<E>, id: IdValue<E>, q?: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E | undefined>>;
|
|
5
14
|
findOne<E>(entity: Type<E>, q: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E | undefined>>;
|
|
6
15
|
findMany<E>(entity: Type<E>, q: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
7
16
|
findManyAndCount<E>(entity: Type<E>, q: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
8
17
|
count<E>(entity: Type<E>, q?: QuerySearch<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
9
18
|
insertOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
10
|
-
updateOneById<E>(entity: Type<E>, id: IdValue<E>, payload: E
|
|
19
|
+
updateOneById<E>(entity: Type<E>, id: IdValue<E>, payload: UpdatePayload<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
11
20
|
saveOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
12
21
|
deleteOneById<E>(entity: Type<E>, id: IdValue<E>, opts?: QueryOptions & RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
13
22
|
deleteMany<E>(entity: Type<E>, qm: QuerySearch<E>, opts?: QueryOptions & RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/type/clientQuerier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"clientQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/type/clientQuerier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,CAAC,EACX,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAElD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAEnH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvG,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/G,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9G,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,UAAU,CAAC,CAAC,EACV,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntityMeta, type FieldKey, type FieldOptions, type Query, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelect, type QuerySelectOptions, type
|
|
1
|
+
import { type EntityMeta, type FieldKey, type FieldOptions, type JsonMergeOp, type Query, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelect, type QuerySelectOptions, type QuerySortMap, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereMap, type QueryWhereOptions, type RelationOptions, type SqlDialect, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
2
|
import { type CallbackKey } from '../util/index.js';
|
|
3
3
|
import { AbstractDialect } from './abstractDialect.js';
|
|
4
4
|
export declare abstract class AbstractSqlDialect extends AbstractDialect implements QueryDialect, SqlQueryDialect {
|
|
@@ -20,6 +20,11 @@ export declare abstract class AbstractSqlDialect extends AbstractDialect impleme
|
|
|
20
20
|
protected selectRelationJoins<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, opts?: {
|
|
21
21
|
prefix?: string;
|
|
22
22
|
}): void;
|
|
23
|
+
/**
|
|
24
|
+
* Iterates over joinable (11/m1) relations for a given select, resolving shared metadata.
|
|
25
|
+
* Used by both `selectRelationFields` and `selectRelationJoins` to avoid duplicated iteration logic.
|
|
26
|
+
*/
|
|
27
|
+
private forEachJoinableRelation;
|
|
23
28
|
where<E>(ctx: QueryContext, entity: Type<E>, where?: QueryWhere<E>, opts?: QueryWhereOptions): void;
|
|
24
29
|
compare<E>(ctx: QueryContext, entity: Type<E>, key: string, val: unknown, opts?: QueryComparisonOptions): void;
|
|
25
30
|
protected compareLogicalOperator<E>(ctx: QueryContext, entity: Type<E>, key: '$and' | '$or' | '$not' | '$nor', val: QueryWhereArray<E>, opts: QueryComparisonOptions): void;
|
|
@@ -31,12 +36,12 @@ export declare abstract class AbstractSqlDialect extends AbstractDialect impleme
|
|
|
31
36
|
*/
|
|
32
37
|
protected buildJsonFieldCondition(ctx: QueryContext, config: JsonFieldConfig, jsonPath: string, op: string, value: unknown): string;
|
|
33
38
|
getComparisonKey<E>(ctx: QueryContext, entity: Type<E>, key: FieldKey<E>, { prefix }?: QueryOptions): void;
|
|
34
|
-
sort<E>(ctx: QueryContext, entity: Type<E>, sort:
|
|
39
|
+
sort<E>(ctx: QueryContext, entity: Type<E>, sort: QuerySortMap<E> | undefined, { prefix }: QueryOptions): void;
|
|
35
40
|
pager(ctx: QueryContext, opts: QueryPager): void;
|
|
36
41
|
count<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
|
|
37
42
|
find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
|
|
38
43
|
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
39
|
-
update<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, payload: E
|
|
44
|
+
update<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, payload: UpdatePayload<E>, opts?: QueryOptions): void;
|
|
40
45
|
upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[]): void;
|
|
41
46
|
protected getUpsertUpdateAssignments<E>(ctx: QueryContext, meta: EntityMeta<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[], callback?: (columnName: string) => string): string;
|
|
42
47
|
protected getUpsertConflictPathsStr<E>(meta: EntityMeta<E>, conflictPaths: QueryConflictPaths<E>): string;
|
|
@@ -45,15 +50,43 @@ export declare abstract class AbstractSqlDialect extends AbstractDialect impleme
|
|
|
45
50
|
protected getPersistables<E>(ctx: QueryContext, meta: EntityMeta<E>, payload: E | E[], callbackKey: CallbackKey): Record<string, unknown>[];
|
|
46
51
|
protected getPersistable<E>(ctx: QueryContext, meta: EntityMeta<E>, payload: E, callbackKey: CallbackKey): Record<string, unknown>;
|
|
47
52
|
protected formatPersistableValue<E>(ctx: QueryContext, field: FieldOptions | undefined, value: unknown): void;
|
|
53
|
+
/**
|
|
54
|
+
* Generate SQL for a JSONB merge and/or unset operation.
|
|
55
|
+
* Called from `update()` when a field value has `$merge` and/or `$unset` operators.
|
|
56
|
+
* Generates the full `"col" = <expression>` assignment.
|
|
57
|
+
*
|
|
58
|
+
* Base implementation uses MySQL-compatible syntax. Override in dialect subclasses.
|
|
59
|
+
*/
|
|
60
|
+
protected formatJsonMerge<E>(ctx: QueryContext, escapedCol: string, value: JsonMergeOp<E>): void;
|
|
61
|
+
/**
|
|
62
|
+
* Checks if a value is a `$merge`/`$unset` operator object.
|
|
63
|
+
*/
|
|
64
|
+
protected isJsonMergeOp(value: unknown): value is JsonMergeOp;
|
|
65
|
+
/** Escapes a JSON key for safe interpolation into SQL string literals. */
|
|
66
|
+
protected escapeJsonKey(key: string): string;
|
|
48
67
|
getRawValue(ctx: QueryContext, opts: QueryRawFnOptions & {
|
|
49
68
|
value: QueryRaw;
|
|
50
69
|
autoPrefixAlias?: boolean;
|
|
51
70
|
}): void;
|
|
71
|
+
/**
|
|
72
|
+
* Resolves a dot-notation key to its JSON field metadata.
|
|
73
|
+
* Shared by `where()` and `sort()` to detect 'column.path' keys where 'column' is a JSON/JSONB field.
|
|
74
|
+
*
|
|
75
|
+
* @returns resolved metadata or `undefined` if the key is not a JSON dot-notation path
|
|
76
|
+
*/
|
|
77
|
+
protected resolveJsonDotPath<E>(meta: EntityMeta<E>, key: string, prefix?: string): {
|
|
78
|
+
root: string;
|
|
79
|
+
jsonPath: string;
|
|
80
|
+
config: JsonFieldConfig;
|
|
81
|
+
} | undefined;
|
|
52
82
|
/**
|
|
53
83
|
* Compare a JSONB dot-notation path, e.g. `'settings.isArchived': { $ne: true }`.
|
|
54
|
-
*
|
|
84
|
+
* Receives a pre-resolved `resolveJsonDotPath` result to avoid redundant computation.
|
|
55
85
|
*/
|
|
56
|
-
protected compareJsonPath
|
|
86
|
+
protected compareJsonPath(ctx: QueryContext, resolved: {
|
|
87
|
+
jsonPath: string;
|
|
88
|
+
config: JsonFieldConfig;
|
|
89
|
+
}, val: unknown): void;
|
|
57
90
|
/**
|
|
58
91
|
* Returns a dialect-specific `JsonFieldConfig` for accessing a nested JSON path.
|
|
59
92
|
* Dialects should override this to provide their specific JSON accessor syntax.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstractSqlDialect.d.ts","sourceRoot":"","sources":["../../src/dialect/abstractSqlDialect.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"abstractSqlDialect.d.ts","sourceRoot":"","sources":["../../src/dialect/abstractSqlDialect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getMeta } from '../entity/index.js';
|
|
2
|
-
import { QueryRaw, } from '../type/index.js';
|
|
3
|
-
import {
|
|
2
|
+
import { QueryRaw, RAW_ALIAS, RAW_VALUE, } from '../type/index.js';
|
|
3
|
+
import { buildQueryWhereAsMap, buildSortMap, escapeSqlId, fillOnFields, filterFieldKeys, filterRelationKeys, flatObject, getFieldCallbackValue, getFieldKeys, getKeys, hasKeys, isJsonType, isSelectingRelations, raw, } from '../util/index.js';
|
|
4
4
|
import { AbstractDialect } from './abstractDialect.js';
|
|
5
5
|
import { SqlQueryContext } from './queryContext.js';
|
|
6
6
|
export class AbstractSqlDialect extends AbstractDialect {
|
|
@@ -87,7 +87,7 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
87
87
|
const columnName = this.resolveColumnName(key, field);
|
|
88
88
|
if (field.virtual) {
|
|
89
89
|
this.getRawValue(ctx, {
|
|
90
|
-
value: raw(field.virtual
|
|
90
|
+
value: raw(field.virtual[RAW_VALUE], key),
|
|
91
91
|
prefix: opts.prefix,
|
|
92
92
|
escapedPrefix,
|
|
93
93
|
autoPrefixAlias: opts.autoPrefixAlias,
|
|
@@ -118,76 +118,19 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
118
118
|
this.selectRelationJoins(ctx, entity, select, { prefix });
|
|
119
119
|
}
|
|
120
120
|
selectRelationFields(ctx, entity, select, opts = {}) {
|
|
121
|
-
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
const meta = getMeta(entity);
|
|
125
|
-
const tableName = this.resolveTableName(entity, meta);
|
|
126
|
-
const relKeys = filterRelationKeys(meta, select);
|
|
127
|
-
const isSelectArray = Array.isArray(select);
|
|
128
|
-
const prefix = opts.prefix;
|
|
129
|
-
for (const relKey of relKeys) {
|
|
130
|
-
const relOpts = meta.relations[relKey];
|
|
131
|
-
if (!relOpts)
|
|
132
|
-
continue;
|
|
133
|
-
if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const isFirstLevel = prefix === tableName;
|
|
137
|
-
const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
|
|
138
|
-
if (!relOpts.entity)
|
|
139
|
-
continue;
|
|
140
|
-
const relEntity = relOpts.entity();
|
|
141
|
-
const relSelect = select[relKey];
|
|
142
|
-
const relQuery = isSelectArray
|
|
143
|
-
? {}
|
|
144
|
-
: Array.isArray(relSelect)
|
|
145
|
-
? { $select: relSelect }
|
|
146
|
-
: (relSelect ?? {});
|
|
121
|
+
this.forEachJoinableRelation(entity, select, opts, (relEntity, relQuery, joinRelAlias) => {
|
|
147
122
|
ctx.append(', ');
|
|
148
|
-
this.selectFields(ctx, relEntity, relQuery.$select, {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
// Recursively add nested relation fields
|
|
153
|
-
this.selectRelationFields(ctx, relEntity, relQuery.$select, {
|
|
154
|
-
prefix: joinRelAlias,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
123
|
+
this.selectFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias, autoPrefixAlias: true });
|
|
124
|
+
this.selectRelationFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias });
|
|
125
|
+
});
|
|
157
126
|
}
|
|
158
127
|
selectRelationJoins(ctx, entity, select, opts = {}) {
|
|
159
|
-
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const meta = getMeta(entity);
|
|
163
|
-
const tableName = this.resolveTableName(entity, meta);
|
|
164
|
-
const relKeys = filterRelationKeys(meta, select);
|
|
165
|
-
const isSelectArray = Array.isArray(select);
|
|
166
|
-
const prefix = opts.prefix;
|
|
167
|
-
for (const relKey of relKeys) {
|
|
168
|
-
const relOpts = meta.relations[relKey];
|
|
169
|
-
if (!relOpts)
|
|
170
|
-
continue;
|
|
171
|
-
if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
const isFirstLevel = prefix === tableName;
|
|
175
|
-
const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
|
|
176
|
-
if (!relOpts.entity)
|
|
177
|
-
continue;
|
|
178
|
-
const relEntity = relOpts.entity();
|
|
179
|
-
const relSelect = select[relKey];
|
|
180
|
-
const relQuery = isSelectArray
|
|
181
|
-
? {}
|
|
182
|
-
: Array.isArray(relSelect)
|
|
183
|
-
? { $select: relSelect }
|
|
184
|
-
: (relSelect ?? {});
|
|
128
|
+
this.forEachJoinableRelation(entity, select, opts, (relEntity, relQuery, joinRelAlias, relOpts, meta, tableName, required) => {
|
|
185
129
|
const relMeta = getMeta(relEntity);
|
|
186
130
|
const relTableName = this.resolveTableName(relEntity, relMeta);
|
|
187
131
|
const relEntityName = this.escapeId(relTableName);
|
|
188
|
-
const relPath = prefix ? this.escapeId(prefix, true) : this.escapeId(tableName);
|
|
189
|
-
const
|
|
190
|
-
const joinType = relQuery[required] ? 'INNER' : 'LEFT';
|
|
132
|
+
const relPath = opts.prefix ? this.escapeId(opts.prefix, true) : this.escapeId(tableName);
|
|
133
|
+
const joinType = required ? 'INNER' : 'LEFT';
|
|
191
134
|
const joinAlias = this.escapeId(joinRelAlias, true);
|
|
192
135
|
ctx.append(` ${joinType} JOIN ${relEntityName} ${joinAlias} ON `);
|
|
193
136
|
ctx.append((relOpts.references ?? [])
|
|
@@ -203,16 +146,47 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
203
146
|
ctx.append(' AND ');
|
|
204
147
|
this.where(ctx, relEntity, relQuery.$where, { prefix: joinRelAlias, clause: false });
|
|
205
148
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
149
|
+
this.selectRelationJoins(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias });
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Iterates over joinable (11/m1) relations for a given select, resolving shared metadata.
|
|
154
|
+
* Used by both `selectRelationFields` and `selectRelationJoins` to avoid duplicated iteration logic.
|
|
155
|
+
*/
|
|
156
|
+
forEachJoinableRelation(entity, select, opts, callback) {
|
|
157
|
+
if (Array.isArray(select))
|
|
158
|
+
return;
|
|
159
|
+
const meta = getMeta(entity);
|
|
160
|
+
const tableName = this.resolveTableName(entity, meta);
|
|
161
|
+
const relKeys = filterRelationKeys(meta, select);
|
|
162
|
+
const prefix = opts.prefix;
|
|
163
|
+
for (const relKey of relKeys) {
|
|
164
|
+
const relOpts = meta.relations[relKey];
|
|
165
|
+
if (!relOpts || relOpts.cardinality === '1m' || relOpts.cardinality === 'mm' || !relOpts.entity)
|
|
166
|
+
continue;
|
|
167
|
+
const isFirstLevel = prefix === tableName;
|
|
168
|
+
const joinRelAlias = isFirstLevel ? relKey : prefix ? `${prefix}.${relKey}` : relKey;
|
|
169
|
+
const relEntity = relOpts.entity();
|
|
170
|
+
const relSelect = select?.[relKey];
|
|
171
|
+
let relQuery;
|
|
172
|
+
let required = false;
|
|
173
|
+
if (isRelationSelectQuery(relSelect)) {
|
|
174
|
+
relQuery = relSelect;
|
|
175
|
+
required = relSelect.$required === true;
|
|
176
|
+
}
|
|
177
|
+
else if (Array.isArray(relSelect)) {
|
|
178
|
+
relQuery = { $select: relSelect };
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
relQuery = {};
|
|
182
|
+
}
|
|
183
|
+
callback(relEntity, relQuery, joinRelAlias, relOpts, meta, tableName, required);
|
|
210
184
|
}
|
|
211
185
|
}
|
|
212
186
|
where(ctx, entity, where = {}, opts = {}) {
|
|
213
187
|
const meta = getMeta(entity);
|
|
214
188
|
const { usePrecedence, clause = 'WHERE', softDelete } = opts;
|
|
215
|
-
where =
|
|
189
|
+
where = buildQueryWhereAsMap(meta, where);
|
|
216
190
|
if (meta.softDelete &&
|
|
217
191
|
(softDelete || softDelete === undefined) &&
|
|
218
192
|
!where[meta.softDelete]) {
|
|
@@ -283,14 +257,10 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
283
257
|
}
|
|
284
258
|
// Detect JSONB dot-notation: 'column.path' where column is a registered JSON/JSONB field
|
|
285
259
|
const keyStr = key;
|
|
286
|
-
const
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (field && isJsonType(field.type)) {
|
|
291
|
-
this.compareJsonPath(ctx, entity, root, keyStr.slice(dotIndex + 1), val, opts);
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
260
|
+
const jsonDot = this.resolveJsonDotPath(meta, keyStr, opts.prefix);
|
|
261
|
+
if (jsonDot) {
|
|
262
|
+
this.compareJsonPath(ctx, jsonDot, val);
|
|
263
|
+
return;
|
|
294
264
|
}
|
|
295
265
|
// Detect relation filtering: key is a known relation with 'mm' or '1m' cardinality
|
|
296
266
|
const rel = meta.relations[keyStr];
|
|
@@ -584,9 +554,15 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
584
554
|
if (index > 0) {
|
|
585
555
|
ctx.append(', ');
|
|
586
556
|
}
|
|
557
|
+
const direction = directionMap[sort];
|
|
558
|
+
// Detect JSONB dot-notation: 'column.path'
|
|
559
|
+
const jsonDot = this.resolveJsonDotPath(meta, key);
|
|
560
|
+
if (jsonDot) {
|
|
561
|
+
ctx.append(jsonDot.config.fieldAccessor(jsonDot.jsonPath) + direction);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
587
564
|
const field = meta.fields[key];
|
|
588
565
|
const name = this.resolveColumnName(key, field);
|
|
589
|
-
const direction = directionMap[sort];
|
|
590
566
|
ctx.append(this.escapeId(name) + direction);
|
|
591
567
|
});
|
|
592
568
|
}
|
|
@@ -644,8 +620,15 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
644
620
|
}
|
|
645
621
|
const field = meta.fields[key];
|
|
646
622
|
const columnName = this.resolveColumnName(key, field);
|
|
647
|
-
|
|
648
|
-
|
|
623
|
+
const escapedCol = this.escapeId(columnName);
|
|
624
|
+
const value = filledPayload[key];
|
|
625
|
+
if (this.isJsonMergeOp(value)) {
|
|
626
|
+
this.formatJsonMerge(ctx, escapedCol, value);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
ctx.append(`${escapedCol} = `);
|
|
630
|
+
this.formatPersistableValue(ctx, field, value);
|
|
631
|
+
}
|
|
649
632
|
});
|
|
650
633
|
this.search(ctx, entity, q, opts);
|
|
651
634
|
}
|
|
@@ -753,10 +736,41 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
753
736
|
}
|
|
754
737
|
ctx.addValue(value);
|
|
755
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Generate SQL for a JSONB merge and/or unset operation.
|
|
741
|
+
* Called from `update()` when a field value has `$merge` and/or `$unset` operators.
|
|
742
|
+
* Generates the full `"col" = <expression>` assignment.
|
|
743
|
+
*
|
|
744
|
+
* Base implementation uses MySQL-compatible syntax. Override in dialect subclasses.
|
|
745
|
+
*/
|
|
746
|
+
formatJsonMerge(ctx, escapedCol, value) {
|
|
747
|
+
let expr = escapedCol;
|
|
748
|
+
if (hasKeys(value.$merge)) {
|
|
749
|
+
expr = `JSON_MERGE_PATCH(COALESCE(${escapedCol}, '{}'), ?)`;
|
|
750
|
+
ctx.pushValue(JSON.stringify(value.$merge));
|
|
751
|
+
}
|
|
752
|
+
if (value.$unset?.length) {
|
|
753
|
+
for (const key of value.$unset) {
|
|
754
|
+
expr = `JSON_REMOVE(${expr}, '$.${this.escapeJsonKey(key)}')`;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
ctx.append(`${escapedCol} = ${expr}`);
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Checks if a value is a `$merge`/`$unset` operator object.
|
|
761
|
+
*/
|
|
762
|
+
isJsonMergeOp(value) {
|
|
763
|
+
return typeof value === 'object' && value !== null && ('$merge' in value || '$unset' in value);
|
|
764
|
+
}
|
|
765
|
+
/** Escapes a JSON key for safe interpolation into SQL string literals. */
|
|
766
|
+
escapeJsonKey(key) {
|
|
767
|
+
return key.replace(/'/g, "''");
|
|
768
|
+
}
|
|
756
769
|
getRawValue(ctx, opts) {
|
|
757
770
|
const { value, prefix = '', escapedPrefix, autoPrefixAlias } = opts;
|
|
758
|
-
|
|
759
|
-
|
|
771
|
+
const rawValue = value[RAW_VALUE];
|
|
772
|
+
if (typeof rawValue === 'function') {
|
|
773
|
+
const res = rawValue({
|
|
760
774
|
...opts,
|
|
761
775
|
ctx,
|
|
762
776
|
dialect: this,
|
|
@@ -768,9 +782,9 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
768
782
|
}
|
|
769
783
|
}
|
|
770
784
|
else {
|
|
771
|
-
ctx.append(prefix + String(
|
|
785
|
+
ctx.append(prefix + String(rawValue));
|
|
772
786
|
}
|
|
773
|
-
const alias = value
|
|
787
|
+
const alias = value[RAW_ALIAS];
|
|
774
788
|
if (alias) {
|
|
775
789
|
const fullAlias = autoPrefixAlias ? prefix + alias : alias;
|
|
776
790
|
// Replace dots with underscores for alias to avoid syntax errors
|
|
@@ -780,15 +794,33 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
780
794
|
}
|
|
781
795
|
}
|
|
782
796
|
/**
|
|
783
|
-
*
|
|
784
|
-
*
|
|
797
|
+
* Resolves a dot-notation key to its JSON field metadata.
|
|
798
|
+
* Shared by `where()` and `sort()` to detect 'column.path' keys where 'column' is a JSON/JSONB field.
|
|
799
|
+
*
|
|
800
|
+
* @returns resolved metadata or `undefined` if the key is not a JSON dot-notation path
|
|
785
801
|
*/
|
|
786
|
-
|
|
787
|
-
const
|
|
802
|
+
resolveJsonDotPath(meta, key, prefix) {
|
|
803
|
+
const dotIndex = key.indexOf('.');
|
|
804
|
+
if (dotIndex <= 0) {
|
|
805
|
+
return undefined;
|
|
806
|
+
}
|
|
807
|
+
const root = key.slice(0, dotIndex);
|
|
788
808
|
const field = meta.fields[root];
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
809
|
+
if (!field || !isJsonType(field.type)) {
|
|
810
|
+
return undefined;
|
|
811
|
+
}
|
|
812
|
+
const jsonPath = key.slice(dotIndex + 1);
|
|
813
|
+
const colName = this.resolveColumnName(root, field);
|
|
814
|
+
const escapedCol = (prefix ? this.escapeId(prefix, true, true) : '') + this.escapeId(colName);
|
|
815
|
+
const config = this.getJsonFieldConfig(escapedCol, jsonPath);
|
|
816
|
+
return { root, jsonPath, config };
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Compare a JSONB dot-notation path, e.g. `'settings.isArchived': { $ne: true }`.
|
|
820
|
+
* Receives a pre-resolved `resolveJsonDotPath` result to avoid redundant computation.
|
|
821
|
+
*/
|
|
822
|
+
compareJsonPath(ctx, resolved, val) {
|
|
823
|
+
const { jsonPath, config } = resolved;
|
|
792
824
|
const value = this.normalizeWhereValue(val);
|
|
793
825
|
const operators = getKeys(value);
|
|
794
826
|
if (operators.length > 1) {
|
|
@@ -811,7 +843,18 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
811
843
|
* @param jsonPath - The dot-separated path within the JSON field (e.g. 'isArchived' or 'theme.color')
|
|
812
844
|
*/
|
|
813
845
|
getJsonFieldConfig(escapedColumn, jsonPath) {
|
|
814
|
-
return {
|
|
846
|
+
return {
|
|
847
|
+
...this.getBaseJsonConfig(),
|
|
848
|
+
fieldAccessor: () => {
|
|
849
|
+
const segments = jsonPath.split('.');
|
|
850
|
+
let expr = escapedColumn;
|
|
851
|
+
for (let i = 0; i < segments.length; i++) {
|
|
852
|
+
const op = i === segments.length - 1 ? '->>' : '->';
|
|
853
|
+
expr = `(${expr}${op}'${this.escapeJsonKey(segments[i])}')`;
|
|
854
|
+
}
|
|
855
|
+
return expr;
|
|
856
|
+
},
|
|
857
|
+
};
|
|
815
858
|
}
|
|
816
859
|
/**
|
|
817
860
|
* Returns the dialect-invariant portion of `JsonFieldConfig`.
|
|
@@ -891,4 +934,10 @@ export class AbstractSqlDialect extends AbstractDialect {
|
|
|
891
934
|
ctx.append(')');
|
|
892
935
|
}
|
|
893
936
|
}
|
|
937
|
+
/**
|
|
938
|
+
* Type guard: narrows a relation select value to a query object (with optional `$required`).
|
|
939
|
+
*/
|
|
940
|
+
function isRelationSelectQuery(val) {
|
|
941
|
+
return val !== null && typeof val === 'object' && !Array.isArray(val);
|
|
942
|
+
}
|
|
894
943
|
//# sourceMappingURL=abstractSqlDialect.js.map
|