@snowtop/ent 0.1.0-alpha160-test5 → 0.1.0-alpha160-test7
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/dist/package.json +64 -0
- package/package.json +52 -7
- package/src/action/action.ts +330 -0
- package/src/action/executor.ts +453 -0
- package/src/action/experimental_action.ts +277 -0
- package/src/action/index.ts +31 -0
- package/src/action/operations.ts +967 -0
- package/src/action/orchestrator.ts +1527 -0
- package/src/action/privacy.ts +37 -0
- package/src/action/relative_value.ts +242 -0
- package/src/action/transaction.ts +38 -0
- package/src/auth/auth.ts +77 -0
- package/src/auth/index.ts +8 -0
- package/src/core/base.ts +367 -0
- package/src/core/clause.ts +1065 -0
- package/src/core/config.ts +219 -0
- package/src/core/const.ts +5 -0
- package/src/core/context.ts +135 -0
- package/src/core/convert.ts +106 -0
- package/src/core/date.ts +23 -0
- package/src/core/db.ts +498 -0
- package/src/core/ent.ts +1740 -0
- package/src/core/global_schema.ts +49 -0
- package/src/core/loaders/assoc_count_loader.ts +99 -0
- package/src/core/loaders/assoc_edge_loader.ts +250 -0
- package/src/core/loaders/index.ts +12 -0
- package/src/core/loaders/loader.ts +66 -0
- package/src/core/loaders/object_loader.ts +489 -0
- package/src/core/loaders/query_loader.ts +314 -0
- package/src/core/loaders/raw_count_loader.ts +175 -0
- package/src/core/logger.ts +49 -0
- package/src/core/privacy.ts +660 -0
- package/src/core/query/assoc_query.ts +240 -0
- package/src/core/query/custom_clause_query.ts +174 -0
- package/src/core/query/custom_query.ts +302 -0
- package/src/core/query/index.ts +9 -0
- package/src/core/query/query.ts +674 -0
- package/src/core/query_impl.ts +32 -0
- package/src/core/viewer.ts +52 -0
- package/src/ent.code-workspace +73 -0
- package/src/graphql/builtins/connection.ts +25 -0
- package/src/graphql/builtins/edge.ts +16 -0
- package/src/graphql/builtins/node.ts +12 -0
- package/src/graphql/graphql.ts +891 -0
- package/src/graphql/graphql_field_helpers.ts +221 -0
- package/src/graphql/index.ts +42 -0
- package/src/graphql/mutations/union.ts +39 -0
- package/src/graphql/node_resolver.ts +122 -0
- package/src/graphql/query/connection_type.ts +113 -0
- package/src/graphql/query/edge_connection.ts +171 -0
- package/src/graphql/query/page_info.ts +34 -0
- package/src/graphql/query/shared_edge_connection.ts +287 -0
- package/src/graphql/scalars/orderby_direction.ts +13 -0
- package/src/graphql/scalars/time.ts +38 -0
- package/src/imports/dataz/example1/_auth.ts +51 -0
- package/src/imports/dataz/example1/_viewer.ts +35 -0
- package/src/imports/index.ts +213 -0
- package/src/index.ts +145 -0
- package/src/parse_schema/parse.ts +585 -0
- package/src/schema/base_schema.ts +224 -0
- package/src/schema/field.ts +1087 -0
- package/src/schema/index.ts +53 -0
- package/src/schema/json_field.ts +94 -0
- package/src/schema/schema.ts +1028 -0
- package/src/schema/struct_field.ts +234 -0
- package/src/schema/union_field.ts +105 -0
- package/src/scripts/custom_compiler.ts +331 -0
- package/src/scripts/custom_graphql.ts +550 -0
- package/src/scripts/migrate_v0.1.ts +41 -0
- package/src/scripts/move_types.ts +131 -0
- package/src/scripts/read_schema.ts +67 -0
- package/src/setupPackage.js +42 -0
- package/src/testutils/action/complex_schemas.ts +517 -0
- package/src/testutils/builder.ts +422 -0
- package/src/testutils/context/test_context.ts +25 -0
- package/src/testutils/db/fixture.ts +32 -0
- package/src/testutils/db/temp_db.ts +941 -0
- package/src/testutils/db/value.ts +294 -0
- package/src/testutils/db_mock.ts +351 -0
- package/src/testutils/db_time_zone.ts +40 -0
- package/src/testutils/ent-graphql-tests/index.ts +653 -0
- package/src/testutils/fake_comms.ts +50 -0
- package/src/testutils/fake_data/const.ts +64 -0
- package/src/testutils/fake_data/events_query.ts +145 -0
- package/src/testutils/fake_data/fake_contact.ts +150 -0
- package/src/testutils/fake_data/fake_event.ts +150 -0
- package/src/testutils/fake_data/fake_tag.ts +139 -0
- package/src/testutils/fake_data/fake_user.ts +232 -0
- package/src/testutils/fake_data/index.ts +1 -0
- package/src/testutils/fake_data/internal.ts +8 -0
- package/src/testutils/fake_data/tag_query.ts +56 -0
- package/src/testutils/fake_data/test_helpers.ts +388 -0
- package/src/testutils/fake_data/user_query.ts +524 -0
- package/src/testutils/fake_log.ts +52 -0
- package/src/testutils/mock_date.ts +10 -0
- package/src/testutils/mock_log.ts +39 -0
- package/src/testutils/parse_sql.ts +685 -0
- package/src/testutils/test_edge_global_schema.ts +49 -0
- package/src/testutils/write.ts +70 -0
- package/src/tsc/ast.ts +351 -0
- package/src/tsc/compilerOptions.ts +85 -0
- package/src/tsc/move_generated.ts +191 -0
- package/src/tsc/transform.ts +226 -0
- package/src/tsc/transform_action.ts +224 -0
- package/src/tsc/transform_ent.ts +66 -0
- package/src/tsc/transform_schema.ts +546 -0
- package/tsconfig.json +20 -0
- package/core/query/shared_assoc_test.d.ts +0 -2
- package/core/query/shared_assoc_test.js +0 -804
- package/core/query/shared_test.d.ts +0 -21
- package/core/query/shared_test.js +0 -736
- package/graphql/query/shared_assoc_test.d.ts +0 -1
- package/graphql/query/shared_assoc_test.js +0 -203
- /package/{action → dist/action}/action.d.ts +0 -0
- /package/{action → dist/action}/action.js +0 -0
- /package/{action → dist/action}/executor.d.ts +0 -0
- /package/{action → dist/action}/executor.js +0 -0
- /package/{action → dist/action}/experimental_action.d.ts +0 -0
- /package/{action → dist/action}/experimental_action.js +0 -0
- /package/{action → dist/action}/index.d.ts +0 -0
- /package/{action → dist/action}/index.js +0 -0
- /package/{action → dist/action}/operations.d.ts +0 -0
- /package/{action → dist/action}/operations.js +0 -0
- /package/{action → dist/action}/orchestrator.d.ts +0 -0
- /package/{action → dist/action}/orchestrator.js +0 -0
- /package/{action → dist/action}/privacy.d.ts +0 -0
- /package/{action → dist/action}/privacy.js +0 -0
- /package/{action → dist/action}/relative_value.d.ts +0 -0
- /package/{action → dist/action}/relative_value.js +0 -0
- /package/{action → dist/action}/transaction.d.ts +0 -0
- /package/{action → dist/action}/transaction.js +0 -0
- /package/{auth → dist/auth}/auth.d.ts +0 -0
- /package/{auth → dist/auth}/auth.js +0 -0
- /package/{auth → dist/auth}/index.d.ts +0 -0
- /package/{auth → dist/auth}/index.js +0 -0
- /package/{core → dist/core}/base.d.ts +0 -0
- /package/{core → dist/core}/base.js +0 -0
- /package/{core → dist/core}/clause.d.ts +0 -0
- /package/{core → dist/core}/clause.js +0 -0
- /package/{core → dist/core}/config.d.ts +0 -0
- /package/{core → dist/core}/config.js +0 -0
- /package/{core → dist/core}/const.d.ts +0 -0
- /package/{core → dist/core}/const.js +0 -0
- /package/{core → dist/core}/context.d.ts +0 -0
- /package/{core → dist/core}/context.js +0 -0
- /package/{core → dist/core}/convert.d.ts +0 -0
- /package/{core → dist/core}/convert.js +0 -0
- /package/{core → dist/core}/date.d.ts +0 -0
- /package/{core → dist/core}/date.js +0 -0
- /package/{core → dist/core}/db.d.ts +0 -0
- /package/{core → dist/core}/db.js +0 -0
- /package/{core → dist/core}/ent.d.ts +0 -0
- /package/{core → dist/core}/ent.js +0 -0
- /package/{core → dist/core}/global_schema.d.ts +0 -0
- /package/{core → dist/core}/global_schema.js +0 -0
- /package/{core → dist/core}/loaders/assoc_count_loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/assoc_count_loader.js +0 -0
- /package/{core → dist/core}/loaders/assoc_edge_loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/assoc_edge_loader.js +0 -0
- /package/{core → dist/core}/loaders/index.d.ts +0 -0
- /package/{core → dist/core}/loaders/index.js +0 -0
- /package/{core → dist/core}/loaders/loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/loader.js +0 -0
- /package/{core → dist/core}/loaders/object_loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/object_loader.js +0 -0
- /package/{core → dist/core}/loaders/query_loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/query_loader.js +0 -0
- /package/{core → dist/core}/loaders/raw_count_loader.d.ts +0 -0
- /package/{core → dist/core}/loaders/raw_count_loader.js +0 -0
- /package/{core → dist/core}/logger.d.ts +0 -0
- /package/{core → dist/core}/logger.js +0 -0
- /package/{core → dist/core}/privacy.d.ts +0 -0
- /package/{core → dist/core}/privacy.js +0 -0
- /package/{core → dist/core}/query/assoc_query.d.ts +0 -0
- /package/{core → dist/core}/query/assoc_query.js +0 -0
- /package/{core → dist/core}/query/custom_clause_query.d.ts +0 -0
- /package/{core → dist/core}/query/custom_clause_query.js +0 -0
- /package/{core → dist/core}/query/custom_query.d.ts +0 -0
- /package/{core → dist/core}/query/custom_query.js +0 -0
- /package/{core → dist/core}/query/index.d.ts +0 -0
- /package/{core → dist/core}/query/index.js +0 -0
- /package/{core → dist/core}/query/query.d.ts +0 -0
- /package/{core → dist/core}/query/query.js +0 -0
- /package/{core → dist/core}/query_impl.d.ts +0 -0
- /package/{core → dist/core}/query_impl.js +0 -0
- /package/{core → dist/core}/viewer.d.ts +0 -0
- /package/{core → dist/core}/viewer.js +0 -0
- /package/{graphql → dist/graphql}/builtins/connection.d.ts +0 -0
- /package/{graphql → dist/graphql}/builtins/connection.js +0 -0
- /package/{graphql → dist/graphql}/builtins/edge.d.ts +0 -0
- /package/{graphql → dist/graphql}/builtins/edge.js +0 -0
- /package/{graphql → dist/graphql}/builtins/node.d.ts +0 -0
- /package/{graphql → dist/graphql}/builtins/node.js +0 -0
- /package/{graphql → dist/graphql}/graphql.d.ts +0 -0
- /package/{graphql → dist/graphql}/graphql.js +0 -0
- /package/{graphql → dist/graphql}/graphql_field_helpers.d.ts +0 -0
- /package/{graphql → dist/graphql}/graphql_field_helpers.js +0 -0
- /package/{graphql → dist/graphql}/index.d.ts +0 -0
- /package/{graphql → dist/graphql}/index.js +0 -0
- /package/{graphql → dist/graphql}/mutations/union.d.ts +0 -0
- /package/{graphql → dist/graphql}/mutations/union.js +0 -0
- /package/{graphql → dist/graphql}/node_resolver.d.ts +0 -0
- /package/{graphql → dist/graphql}/node_resolver.js +0 -0
- /package/{graphql → dist/graphql}/query/connection_type.d.ts +0 -0
- /package/{graphql → dist/graphql}/query/connection_type.js +0 -0
- /package/{graphql → dist/graphql}/query/edge_connection.d.ts +0 -0
- /package/{graphql → dist/graphql}/query/edge_connection.js +0 -0
- /package/{graphql → dist/graphql}/query/page_info.d.ts +0 -0
- /package/{graphql → dist/graphql}/query/page_info.js +0 -0
- /package/{graphql → dist/graphql}/query/shared_edge_connection.d.ts +0 -0
- /package/{graphql → dist/graphql}/query/shared_edge_connection.js +0 -0
- /package/{graphql → dist/graphql}/scalars/orderby_direction.d.ts +0 -0
- /package/{graphql → dist/graphql}/scalars/orderby_direction.js +0 -0
- /package/{graphql → dist/graphql}/scalars/time.d.ts +0 -0
- /package/{graphql → dist/graphql}/scalars/time.js +0 -0
- /package/{imports → dist/imports}/dataz/example1/_auth.d.ts +0 -0
- /package/{imports → dist/imports}/dataz/example1/_auth.js +0 -0
- /package/{imports → dist/imports}/dataz/example1/_viewer.d.ts +0 -0
- /package/{imports → dist/imports}/dataz/example1/_viewer.js +0 -0
- /package/{imports → dist/imports}/index.d.ts +0 -0
- /package/{imports → dist/imports}/index.js +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{index.js → dist/index.js} +0 -0
- /package/{parse_schema → dist/parse_schema}/parse.d.ts +0 -0
- /package/{parse_schema → dist/parse_schema}/parse.js +0 -0
- /package/{schema → dist/schema}/base_schema.d.ts +0 -0
- /package/{schema → dist/schema}/base_schema.js +0 -0
- /package/{schema → dist/schema}/field.d.ts +0 -0
- /package/{schema → dist/schema}/field.js +0 -0
- /package/{schema → dist/schema}/index.d.ts +0 -0
- /package/{schema → dist/schema}/index.js +0 -0
- /package/{schema → dist/schema}/json_field.d.ts +0 -0
- /package/{schema → dist/schema}/json_field.js +0 -0
- /package/{schema → dist/schema}/schema.d.ts +0 -0
- /package/{schema → dist/schema}/schema.js +0 -0
- /package/{schema → dist/schema}/struct_field.d.ts +0 -0
- /package/{schema → dist/schema}/struct_field.js +0 -0
- /package/{schema → dist/schema}/union_field.d.ts +0 -0
- /package/{schema → dist/schema}/union_field.js +0 -0
- /package/{scripts → dist/scripts}/custom_compiler.d.ts +0 -0
- /package/{scripts → dist/scripts}/custom_compiler.js +0 -0
- /package/{scripts → dist/scripts}/custom_graphql.d.ts +0 -0
- /package/{scripts → dist/scripts}/custom_graphql.js +0 -0
- /package/{scripts → dist/scripts}/migrate_v0.1.d.ts +0 -0
- /package/{scripts → dist/scripts}/migrate_v0.1.js +0 -0
- /package/{scripts → dist/scripts}/move_types.d.ts +0 -0
- /package/{scripts → dist/scripts}/move_types.js +0 -0
- /package/{scripts → dist/scripts}/read_schema.d.ts +0 -0
- /package/{scripts → dist/scripts}/read_schema.js +0 -0
- /package/{testutils → dist/testutils}/action/complex_schemas.d.ts +0 -0
- /package/{testutils → dist/testutils}/action/complex_schemas.js +0 -0
- /package/{testutils → dist/testutils}/builder.d.ts +0 -0
- /package/{testutils → dist/testutils}/builder.js +0 -0
- /package/{testutils → dist/testutils}/context/test_context.d.ts +0 -0
- /package/{testutils → dist/testutils}/context/test_context.js +0 -0
- /package/{testutils → dist/testutils}/db/fixture.d.ts +0 -0
- /package/{testutils → dist/testutils}/db/fixture.js +0 -0
- /package/{testutils → dist/testutils}/db/temp_db.d.ts +0 -0
- /package/{testutils → dist/testutils}/db/temp_db.js +0 -0
- /package/{testutils → dist/testutils}/db/value.d.ts +0 -0
- /package/{testutils → dist/testutils}/db/value.js +0 -0
- /package/{testutils → dist/testutils}/db_mock.d.ts +0 -0
- /package/{testutils → dist/testutils}/db_mock.js +0 -0
- /package/{testutils → dist/testutils}/db_time_zone.d.ts +0 -0
- /package/{testutils → dist/testutils}/db_time_zone.js +0 -0
- /package/{testutils → dist/testutils}/ent-graphql-tests/index.d.ts +0 -0
- /package/{testutils → dist/testutils}/ent-graphql-tests/index.js +0 -0
- /package/{testutils → dist/testutils}/fake_comms.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_comms.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/const.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/const.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/events_query.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/events_query.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_contact.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_contact.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_event.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_event.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_tag.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_tag.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_user.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/fake_user.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/index.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/index.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/internal.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/internal.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/tag_query.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/tag_query.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/test_helpers.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/test_helpers.js +0 -0
- /package/{testutils → dist/testutils}/fake_data/user_query.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_data/user_query.js +0 -0
- /package/{testutils → dist/testutils}/fake_log.d.ts +0 -0
- /package/{testutils → dist/testutils}/fake_log.js +0 -0
- /package/{testutils → dist/testutils}/mock_date.d.ts +0 -0
- /package/{testutils → dist/testutils}/mock_date.js +0 -0
- /package/{testutils → dist/testutils}/mock_log.d.ts +0 -0
- /package/{testutils → dist/testutils}/mock_log.js +0 -0
- /package/{testutils → dist/testutils}/parse_sql.d.ts +0 -0
- /package/{testutils → dist/testutils}/parse_sql.js +0 -0
- /package/{testutils → dist/testutils}/test_edge_global_schema.d.ts +0 -0
- /package/{testutils → dist/testutils}/test_edge_global_schema.js +0 -0
- /package/{testutils → dist/testutils}/write.d.ts +0 -0
- /package/{testutils → dist/testutils}/write.js +0 -0
- /package/{tsc → dist/tsc}/ast.d.ts +0 -0
- /package/{tsc → dist/tsc}/ast.js +0 -0
- /package/{tsc → dist/tsc}/compilerOptions.d.ts +0 -0
- /package/{tsc → dist/tsc}/compilerOptions.js +0 -0
- /package/{tsc → dist/tsc}/move_generated.d.ts +0 -0
- /package/{tsc → dist/tsc}/move_generated.js +0 -0
- /package/{tsc → dist/tsc}/transform.d.ts +0 -0
- /package/{tsc → dist/tsc}/transform.js +0 -0
- /package/{tsc → dist/tsc}/transform_action.d.ts +0 -0
- /package/{tsc → dist/tsc}/transform_action.js +0 -0
- /package/{tsc → dist/tsc}/transform_ent.d.ts +0 -0
- /package/{tsc → dist/tsc}/transform_ent.js +0 -0
- /package/{tsc → dist/tsc}/transform_schema.d.ts +0 -0
- /package/{tsc → dist/tsc}/transform_schema.js +0 -0
|
@@ -0,0 +1,1065 @@
|
|
|
1
|
+
import { Data, ID, SelectDataOptions } from "./base";
|
|
2
|
+
import DB, { Dialect } from "./db";
|
|
3
|
+
|
|
4
|
+
// NOTE: we use ? for sqlite dialect even though it supports $1 like postgres so that it'll be easier to support different dialects down the line
|
|
5
|
+
|
|
6
|
+
export interface Clause<T extends Data = Data, K = keyof T> {
|
|
7
|
+
clause(idx: number): string;
|
|
8
|
+
columns(): K[];
|
|
9
|
+
values(): any[];
|
|
10
|
+
instanceKey(): string;
|
|
11
|
+
// values to log when querying
|
|
12
|
+
logValues(): any[];
|
|
13
|
+
// to indicate if a composite clause e.g. combining multiple things
|
|
14
|
+
// one such reason is to be used by other composite clauses to know if to add parens
|
|
15
|
+
// around a clause to ensure order of operations is met
|
|
16
|
+
compositeOp?: string; // e.g. AND, OR etc
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SensitiveValue {
|
|
20
|
+
value(): any;
|
|
21
|
+
logValue(): any;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isSensitive(val: any): val is SensitiveValue {
|
|
25
|
+
return (
|
|
26
|
+
val !== null &&
|
|
27
|
+
typeof val === "object" &&
|
|
28
|
+
(val as SensitiveValue).logValue !== undefined
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function rawValue(val: any) {
|
|
33
|
+
if (isSensitive(val)) {
|
|
34
|
+
return val.value();
|
|
35
|
+
}
|
|
36
|
+
return val;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class simpleClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
40
|
+
constructor(
|
|
41
|
+
protected col: K,
|
|
42
|
+
private value: any,
|
|
43
|
+
private op: string,
|
|
44
|
+
private handleNull?: Clause<T, K>,
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
clause(idx: number): string {
|
|
48
|
+
const nullClause = this.nullClause();
|
|
49
|
+
if (nullClause) {
|
|
50
|
+
return nullClause.clause(idx);
|
|
51
|
+
}
|
|
52
|
+
if (DB.getDialect() === Dialect.Postgres) {
|
|
53
|
+
return `${this.col} ${this.op} $${idx}`;
|
|
54
|
+
}
|
|
55
|
+
return `${this.col} ${this.op} ?`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private nullClause() {
|
|
59
|
+
if (!this.handleNull || this.value !== null) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
return this.handleNull;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
columns(): K[] {
|
|
66
|
+
return [this.col];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
values(): any[] {
|
|
70
|
+
const nullClause = this.nullClause();
|
|
71
|
+
if (nullClause) {
|
|
72
|
+
return nullClause.values();
|
|
73
|
+
}
|
|
74
|
+
if (isSensitive(this.value)) {
|
|
75
|
+
return [this.value.value()];
|
|
76
|
+
}
|
|
77
|
+
return [this.value];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
logValues(): any[] {
|
|
81
|
+
const nullClause = this.nullClause();
|
|
82
|
+
if (nullClause) {
|
|
83
|
+
return nullClause.logValues();
|
|
84
|
+
}
|
|
85
|
+
if (isSensitive(this.value)) {
|
|
86
|
+
return [this.value.logValue()];
|
|
87
|
+
}
|
|
88
|
+
return [this.value];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
instanceKey(): string {
|
|
92
|
+
const nullClause = this.nullClause();
|
|
93
|
+
if (nullClause) {
|
|
94
|
+
return nullClause.instanceKey();
|
|
95
|
+
}
|
|
96
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class isNullClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
101
|
+
constructor(protected col: K) {}
|
|
102
|
+
|
|
103
|
+
clause(_idx: number): string {
|
|
104
|
+
return `${this.col} IS NULL`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
columns(): K[] {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
values(): any[] {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
logValues(): any[] {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
instanceKey(): string {
|
|
120
|
+
return `${this.col} IS NULL`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class isNotNullClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
125
|
+
constructor(protected col: K) {}
|
|
126
|
+
|
|
127
|
+
clause(idx: number): string {
|
|
128
|
+
return `${this.col} IS NOT NULL`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
columns(): K[] {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
values(): any[] {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
logValues(): any[] {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
instanceKey(): string {
|
|
144
|
+
return `${this.col} IS NOT NULL`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
class arraySimpleClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
149
|
+
constructor(protected col: K, private value: any, private op: string) {}
|
|
150
|
+
|
|
151
|
+
clause(idx: number): string {
|
|
152
|
+
if (DB.getDialect() === Dialect.Postgres) {
|
|
153
|
+
return `$${idx} ${this.op} ANY(${this.col})`;
|
|
154
|
+
}
|
|
155
|
+
return `${this.col} ${this.op} ?`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
columns(): K[] {
|
|
159
|
+
return [this.col];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
values(): any[] {
|
|
163
|
+
if (isSensitive(this.value)) {
|
|
164
|
+
return [this.value.value()];
|
|
165
|
+
}
|
|
166
|
+
return [this.value];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
logValues(): any[] {
|
|
170
|
+
if (isSensitive(this.value)) {
|
|
171
|
+
return [this.value.logValue()];
|
|
172
|
+
}
|
|
173
|
+
return [this.value];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
instanceKey(): string {
|
|
177
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class postgresArrayOperator<T extends Data, K = keyof T>
|
|
182
|
+
implements Clause<T, K>
|
|
183
|
+
{
|
|
184
|
+
constructor(
|
|
185
|
+
protected col: K,
|
|
186
|
+
protected value: any,
|
|
187
|
+
private op: string,
|
|
188
|
+
private not?: boolean,
|
|
189
|
+
) {}
|
|
190
|
+
|
|
191
|
+
clause(idx: number): string {
|
|
192
|
+
if (DB.getDialect() === Dialect.Postgres) {
|
|
193
|
+
if (this.not) {
|
|
194
|
+
return `NOT ${this.col} ${this.op} $${idx}`;
|
|
195
|
+
}
|
|
196
|
+
return `${this.col} ${this.op} $${idx}`;
|
|
197
|
+
}
|
|
198
|
+
throw new Error(`not supported`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
columns(): K[] {
|
|
202
|
+
return [this.col];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
values(): any[] {
|
|
206
|
+
if (isSensitive(this.value)) {
|
|
207
|
+
return [`{${this.value.value()}}`];
|
|
208
|
+
}
|
|
209
|
+
return [`{${this.value}}`];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
logValues(): any[] {
|
|
213
|
+
if (isSensitive(this.value)) {
|
|
214
|
+
return [`{${this.value.logValue()}}`];
|
|
215
|
+
}
|
|
216
|
+
return [`{${this.value}}`];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
instanceKey(): string {
|
|
220
|
+
if (this.not) {
|
|
221
|
+
return `NOT:${this.col}${this.op}${rawValue(this.value)}`;
|
|
222
|
+
}
|
|
223
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
class postgresArrayOperatorList<
|
|
228
|
+
T extends Data,
|
|
229
|
+
K = keyof T,
|
|
230
|
+
> extends postgresArrayOperator<T, K> {
|
|
231
|
+
constructor(col: K, value: any[], op: string, not?: boolean) {
|
|
232
|
+
super(col, value, op, not);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
values(): any[] {
|
|
236
|
+
return [
|
|
237
|
+
`{${this.value
|
|
238
|
+
.map((v: any) => {
|
|
239
|
+
if (isSensitive(v)) {
|
|
240
|
+
return v.value();
|
|
241
|
+
}
|
|
242
|
+
return v;
|
|
243
|
+
})
|
|
244
|
+
.join(", ")}}`,
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
logValues(): any[] {
|
|
249
|
+
return [
|
|
250
|
+
`{${this.value
|
|
251
|
+
.map((v: any) => {
|
|
252
|
+
if (isSensitive(v)) {
|
|
253
|
+
return v.logValue();
|
|
254
|
+
}
|
|
255
|
+
return v;
|
|
256
|
+
})
|
|
257
|
+
.join(", ")}}`,
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
type InClauseOperator = "IN" | "NOT IN";
|
|
263
|
+
|
|
264
|
+
export class inClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
265
|
+
protected op: InClauseOperator = "IN";
|
|
266
|
+
|
|
267
|
+
static getPostgresInClauseValuesThreshold() {
|
|
268
|
+
return 70;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
constructor(private col: K, private value: any[], private type = "uuid") {}
|
|
272
|
+
|
|
273
|
+
clause(idx: number): string {
|
|
274
|
+
// do a simple = when only one item
|
|
275
|
+
if (this.value.length === 1) {
|
|
276
|
+
if (this.op === "IN") {
|
|
277
|
+
return new simpleClause(this.col, this.value[0], "=").clause(idx);
|
|
278
|
+
} else {
|
|
279
|
+
return new simpleClause(this.col, this.value[0], "!=").clause(idx);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const postgres = DB.getDialect() === Dialect.Postgres;
|
|
284
|
+
const postgresValuesList =
|
|
285
|
+
postgres &&
|
|
286
|
+
this.value.length >= inClause.getPostgresInClauseValuesThreshold();
|
|
287
|
+
|
|
288
|
+
let indices: string[];
|
|
289
|
+
if (postgres) {
|
|
290
|
+
indices = [];
|
|
291
|
+
for (let i = 0; i < this.value.length; i++) {
|
|
292
|
+
if (postgresValuesList) {
|
|
293
|
+
if (i === 0) {
|
|
294
|
+
indices.push(`($${idx}::${this.type})`);
|
|
295
|
+
} else {
|
|
296
|
+
indices.push(`($${idx})`);
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
indices.push(`$${idx}`);
|
|
300
|
+
}
|
|
301
|
+
idx++;
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
indices = new Array(this.value.length);
|
|
305
|
+
indices.fill("?", 0);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let inValue = indices.join(", ");
|
|
309
|
+
|
|
310
|
+
// wrap in VALUES list for postgres...
|
|
311
|
+
if (postgresValuesList) {
|
|
312
|
+
inValue = `VALUES${inValue}`;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return `${this.col} ${this.op} (${inValue})`;
|
|
316
|
+
// TODO we need to return idx at end to query builder...
|
|
317
|
+
// or anything that's doing a composite query so next clause knows where to start
|
|
318
|
+
// or change to a sqlx.Rebind format
|
|
319
|
+
// here's what sqlx does: https://play.golang.org/p/vPzvYqeAcP0
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
columns(): K[] {
|
|
323
|
+
return [this.col];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
values(): any[] {
|
|
327
|
+
const result: any[] = [];
|
|
328
|
+
for (let value of this.value) {
|
|
329
|
+
result.push(rawValue(value));
|
|
330
|
+
}
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
logValues(): any[] {
|
|
335
|
+
const result: any[] = [];
|
|
336
|
+
for (let value of this.value) {
|
|
337
|
+
result.push(isSensitive(value) ? value.logValue() : value);
|
|
338
|
+
}
|
|
339
|
+
return result;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
instanceKey(): string {
|
|
343
|
+
return `${this.op.toLowerCase()}:${this.col}:${this.values().join(",")}`;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export class notInClause<T extends Data, K = keyof T> extends inClause<T, K> {
|
|
348
|
+
protected op: InClauseOperator = "NOT IN";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
class compositeClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
352
|
+
compositeOp: string;
|
|
353
|
+
|
|
354
|
+
constructor(private clauses: Clause<T, K>[], private sep: string) {
|
|
355
|
+
this.compositeOp = this.sep;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
clause(idx: number): string {
|
|
359
|
+
let clauses: string[] = [];
|
|
360
|
+
for (const clause of this.clauses) {
|
|
361
|
+
let cls = clause.clause(idx);
|
|
362
|
+
// if composite clause and a different op, add parens so that we enforce order of precedence
|
|
363
|
+
if (clause.compositeOp && clause.compositeOp !== this.sep) {
|
|
364
|
+
cls = `(${cls})`;
|
|
365
|
+
}
|
|
366
|
+
clauses.push(cls);
|
|
367
|
+
idx = idx + clause.values().length;
|
|
368
|
+
}
|
|
369
|
+
return clauses.join(this.sep);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
columns(): K[] {
|
|
373
|
+
const ret: K[] = [];
|
|
374
|
+
for (const cls of this.clauses) {
|
|
375
|
+
ret.push(...cls.columns());
|
|
376
|
+
}
|
|
377
|
+
return ret;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
values(): any[] {
|
|
381
|
+
let result = [];
|
|
382
|
+
for (const clause of this.clauses) {
|
|
383
|
+
result = result.concat(...clause.values());
|
|
384
|
+
}
|
|
385
|
+
return result;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
logValues(): any[] {
|
|
389
|
+
let result = [];
|
|
390
|
+
for (const clause of this.clauses) {
|
|
391
|
+
result = result.concat(...clause.logValues());
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
instanceKey(): string {
|
|
397
|
+
let keys: string[] = [];
|
|
398
|
+
this.clauses.forEach((clause) => {
|
|
399
|
+
if (clause.compositeOp && clause.compositeOp != this.sep) {
|
|
400
|
+
keys.push(`(${clause.instanceKey()})`);
|
|
401
|
+
} else {
|
|
402
|
+
keys.push(clause.instanceKey());
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
return keys.join(this.sep);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
class tsQueryClause<T extends Data, K = keyof T> implements Clause<T, K> {
|
|
410
|
+
constructor(
|
|
411
|
+
protected col: K,
|
|
412
|
+
protected val: string | TsQuery,
|
|
413
|
+
private tsVectorCol?: boolean,
|
|
414
|
+
) {}
|
|
415
|
+
|
|
416
|
+
private isTsQuery(val: string | TsQuery): val is TsQuery {
|
|
417
|
+
return typeof val !== "string";
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
protected getInfo() {
|
|
421
|
+
if (this.isTsQuery(this.val)) {
|
|
422
|
+
return { value: this.val.value, language: this.val.language };
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
language: "english",
|
|
426
|
+
value: this.val,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
clause(idx: number): string {
|
|
431
|
+
const { language } = this.getInfo();
|
|
432
|
+
if (Dialect.Postgres === DB.getDialect()) {
|
|
433
|
+
if (this.tsVectorCol) {
|
|
434
|
+
return `to_tsvector(${
|
|
435
|
+
this.col
|
|
436
|
+
}) @@ ${this.getFunction()}('${language}', $${idx})`;
|
|
437
|
+
}
|
|
438
|
+
return `${this.col} @@ ${this.getFunction()}('${language}', $${idx})`;
|
|
439
|
+
}
|
|
440
|
+
// FYI this doesn't actually work for sqlite since different
|
|
441
|
+
return `${this.col} @@ ${this.getFunction()}('${language}', ?)`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
columns(): K[] {
|
|
445
|
+
return [this.col];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
values(): any[] {
|
|
449
|
+
const { value } = this.getInfo();
|
|
450
|
+
return [value];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
logValues(): any[] {
|
|
454
|
+
const { value } = this.getInfo();
|
|
455
|
+
return [value];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
protected getFunction(): string {
|
|
459
|
+
return "to_tsquery";
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
instanceKey(): string {
|
|
463
|
+
const { language, value } = this.getInfo();
|
|
464
|
+
if (this.tsVectorCol) {
|
|
465
|
+
return `to_tsvector(${
|
|
466
|
+
this.col
|
|
467
|
+
})@@${this.getFunction()}:${language}:${value}`;
|
|
468
|
+
}
|
|
469
|
+
return `${this.col}@@${this.getFunction()}:${language}:${value}`;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
class plainToTsQueryClause<T extends Data, K = keyof T> extends tsQueryClause<
|
|
474
|
+
T,
|
|
475
|
+
K
|
|
476
|
+
> {
|
|
477
|
+
protected getFunction(): string {
|
|
478
|
+
return "plainto_tsquery";
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
class phraseToTsQueryClause<T extends Data, K = keyof T> extends tsQueryClause<
|
|
483
|
+
T,
|
|
484
|
+
K
|
|
485
|
+
> {
|
|
486
|
+
protected getFunction(): string {
|
|
487
|
+
return "phraseto_tsquery";
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
class websearchTosQueryClause<
|
|
492
|
+
T extends Data,
|
|
493
|
+
K = keyof T,
|
|
494
|
+
> extends tsQueryClause<T, K> {
|
|
495
|
+
protected getFunction(): string {
|
|
496
|
+
return "websearch_to_tsquery";
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// postgres array operators
|
|
501
|
+
// https://www.postgresql.org/docs/current/functions-array.html
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* creates a clause to determine if the given value is contained in the array stored in the column in the db
|
|
505
|
+
* only works with postgres gin indexes
|
|
506
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
507
|
+
*/
|
|
508
|
+
export function PostgresArrayContainsValue<T extends Data, K = keyof T>(
|
|
509
|
+
col: K,
|
|
510
|
+
value: any,
|
|
511
|
+
): Clause<T, K> {
|
|
512
|
+
return new postgresArrayOperator(col, value, "@>");
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* creates a clause to determine if every item in the list is stored in the array stored in the column in the db
|
|
517
|
+
* only works with postgres gin indexes
|
|
518
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
519
|
+
*/
|
|
520
|
+
export function PostgresArrayContains<T extends Data, K = keyof T>(
|
|
521
|
+
col: K,
|
|
522
|
+
value: any[],
|
|
523
|
+
): Clause<T, K> {
|
|
524
|
+
return new postgresArrayOperatorList(col, value, "@>");
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* creates a clause to determine if the given value is NOT contained in the array stored in the column in the db
|
|
529
|
+
* only works with postgres gin indexes
|
|
530
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
531
|
+
*/
|
|
532
|
+
export function PostgresArrayNotContainsValue<T extends Data, K = keyof T>(
|
|
533
|
+
col: K,
|
|
534
|
+
value: any,
|
|
535
|
+
): Clause<T, K> {
|
|
536
|
+
return new postgresArrayOperator(col, value, "@>", true);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* creates a clause to determine if every item in the list is NOT stored in the array stored in the column in the db
|
|
541
|
+
* only works with postgres gin indexes
|
|
542
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
543
|
+
*/
|
|
544
|
+
export function PostgresArrayNotContains<T extends Data, K = keyof T>(
|
|
545
|
+
col: K,
|
|
546
|
+
value: any[],
|
|
547
|
+
): Clause<T, K> {
|
|
548
|
+
return new postgresArrayOperatorList(col, value, "@>", true);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* creates a clause to determine if the arrays overlap, that is, do they have any elements in common
|
|
553
|
+
* only works with postgres gin indexes
|
|
554
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
555
|
+
*/
|
|
556
|
+
export function PostgresArrayOverlaps<T extends Data, K = keyof T>(
|
|
557
|
+
col: K,
|
|
558
|
+
value: any[],
|
|
559
|
+
): Clause<T, K> {
|
|
560
|
+
return new postgresArrayOperatorList(col, value, "&&");
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* creates a clause to determine if the arrays do not overlap, that is, do they have any elements in common
|
|
565
|
+
* only works with postgres gin indexes
|
|
566
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
567
|
+
*/
|
|
568
|
+
export function PostgresArrayNotOverlaps<T extends Data, K = keyof T>(
|
|
569
|
+
col: K,
|
|
570
|
+
value: any[],
|
|
571
|
+
): Clause<T, K> {
|
|
572
|
+
return new postgresArrayOperatorList(col, value, "&&", true);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* @deprecated use PostgresArrayContainsValue
|
|
577
|
+
*/
|
|
578
|
+
export function ArrayEq<T extends Data, K = keyof T>(
|
|
579
|
+
col: K,
|
|
580
|
+
value: any,
|
|
581
|
+
): Clause<T, K> {
|
|
582
|
+
return new arraySimpleClause(col, value, "=");
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* @deprecated use PostgresNotArrayContains
|
|
587
|
+
*/
|
|
588
|
+
export function ArrayNotEq<T extends Data, K = keyof T>(
|
|
589
|
+
col: K,
|
|
590
|
+
value: any,
|
|
591
|
+
): Clause<T, K> {
|
|
592
|
+
return new arraySimpleClause(col, value, "!=");
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
export function Eq<T extends Data, K = keyof T>(
|
|
596
|
+
col: K,
|
|
597
|
+
value: any,
|
|
598
|
+
): Clause<T, K> {
|
|
599
|
+
return new simpleClause<T, K>(col, value, "=", new isNullClause(col));
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export function NotEq<T extends Data, K = keyof T>(
|
|
603
|
+
col: K,
|
|
604
|
+
value: any,
|
|
605
|
+
): Clause<T, K> {
|
|
606
|
+
return new simpleClause<T, K>(col, value, "!=", new isNotNullClause(col));
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export function Greater<T extends Data, K = keyof T>(
|
|
610
|
+
col: K,
|
|
611
|
+
value: any,
|
|
612
|
+
): Clause<T, K> {
|
|
613
|
+
return new simpleClause<T, K>(col, value, ">");
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export function Less<T extends Data, K = keyof T>(
|
|
617
|
+
col: K,
|
|
618
|
+
value: any,
|
|
619
|
+
): Clause<T, K> {
|
|
620
|
+
return new simpleClause<T, K>(col, value, "<");
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
export function GreaterEq<T extends Data, K = keyof T>(
|
|
624
|
+
col: K,
|
|
625
|
+
value: any,
|
|
626
|
+
): Clause<T, K> {
|
|
627
|
+
return new simpleClause<T, K>(col, value, ">=");
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
export function LessEq<T extends Data, K = keyof T>(
|
|
631
|
+
col: K,
|
|
632
|
+
value: any,
|
|
633
|
+
): Clause<T, K> {
|
|
634
|
+
return new simpleClause<T, K>(col, value, "<=");
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
export function And<T extends Data, K = keyof T>(
|
|
638
|
+
...args: Clause<T, K>[]
|
|
639
|
+
): Clause<T, K> {
|
|
640
|
+
return new compositeClause(args, " AND ");
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export function AndOptional<T extends Data, K = keyof T>(
|
|
644
|
+
...args: (Clause<T, K> | undefined)[]
|
|
645
|
+
): Clause<T, K> {
|
|
646
|
+
// @ts-ignore
|
|
647
|
+
let filtered: Clause<T, K>[] = args.filter((v) => v !== undefined);
|
|
648
|
+
if (filtered.length === 1) {
|
|
649
|
+
return filtered[0];
|
|
650
|
+
}
|
|
651
|
+
return And(...filtered);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
export function Or<T extends Data, K = keyof T>(
|
|
655
|
+
...args: Clause<T, K>[]
|
|
656
|
+
): Clause<T, K> {
|
|
657
|
+
return new compositeClause(args, " OR ");
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export function OrOptional<T extends Data, K = keyof T>(
|
|
661
|
+
...args: (Clause<T, K> | undefined)[]
|
|
662
|
+
): Clause<T, K> {
|
|
663
|
+
// @ts-ignore
|
|
664
|
+
let filtered: Clause<T, K>[] = args.filter((v) => v !== undefined);
|
|
665
|
+
if (filtered.length === 1) {
|
|
666
|
+
return filtered[0];
|
|
667
|
+
}
|
|
668
|
+
return Or(...filtered);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* @deprecated use UUidIn, TextIn, IntegerIn, or TypeIn
|
|
673
|
+
*/
|
|
674
|
+
export function In<T extends Data, K = keyof T>(
|
|
675
|
+
col: K,
|
|
676
|
+
...values: any
|
|
677
|
+
): Clause<T, K>;
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* @deprecated use UUidIn, TextIn, IntegerIn, or TypeIn
|
|
681
|
+
*/
|
|
682
|
+
export function In<T extends Data, K = keyof T>(
|
|
683
|
+
col: K,
|
|
684
|
+
values: any[],
|
|
685
|
+
type?: string,
|
|
686
|
+
): Clause<T, K>;
|
|
687
|
+
|
|
688
|
+
export function In<T extends Data, K = keyof T>(...args: any[]): Clause<T, K> {
|
|
689
|
+
if (args.length < 2) {
|
|
690
|
+
throw new Error(`invalid args passed to In`);
|
|
691
|
+
}
|
|
692
|
+
// 2nd overload
|
|
693
|
+
if (Array.isArray(args[1])) {
|
|
694
|
+
return new inClause(args[0], args[1], args[2]);
|
|
695
|
+
}
|
|
696
|
+
return new inClause(args[0], args.slice(1));
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export function UuidIn<T extends Data, K = keyof T>(
|
|
700
|
+
col: K,
|
|
701
|
+
values: ID[],
|
|
702
|
+
): Clause<T, K> {
|
|
703
|
+
return new inClause(col, values, "uuid");
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export function IntegerIn<T extends Data, K = keyof T>(
|
|
707
|
+
col: K,
|
|
708
|
+
values: number[],
|
|
709
|
+
): Clause<T, K> {
|
|
710
|
+
return new inClause(col, values, "integer");
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
export function TextIn<T extends Data, K = keyof T>(
|
|
714
|
+
col: K,
|
|
715
|
+
values: any[],
|
|
716
|
+
): Clause<T, K> {
|
|
717
|
+
return new inClause(col, values, "text");
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/*
|
|
721
|
+
* if not uuid or text, pass the db type that can be used to cast this query
|
|
722
|
+
* if we end up with a large list of ids
|
|
723
|
+
*/
|
|
724
|
+
export function DBTypeIn<T extends Data, K = keyof T>(
|
|
725
|
+
col: K,
|
|
726
|
+
values: any[],
|
|
727
|
+
typ: string,
|
|
728
|
+
): Clause<T, K> {
|
|
729
|
+
return new inClause(col, values, typ);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
export function UuidNotIn<T extends Data, K = keyof T>(
|
|
733
|
+
col: K,
|
|
734
|
+
values: ID[],
|
|
735
|
+
): Clause<T, K> {
|
|
736
|
+
return new notInClause(col, values, "uuid");
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export function IntegerNotIn<T extends Data, K = keyof T>(
|
|
740
|
+
col: K,
|
|
741
|
+
values: number[],
|
|
742
|
+
): Clause<T, K> {
|
|
743
|
+
return new notInClause(col, values, "integer");
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
export function TextNotIn<T extends Data, K = keyof T>(
|
|
747
|
+
col: K,
|
|
748
|
+
values: any[],
|
|
749
|
+
): Clause<T, K> {
|
|
750
|
+
return new notInClause(col, values, "text");
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/*
|
|
754
|
+
* if not uuid or text, pass the db type that can be used to cast this query
|
|
755
|
+
* if we end up with a large list of ids
|
|
756
|
+
*/
|
|
757
|
+
export function DBTypeNotIn<T extends Data, K = keyof T>(
|
|
758
|
+
col: K,
|
|
759
|
+
values: any[],
|
|
760
|
+
typ: string,
|
|
761
|
+
): Clause<T, K> {
|
|
762
|
+
return new notInClause(col, values, typ);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
interface TsQuery {
|
|
766
|
+
// todo lang ::reconfig
|
|
767
|
+
language: "english" | "french" | "german" | "simple";
|
|
768
|
+
value: string;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// if string defaults to english
|
|
772
|
+
// https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
|
|
773
|
+
// to_tsquery
|
|
774
|
+
// plainto_tsquery
|
|
775
|
+
// phraseto_tsquery;
|
|
776
|
+
// websearch_to_tsquery
|
|
777
|
+
export function TsQuery<T extends Data, K = keyof T>(
|
|
778
|
+
col: K,
|
|
779
|
+
val: string | TsQuery,
|
|
780
|
+
): Clause<T, K> {
|
|
781
|
+
return new tsQueryClause(col, val);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
export function PlainToTsQuery<T extends Data, K = keyof T>(
|
|
785
|
+
col: K,
|
|
786
|
+
val: string | TsQuery,
|
|
787
|
+
): Clause<T, K> {
|
|
788
|
+
return new plainToTsQueryClause(col, val);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
export function PhraseToTsQuery<T extends Data, K = keyof T>(
|
|
792
|
+
col: K,
|
|
793
|
+
val: string | TsQuery,
|
|
794
|
+
): Clause<T, K> {
|
|
795
|
+
return new phraseToTsQueryClause(col, val);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
export function WebsearchToTsQuery<T extends Data, K = keyof T>(
|
|
799
|
+
col: K,
|
|
800
|
+
val: string | TsQuery,
|
|
801
|
+
): Clause<T, K> {
|
|
802
|
+
return new websearchTosQueryClause(col, val);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// TsVectorColTsQuery is used when the column is not a tsvector field e.g.
|
|
806
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
807
|
+
export function TsVectorColTsQuery<T extends Data, K = keyof T>(
|
|
808
|
+
col: K,
|
|
809
|
+
val: string | TsQuery,
|
|
810
|
+
): Clause<T, K> {
|
|
811
|
+
return new tsQueryClause(col, val, true);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// TsVectorPlainToTsQuery is used when the column is not a tsvector field e.g.
|
|
815
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
816
|
+
// TODO do these 4 need TsQuery because would be nice to have language?
|
|
817
|
+
// it seems to default to the config of the column
|
|
818
|
+
export function TsVectorPlainToTsQuery<T extends Data, K = keyof T>(
|
|
819
|
+
col: K,
|
|
820
|
+
val: string | TsQuery,
|
|
821
|
+
): Clause<T, K> {
|
|
822
|
+
return new plainToTsQueryClause(col, val, true);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// TsVectorPhraseToTsQuery is used when the column is not a tsvector field e.g.
|
|
826
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
827
|
+
export function TsVectorPhraseToTsQuery<T extends Data, K = keyof T>(
|
|
828
|
+
col: K,
|
|
829
|
+
val: string | TsQuery,
|
|
830
|
+
): Clause<T, K> {
|
|
831
|
+
return new phraseToTsQueryClause(col, val, true);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// TsVectorWebsearchToTsQuery is used when the column is not a tsvector field e.g.
|
|
835
|
+
// when there's an index just on the field and is not a combination of multiple fields
|
|
836
|
+
export function TsVectorWebsearchToTsQuery<T extends Data, K = keyof T>(
|
|
837
|
+
col: K,
|
|
838
|
+
val: string | TsQuery,
|
|
839
|
+
): Clause<T, K> {
|
|
840
|
+
return new websearchTosQueryClause(col, val, true);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// TODO would be nice to support this with building blocks but not supporting for now
|
|
844
|
+
// AND: foo & bar,
|
|
845
|
+
// OR: foo | bar
|
|
846
|
+
// followed by: foo <-> bar
|
|
847
|
+
// NOT: !foo
|
|
848
|
+
// starts_with: theo:*
|
|
849
|
+
|
|
850
|
+
// wrap a query in the db with this to ensure that it doesn't show up in the logs
|
|
851
|
+
// e.g. if querying for password, SSN, etc
|
|
852
|
+
// we'll pass the right fields to query and log something along the lines of `****`
|
|
853
|
+
export function sensitiveValue(val: any): SensitiveValue {
|
|
854
|
+
return {
|
|
855
|
+
value() {
|
|
856
|
+
return val;
|
|
857
|
+
},
|
|
858
|
+
logValue() {
|
|
859
|
+
return "*".repeat(`${val}`.length);
|
|
860
|
+
},
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// These don't return Clauses but return helpful things that can be passed to clauses
|
|
865
|
+
|
|
866
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
867
|
+
// see test in db_clause.test.ts
|
|
868
|
+
// unclear best time to use this...
|
|
869
|
+
export function JSONObjectFieldKeyASJSON<T extends Data, K = keyof T>(
|
|
870
|
+
col: K,
|
|
871
|
+
field: string,
|
|
872
|
+
): keyof T {
|
|
873
|
+
// type as keyof T to make it easier to use in other queries
|
|
874
|
+
return `${col}->'${field}'`;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
export function JSONObjectFieldKeyAsText<T extends Data, K = keyof T>(
|
|
878
|
+
col: K,
|
|
879
|
+
field: string,
|
|
880
|
+
): keyof T {
|
|
881
|
+
// type as keyof T to make it easier to use in other queries
|
|
882
|
+
return `${col}->>'${field}'`;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// can't get this to work...
|
|
886
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
887
|
+
// export function ArrayIndexAsText(col: string, index: number) {
|
|
888
|
+
// return `${col}->>${index}`;
|
|
889
|
+
// }
|
|
890
|
+
|
|
891
|
+
type predicate = "==" | ">" | "<" | "!=" | ">=" | "<=";
|
|
892
|
+
|
|
893
|
+
class jSONPathValuePredicateClause<T extends Data, K = keyof T>
|
|
894
|
+
implements Clause<T, K>
|
|
895
|
+
{
|
|
896
|
+
constructor(
|
|
897
|
+
protected col: K,
|
|
898
|
+
protected path: string,
|
|
899
|
+
protected value: any,
|
|
900
|
+
private pred: predicate,
|
|
901
|
+
) {}
|
|
902
|
+
|
|
903
|
+
clause(idx: number): string {
|
|
904
|
+
if (DB.getDialect() !== Dialect.Postgres) {
|
|
905
|
+
throw new Error(`not supported`);
|
|
906
|
+
}
|
|
907
|
+
return `${this.col} @@ $${idx}`;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
columns(): K[] {
|
|
911
|
+
return [this.col];
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
private wrap(val: any) {
|
|
915
|
+
return `${this.path} ${this.pred} ${JSON.stringify(val)}`;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
values(): any[] {
|
|
919
|
+
if (isSensitive(this.value)) {
|
|
920
|
+
return [this.wrap(this.value.value())];
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
return [this.wrap(this.value)];
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
logValues(): any[] {
|
|
927
|
+
if (isSensitive(this.value)) {
|
|
928
|
+
return [this.wrap(this.value.logValue())];
|
|
929
|
+
}
|
|
930
|
+
return [this.wrap(this.value)];
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
instanceKey(): string {
|
|
934
|
+
return `${this.col}${this.path}${rawValue(this.value)}${this.pred}`;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
939
|
+
export function JSONPathValuePredicate<T extends Data, K = keyof T>(
|
|
940
|
+
dbCol: K,
|
|
941
|
+
path: string,
|
|
942
|
+
val: any,
|
|
943
|
+
pred: predicate,
|
|
944
|
+
): Clause<T, K> {
|
|
945
|
+
return new jSONPathValuePredicateClause(dbCol, path, val, pred);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// TODO need a better name for this lol
|
|
949
|
+
// this assumes we're doing the same direction twice which isn't necessarily accurate in the future...
|
|
950
|
+
class paginationMultipleColumnsSubQueryClause<T extends Data, K = keyof T>
|
|
951
|
+
implements Clause<T, K>
|
|
952
|
+
{
|
|
953
|
+
constructor(
|
|
954
|
+
private col: K,
|
|
955
|
+
private op: string,
|
|
956
|
+
private tableName: string,
|
|
957
|
+
private uniqueCol: K,
|
|
958
|
+
private val: any,
|
|
959
|
+
) {}
|
|
960
|
+
|
|
961
|
+
private buildSimpleQuery(clause: Clause<T, K>, idx: number) {
|
|
962
|
+
return `SELECT ${this.col} FROM ${this.tableName} WHERE ${clause.clause(
|
|
963
|
+
idx,
|
|
964
|
+
)}`;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
clause(idx: number): string {
|
|
968
|
+
const eq1 = this.buildSimpleQuery(Eq(this.uniqueCol, this.val), idx);
|
|
969
|
+
const eq2 = this.buildSimpleQuery(Eq(this.uniqueCol, this.val), idx + 1);
|
|
970
|
+
const op = new simpleClause(this.uniqueCol, this.val, this.op).clause(
|
|
971
|
+
idx + 2,
|
|
972
|
+
);
|
|
973
|
+
|
|
974
|
+
// nest in () to make sure it's scoped correctly
|
|
975
|
+
return `(${this.col} ${this.op} (${eq1}) OR (${this.col} = (${eq2}) AND ${op}))`;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
columns(): K[] {
|
|
979
|
+
return [this.col];
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
values(): any[] {
|
|
983
|
+
return [this.val, this.val, this.val];
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
logValues(): any[] {
|
|
987
|
+
const log = isSensitive(this.val) ? this.val.logValue() : this.val;
|
|
988
|
+
return [log, log, log];
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
instanceKey(): string {
|
|
992
|
+
return `${this.col}-${this.op}-${this.tableName}-${this.uniqueCol}-${this.val}`;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
export function PaginationMultipleColsSubQuery<T extends Data, K = keyof T>(
|
|
997
|
+
col: K,
|
|
998
|
+
op: string,
|
|
999
|
+
tableName: string,
|
|
1000
|
+
uniqueCol: K,
|
|
1001
|
+
val: any,
|
|
1002
|
+
): Clause<T, K> {
|
|
1003
|
+
return new paginationMultipleColumnsSubQueryClause(
|
|
1004
|
+
col,
|
|
1005
|
+
op,
|
|
1006
|
+
tableName,
|
|
1007
|
+
uniqueCol,
|
|
1008
|
+
val,
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// These 5 are used on the RHS of an expression
|
|
1013
|
+
export function Add<T extends Data, K = keyof T>(
|
|
1014
|
+
col: K,
|
|
1015
|
+
value: any,
|
|
1016
|
+
): Clause<T, K> {
|
|
1017
|
+
return new simpleClause(col, value, "+", new isNullClause(col));
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
export function Subtract<T extends Data, K = keyof T>(
|
|
1021
|
+
col: K,
|
|
1022
|
+
value: any,
|
|
1023
|
+
): Clause<T, K> {
|
|
1024
|
+
return new simpleClause(col, value, "-", new isNullClause(col));
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
export function Multiply<T extends Data, K = keyof T>(
|
|
1028
|
+
col: K,
|
|
1029
|
+
value: any,
|
|
1030
|
+
): Clause<T, K> {
|
|
1031
|
+
return new simpleClause(col, value, "*", new isNullClause(col));
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
export function Divide<T extends Data, K = keyof T>(
|
|
1035
|
+
col: K,
|
|
1036
|
+
value: any,
|
|
1037
|
+
): Clause<T, K> {
|
|
1038
|
+
return new simpleClause(col, value, "/", new isNullClause(col));
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
export function Modulo<T extends Data, K = keyof T>(
|
|
1042
|
+
col: K,
|
|
1043
|
+
value: any,
|
|
1044
|
+
): Clause<T, K> {
|
|
1045
|
+
return new simpleClause(col, value, "%", new isNullClause(col));
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
export function getCombinedClause<V extends Data = Data, K = keyof V>(
|
|
1049
|
+
options: Omit<SelectDataOptions, "key">,
|
|
1050
|
+
cls: Clause<V, K>,
|
|
1051
|
+
): Clause<V, K> {
|
|
1052
|
+
if (options.clause) {
|
|
1053
|
+
let optionClause: Clause | undefined;
|
|
1054
|
+
if (typeof options.clause === "function") {
|
|
1055
|
+
optionClause = options.clause();
|
|
1056
|
+
} else {
|
|
1057
|
+
optionClause = options.clause;
|
|
1058
|
+
}
|
|
1059
|
+
if (optionClause) {
|
|
1060
|
+
// @ts-expect-error different types
|
|
1061
|
+
cls = And(cls, optionClause);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
return cls;
|
|
1065
|
+
}
|