@snowtop/ent 0.1.0-alpha1 → 0.1.0-alpha100
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/action.d.ts +38 -30
- package/action/action.js +22 -7
- package/action/executor.d.ts +4 -4
- package/action/executor.js +8 -3
- package/action/experimental_action.d.ts +32 -22
- package/action/experimental_action.js +35 -9
- package/action/index.d.ts +2 -0
- package/action/index.js +7 -1
- package/action/orchestrator.d.ts +48 -16
- package/action/orchestrator.js +343 -81
- package/action/privacy.d.ts +2 -2
- package/action/relative_value.d.ts +47 -0
- package/action/relative_value.js +125 -0
- package/action/transaction.d.ts +10 -0
- package/action/transaction.js +23 -0
- package/auth/auth.d.ts +1 -1
- package/core/base.d.ts +54 -27
- package/core/base.js +23 -1
- package/core/clause.d.ts +105 -3
- package/core/clause.js +563 -30
- package/core/config.d.ts +30 -1
- package/core/config.js +24 -1
- package/core/context.d.ts +5 -3
- package/core/context.js +20 -2
- package/core/convert.d.ts +1 -1
- package/core/date.js +1 -5
- package/core/db.d.ts +14 -11
- package/core/db.js +22 -8
- package/core/ent.d.ts +82 -28
- package/core/ent.js +692 -202
- package/core/loaders/assoc_count_loader.d.ts +3 -2
- package/core/loaders/assoc_count_loader.js +10 -2
- package/core/loaders/assoc_edge_loader.d.ts +3 -3
- package/core/loaders/assoc_edge_loader.js +13 -15
- package/core/loaders/index.d.ts +1 -1
- package/core/loaders/index.js +1 -3
- package/core/loaders/index_loader.d.ts +2 -2
- package/core/loaders/index_loader.js +1 -0
- package/core/loaders/loader.js +5 -5
- package/core/loaders/object_loader.d.ts +13 -7
- package/core/loaders/object_loader.js +95 -32
- package/core/loaders/query_loader.d.ts +6 -12
- package/core/loaders/query_loader.js +52 -11
- package/core/loaders/raw_count_loader.d.ts +2 -2
- package/core/loaders/raw_count_loader.js +5 -1
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +26 -25
- package/core/privacy.js +23 -24
- package/core/query/assoc_query.d.ts +7 -6
- package/core/query/assoc_query.js +9 -1
- package/core/query/custom_clause_query.d.ts +26 -0
- package/core/query/custom_clause_query.js +78 -0
- package/core/query/custom_query.d.ts +20 -5
- package/core/query/custom_query.js +87 -12
- package/core/query/index.d.ts +1 -0
- package/core/query/index.js +3 -1
- package/core/query/query.d.ts +8 -4
- package/core/query/query.js +101 -53
- package/core/query/shared_assoc_test.d.ts +2 -1
- package/core/query/shared_assoc_test.js +35 -45
- package/core/query/shared_test.d.ts +8 -1
- package/core/query/shared_test.js +469 -236
- package/core/viewer.d.ts +4 -3
- package/core/viewer.js +5 -1
- package/graphql/builtins/connection.js +3 -3
- package/graphql/builtins/edge.js +2 -2
- package/graphql/builtins/node.js +1 -1
- package/graphql/graphql.d.ts +17 -9
- package/graphql/graphql.js +47 -30
- package/graphql/index.d.ts +1 -1
- package/graphql/index.js +3 -4
- package/graphql/mutations/union.d.ts +2 -0
- package/graphql/mutations/union.js +35 -0
- package/graphql/node_resolver.d.ts +0 -1
- package/graphql/query/connection_type.d.ts +9 -9
- package/graphql/query/connection_type.js +6 -6
- package/graphql/query/edge_connection.d.ts +9 -9
- package/graphql/query/page_info.d.ts +1 -1
- package/graphql/query/page_info.js +4 -4
- package/graphql/query/shared_assoc_test.js +3 -3
- package/graphql/query/shared_edge_connection.js +1 -19
- package/graphql/scalars/time.d.ts +1 -1
- package/imports/index.d.ts +6 -1
- package/imports/index.js +19 -4
- package/index.d.ts +23 -1
- package/index.js +32 -6
- package/package.json +18 -17
- package/parse_schema/parse.d.ts +45 -8
- package/parse_schema/parse.js +193 -15
- package/schema/base_schema.d.ts +38 -1
- package/schema/base_schema.js +53 -2
- package/schema/field.d.ts +75 -21
- package/schema/field.js +185 -72
- package/schema/index.d.ts +4 -2
- package/schema/index.js +15 -2
- package/schema/json_field.d.ts +13 -1
- package/schema/json_field.js +28 -1
- package/schema/schema.d.ts +125 -10
- package/schema/schema.js +133 -5
- package/schema/struct_field.d.ts +27 -0
- package/schema/struct_field.js +138 -0
- package/schema/union_field.d.ts +23 -0
- package/schema/union_field.js +79 -0
- package/scripts/custom_compiler.js +10 -6
- package/scripts/custom_graphql.js +224 -36
- package/scripts/{transform_schema.d.ts → migrate_v0.1.d.ts} +0 -0
- package/scripts/migrate_v0.1.js +36 -0
- package/scripts/move_types.d.ts +1 -0
- package/scripts/move_types.js +117 -0
- package/scripts/read_schema.js +35 -6
- package/testutils/action/complex_schemas.d.ts +69 -0
- package/testutils/action/complex_schemas.js +398 -0
- package/testutils/builder.d.ts +52 -49
- package/testutils/builder.js +143 -44
- package/testutils/context/test_context.d.ts +2 -2
- package/testutils/context/test_context.js +7 -1
- package/testutils/db/fixture.d.ts +10 -0
- package/testutils/db/fixture.js +26 -0
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +26 -9
- package/testutils/db/{test_db.js → temp_db.js} +190 -46
- package/testutils/db/value.d.ts +7 -0
- package/testutils/db/value.js +251 -0
- package/testutils/db_mock.d.ts +16 -4
- package/testutils/db_mock.js +51 -6
- package/testutils/db_time_zone.d.ts +4 -0
- package/testutils/db_time_zone.js +41 -0
- package/testutils/ent-graphql-tests/index.d.ts +9 -1
- package/testutils/ent-graphql-tests/index.js +53 -25
- package/testutils/fake_data/const.d.ts +2 -1
- package/testutils/fake_data/const.js +3 -0
- package/testutils/fake_data/fake_contact.d.ts +10 -10
- package/testutils/fake_data/fake_contact.js +23 -21
- package/testutils/fake_data/fake_event.d.ts +8 -9
- package/testutils/fake_data/fake_event.js +25 -28
- package/testutils/fake_data/fake_tag.d.ts +36 -0
- package/testutils/fake_data/fake_tag.js +89 -0
- package/testutils/fake_data/fake_user.d.ts +10 -11
- package/testutils/fake_data/fake_user.js +20 -23
- package/testutils/fake_data/index.js +5 -1
- package/testutils/fake_data/internal.d.ts +2 -0
- package/testutils/fake_data/internal.js +7 -1
- package/testutils/fake_data/tag_query.d.ts +13 -0
- package/testutils/fake_data/tag_query.js +43 -0
- package/testutils/fake_data/test_helpers.d.ts +11 -4
- package/testutils/fake_data/test_helpers.js +29 -13
- package/testutils/fake_data/user_query.d.ts +13 -6
- package/testutils/fake_data/user_query.js +54 -22
- package/testutils/fake_log.d.ts +3 -3
- package/testutils/parse_sql.d.ts +6 -0
- package/testutils/parse_sql.js +16 -2
- package/testutils/test_edge_global_schema.d.ts +15 -0
- package/testutils/test_edge_global_schema.js +62 -0
- package/testutils/write.d.ts +2 -2
- package/testutils/write.js +33 -7
- package/tsc/ast.d.ts +44 -0
- package/tsc/ast.js +277 -0
- package/tsc/compilerOptions.d.ts +6 -0
- package/tsc/compilerOptions.js +45 -2
- package/tsc/move_generated.d.ts +1 -0
- package/tsc/move_generated.js +164 -0
- package/tsc/transform.d.ts +22 -0
- package/tsc/transform.js +181 -0
- package/tsc/transform_action.d.ts +22 -0
- package/tsc/transform_action.js +183 -0
- package/tsc/transform_ent.d.ts +17 -0
- package/tsc/transform_ent.js +59 -0
- package/tsc/transform_schema.d.ts +27 -0
- package/tsc/transform_schema.js +383 -0
- package/graphql/enums.d.ts +0 -3
- package/graphql/enums.js +0 -25
- package/scripts/transform_schema.js +0 -288
package/core/clause.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -19,10 +23,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
21
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.sensitiveValue = exports.In = exports.Or = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = void 0;
|
|
26
|
+
exports.Modulo = exports.Divide = exports.Multiply = exports.Subtract = exports.Add = exports.PaginationMultipleColsSubQuery = exports.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.OrOptional = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = exports.inClause = void 0;
|
|
23
27
|
const db_1 = __importStar(require("./db"));
|
|
24
28
|
function isSensitive(val) {
|
|
25
|
-
return (
|
|
29
|
+
return (val !== null &&
|
|
30
|
+
typeof val === "object" &&
|
|
31
|
+
val.logValue !== undefined);
|
|
26
32
|
}
|
|
27
33
|
function rawValue(val) {
|
|
28
34
|
if (isSensitive(val)) {
|
|
@@ -31,17 +37,114 @@ function rawValue(val) {
|
|
|
31
37
|
return val;
|
|
32
38
|
}
|
|
33
39
|
class simpleClause {
|
|
34
|
-
constructor(col, value, op) {
|
|
40
|
+
constructor(col, value, op, handleNull) {
|
|
35
41
|
this.col = col;
|
|
36
42
|
this.value = value;
|
|
37
43
|
this.op = op;
|
|
44
|
+
this.handleNull = handleNull;
|
|
38
45
|
}
|
|
39
46
|
clause(idx) {
|
|
47
|
+
const nullClause = this.nullClause();
|
|
48
|
+
if (nullClause) {
|
|
49
|
+
return nullClause.clause(idx);
|
|
50
|
+
}
|
|
40
51
|
if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
|
|
41
52
|
return `${this.col} ${this.op} $${idx}`;
|
|
42
53
|
}
|
|
43
54
|
return `${this.col} ${this.op} ?`;
|
|
44
55
|
}
|
|
56
|
+
nullClause() {
|
|
57
|
+
if (!this.handleNull || this.value !== null) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
return this.handleNull;
|
|
61
|
+
}
|
|
62
|
+
columns() {
|
|
63
|
+
return [this.col];
|
|
64
|
+
}
|
|
65
|
+
values() {
|
|
66
|
+
const nullClause = this.nullClause();
|
|
67
|
+
if (nullClause) {
|
|
68
|
+
return nullClause.values();
|
|
69
|
+
}
|
|
70
|
+
if (isSensitive(this.value)) {
|
|
71
|
+
return [this.value.value()];
|
|
72
|
+
}
|
|
73
|
+
return [this.value];
|
|
74
|
+
}
|
|
75
|
+
logValues() {
|
|
76
|
+
const nullClause = this.nullClause();
|
|
77
|
+
if (nullClause) {
|
|
78
|
+
return nullClause.logValues();
|
|
79
|
+
}
|
|
80
|
+
if (isSensitive(this.value)) {
|
|
81
|
+
return [this.value.logValue()];
|
|
82
|
+
}
|
|
83
|
+
return [this.value];
|
|
84
|
+
}
|
|
85
|
+
instanceKey() {
|
|
86
|
+
const nullClause = this.nullClause();
|
|
87
|
+
if (nullClause) {
|
|
88
|
+
return nullClause.instanceKey();
|
|
89
|
+
}
|
|
90
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
class isNullClause {
|
|
94
|
+
constructor(col) {
|
|
95
|
+
this.col = col;
|
|
96
|
+
}
|
|
97
|
+
clause(idx) {
|
|
98
|
+
return `${this.col} IS NULL`;
|
|
99
|
+
}
|
|
100
|
+
columns() {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
values() {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
logValues() {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
instanceKey() {
|
|
110
|
+
return `${this.col} IS NULL`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
class isNotNullClause {
|
|
114
|
+
constructor(col) {
|
|
115
|
+
this.col = col;
|
|
116
|
+
}
|
|
117
|
+
clause(idx) {
|
|
118
|
+
return `${this.col} IS NOT NULL`;
|
|
119
|
+
}
|
|
120
|
+
columns() {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
values() {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
logValues() {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
instanceKey() {
|
|
130
|
+
return `${this.col} IS NOT NULL`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
class arraySimpleClause {
|
|
134
|
+
constructor(col, value, op) {
|
|
135
|
+
this.col = col;
|
|
136
|
+
this.value = value;
|
|
137
|
+
this.op = op;
|
|
138
|
+
}
|
|
139
|
+
clause(idx) {
|
|
140
|
+
if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
|
|
141
|
+
return `$${idx} ${this.op} ANY(${this.col})`;
|
|
142
|
+
}
|
|
143
|
+
return `${this.col} ${this.op} ?`;
|
|
144
|
+
}
|
|
145
|
+
columns() {
|
|
146
|
+
return [this.col];
|
|
147
|
+
}
|
|
45
148
|
values() {
|
|
46
149
|
if (isSensitive(this.value)) {
|
|
47
150
|
return [this.value.value()];
|
|
@@ -58,18 +161,105 @@ class simpleClause {
|
|
|
58
161
|
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
59
162
|
}
|
|
60
163
|
}
|
|
164
|
+
class postgresArrayOperator {
|
|
165
|
+
constructor(col, value, op, not) {
|
|
166
|
+
this.col = col;
|
|
167
|
+
this.value = value;
|
|
168
|
+
this.op = op;
|
|
169
|
+
this.not = not;
|
|
170
|
+
}
|
|
171
|
+
clause(idx) {
|
|
172
|
+
if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
|
|
173
|
+
if (this.not) {
|
|
174
|
+
return `NOT ${this.col} ${this.op} $${idx}`;
|
|
175
|
+
}
|
|
176
|
+
return `${this.col} ${this.op} $${idx}`;
|
|
177
|
+
}
|
|
178
|
+
throw new Error(`not supported`);
|
|
179
|
+
}
|
|
180
|
+
columns() {
|
|
181
|
+
return [this.col];
|
|
182
|
+
}
|
|
183
|
+
values() {
|
|
184
|
+
if (isSensitive(this.value)) {
|
|
185
|
+
return [`{${this.value.value()}}`];
|
|
186
|
+
}
|
|
187
|
+
return [`{${this.value}}`];
|
|
188
|
+
}
|
|
189
|
+
logValues() {
|
|
190
|
+
if (isSensitive(this.value)) {
|
|
191
|
+
return [`{${this.value.logValue()}}`];
|
|
192
|
+
}
|
|
193
|
+
return [`{${this.value}}`];
|
|
194
|
+
}
|
|
195
|
+
instanceKey() {
|
|
196
|
+
if (this.not) {
|
|
197
|
+
return `NOT:${this.col}${this.op}${rawValue(this.value)}`;
|
|
198
|
+
}
|
|
199
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
class postgresArrayOperatorList extends postgresArrayOperator {
|
|
203
|
+
constructor(col, value, op, not) {
|
|
204
|
+
super(col, value, op, not);
|
|
205
|
+
}
|
|
206
|
+
values() {
|
|
207
|
+
return [
|
|
208
|
+
`{${this.value
|
|
209
|
+
.map((v) => {
|
|
210
|
+
if (isSensitive(v)) {
|
|
211
|
+
return v.value();
|
|
212
|
+
}
|
|
213
|
+
return v;
|
|
214
|
+
})
|
|
215
|
+
.join(", ")}}`,
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
logValues() {
|
|
219
|
+
return [
|
|
220
|
+
`{${this.value
|
|
221
|
+
.map((v) => {
|
|
222
|
+
if (isSensitive(v)) {
|
|
223
|
+
return v.logValue();
|
|
224
|
+
}
|
|
225
|
+
return v;
|
|
226
|
+
})
|
|
227
|
+
.join(", ")}}`,
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
61
231
|
class inClause {
|
|
62
|
-
|
|
232
|
+
static getPostgresInClauseValuesThreshold() {
|
|
233
|
+
return 70;
|
|
234
|
+
}
|
|
235
|
+
constructor(col, value, type = "uuid") {
|
|
63
236
|
this.col = col;
|
|
64
237
|
this.value = value;
|
|
238
|
+
this.type = type;
|
|
65
239
|
}
|
|
66
240
|
clause(idx) {
|
|
67
|
-
|
|
241
|
+
// do a simple = when only one item
|
|
242
|
+
if (this.value.length === 1) {
|
|
243
|
+
return new simpleClause(this.col, this.value[0], "=").clause(idx);
|
|
244
|
+
}
|
|
245
|
+
const postgres = db_1.default.getDialect() === db_1.Dialect.Postgres;
|
|
246
|
+
const postgresValuesList = postgres &&
|
|
247
|
+
this.value.length >= inClause.getPostgresInClauseValuesThreshold();
|
|
68
248
|
let indices;
|
|
69
|
-
if (
|
|
249
|
+
if (postgres) {
|
|
70
250
|
indices = [];
|
|
71
251
|
for (let i = 0; i < this.value.length; i++) {
|
|
72
|
-
|
|
252
|
+
if (postgresValuesList) {
|
|
253
|
+
if (i === 0) {
|
|
254
|
+
indices.push(`($${idx}::${this.type})`);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
indices.push(`($${idx})`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
indices.push(`$${idx}`);
|
|
262
|
+
}
|
|
73
263
|
idx++;
|
|
74
264
|
}
|
|
75
265
|
}
|
|
@@ -77,34 +267,31 @@ class inClause {
|
|
|
77
267
|
indices = new Array(this.value.length);
|
|
78
268
|
indices.fill("?", 0);
|
|
79
269
|
}
|
|
80
|
-
|
|
270
|
+
let inValue = indices.join(", ");
|
|
271
|
+
// wrap in VALUES list for postgres...
|
|
272
|
+
if (postgresValuesList) {
|
|
273
|
+
inValue = `VALUES${inValue}`;
|
|
274
|
+
}
|
|
81
275
|
return `${this.col} IN (${inValue})`;
|
|
82
276
|
// TODO we need to return idx at end to query builder...
|
|
83
277
|
// or anything that's doing a composite query so next clause knows where to start
|
|
84
278
|
// or change to a sqlx.Rebind format
|
|
85
279
|
// here's what sqlx does: https://play.golang.org/p/vPzvYqeAcP0
|
|
86
280
|
}
|
|
281
|
+
columns() {
|
|
282
|
+
return [this.col];
|
|
283
|
+
}
|
|
87
284
|
values() {
|
|
88
285
|
const result = [];
|
|
89
|
-
for (
|
|
90
|
-
|
|
91
|
-
result.push(value.value());
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
result.push(value);
|
|
95
|
-
}
|
|
286
|
+
for (let value of this.value) {
|
|
287
|
+
result.push(rawValue(value));
|
|
96
288
|
}
|
|
97
289
|
return result;
|
|
98
290
|
}
|
|
99
291
|
logValues() {
|
|
100
292
|
const result = [];
|
|
101
|
-
for (
|
|
102
|
-
|
|
103
|
-
result.push(value.logValue());
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
result.push(value);
|
|
107
|
-
}
|
|
293
|
+
for (let value of this.value) {
|
|
294
|
+
result.push(isSensitive(value) ? value.logValue() : value);
|
|
108
295
|
}
|
|
109
296
|
return result;
|
|
110
297
|
}
|
|
@@ -112,19 +299,33 @@ class inClause {
|
|
|
112
299
|
return `in:${this.col}:${this.values().join(",")}`;
|
|
113
300
|
}
|
|
114
301
|
}
|
|
302
|
+
exports.inClause = inClause;
|
|
115
303
|
class compositeClause {
|
|
116
304
|
constructor(clauses, sep) {
|
|
117
305
|
this.clauses = clauses;
|
|
118
306
|
this.sep = sep;
|
|
307
|
+
this.compositeOp = this.sep;
|
|
119
308
|
}
|
|
120
309
|
clause(idx) {
|
|
121
310
|
let clauses = [];
|
|
122
311
|
for (const clause of this.clauses) {
|
|
123
|
-
|
|
312
|
+
let cls = clause.clause(idx);
|
|
313
|
+
// if composite clause and a different op, add parens so that we enforce order of precedence
|
|
314
|
+
if (clause.compositeOp && clause.compositeOp !== this.sep) {
|
|
315
|
+
cls = `(${cls})`;
|
|
316
|
+
}
|
|
317
|
+
clauses.push(cls);
|
|
124
318
|
idx = idx + clause.values().length;
|
|
125
319
|
}
|
|
126
320
|
return clauses.join(this.sep);
|
|
127
321
|
}
|
|
322
|
+
columns() {
|
|
323
|
+
const ret = [];
|
|
324
|
+
for (const cls of this.clauses) {
|
|
325
|
+
ret.push(...cls.columns());
|
|
326
|
+
}
|
|
327
|
+
return ret;
|
|
328
|
+
}
|
|
128
329
|
values() {
|
|
129
330
|
let result = [];
|
|
130
331
|
for (const clause of this.clauses) {
|
|
@@ -141,16 +342,159 @@ class compositeClause {
|
|
|
141
342
|
}
|
|
142
343
|
instanceKey() {
|
|
143
344
|
let keys = [];
|
|
144
|
-
this.clauses.forEach((clause) =>
|
|
345
|
+
this.clauses.forEach((clause) => {
|
|
346
|
+
if (clause.compositeOp && clause.compositeOp != this.sep) {
|
|
347
|
+
keys.push(`(${clause.instanceKey()})`);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
keys.push(clause.instanceKey());
|
|
351
|
+
}
|
|
352
|
+
});
|
|
145
353
|
return keys.join(this.sep);
|
|
146
354
|
}
|
|
147
355
|
}
|
|
356
|
+
class tsQueryClause {
|
|
357
|
+
constructor(col, val, tsVectorCol) {
|
|
358
|
+
this.col = col;
|
|
359
|
+
this.val = val;
|
|
360
|
+
this.tsVectorCol = tsVectorCol;
|
|
361
|
+
}
|
|
362
|
+
isTsQuery(val) {
|
|
363
|
+
return typeof val !== "string";
|
|
364
|
+
}
|
|
365
|
+
getInfo() {
|
|
366
|
+
if (this.isTsQuery(this.val)) {
|
|
367
|
+
return { value: this.val.value, language: this.val.language };
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
language: "english",
|
|
371
|
+
value: this.val,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
clause(idx) {
|
|
375
|
+
const { language } = this.getInfo();
|
|
376
|
+
if (db_1.Dialect.Postgres === db_1.default.getDialect()) {
|
|
377
|
+
if (this.tsVectorCol) {
|
|
378
|
+
return `to_tsvector(${this.col}) @@ ${this.getFunction()}('${language}', $${idx})`;
|
|
379
|
+
}
|
|
380
|
+
return `${this.col} @@ ${this.getFunction()}('${language}', $${idx})`;
|
|
381
|
+
}
|
|
382
|
+
// FYI this doesn't actually work for sqlite since different
|
|
383
|
+
return `${this.col} @@ ${this.getFunction()}('${language}', ?)`;
|
|
384
|
+
}
|
|
385
|
+
columns() {
|
|
386
|
+
return [this.col];
|
|
387
|
+
}
|
|
388
|
+
values() {
|
|
389
|
+
const { value } = this.getInfo();
|
|
390
|
+
return [value];
|
|
391
|
+
}
|
|
392
|
+
logValues() {
|
|
393
|
+
const { value } = this.getInfo();
|
|
394
|
+
return [value];
|
|
395
|
+
}
|
|
396
|
+
getFunction() {
|
|
397
|
+
return "to_tsquery";
|
|
398
|
+
}
|
|
399
|
+
instanceKey() {
|
|
400
|
+
const { language, value } = this.getInfo();
|
|
401
|
+
if (this.tsVectorCol) {
|
|
402
|
+
return `to_tsvector(${this.col})@@${this.getFunction()}:${language}:${value}`;
|
|
403
|
+
}
|
|
404
|
+
return `${this.col}@@${this.getFunction()}:${language}:${value}`;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
class plainToTsQueryClause extends tsQueryClause {
|
|
408
|
+
getFunction() {
|
|
409
|
+
return "plainto_tsquery";
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
class phraseToTsQueryClause extends tsQueryClause {
|
|
413
|
+
getFunction() {
|
|
414
|
+
return "phraseto_tsquery";
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
class websearchTosQueryClause extends tsQueryClause {
|
|
418
|
+
getFunction() {
|
|
419
|
+
return "websearch_to_tsquery";
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// postgres array operators
|
|
423
|
+
// https://www.postgresql.org/docs/current/functions-array.html
|
|
424
|
+
/**
|
|
425
|
+
* creates a clause to determine if the given value is contained in the array stored in the column in the db
|
|
426
|
+
* only works with postgres gin indexes
|
|
427
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
428
|
+
*/
|
|
429
|
+
function PostgresArrayContainsValue(col, value) {
|
|
430
|
+
return new postgresArrayOperator(col, value, "@>");
|
|
431
|
+
}
|
|
432
|
+
exports.PostgresArrayContainsValue = PostgresArrayContainsValue;
|
|
433
|
+
/**
|
|
434
|
+
* creates a clause to determine if every item in the list is stored in the array stored in the column in the db
|
|
435
|
+
* only works with postgres gin indexes
|
|
436
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
437
|
+
*/
|
|
438
|
+
function PostgresArrayContains(col, value) {
|
|
439
|
+
return new postgresArrayOperatorList(col, value, "@>");
|
|
440
|
+
}
|
|
441
|
+
exports.PostgresArrayContains = PostgresArrayContains;
|
|
442
|
+
/**
|
|
443
|
+
* creates a clause to determine if the given value is NOT contained in the array stored in the column in the db
|
|
444
|
+
* only works with postgres gin indexes
|
|
445
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
446
|
+
*/
|
|
447
|
+
function PostgresArrayNotContainsValue(col, value) {
|
|
448
|
+
return new postgresArrayOperator(col, value, "@>", true);
|
|
449
|
+
}
|
|
450
|
+
exports.PostgresArrayNotContainsValue = PostgresArrayNotContainsValue;
|
|
451
|
+
/**
|
|
452
|
+
* creates a clause to determine if every item in the list is NOT stored in the array stored in the column in the db
|
|
453
|
+
* only works with postgres gin indexes
|
|
454
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
455
|
+
*/
|
|
456
|
+
function PostgresArrayNotContains(col, value) {
|
|
457
|
+
return new postgresArrayOperatorList(col, value, "@>", true);
|
|
458
|
+
}
|
|
459
|
+
exports.PostgresArrayNotContains = PostgresArrayNotContains;
|
|
460
|
+
/**
|
|
461
|
+
* creates a clause to determine if the arrays overlap, that is, do they have any elements in common
|
|
462
|
+
* only works with postgres gin indexes
|
|
463
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
464
|
+
*/
|
|
465
|
+
function PostgresArrayOverlaps(col, value) {
|
|
466
|
+
return new postgresArrayOperatorList(col, value, "&&");
|
|
467
|
+
}
|
|
468
|
+
exports.PostgresArrayOverlaps = PostgresArrayOverlaps;
|
|
469
|
+
/**
|
|
470
|
+
* creates a clause to determine if the arrays do not overlap, that is, do they have any elements in common
|
|
471
|
+
* only works with postgres gin indexes
|
|
472
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
473
|
+
*/
|
|
474
|
+
function PostgresArrayNotOverlaps(col, value) {
|
|
475
|
+
return new postgresArrayOperatorList(col, value, "&&", true);
|
|
476
|
+
}
|
|
477
|
+
exports.PostgresArrayNotOverlaps = PostgresArrayNotOverlaps;
|
|
478
|
+
/**
|
|
479
|
+
* @deprecated use PostgresArrayContainsValue
|
|
480
|
+
*/
|
|
481
|
+
function ArrayEq(col, value) {
|
|
482
|
+
return new arraySimpleClause(col, value, "=");
|
|
483
|
+
}
|
|
484
|
+
exports.ArrayEq = ArrayEq;
|
|
485
|
+
/**
|
|
486
|
+
* @deprecated use PostgresNotArrayContains
|
|
487
|
+
*/
|
|
488
|
+
function ArrayNotEq(col, value) {
|
|
489
|
+
return new arraySimpleClause(col, value, "!=");
|
|
490
|
+
}
|
|
491
|
+
exports.ArrayNotEq = ArrayNotEq;
|
|
148
492
|
function Eq(col, value) {
|
|
149
|
-
return new simpleClause(col, value, "=");
|
|
493
|
+
return new simpleClause(col, value, "=", new isNullClause(col));
|
|
150
494
|
}
|
|
151
495
|
exports.Eq = Eq;
|
|
152
496
|
function NotEq(col, value) {
|
|
153
|
-
return new simpleClause(col, value, "!=");
|
|
497
|
+
return new simpleClause(col, value, "!=", new isNotNullClause(col));
|
|
154
498
|
}
|
|
155
499
|
exports.NotEq = NotEq;
|
|
156
500
|
function Greater(col, value) {
|
|
@@ -173,15 +517,93 @@ function And(...args) {
|
|
|
173
517
|
return new compositeClause(args, " AND ");
|
|
174
518
|
}
|
|
175
519
|
exports.And = And;
|
|
520
|
+
function AndOptional(...args) {
|
|
521
|
+
// @ts-ignore
|
|
522
|
+
let filtered = args.filter((v) => v !== undefined);
|
|
523
|
+
if (filtered.length === 1) {
|
|
524
|
+
return filtered[0];
|
|
525
|
+
}
|
|
526
|
+
return And(...filtered);
|
|
527
|
+
}
|
|
528
|
+
exports.AndOptional = AndOptional;
|
|
176
529
|
function Or(...args) {
|
|
177
530
|
return new compositeClause(args, " OR ");
|
|
178
531
|
}
|
|
179
532
|
exports.Or = Or;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
533
|
+
function OrOptional(...args) {
|
|
534
|
+
// @ts-ignore
|
|
535
|
+
let filtered = args.filter((v) => v !== undefined);
|
|
536
|
+
if (filtered.length === 1) {
|
|
537
|
+
return filtered[0];
|
|
538
|
+
}
|
|
539
|
+
return Or(...filtered);
|
|
540
|
+
}
|
|
541
|
+
exports.OrOptional = OrOptional;
|
|
542
|
+
function In(...args) {
|
|
543
|
+
if (args.length < 2) {
|
|
544
|
+
throw new Error(`invalid args passed to In`);
|
|
545
|
+
}
|
|
546
|
+
// 2nd overload
|
|
547
|
+
if (Array.isArray(args[1])) {
|
|
548
|
+
return new inClause(args[0], args[1], args[2]);
|
|
549
|
+
}
|
|
550
|
+
return new inClause(args[0], args.slice(1));
|
|
183
551
|
}
|
|
184
552
|
exports.In = In;
|
|
553
|
+
// if string defaults to english
|
|
554
|
+
// https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
|
|
555
|
+
// to_tsquery
|
|
556
|
+
// plainto_tsquery
|
|
557
|
+
// phraseto_tsquery;
|
|
558
|
+
// websearch_to_tsquery
|
|
559
|
+
function TsQuery(col, val) {
|
|
560
|
+
return new tsQueryClause(col, val);
|
|
561
|
+
}
|
|
562
|
+
exports.TsQuery = TsQuery;
|
|
563
|
+
function PlainToTsQuery(col, val) {
|
|
564
|
+
return new plainToTsQueryClause(col, val);
|
|
565
|
+
}
|
|
566
|
+
exports.PlainToTsQuery = PlainToTsQuery;
|
|
567
|
+
function PhraseToTsQuery(col, val) {
|
|
568
|
+
return new phraseToTsQueryClause(col, val);
|
|
569
|
+
}
|
|
570
|
+
exports.PhraseToTsQuery = PhraseToTsQuery;
|
|
571
|
+
function WebsearchToTsQuery(col, val) {
|
|
572
|
+
return new websearchTosQueryClause(col, val);
|
|
573
|
+
}
|
|
574
|
+
exports.WebsearchToTsQuery = WebsearchToTsQuery;
|
|
575
|
+
// TsVectorColTsQuery is used when the column is not a tsvector field e.g.
|
|
576
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
577
|
+
function TsVectorColTsQuery(col, val) {
|
|
578
|
+
return new tsQueryClause(col, val, true);
|
|
579
|
+
}
|
|
580
|
+
exports.TsVectorColTsQuery = TsVectorColTsQuery;
|
|
581
|
+
// TsVectorPlainToTsQuery is used when the column is not a tsvector field e.g.
|
|
582
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
583
|
+
// TODO do these 4 need TsQuery because would be nice to have language?
|
|
584
|
+
// it seems to default to the config of the column
|
|
585
|
+
function TsVectorPlainToTsQuery(col, val) {
|
|
586
|
+
return new plainToTsQueryClause(col, val, true);
|
|
587
|
+
}
|
|
588
|
+
exports.TsVectorPlainToTsQuery = TsVectorPlainToTsQuery;
|
|
589
|
+
// TsVectorPhraseToTsQuery is used when the column is not a tsvector field e.g.
|
|
590
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
591
|
+
function TsVectorPhraseToTsQuery(col, val) {
|
|
592
|
+
return new phraseToTsQueryClause(col, val, true);
|
|
593
|
+
}
|
|
594
|
+
exports.TsVectorPhraseToTsQuery = TsVectorPhraseToTsQuery;
|
|
595
|
+
// TsVectorWebsearchToTsQuery is used when the column is not a tsvector field e.g.
|
|
596
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
597
|
+
function TsVectorWebsearchToTsQuery(col, val) {
|
|
598
|
+
return new websearchTosQueryClause(col, val, true);
|
|
599
|
+
}
|
|
600
|
+
exports.TsVectorWebsearchToTsQuery = TsVectorWebsearchToTsQuery;
|
|
601
|
+
// TODO would be nice to support this with building blocks but not supporting for now
|
|
602
|
+
// AND: foo & bar,
|
|
603
|
+
// OR: foo | bar
|
|
604
|
+
// followed by: foo <-> bar
|
|
605
|
+
// NOT: !foo
|
|
606
|
+
// starts_with: theo:*
|
|
185
607
|
// wrap a query in the db with this to ensure that it doesn't show up in the logs
|
|
186
608
|
// e.g. if querying for password, SSN, etc
|
|
187
609
|
// we'll pass the right fields to query and log something along the lines of `****`
|
|
@@ -196,3 +618,114 @@ function sensitiveValue(val) {
|
|
|
196
618
|
};
|
|
197
619
|
}
|
|
198
620
|
exports.sensitiveValue = sensitiveValue;
|
|
621
|
+
// These don't return Clauses but return helpful things that can be passed to clauses
|
|
622
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
623
|
+
// see test in db_clause.test.ts
|
|
624
|
+
// unclear best time to use this...
|
|
625
|
+
function JSONObjectFieldKeyASJSON(col, field) {
|
|
626
|
+
return `${col}->'${field}'`;
|
|
627
|
+
}
|
|
628
|
+
exports.JSONObjectFieldKeyASJSON = JSONObjectFieldKeyASJSON;
|
|
629
|
+
function JSONObjectFieldKeyAsText(col, field) {
|
|
630
|
+
return `${col}->>'${field}'`;
|
|
631
|
+
}
|
|
632
|
+
exports.JSONObjectFieldKeyAsText = JSONObjectFieldKeyAsText;
|
|
633
|
+
class jSONPathValuePredicateClause {
|
|
634
|
+
constructor(col, path, value, pred) {
|
|
635
|
+
this.col = col;
|
|
636
|
+
this.path = path;
|
|
637
|
+
this.value = value;
|
|
638
|
+
this.pred = pred;
|
|
639
|
+
}
|
|
640
|
+
clause(idx) {
|
|
641
|
+
if (db_1.default.getDialect() !== db_1.Dialect.Postgres) {
|
|
642
|
+
throw new Error(`not supported`);
|
|
643
|
+
}
|
|
644
|
+
return `${this.col} @@ $${idx}`;
|
|
645
|
+
}
|
|
646
|
+
columns() {
|
|
647
|
+
return [this.col];
|
|
648
|
+
}
|
|
649
|
+
wrap(val) {
|
|
650
|
+
return `${this.path} ${this.pred} ${JSON.stringify(val)}`;
|
|
651
|
+
}
|
|
652
|
+
values() {
|
|
653
|
+
if (isSensitive(this.value)) {
|
|
654
|
+
return [this.wrap(this.value.value())];
|
|
655
|
+
}
|
|
656
|
+
return [this.wrap(this.value)];
|
|
657
|
+
}
|
|
658
|
+
logValues() {
|
|
659
|
+
if (isSensitive(this.value)) {
|
|
660
|
+
return [this.wrap(this.value.logValue())];
|
|
661
|
+
}
|
|
662
|
+
return [this.wrap(this.value)];
|
|
663
|
+
}
|
|
664
|
+
instanceKey() {
|
|
665
|
+
return `${this.col}${this.path}${rawValue(this.value)}${this.pred}`;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
669
|
+
function JSONPathValuePredicate(dbCol, path, val, pred) {
|
|
670
|
+
return new jSONPathValuePredicateClause(dbCol, path, val, pred);
|
|
671
|
+
}
|
|
672
|
+
exports.JSONPathValuePredicate = JSONPathValuePredicate;
|
|
673
|
+
// TODO need a better name for this lol
|
|
674
|
+
// this assumes we're doing the same direction twice which isn't necessarily accurate in the future...
|
|
675
|
+
class paginationMultipleColumnsSubQueryClause {
|
|
676
|
+
constructor(col, op, tableName, uniqueCol, val) {
|
|
677
|
+
this.col = col;
|
|
678
|
+
this.op = op;
|
|
679
|
+
this.tableName = tableName;
|
|
680
|
+
this.uniqueCol = uniqueCol;
|
|
681
|
+
this.val = val;
|
|
682
|
+
}
|
|
683
|
+
buildSimpleQuery(clause, idx) {
|
|
684
|
+
return `SELECT ${this.col} FROM ${this.tableName} WHERE ${clause.clause(idx)}`;
|
|
685
|
+
}
|
|
686
|
+
clause(idx) {
|
|
687
|
+
const eq1 = this.buildSimpleQuery(Eq(this.uniqueCol, this.val), idx);
|
|
688
|
+
const eq2 = this.buildSimpleQuery(Eq(this.uniqueCol, this.val), idx + 1);
|
|
689
|
+
const op = new simpleClause(this.uniqueCol, this.val, this.op).clause(idx + 2);
|
|
690
|
+
// nest in () to make sure it's scoped correctly
|
|
691
|
+
return `(${this.col} ${this.op} (${eq1}) OR (${this.col} = (${eq2}) AND ${op}))`;
|
|
692
|
+
}
|
|
693
|
+
columns() {
|
|
694
|
+
return [this.col];
|
|
695
|
+
}
|
|
696
|
+
values() {
|
|
697
|
+
return [this.val, this.val, this.val];
|
|
698
|
+
}
|
|
699
|
+
logValues() {
|
|
700
|
+
const log = isSensitive(this.val) ? this.val.logValue() : this.val;
|
|
701
|
+
return [log, log, log];
|
|
702
|
+
}
|
|
703
|
+
instanceKey() {
|
|
704
|
+
return `${this.col}-${this.op}-${this.tableName}-${this.uniqueCol}-${this.val}`;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function PaginationMultipleColsSubQuery(col, op, tableName, uniqueCol, val) {
|
|
708
|
+
return new paginationMultipleColumnsSubQueryClause(col, op, tableName, uniqueCol, val);
|
|
709
|
+
}
|
|
710
|
+
exports.PaginationMultipleColsSubQuery = PaginationMultipleColsSubQuery;
|
|
711
|
+
// These 5 are used on the RHS of an expression
|
|
712
|
+
function Add(col, value) {
|
|
713
|
+
return new simpleClause(col, value, "+", new isNullClause(col));
|
|
714
|
+
}
|
|
715
|
+
exports.Add = Add;
|
|
716
|
+
function Subtract(col, value) {
|
|
717
|
+
return new simpleClause(col, value, "-", new isNullClause(col));
|
|
718
|
+
}
|
|
719
|
+
exports.Subtract = Subtract;
|
|
720
|
+
function Multiply(col, value) {
|
|
721
|
+
return new simpleClause(col, value, "*", new isNullClause(col));
|
|
722
|
+
}
|
|
723
|
+
exports.Multiply = Multiply;
|
|
724
|
+
function Divide(col, value) {
|
|
725
|
+
return new simpleClause(col, value, "/", new isNullClause(col));
|
|
726
|
+
}
|
|
727
|
+
exports.Divide = Divide;
|
|
728
|
+
function Modulo(col, value) {
|
|
729
|
+
return new simpleClause(col, value, "%", new isNullClause(col));
|
|
730
|
+
}
|
|
731
|
+
exports.Modulo = Modulo;
|