@snowtop/ent 0.2.7 → 0.2.9
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/action/executor.js +4 -4
- package/action/operations.js +3 -0
- package/action/orchestrator.js +10 -12
- package/action/topological_sort.d.ts +9 -0
- package/action/topological_sort.js +46 -0
- package/core/base.d.ts +11 -4
- package/core/clause.d.ts +3 -5
- package/core/clause.js +32 -0
- package/core/config.d.ts +26 -2
- package/core/config.js +7 -1
- package/core/context.js +5 -12
- package/core/db.d.ts +12 -2
- package/core/db.js +102 -7
- package/core/dev_schema.d.ts +9 -0
- package/core/dev_schema.js +306 -0
- package/core/ent.d.ts +3 -5
- package/core/ent.js +22 -7
- package/core/extensions.d.ts +25 -0
- package/core/extensions.js +220 -0
- package/core/loaders/assoc_count_loader.js +2 -5
- package/core/loaders/assoc_edge_loader.js +5 -8
- package/core/loaders/loader.js +1 -1
- package/core/loaders/object_loader.js +3 -6
- package/core/loaders/query_loader.d.ts +2 -5
- package/core/loaders/query_loader.js +11 -10
- package/core/memoize.d.ts +1 -0
- package/core/memoize.js +15 -0
- package/core/query/custom_clause_query.js +5 -1
- package/core/query/query.d.ts +1 -1
- package/core/query/query.js +10 -7
- package/core/query_expression.d.ts +6 -0
- package/core/query_expression.js +2 -0
- package/core/query_impl.d.ts +19 -3
- package/core/query_impl.js +148 -35
- package/index.d.ts +5 -1
- package/index.js +9 -2
- package/package.json +1 -7
- package/parse_schema/parse.d.ts +2 -12
- package/parse_schema/parse.js +22 -41
- package/schema/index.d.ts +1 -1
- package/schema/schema.d.ts +20 -1
- package/scripts/custom_graphql.js +12 -5
- package/scripts/fix_action_exports.js +1 -1
- package/scripts/migrate_v0.1.js +2 -5
- package/scripts/move_types.js +1 -1
- package/scripts/parse_args.d.ts +3 -0
- package/scripts/parse_args.js +74 -0
- package/scripts/read_schema.js +2 -5
- package/testutils/builder.js +1 -2
- package/testutils/parse_sql.js +1 -1
- package/tsc/compilerOptions.d.ts +2 -2
- package/tsc/compilerOptions.js +12 -18
- package/tsc/move_generated.js +2 -2
- package/tsc/transform.d.ts +1 -1
- package/tsc/transform.js +16 -2
- package/tsc/transform_action.d.ts +1 -1
- package/tsc/transform_action.js +1 -1
- package/tsc/transform_ent.d.ts +1 -1
- package/tsc/transform_ent.js +1 -1
- package/tsc/transform_schema.d.ts +1 -1
- package/tsc/transform_schema.js +2 -2
|
@@ -32,15 +32,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.AssocEdgeLoaderFactory = exports.AssocDirectEdgeLoader = exports.AssocEdgeLoader = void 0;
|
|
40
|
-
const memoizee_1 = __importDefault(require("memoizee"));
|
|
41
37
|
const clause = __importStar(require("../clause"));
|
|
42
38
|
const ent_1 = require("../ent");
|
|
43
|
-
const
|
|
39
|
+
const memoize_1 = require("../memoize");
|
|
40
|
+
const query_impl_1 = require("../query_impl");
|
|
44
41
|
const loader_1 = require("./loader");
|
|
45
42
|
function getDefaultOrderBy() {
|
|
46
43
|
return [
|
|
@@ -121,7 +118,7 @@ class AssocEdgeLoader {
|
|
|
121
118
|
this.edgeCtr = edgeCtr;
|
|
122
119
|
this.options = options;
|
|
123
120
|
this.context = context;
|
|
124
|
-
this.loaderFn = (0,
|
|
121
|
+
this.loaderFn = (0, memoize_1.memoizeNoArgs)(this.getLoader.bind(this));
|
|
125
122
|
}
|
|
126
123
|
async getLoader() {
|
|
127
124
|
const edgeData = await (0, ent_1.loadEdgeData)(this.edgeType);
|
|
@@ -167,7 +164,7 @@ class AssocDirectEdgeLoader {
|
|
|
167
164
|
this.options = options;
|
|
168
165
|
this.context = context;
|
|
169
166
|
if (this.context) {
|
|
170
|
-
this.loaderFn = (0,
|
|
167
|
+
this.loaderFn = (0, memoize_1.memoizeNoArgs)(this.getLoader.bind(this));
|
|
171
168
|
}
|
|
172
169
|
}
|
|
173
170
|
async getLoader() {
|
|
@@ -264,7 +261,7 @@ class AssocEdgeLoaderFactory {
|
|
|
264
261
|
return new AssocDirectEdgeLoader(this.edgeType, edgeCtr, options, context);
|
|
265
262
|
}
|
|
266
263
|
const effectiveOptions = getEffectiveOptions(options);
|
|
267
|
-
const key = `${this.name}:limit:${effectiveOptions.limit}:orderby:${(0,
|
|
264
|
+
const key = `${this.name}:limit:${effectiveOptions.limit}:orderby:${(0, query_impl_1.getOrderByKey)(effectiveOptions.orderby ?? getDefaultOrderBy())}:disableTransformations:${effectiveOptions.disableTransformations}`;
|
|
268
265
|
return (0, loader_1.getCustomLoader)(key, () => new AssocEdgeLoader(this.edgeType, ctr, effectiveOptions, context), context);
|
|
269
266
|
}
|
|
270
267
|
}
|
package/core/loaders/loader.js
CHANGED
|
@@ -195,7 +195,7 @@ class CacheMap {
|
|
|
195
195
|
// was designed for ObjectLoader time. Now we have different needs e.g. count, assoc etc
|
|
196
196
|
(0, logger_1.log)("cache", {
|
|
197
197
|
"dataloader-cache-hit": key,
|
|
198
|
-
|
|
198
|
+
tableName: this.options.tableName,
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
return ret;
|
|
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.ObjectLoaderFactory = exports.ObjectCountLoader = exports.ObjectLoader = exports.mapWithConcurrency = void 0;
|
|
40
37
|
exports.setClauseLoaderConcurrency = setClauseLoaderConcurrency;
|
|
@@ -45,7 +42,7 @@ const clause = __importStar(require("../clause"));
|
|
|
45
42
|
const logger_1 = require("../logger");
|
|
46
43
|
const clause_1 = require("../clause");
|
|
47
44
|
const loader_1 = require("./loader");
|
|
48
|
-
const
|
|
45
|
+
const memoize_1 = require("../memoize");
|
|
49
46
|
const DEFAULT_CLAUSE_LOADER_CONCURRENCY = 10;
|
|
50
47
|
let clauseLoaderConcurrency = DEFAULT_CLAUSE_LOADER_CONCURRENCY;
|
|
51
48
|
function setClauseLoaderConcurrency(limit) {
|
|
@@ -151,7 +148,7 @@ class clauseCacheMap {
|
|
|
151
148
|
if (ret) {
|
|
152
149
|
(0, logger_1.log)("cache", {
|
|
153
150
|
"dataloader-cache-hit": key2 + (this.count ? ":count" : ""),
|
|
154
|
-
|
|
151
|
+
tableName: this.options.tableName,
|
|
155
152
|
});
|
|
156
153
|
}
|
|
157
154
|
return ret;
|
|
@@ -205,7 +202,7 @@ class ObjectLoader {
|
|
|
205
202
|
this.idLoader = createDataLoader(options, context);
|
|
206
203
|
this.clauseLoader = createClauseDataLoder(options, context);
|
|
207
204
|
}
|
|
208
|
-
this.memoizedInitPrime = (0,
|
|
205
|
+
this.memoizedInitPrime = (0, memoize_1.memoizeNoArgs)(this.initPrime.bind(this));
|
|
209
206
|
}
|
|
210
207
|
getOptions() {
|
|
211
208
|
return this.options;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, Data, EdgeQueryableDataOptions, Loader, LoaderFactory } from "../base";
|
|
1
|
+
import { Context, Data, EdgeQueryableDataOptions, Loader, LoaderFactory, SelectBaseDataOptions } from "../base";
|
|
2
2
|
import * as clause from "../clause";
|
|
3
3
|
import { OrderBy } from "../query_impl";
|
|
4
4
|
import { ObjectLoaderFactory } from "./object_loader";
|
|
@@ -14,10 +14,7 @@ declare class QueryDirectLoader<K extends any> implements Loader<K, Data[]> {
|
|
|
14
14
|
clearAll(): void;
|
|
15
15
|
}
|
|
16
16
|
interface QueryOptions {
|
|
17
|
-
fields:
|
|
18
|
-
alias: string;
|
|
19
|
-
column: string;
|
|
20
|
-
})[];
|
|
17
|
+
fields: SelectBaseDataOptions["fields"];
|
|
21
18
|
tableName: string;
|
|
22
19
|
groupCol?: string;
|
|
23
20
|
clause?: clause.Clause;
|
|
@@ -32,15 +32,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.QueryLoaderFactory = void 0;
|
|
40
|
-
const memoizee_1 = __importDefault(require("memoizee"));
|
|
41
37
|
const clause = __importStar(require("../clause"));
|
|
42
38
|
const ent_1 = require("../ent");
|
|
43
|
-
const
|
|
39
|
+
const memoize_1 = require("../memoize");
|
|
40
|
+
const query_impl_1 = require("../query_impl");
|
|
44
41
|
const loader_1 = require("./loader");
|
|
45
42
|
function getOrderByLocal(options, queryOptions) {
|
|
46
43
|
return (options.orderby ??
|
|
@@ -105,6 +102,10 @@ function createLoader(options, queryOptions, context) {
|
|
|
105
102
|
m.set(keys[i], i);
|
|
106
103
|
}
|
|
107
104
|
const col = options.groupCol;
|
|
105
|
+
const effectiveOrderBy = getOrderByLocal(options, queryOptions);
|
|
106
|
+
if ((0, query_impl_1.orderByHasExpressions)(effectiveOrderBy)) {
|
|
107
|
+
throw new Error("grouped query loaders do not support computed order expressions");
|
|
108
|
+
}
|
|
108
109
|
let extraClause;
|
|
109
110
|
if (options.clause && queryOptions?.clause) {
|
|
110
111
|
extraClause = clause.And(options.clause, queryOptions.clause);
|
|
@@ -119,7 +120,7 @@ function createLoader(options, queryOptions, context) {
|
|
|
119
120
|
tableName: options.tableName,
|
|
120
121
|
fields: options.fields,
|
|
121
122
|
values: keys,
|
|
122
|
-
orderby:
|
|
123
|
+
orderby: effectiveOrderBy,
|
|
123
124
|
limit: queryOptions?.limit || (0, ent_1.getDefaultLimit)(),
|
|
124
125
|
groupColumn: col,
|
|
125
126
|
clause: extraClause,
|
|
@@ -142,7 +143,7 @@ class QueryDirectLoader {
|
|
|
142
143
|
this.options = options;
|
|
143
144
|
this.queryOptions = queryOptions;
|
|
144
145
|
this.context = context;
|
|
145
|
-
this.memoizedInitPrime = (0,
|
|
146
|
+
this.memoizedInitPrime = (0, memoize_1.memoizeNoArgs)(this.initPrime.bind(this));
|
|
146
147
|
}
|
|
147
148
|
initPrime() {
|
|
148
149
|
if (!this.context || !this.options?.toPrime) {
|
|
@@ -187,7 +188,7 @@ class QueryLoader {
|
|
|
187
188
|
if (context) {
|
|
188
189
|
this.loader = createLoader(options, queryOptions, context);
|
|
189
190
|
}
|
|
190
|
-
this.memoizedInitPrime = (0,
|
|
191
|
+
this.memoizedInitPrime = (0, memoize_1.memoizeNoArgs)(this.initPrime.bind(this));
|
|
191
192
|
}
|
|
192
193
|
initPrime() {
|
|
193
194
|
if (!this.context || !this.options?.toPrime) {
|
|
@@ -259,7 +260,7 @@ class QueryLoaderFactory {
|
|
|
259
260
|
? `baseClause:${queryOptions.clause.instanceKey()}`
|
|
260
261
|
: undefined,
|
|
261
262
|
`limit:${effectiveLimit}`,
|
|
262
|
-
`orderby:${(0,
|
|
263
|
+
`orderby:${(0, query_impl_1.getOrderByKey)(effectiveOrderBy)}`,
|
|
263
264
|
`disableTransformations:${disableTransformations}`,
|
|
264
265
|
];
|
|
265
266
|
const key = keyParts
|
|
@@ -270,7 +271,7 @@ class QueryLoaderFactory {
|
|
|
270
271
|
const effectiveOrderBy = getOrderByLocal(queryOptions, options);
|
|
271
272
|
const effectiveLimit = options.limit || (0, ent_1.getDefaultLimit)();
|
|
272
273
|
const disableTransformations = options.disableTransformations ?? false;
|
|
273
|
-
const key = `${name}:limit:${effectiveLimit}:orderby:${(0,
|
|
274
|
+
const key = `${name}:limit:${effectiveLimit}:orderby:${(0, query_impl_1.getOrderByKey)(effectiveOrderBy)}:disableTransformations:${disableTransformations}`;
|
|
274
275
|
return (0, loader_1.getCustomLoader)(key, () => new QueryLoader(queryOptions, context, options), context);
|
|
275
276
|
}
|
|
276
277
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function memoizeNoArgs<T>(fn: () => T): () => T;
|
package/core/memoize.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memoizeNoArgs = memoizeNoArgs;
|
|
4
|
+
function memoizeNoArgs(fn) {
|
|
5
|
+
let called = false;
|
|
6
|
+
let value;
|
|
7
|
+
return () => {
|
|
8
|
+
if (called) {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
value = fn();
|
|
12
|
+
called = true;
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -81,7 +81,11 @@ class CustomClauseQuery extends query_1.BaseEdgeQuery {
|
|
|
81
81
|
const alias = this.options.loadEntOptions.fieldsAlias ??
|
|
82
82
|
this.options.loadEntOptions.alias;
|
|
83
83
|
const fieldString = typeof firstRequestedField === "object"
|
|
84
|
-
?
|
|
84
|
+
? "expression" in firstRequestedField
|
|
85
|
+
? (() => {
|
|
86
|
+
throw new Error("join-backed raw counts do not support computed select expressions");
|
|
87
|
+
})()
|
|
88
|
+
: `${firstRequestedField.alias}.${firstRequestedField.column}`
|
|
85
89
|
: alias
|
|
86
90
|
? `${alias}.${firstRequestedField}`
|
|
87
91
|
: firstRequestedField;
|
package/core/query/query.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
|
|
|
84
84
|
protected genIDInfosToFetchImpl(): Promise<IDInfo[]>;
|
|
85
85
|
private _defaultEdgeQueryableOptions;
|
|
86
86
|
protected configureEdgeQueryableDataOptions(opts: EdgeQueryableDataOptionsConfigureLoader): void;
|
|
87
|
-
protected getDefaultEdgeQueryOptions(): Partial<Pick<QueryableDataOptions, "
|
|
87
|
+
protected getDefaultEdgeQueryOptions(): Partial<Pick<QueryableDataOptions, "limit" | "orderby" | "clause" | "disableTransformations">> | undefined;
|
|
88
88
|
private loadEdges;
|
|
89
89
|
getCursor(row: TEdge): string;
|
|
90
90
|
}
|
package/core/query/query.js
CHANGED
|
@@ -32,16 +32,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.BaseEdgeQuery = void 0;
|
|
40
|
-
const memoizee_1 = __importDefault(require("memoizee"));
|
|
41
37
|
const types_1 = require("util/types");
|
|
42
38
|
const clause = __importStar(require("../clause"));
|
|
43
39
|
const ent_1 = require("../ent");
|
|
44
40
|
const privacy_1 = require("../privacy");
|
|
41
|
+
const memoize_1 = require("../memoize");
|
|
45
42
|
const query_impl_1 = require("../query_impl");
|
|
46
43
|
// TODO can we generalize EdgeQuery to support any clause
|
|
47
44
|
function assertPositive(n) {
|
|
@@ -51,7 +48,7 @@ function assertPositive(n) {
|
|
|
51
48
|
}
|
|
52
49
|
function translateCursorToKeyValues(cursor, opts) {
|
|
53
50
|
const { keys } = opts;
|
|
54
|
-
const decoded =
|
|
51
|
+
const decoded = (0, ent_1.decodeCursorPayload)(cursor);
|
|
55
52
|
let cursorData = [];
|
|
56
53
|
try {
|
|
57
54
|
cursorData = JSON.parse(decoded);
|
|
@@ -149,6 +146,9 @@ class FirstFilter {
|
|
|
149
146
|
options.limit = this.options.limit + 1;
|
|
150
147
|
const orderBy = this.options.orderby;
|
|
151
148
|
if (this.offset) {
|
|
149
|
+
if ((0, query_impl_1.orderByHasExpressions)(orderBy)) {
|
|
150
|
+
throw new Error("cursor pagination does not support computed order expressions");
|
|
151
|
+
}
|
|
152
152
|
const keyValuePairs = {};
|
|
153
153
|
for (const [key, value] of this.cursorKeyValues) {
|
|
154
154
|
keyValuePairs[key] = value;
|
|
@@ -219,6 +219,9 @@ class LastFilter {
|
|
|
219
219
|
// we also sort cursor col in same direction. (direction doesn't matter)
|
|
220
220
|
const orderBy = (0, query_impl_1.reverseOrderBy)(this.options.orderby);
|
|
221
221
|
if (this.offset) {
|
|
222
|
+
if ((0, query_impl_1.orderByHasExpressions)(orderBy)) {
|
|
223
|
+
throw new Error("cursor pagination does not support computed order expressions");
|
|
224
|
+
}
|
|
222
225
|
const keyValuePairs = {};
|
|
223
226
|
for (const [key, value] of this.cursorKeyValues) {
|
|
224
227
|
keyValuePairs[key] = value;
|
|
@@ -316,8 +319,8 @@ class BaseEdgeQuery {
|
|
|
316
319
|
this.edgeQueryOptions = { ...options, orderby: orderBy };
|
|
317
320
|
this.cursorCol = options.cursorCol;
|
|
318
321
|
this.cursorKeys = orderBy.map((orderBy) => orderBy.column);
|
|
319
|
-
this.memoizedloadEdges = (0,
|
|
320
|
-
this.genIDInfosToFetch = (0,
|
|
322
|
+
this.memoizedloadEdges = (0, memoize_1.memoizeNoArgs)(this.loadEdges.bind(this));
|
|
323
|
+
this.genIDInfosToFetch = (0, memoize_1.memoizeNoArgs)(this.genIDInfosToFetchImpl.bind(this));
|
|
321
324
|
}
|
|
322
325
|
getCursorCol() {
|
|
323
326
|
return this.cursorCol;
|
package/core/query_impl.d.ts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { QueryableDataOptions } from "./base";
|
|
2
|
+
import { QueryExpression } from "./query_expression";
|
|
2
3
|
export interface OrderByOption {
|
|
3
4
|
column: string;
|
|
4
5
|
direction: "ASC" | "DESC";
|
|
5
6
|
alias?: string;
|
|
6
7
|
nullsPlacement?: "first" | "last";
|
|
8
|
+
expression?: QueryExpression;
|
|
7
9
|
}
|
|
8
10
|
export type OrderBy = OrderByOption[];
|
|
9
|
-
|
|
10
|
-
export declare function reverseOrderBy(orderby: OrderBy): OrderBy;
|
|
11
|
-
interface JoinInfo {
|
|
11
|
+
interface QueryFragmentInfo {
|
|
12
12
|
phrase: string;
|
|
13
|
+
values: any[];
|
|
14
|
+
logValues: any[];
|
|
13
15
|
valuesUsed: number;
|
|
14
16
|
}
|
|
17
|
+
export interface BuiltQueryData {
|
|
18
|
+
query: string;
|
|
19
|
+
values: any[];
|
|
20
|
+
logValues: any[];
|
|
21
|
+
}
|
|
22
|
+
export declare function getSelectFieldsKey(fields: QueryableDataOptions["fields"]): string;
|
|
23
|
+
export declare function getOrderByKey(orderby: OrderBy): string;
|
|
24
|
+
export declare function orderByHasExpressions(orderby?: OrderBy): boolean;
|
|
25
|
+
export declare function getOrderByInfo(orderby: OrderBy, alias?: string, clauseIdx?: number): QueryFragmentInfo;
|
|
26
|
+
export declare function getOrderByPhrase(orderby: OrderBy, alias?: string): string;
|
|
27
|
+
export declare function reverseOrderBy(orderby: OrderBy): OrderBy;
|
|
28
|
+
interface JoinInfo extends QueryFragmentInfo {
|
|
29
|
+
}
|
|
15
30
|
export declare function getJoinInfo(join: NonNullable<QueryableDataOptions["join"]>, clauseIdx?: number): JoinInfo;
|
|
31
|
+
export declare function buildQueryData(options: QueryableDataOptions): BuiltQueryData;
|
|
16
32
|
export declare function buildQuery(options: QueryableDataOptions): string;
|
|
17
33
|
export {};
|
package/core/query_impl.js
CHANGED
|
@@ -1,14 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSelectFieldsKey = getSelectFieldsKey;
|
|
4
|
+
exports.getOrderByKey = getOrderByKey;
|
|
5
|
+
exports.orderByHasExpressions = orderByHasExpressions;
|
|
6
|
+
exports.getOrderByInfo = getOrderByInfo;
|
|
3
7
|
exports.getOrderByPhrase = getOrderByPhrase;
|
|
4
8
|
exports.reverseOrderBy = reverseOrderBy;
|
|
5
9
|
exports.getJoinInfo = getJoinInfo;
|
|
10
|
+
exports.buildQueryData = buildQueryData;
|
|
6
11
|
exports.buildQuery = buildQuery;
|
|
7
|
-
|
|
12
|
+
const cache_utils_1 = require("./cache_utils");
|
|
13
|
+
function isExpressionField(field) {
|
|
14
|
+
return typeof field === "object" && "expression" in field;
|
|
15
|
+
}
|
|
16
|
+
function getCacheKeyForExpression(expression) {
|
|
17
|
+
return expression.instanceKey();
|
|
18
|
+
}
|
|
19
|
+
function getSelectFieldsKey(fields) {
|
|
20
|
+
return fields
|
|
21
|
+
.map((field) => {
|
|
22
|
+
if (typeof field === "string") {
|
|
23
|
+
return field;
|
|
24
|
+
}
|
|
25
|
+
if (isExpressionField(field)) {
|
|
26
|
+
return (0, cache_utils_1.stableStringify)({
|
|
27
|
+
alias: field.alias,
|
|
28
|
+
expression: getCacheKeyForExpression(field.expression),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return (0, cache_utils_1.stableStringify)({
|
|
32
|
+
alias: field.alias,
|
|
33
|
+
column: field.column,
|
|
34
|
+
});
|
|
35
|
+
})
|
|
36
|
+
.join(",");
|
|
37
|
+
}
|
|
38
|
+
function getOrderByKey(orderby) {
|
|
8
39
|
return orderby
|
|
9
|
-
.map((
|
|
40
|
+
.map((entry) => (0, cache_utils_1.stableStringify)({
|
|
41
|
+
column: entry.column,
|
|
42
|
+
direction: entry.direction,
|
|
43
|
+
alias: entry.alias,
|
|
44
|
+
nullsPlacement: entry.nullsPlacement,
|
|
45
|
+
expression: entry.expression
|
|
46
|
+
? getCacheKeyForExpression(entry.expression)
|
|
47
|
+
: undefined,
|
|
48
|
+
}))
|
|
49
|
+
.join("|");
|
|
50
|
+
}
|
|
51
|
+
function orderByHasExpressions(orderby) {
|
|
52
|
+
return orderby?.some((entry) => entry.expression !== undefined) ?? false;
|
|
53
|
+
}
|
|
54
|
+
function getFieldsInfo(fields, alias, disableFieldsAlias, clauseIdx = 1) {
|
|
55
|
+
let valuesUsed = 0;
|
|
56
|
+
const values = [];
|
|
57
|
+
const logValues = [];
|
|
58
|
+
const phrase = fields
|
|
59
|
+
.map((field) => {
|
|
60
|
+
if (typeof field === "string") {
|
|
61
|
+
if (alias && !disableFieldsAlias) {
|
|
62
|
+
return `${alias}.${field}`;
|
|
63
|
+
}
|
|
64
|
+
return field;
|
|
65
|
+
}
|
|
66
|
+
if (isExpressionField(field)) {
|
|
67
|
+
const expression = field.expression;
|
|
68
|
+
const rendered = expression.clause(clauseIdx + valuesUsed, disableFieldsAlias ? undefined : alias);
|
|
69
|
+
const expressionValues = expression.values();
|
|
70
|
+
valuesUsed += expressionValues.length;
|
|
71
|
+
values.push(...expressionValues);
|
|
72
|
+
logValues.push(...expression.logValues());
|
|
73
|
+
return `${rendered} AS ${field.alias}`;
|
|
74
|
+
}
|
|
75
|
+
if (!disableFieldsAlias) {
|
|
76
|
+
return `${field.alias}.${field.column}`;
|
|
77
|
+
}
|
|
78
|
+
return field.column;
|
|
79
|
+
})
|
|
80
|
+
.join(", ");
|
|
81
|
+
return {
|
|
82
|
+
phrase,
|
|
83
|
+
valuesUsed,
|
|
84
|
+
values,
|
|
85
|
+
logValues,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function getOrderByInfo(orderby, alias, clauseIdx = 1) {
|
|
89
|
+
let valuesUsed = 0;
|
|
90
|
+
const values = [];
|
|
91
|
+
const logValues = [];
|
|
92
|
+
const phrase = orderby
|
|
93
|
+
.map((entry) => {
|
|
10
94
|
let nullsPlacement = "";
|
|
11
|
-
switch (
|
|
95
|
+
switch (entry.nullsPlacement) {
|
|
12
96
|
case "first":
|
|
13
97
|
nullsPlacement = " NULLS FIRST";
|
|
14
98
|
break;
|
|
@@ -16,11 +100,28 @@ function getOrderByPhrase(orderby, alias) {
|
|
|
16
100
|
nullsPlacement = " NULLS LAST";
|
|
17
101
|
break;
|
|
18
102
|
}
|
|
19
|
-
const orderByAlias =
|
|
20
|
-
|
|
21
|
-
|
|
103
|
+
const orderByAlias = entry.alias ?? alias;
|
|
104
|
+
let col = orderByAlias ? `${orderByAlias}.${entry.column}` : entry.column;
|
|
105
|
+
if (entry.expression) {
|
|
106
|
+
const rendered = entry.expression.clause(clauseIdx + valuesUsed, orderByAlias);
|
|
107
|
+
const expressionValues = entry.expression.values();
|
|
108
|
+
valuesUsed += expressionValues.length;
|
|
109
|
+
values.push(...expressionValues);
|
|
110
|
+
logValues.push(...entry.expression.logValues());
|
|
111
|
+
col = rendered;
|
|
112
|
+
}
|
|
113
|
+
return `${col} ${entry.direction}${nullsPlacement}`;
|
|
22
114
|
})
|
|
23
115
|
.join(", ");
|
|
116
|
+
return {
|
|
117
|
+
phrase,
|
|
118
|
+
valuesUsed,
|
|
119
|
+
values,
|
|
120
|
+
logValues,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function getOrderByPhrase(orderby, alias) {
|
|
124
|
+
return getOrderByInfo(orderby, alias).phrase;
|
|
24
125
|
}
|
|
25
126
|
function reverseOrderBy(orderby) {
|
|
26
127
|
return orderby.map((o) => {
|
|
@@ -31,12 +132,18 @@ function reverseOrderBy(orderby) {
|
|
|
31
132
|
}
|
|
32
133
|
function getJoinInfo(join, clauseIdx = 1) {
|
|
33
134
|
let valuesUsed = 0;
|
|
34
|
-
const
|
|
135
|
+
const values = [];
|
|
136
|
+
const logValues = [];
|
|
137
|
+
const phrase = join
|
|
35
138
|
.map((join) => {
|
|
36
139
|
const joinTable = join.alias
|
|
37
140
|
? `${join.tableName} ${join.alias}`
|
|
38
141
|
: join.tableName;
|
|
39
|
-
|
|
142
|
+
const joinValues = join.clause.values();
|
|
143
|
+
const renderedClause = join.clause.clause(clauseIdx + valuesUsed);
|
|
144
|
+
valuesUsed += joinValues.length;
|
|
145
|
+
values.push(...joinValues);
|
|
146
|
+
logValues.push(...join.clause.logValues());
|
|
40
147
|
let joinType;
|
|
41
148
|
switch (join.type) {
|
|
42
149
|
case "left":
|
|
@@ -54,53 +161,52 @@ function getJoinInfo(join, clauseIdx = 1) {
|
|
|
54
161
|
default:
|
|
55
162
|
joinType = "JOIN";
|
|
56
163
|
}
|
|
57
|
-
return `${joinType} ${joinTable} ON ${
|
|
164
|
+
return `${joinType} ${joinTable} ON ${renderedClause}`;
|
|
58
165
|
})
|
|
59
166
|
.join(" ");
|
|
60
167
|
return {
|
|
61
|
-
phrase
|
|
168
|
+
phrase,
|
|
62
169
|
valuesUsed,
|
|
170
|
+
values,
|
|
171
|
+
logValues,
|
|
63
172
|
};
|
|
64
173
|
}
|
|
65
|
-
function
|
|
174
|
+
function buildQueryData(options) {
|
|
66
175
|
const fieldsAlias = options.fieldsAlias ?? options.alias;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return `${f.alias}.${f.column}`;
|
|
72
|
-
}
|
|
73
|
-
return f.column;
|
|
74
|
-
}
|
|
75
|
-
if (fieldsAlias && !options.disableFieldsAlias) {
|
|
76
|
-
return `${fieldsAlias}.${f}`;
|
|
77
|
-
}
|
|
78
|
-
return f;
|
|
79
|
-
})
|
|
80
|
-
.join(", ");
|
|
81
|
-
// always start at 1
|
|
176
|
+
const fieldInfo = getFieldsInfo(options.fields, fieldsAlias, options.disableFieldsAlias, 1);
|
|
177
|
+
const values = [...fieldInfo.values];
|
|
178
|
+
const logValues = [...fieldInfo.logValues];
|
|
179
|
+
let clauseIdx = 1 + fieldInfo.valuesUsed;
|
|
82
180
|
const parts = [];
|
|
83
181
|
const tableName = options.alias
|
|
84
182
|
? `${options.tableName} AS ${options.alias}`
|
|
85
183
|
: options.tableName;
|
|
86
184
|
if (options.distinct) {
|
|
87
|
-
parts.push(`SELECT DISTINCT ${
|
|
185
|
+
parts.push(`SELECT DISTINCT ${fieldInfo.phrase} FROM ${tableName}`);
|
|
88
186
|
}
|
|
89
187
|
else {
|
|
90
|
-
parts.push(`SELECT ${
|
|
188
|
+
parts.push(`SELECT ${fieldInfo.phrase} FROM ${tableName}`);
|
|
91
189
|
}
|
|
92
|
-
let whereStart = 1;
|
|
93
190
|
if (options.join) {
|
|
94
|
-
const
|
|
95
|
-
parts.push(phrase);
|
|
96
|
-
|
|
191
|
+
const joinInfo = getJoinInfo(options.join, clauseIdx);
|
|
192
|
+
parts.push(joinInfo.phrase);
|
|
193
|
+
values.push(...joinInfo.values);
|
|
194
|
+
logValues.push(...joinInfo.logValues);
|
|
195
|
+
clauseIdx += joinInfo.valuesUsed;
|
|
97
196
|
}
|
|
98
|
-
parts.push(`WHERE ${options.clause.clause(
|
|
197
|
+
parts.push(`WHERE ${options.clause.clause(clauseIdx, options.alias)}`);
|
|
198
|
+
values.push(...options.clause.values());
|
|
199
|
+
logValues.push(...options.clause.logValues());
|
|
200
|
+
clauseIdx += options.clause.values().length;
|
|
99
201
|
if (options.groupby) {
|
|
100
202
|
parts.push(`GROUP BY ${options.groupby}`);
|
|
101
203
|
}
|
|
102
204
|
if (options.orderby) {
|
|
103
|
-
|
|
205
|
+
const orderByInfo = getOrderByInfo(options.orderby, options.disableDefaultOrderByAlias ? undefined : fieldsAlias, clauseIdx);
|
|
206
|
+
parts.push(`ORDER BY ${orderByInfo.phrase}`);
|
|
207
|
+
values.push(...orderByInfo.values);
|
|
208
|
+
logValues.push(...orderByInfo.logValues);
|
|
209
|
+
clauseIdx += orderByInfo.valuesUsed;
|
|
104
210
|
}
|
|
105
211
|
if (options.limit !== undefined) {
|
|
106
212
|
parts.push(`LIMIT ${options.limit}`);
|
|
@@ -108,5 +214,12 @@ function buildQuery(options) {
|
|
|
108
214
|
if (options.offset !== undefined) {
|
|
109
215
|
parts.push(`OFFSET ${options.offset}`);
|
|
110
216
|
}
|
|
111
|
-
return
|
|
217
|
+
return {
|
|
218
|
+
query: parts.join(" "),
|
|
219
|
+
values,
|
|
220
|
+
logValues,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function buildQuery(options) {
|
|
224
|
+
return buildQueryData(options).query;
|
|
112
225
|
}
|
package/index.d.ts
CHANGED
|
@@ -2,15 +2,17 @@ export * from "./core/base";
|
|
|
2
2
|
export { loadEnt, loadCustomData, loadCustomEnts, loadCustomCount, loadEntX, loadEnts, CustomQuery, loadDerivedEnt, loadDerivedEntX, loadEntViaKey, loadEntXViaKey, performRawQuery, loadRowX, loadRow, loadRows, AssocEdge, AssocEdgeData, loadEdgeData, loadEdgeDatas, loadEdges, loadUniqueEdge, loadUniqueNode, loadRawEdgeCountX, loadEdgeForID2, loadNodesByEdge, getEdgeTypeInGroup, setEntLoaderPrivacyConcurrencyLimit, getEntLoaderPrivacyConcurrencyLimit, } from "./core/ent";
|
|
3
3
|
export { DataOperation, EditNodeOptions, EditNodeOperation, RawQueryOperation, EdgeOperation, DeleteNodeOperation, AssocEdgeInputOptions, AssocEdgeInput, } from "./action/operations";
|
|
4
4
|
export { setGlobalSchema } from "./core/global_schema";
|
|
5
|
+
export { registerExtensionRuntime } from "./core/extensions";
|
|
5
6
|
import DB from "./core/db";
|
|
6
7
|
export * from "./core/loaders";
|
|
7
8
|
export { DB };
|
|
8
9
|
export { EntPrivacyError, AlwaysAllowRule, AlwaysDenyRule, DenyIfLoggedInRule, DenyIfLoggedOutRule, AllowIfHasIdentity, AllowIfViewerRule, AllowIfFuncRule, AllowIfViewerIsRule, AllowIfViewerIsEntPropertyRule, AllowIfEntPropertyIsRule, DenyIfEntPropertyIsRule, AllowIfViewerEqualsRule, DenyIfViewerEqualsRule, AllowIfEdgeExistsRule, AllowIfViewerInboundEdgeExistsRule, AllowIfViewerOutboundEdgeExistsRule, DenyIfEdgeExistsRule, DenyIfViewerInboundEdgeExistsRule, DenyIfViewerOutboundEdgeExistsRule, DenyIfEdgeDoesNotExistRule, DenyIfViewerInboundEdgeDoesNotExistRule, DenyIfViewerOutboundEdgeDoesNotExistRule, AllowIfEntIsVisibleRule, AllowIfEntIsNotVisibleRule, DenyIfEntIsVisibleRule, DenyIfEntIsNotVisibleRule, AllowIfEntIsVisiblePolicy, DenyIfEntIsVisiblePolicy, DelayedResultRule, applyPrivacyPolicy, applyPrivacyPolicyX, AlwaysAllowPrivacyPolicy, AlwaysDenyPrivacyPolicy, AllowIfConditionAppliesRule, AllowIfSubPolicyAllowsRule, AllowIfViewerPrivacyPolicy, AllowIfViewerHasIdentityPrivacyPolicy, } from "./core/privacy";
|
|
9
10
|
export * from "./core/query";
|
|
10
11
|
export * from "./core/query_impl";
|
|
12
|
+
export type { QueryExpression } from "./core/query_expression";
|
|
11
13
|
export * from "./schema/";
|
|
12
14
|
import * as q from "./core/clause";
|
|
13
|
-
export { Clause } from "./core/clause";
|
|
15
|
+
export { Clause, Expression, ParameterizedExpression } from "./core/clause";
|
|
14
16
|
declare const query: {
|
|
15
17
|
Eq: typeof q.Eq;
|
|
16
18
|
NotEq: typeof q.NotEq;
|
|
@@ -50,6 +52,8 @@ declare const query: {
|
|
|
50
52
|
TsVectorPlainToTsQuery: typeof q.TsVectorPlainToTsQuery;
|
|
51
53
|
TsVectorPhraseToTsQuery: typeof q.TsVectorPhraseToTsQuery;
|
|
52
54
|
TsVectorWebsearchToTsQuery: typeof q.TsVectorWebsearchToTsQuery;
|
|
55
|
+
Expression: typeof q.Expression;
|
|
56
|
+
ParameterizedExpression: typeof q.ParameterizedExpression;
|
|
53
57
|
};
|
|
54
58
|
export { query };
|
|
55
59
|
export { RequestContext, ContextCache } from "./core/context";
|
package/index.js
CHANGED
|
@@ -39,8 +39,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
40
|
};
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.
|
|
43
|
-
exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = void 0;
|
|
42
|
+
exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.AllowIfFuncRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedOutRule = exports.DenyIfLoggedInRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = exports.DB = exports.registerExtensionRuntime = exports.setGlobalSchema = exports.DeleteNodeOperation = exports.EdgeOperation = exports.RawQueryOperation = exports.EditNodeOperation = exports.getEntLoaderPrivacyConcurrencyLimit = exports.setEntLoaderPrivacyConcurrencyLimit = exports.getEdgeTypeInGroup = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadEdges = exports.loadEdgeDatas = exports.loadEdgeData = exports.AssocEdgeData = exports.AssocEdge = exports.loadRows = exports.loadRow = exports.loadRowX = exports.performRawQuery = exports.loadEntXViaKey = exports.loadEntViaKey = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadEnts = exports.loadEntX = exports.loadCustomCount = exports.loadCustomEnts = exports.loadCustomData = exports.loadEnt = void 0;
|
|
43
|
+
exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.ParameterizedExpression = exports.Expression = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = void 0;
|
|
44
44
|
__exportStar(require("./core/base"), exports);
|
|
45
45
|
var ent_1 = require("./core/ent");
|
|
46
46
|
Object.defineProperty(exports, "loadEnt", { enumerable: true, get: function () { return ent_1.loadEnt; } });
|
|
@@ -79,6 +79,8 @@ Object.defineProperty(exports, "EdgeOperation", { enumerable: true, get: functio
|
|
|
79
79
|
Object.defineProperty(exports, "DeleteNodeOperation", { enumerable: true, get: function () { return operations_1.DeleteNodeOperation; } });
|
|
80
80
|
var global_schema_1 = require("./core/global_schema");
|
|
81
81
|
Object.defineProperty(exports, "setGlobalSchema", { enumerable: true, get: function () { return global_schema_1.setGlobalSchema; } });
|
|
82
|
+
var extensions_1 = require("./core/extensions");
|
|
83
|
+
Object.defineProperty(exports, "registerExtensionRuntime", { enumerable: true, get: function () { return extensions_1.registerExtensionRuntime; } });
|
|
82
84
|
const db_1 = __importDefault(require("./core/db"));
|
|
83
85
|
exports.DB = db_1.default;
|
|
84
86
|
__exportStar(require("./core/loaders"), exports);
|
|
@@ -126,6 +128,9 @@ __exportStar(require("./core/query"), exports);
|
|
|
126
128
|
__exportStar(require("./core/query_impl"), exports);
|
|
127
129
|
__exportStar(require("./schema/"), exports);
|
|
128
130
|
const q = __importStar(require("./core/clause"));
|
|
131
|
+
var clause_1 = require("./core/clause");
|
|
132
|
+
Object.defineProperty(exports, "Expression", { enumerable: true, get: function () { return clause_1.Expression; } });
|
|
133
|
+
Object.defineProperty(exports, "ParameterizedExpression", { enumerable: true, get: function () { return clause_1.ParameterizedExpression; } });
|
|
129
134
|
const query = {
|
|
130
135
|
Eq: q.Eq,
|
|
131
136
|
NotEq: q.NotEq,
|
|
@@ -165,6 +170,8 @@ const query = {
|
|
|
165
170
|
TsVectorPlainToTsQuery: q.TsVectorPlainToTsQuery,
|
|
166
171
|
TsVectorPhraseToTsQuery: q.TsVectorPhraseToTsQuery,
|
|
167
172
|
TsVectorWebsearchToTsQuery: q.TsVectorWebsearchToTsQuery,
|
|
173
|
+
Expression: q.Expression,
|
|
174
|
+
ParameterizedExpression: q.ParameterizedExpression,
|
|
168
175
|
};
|
|
169
176
|
exports.query = query;
|
|
170
177
|
var context_1 = require("./core/context");
|