@contember/engine-content-api 1.1.1 → 1.2.0-alpha.10
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/src/acl/EvaluatedPredicateReplacer.d.ts +9 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.d.ts.map +1 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.js +31 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.js.map +1 -0
- package/dist/src/acl/PermissionFactory.d.ts.map +1 -1
- package/dist/src/acl/PermissionFactory.js +15 -11
- package/dist/src/acl/PermissionFactory.js.map +1 -1
- package/dist/src/acl/PredicateFactory.d.ts +4 -2
- package/dist/src/acl/PredicateFactory.d.ts.map +1 -1
- package/dist/src/acl/PredicateFactory.js +24 -6
- package/dist/src/acl/PredicateFactory.js.map +1 -1
- package/dist/src/acl/PredicatesInjector.d.ts +1 -1
- package/dist/src/acl/PredicatesInjector.d.ts.map +1 -1
- package/dist/src/acl/PredicatesInjector.js +18 -14
- package/dist/src/acl/PredicatesInjector.js.map +1 -1
- package/dist/src/acl/VariableInjector.d.ts +0 -1
- package/dist/src/acl/VariableInjector.d.ts.map +1 -1
- package/dist/src/acl/VariableInjector.js +4 -14
- package/dist/src/acl/VariableInjector.js.map +1 -1
- package/dist/src/acl/VariableUtils.d.ts +2 -13
- package/dist/src/acl/VariableUtils.d.ts.map +1 -1
- package/dist/src/acl/VariableUtils.js +5 -16
- package/dist/src/acl/VariableUtils.js.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.js +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.js +25 -13
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.js +26 -13
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.js.map +1 -1
- package/dist/src/input-validation/ValidationContext.d.ts +2 -2
- package/dist/src/input-validation/ValidationContext.d.ts.map +1 -1
- package/dist/src/input-validation/ValidationContext.js.map +1 -1
- package/dist/src/input-validation/ValidationDataSelector.d.ts.map +1 -1
- package/dist/src/input-validation/ValidationDataSelector.js +1 -1
- package/dist/src/input-validation/ValidationDataSelector.js.map +1 -1
- package/dist/src/introspection/content-schema.types.d.ts +19 -223
- package/dist/src/introspection/content-schema.types.d.ts.map +1 -1
- package/dist/src/introspection/content-schema.types.js +2 -2
- package/dist/src/introspection/content-schema.types.js.map +1 -1
- package/dist/src/mapper/Mapper.d.ts +4 -4
- package/dist/src/mapper/Mapper.d.ts.map +1 -1
- package/dist/src/mapper/Mapper.js +7 -7
- package/dist/src/mapper/Mapper.js.map +1 -1
- package/dist/src/mapper/MapperContainer.d.ts.map +1 -1
- package/dist/src/mapper/MapperContainer.js +5 -2
- package/dist/src/mapper/MapperContainer.js.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.d.ts +40 -5
- package/dist/src/mapper/select/RelationFetcher.d.ts.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.js +19 -6
- package/dist/src/mapper/select/RelationFetcher.js.map +1 -1
- package/dist/src/mapper/select/WhereBuilder.d.ts +3 -1
- package/dist/src/mapper/select/WhereBuilder.d.ts.map +1 -1
- package/dist/src/mapper/select/WhereBuilder.js +4 -2
- package/dist/src/mapper/select/WhereBuilder.js.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts +2 -2
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.js +31 -18
- package/dist/src/mapper/select/handlers/FieldsVisitor.js.map +1 -1
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.d.ts +5 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.js +33 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.d.ts +14 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.js +86 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.d.ts +3 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.js +27 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/helpers.d.ts +10 -0
- package/dist/src/mapper/select/optimizer/helpers.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/helpers.js +72 -0
- package/dist/src/mapper/select/optimizer/helpers.js.map +1 -0
- package/dist/src/resolvers/GraphQlQueryAstFactory.js +2 -2
- package/dist/src/resolvers/GraphQlQueryAstFactory.js.map +1 -1
- package/dist/src/resolvers/MutationResolver.js +15 -15
- package/dist/src/resolvers/MutationResolver.js.map +1 -1
- package/dist/src/resolvers/ReadHelpers.js +10 -10
- package/dist/src/resolvers/ReadHelpers.js.map +1 -1
- package/dist/src/resolvers/ReadResolver.js +2 -2
- package/dist/src/resolvers/ReadResolver.js.map +1 -1
- package/dist/src/schema/MutationProvider.js +4 -4
- package/dist/src/schema/MutationProvider.js.map +1 -1
- package/dist/src/schema/QueryProvider.js +3 -3
- package/dist/src/schema/QueryProvider.js.map +1 -1
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts +2 -2
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts.map +1 -1
- package/dist/src/schema/entities/FieldArgsVisitor.d.ts +4 -4
- package/dist/src/schema/entities/FieldArgsVisitor.d.ts.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/utils/object.d.ts.map +1 -1
- package/dist/src/utils/object.js +3 -4
- package/dist/src/utils/object.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/delete/aclDelete.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/delete/aclDelete.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/acl/setField.test.js +2 -2
- package/dist/tests/cases/integration/graphQlRequests/insert/acl/setField.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/aclInsert.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/aclInsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.js +7 -6
- package/dist/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.d.ts +2 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.js +137 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.js.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/filter/complexCondition.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.js +73 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js +73 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js +6 -6
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js +6 -3
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlSchema/model.js.map +1 -1
- package/dist/tests/cases/unit/aclVariablesFactory.test.js +7 -33
- package/dist/tests/cases/unit/aclVariablesFactory.test.js.map +1 -1
- package/dist/tests/cases/unit/conditionOptimizer.test.d.ts +2 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.js +118 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.js.map +1 -0
- package/dist/tests/cases/unit/orderbyHelper.test.js +1 -0
- package/dist/tests/cases/unit/orderbyHelper.test.js.map +1 -1
- package/dist/tests/cases/unit/permissionMerger.test.js +2 -0
- package/dist/tests/cases/unit/permissionMerger.test.js.map +1 -1
- package/dist/tests/cases/unit/predicatesFactory.test.d.ts +2 -0
- package/dist/tests/cases/unit/predicatesFactory.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/predicatesFactory.test.js +103 -0
- package/dist/tests/cases/unit/predicatesFactory.test.js.map +1 -0
- package/dist/tests/cases/unit/predicatesInjector.test.js +88 -14
- package/dist/tests/cases/unit/predicatesInjector.test.js.map +1 -1
- package/dist/tests/cases/unit/variableInjector.test.js +4 -3
- package/dist/tests/cases/unit/variableInjector.test.js.map +1 -1
- package/dist/tests/cases/unit/whereOptimizer.test.d.ts +2 -0
- package/dist/tests/cases/unit/whereOptimizer.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/whereOptimizer.test.js +183 -0
- package/dist/tests/cases/unit/whereOptimizer.test.js.map +1 -0
- package/dist/tests/src/testGraphql.d.ts.map +1 -1
- package/dist/tests/src/testGraphql.js +10 -2
- package/dist/tests/src/testGraphql.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/graphql.codegen.yml +0 -3
- package/package.json +16 -16
- package/src/acl/EvaluatedPredicateReplacer.ts +32 -0
- package/src/acl/PermissionFactory.ts +18 -13
- package/src/acl/PredicateFactory.ts +39 -8
- package/src/acl/PredicatesInjector.ts +26 -13
- package/src/acl/VariableInjector.ts +2 -15
- package/src/acl/VariableUtils.ts +7 -23
- package/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.ts +3 -3
- package/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.ts +26 -28
- package/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.ts +27 -31
- package/src/input-validation/ValidationContext.ts +2 -2
- package/src/input-validation/ValidationDataSelector.ts +2 -2
- package/src/introspection/content-schema.types.ts +19 -286
- package/src/mapper/Mapper.ts +10 -6
- package/src/mapper/MapperContainer.ts +7 -3
- package/src/mapper/select/RelationFetcher.ts +95 -34
- package/src/mapper/select/WhereBuilder.ts +5 -2
- package/src/mapper/select/handlers/FieldsVisitor.ts +31 -24
- package/src/mapper/select/optimizer/ConditionOptimizer.ts +35 -0
- package/src/mapper/select/optimizer/WhereOptimizer.ts +100 -0
- package/src/mapper/select/optimizer/WhereReplacer.ts +22 -0
- package/src/mapper/select/optimizer/helpers.ts +58 -0
- package/src/resolvers/GraphQlQueryAstFactory.ts +3 -3
- package/src/resolvers/MutationResolver.ts +1 -1
- package/src/resolvers/ReadHelpers.ts +3 -3
- package/src/resolvers/ReadResolver.ts +2 -2
- package/src/utils/object.ts +6 -6
- package/tests/cases/integration/graphQlRequests/delete/aclDelete.test.ts +2 -2
- package/tests/cases/integration/graphQlRequests/insert/acl/setField.test.ts +3 -3
- package/tests/cases/integration/graphQlRequests/insert/aclInsert.test.ts +2 -2
- package/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.ts +7 -6
- package/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.ts +130 -0
- package/tests/cases/integration/graphQlRequests/query/filter/complexCondition.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.ts +74 -0
- package/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.ts +77 -0
- package/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.ts +7 -7
- package/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.ts +5 -5
- package/tests/cases/unit/aclVariablesFactory.test.ts +8 -35
- package/tests/cases/unit/conditionOptimizer.test.ts +135 -0
- package/tests/cases/unit/orderbyHelper.test.ts +1 -0
- package/tests/cases/unit/permissionMerger.test.ts +2 -0
- package/tests/cases/unit/predicatesFactory.test.ts +97 -0
- package/tests/cases/unit/predicatesInjector.test.ts +78 -16
- package/tests/cases/unit/variableInjector.test.ts +6 -5
- package/tests/cases/unit/whereOptimizer.test.ts +195 -0
- package/tests/src/testGraphql.ts +9 -2
- package/jasmine.json +0 -7
|
@@ -5,6 +5,7 @@ import { Path, PathFactory } from './Path'
|
|
|
5
5
|
import { JoinBuilder } from './JoinBuilder'
|
|
6
6
|
import { ConditionBuilder } from './ConditionBuilder'
|
|
7
7
|
import { ConditionBuilder as SqlConditionBuilder, Operator, QueryBuilder, SelectBuilder } from '@contember/database'
|
|
8
|
+
import { WhereOptimizer } from './optimizer/WhereOptimizer'
|
|
8
9
|
|
|
9
10
|
export class WhereBuilder {
|
|
10
11
|
constructor(
|
|
@@ -12,6 +13,7 @@ export class WhereBuilder {
|
|
|
12
13
|
private readonly joinBuilder: JoinBuilder,
|
|
13
14
|
private readonly conditionBuilder: ConditionBuilder,
|
|
14
15
|
private readonly pathFactory: PathFactory,
|
|
16
|
+
private readonly whereOptimizer: WhereOptimizer,
|
|
15
17
|
) {}
|
|
16
18
|
|
|
17
19
|
public build(
|
|
@@ -31,9 +33,10 @@ export class WhereBuilder {
|
|
|
31
33
|
callback: (clauseCb: (clause: SqlConditionBuilder) => SqlConditionBuilder) => SelectBuilder<SelectBuilder.Result>,
|
|
32
34
|
allowManyJoin: boolean = false,
|
|
33
35
|
) {
|
|
36
|
+
const optimizedWhere = this.whereOptimizer.optimize(where, entity)
|
|
34
37
|
const joinList: WhereJoinDefinition[] = []
|
|
35
38
|
|
|
36
|
-
const qbWithWhere = callback(clause => this.buildInternal(clause, entity, path,
|
|
39
|
+
const qbWithWhere = callback(clause => this.buildInternal(clause, entity, path, optimizedWhere, allowManyJoin, joinList))
|
|
37
40
|
return joinList.reduce<SelectBuilder<SelectBuilder.Result>>(
|
|
38
41
|
(qb, { path, entity, relationName }) => this.joinBuilder.join(qb, path, entity, relationName),
|
|
39
42
|
qbWithWhere,
|
|
@@ -44,7 +47,7 @@ export class WhereBuilder {
|
|
|
44
47
|
conditionBuilder: SqlConditionBuilder,
|
|
45
48
|
entity: Model.Entity,
|
|
46
49
|
path: Path,
|
|
47
|
-
where: Input.
|
|
50
|
+
where: Input.Where,
|
|
48
51
|
allowManyJoin: boolean,
|
|
49
52
|
joinList: WhereJoinDefinition[],
|
|
50
53
|
): SqlConditionBuilder {
|
|
@@ -4,7 +4,6 @@ import { RelationFetcher } from '../RelationFetcher'
|
|
|
4
4
|
import { SelectExecutionHandlerContext } from '../SelectExecutionHandler'
|
|
5
5
|
import { PredicateFactory } from '../../../acl'
|
|
6
6
|
import { WhereBuilder } from '../WhereBuilder'
|
|
7
|
-
import { JoiningColumns } from '../../types'
|
|
8
7
|
|
|
9
8
|
export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.ColumnVisitor<void> {
|
|
10
9
|
constructor(
|
|
@@ -56,11 +55,6 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
56
55
|
targetEntity: Model.Entity,
|
|
57
56
|
targetRelation: Model.ManyHasManyOwningRelation,
|
|
58
57
|
): void {
|
|
59
|
-
const joiningTable = targetRelation.joiningTable
|
|
60
|
-
const columns: JoiningColumns = {
|
|
61
|
-
sourceColumn: joiningTable.inverseJoiningColumn,
|
|
62
|
-
targetColumn: joiningTable.joiningColumn,
|
|
63
|
-
}
|
|
64
58
|
const field = this.executionContext.objectNode
|
|
65
59
|
if (!field) {
|
|
66
60
|
throw new Error()
|
|
@@ -69,13 +63,15 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
69
63
|
entity.primary,
|
|
70
64
|
async ids =>
|
|
71
65
|
this.relationFetcher.fetchManyHasManyGroups(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
{
|
|
67
|
+
mapper: this.mapper,
|
|
68
|
+
field: field,
|
|
69
|
+
targetEntity: targetEntity,
|
|
70
|
+
sourceRelation: relation,
|
|
71
|
+
targetRelation,
|
|
72
|
+
directionFrom: 'inverse',
|
|
73
|
+
ids: ids,
|
|
74
|
+
},
|
|
79
75
|
),
|
|
80
76
|
[],
|
|
81
77
|
)
|
|
@@ -85,12 +81,8 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
85
81
|
entity: Model.Entity,
|
|
86
82
|
relation: Model.ManyHasManyOwningRelation,
|
|
87
83
|
targetEntity: Model.Entity,
|
|
84
|
+
targetRelation: Model.ManyHasManyInverseRelation | null,
|
|
88
85
|
): void {
|
|
89
|
-
const joiningTable = relation.joiningTable
|
|
90
|
-
const columns: JoiningColumns = {
|
|
91
|
-
sourceColumn: joiningTable.joiningColumn,
|
|
92
|
-
targetColumn: joiningTable.inverseJoiningColumn,
|
|
93
|
-
}
|
|
94
86
|
const field = this.executionContext.objectNode
|
|
95
87
|
if (!field) {
|
|
96
88
|
throw new Error()
|
|
@@ -99,7 +91,15 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
99
91
|
this.executionContext.addData(
|
|
100
92
|
entity.primary,
|
|
101
93
|
async ids =>
|
|
102
|
-
this.relationFetcher.fetchManyHasManyGroups(
|
|
94
|
+
this.relationFetcher.fetchManyHasManyGroups({
|
|
95
|
+
mapper: this.mapper,
|
|
96
|
+
field: field,
|
|
97
|
+
targetEntity: targetEntity,
|
|
98
|
+
sourceRelation: relation,
|
|
99
|
+
targetRelation,
|
|
100
|
+
directionFrom: 'owning',
|
|
101
|
+
ids: ids,
|
|
102
|
+
}),
|
|
103
103
|
[],
|
|
104
104
|
)
|
|
105
105
|
}
|
|
@@ -118,7 +118,14 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
118
118
|
this.executionContext.addData(
|
|
119
119
|
entity.primary,
|
|
120
120
|
async ids =>
|
|
121
|
-
this.relationFetcher.fetchOneHasManyGroups(
|
|
121
|
+
this.relationFetcher.fetchOneHasManyGroups({
|
|
122
|
+
mapper: this.mapper,
|
|
123
|
+
objectNode: field,
|
|
124
|
+
targetEntity: targetEntity,
|
|
125
|
+
relation: relation,
|
|
126
|
+
targetRelation: targetRelation,
|
|
127
|
+
ids: ids,
|
|
128
|
+
}),
|
|
122
129
|
[],
|
|
123
130
|
)
|
|
124
131
|
}
|
|
@@ -148,7 +155,7 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
148
155
|
}
|
|
149
156
|
const objectWithWhere = field.withArg('filter', where)
|
|
150
157
|
|
|
151
|
-
return this.mapper.select(targetEntity, objectWithWhere, targetRelation.name)
|
|
158
|
+
return this.mapper.select(targetEntity, objectWithWhere, targetRelation, targetRelation.name)
|
|
152
159
|
},
|
|
153
160
|
null,
|
|
154
161
|
)
|
|
@@ -177,13 +184,13 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
177
184
|
}
|
|
178
185
|
const objectWithWhere = objectNode.withArg('filter', where)
|
|
179
186
|
|
|
180
|
-
return this.mapper.select(targetEntity, objectWithWhere, targetEntity.primary)
|
|
187
|
+
return this.mapper.select(targetEntity, objectWithWhere, targetRelation, targetEntity.primary)
|
|
181
188
|
},
|
|
182
189
|
null,
|
|
183
190
|
)
|
|
184
191
|
}
|
|
185
192
|
|
|
186
|
-
public visitManyHasOne(entity: Model.Entity, relation: Model.ManyHasOneRelation, targetEntity: Model.Entity): void {
|
|
193
|
+
public visitManyHasOne(entity: Model.Entity, relation: Model.ManyHasOneRelation, targetEntity: Model.Entity, targetRelation: Model.OneHasManyRelation | null): void {
|
|
187
194
|
this.executionContext.addData(
|
|
188
195
|
relation.name,
|
|
189
196
|
async ids => {
|
|
@@ -201,7 +208,7 @@ export class FieldsVisitor implements Model.RelationByTypeVisitor<void>, Model.C
|
|
|
201
208
|
}
|
|
202
209
|
const objectWithWhere = objectNode.withArg('filter', where)
|
|
203
210
|
|
|
204
|
-
return this.mapper.select(targetEntity, objectWithWhere, targetEntity.primary)
|
|
211
|
+
return this.mapper.select(targetEntity, objectWithWhere, targetRelation, targetEntity.primary)
|
|
205
212
|
},
|
|
206
213
|
null,
|
|
207
214
|
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Input } from '@contember/schema'
|
|
2
|
+
import { optimizeAnd, optimizeNot, optimizeOr } from './helpers'
|
|
3
|
+
|
|
4
|
+
type ObjectEntry<T> = { [K in keyof Required<T>]: [K, T[K]] }[keyof T]
|
|
5
|
+
|
|
6
|
+
export class ConditionOptimizer {
|
|
7
|
+
public optimize(condition: Input.Condition): Omit<Input.Condition, 'always' | 'never'> | boolean {
|
|
8
|
+
if (condition.never) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return optimizeAnd(
|
|
13
|
+
(Object.entries(condition) as ObjectEntry<typeof condition>[]).map(([key, value]) => {
|
|
14
|
+
if (value === undefined || value === null) {
|
|
15
|
+
return undefined
|
|
16
|
+
|
|
17
|
+
} else if (key === 'always') {
|
|
18
|
+
return true
|
|
19
|
+
|
|
20
|
+
} else if (key === 'and') {
|
|
21
|
+
return optimizeAnd(value.map(it => this.optimize(it)))
|
|
22
|
+
|
|
23
|
+
} else if (key === 'or') {
|
|
24
|
+
return optimizeOr(value.map(it => this.optimize(it)))
|
|
25
|
+
|
|
26
|
+
} else if (key === 'not') {
|
|
27
|
+
return optimizeNot(this.optimize(value))
|
|
28
|
+
|
|
29
|
+
} else {
|
|
30
|
+
return { [key]: value }
|
|
31
|
+
}
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Input, Model } from '@contember/schema'
|
|
2
|
+
import { ConditionOptimizer } from './ConditionOptimizer'
|
|
3
|
+
import { acceptFieldVisitor } from '@contember/schema-utils'
|
|
4
|
+
import { optimizeAnd, optimizeNot, optimizeOr } from './helpers'
|
|
5
|
+
import { replaceWhere } from './WhereReplacer'
|
|
6
|
+
|
|
7
|
+
export class WhereOptimizer {
|
|
8
|
+
constructor(
|
|
9
|
+
private readonly model: Model.Schema,
|
|
10
|
+
private readonly conditionOptimizer: ConditionOptimizer,
|
|
11
|
+
) {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public optimize(where: Input.OptionalWhere, entity: Model.Entity): Input.Where {
|
|
15
|
+
const result = this.optimizeWhere(where, entity)
|
|
16
|
+
|
|
17
|
+
if (typeof result === 'boolean') {
|
|
18
|
+
return { [entity.primary]: { [result ? 'always' : 'never']: true } }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return result
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private optimizeWhere(where: Input.OptionalWhere, entity: Model.Entity): Input.Where | boolean {
|
|
25
|
+
return this.optimizeAnd(
|
|
26
|
+
Object.entries(where).map(([key, value]) => {
|
|
27
|
+
if (value === undefined || value === null) {
|
|
28
|
+
return undefined
|
|
29
|
+
|
|
30
|
+
} else if (key === 'and') {
|
|
31
|
+
return this.optimizeAnd((value as readonly Input.Where[]).map(it => this.optimizeWhere(it, entity)), entity)
|
|
32
|
+
|
|
33
|
+
} else if (key === 'or') {
|
|
34
|
+
return this.optimizeOr((value as readonly Input.Where[]).map(it => this.optimizeWhere(it, entity)), entity)
|
|
35
|
+
|
|
36
|
+
} else if (key === 'not') {
|
|
37
|
+
return optimizeNot(this.optimizeWhere(value as Input.Where, entity))
|
|
38
|
+
|
|
39
|
+
} else {
|
|
40
|
+
return this.resolveFieldValue(entity, key, value)
|
|
41
|
+
}
|
|
42
|
+
}),
|
|
43
|
+
entity,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private optimizeOr(operands: readonly (Input.Where | undefined | boolean)[], entity: Model.Entity): Input.Where | boolean {
|
|
48
|
+
const optimized = optimizeOr(operands)
|
|
49
|
+
if (typeof optimized === 'boolean' || !Array.isArray(optimized.or)) {
|
|
50
|
+
return optimized
|
|
51
|
+
}
|
|
52
|
+
const result = this.crossOptimize(optimized.or, entity, { never: true })
|
|
53
|
+
return optimizeOr(result.map(it => this.optimizeWhere(it, entity)))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private optimizeAnd(operands: readonly (Input.Where | undefined | boolean)[], entity: Model.Entity): Input.Where | boolean {
|
|
57
|
+
const optimized = optimizeAnd(operands)
|
|
58
|
+
if (typeof optimized === 'boolean' || !Array.isArray(optimized.and)) {
|
|
59
|
+
return optimized
|
|
60
|
+
}
|
|
61
|
+
const result = this.crossOptimize(optimized.and, entity, { always: true })
|
|
62
|
+
return optimizeAnd(result.map(it => this.optimizeWhere(it, entity)))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private crossOptimize(operands: Input.Where[], entity: Model.Entity, replacement: Input.Condition): Input.Where[] {
|
|
66
|
+
const result = [...operands]
|
|
67
|
+
const count = result.length
|
|
68
|
+
for (let i = 0; i < count; i++) {
|
|
69
|
+
for (let j = 0; j < count; j++) {
|
|
70
|
+
if (i !== j) {
|
|
71
|
+
result[j] = replaceWhere(result[j], result[i], { [entity.primary]: replacement })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private resolveFieldValue(entity: Model.Entity, key: string, value: Input.OptionalWhere[string]) {
|
|
79
|
+
return acceptFieldVisitor<Input.Where | boolean>(this.model, entity, key, {
|
|
80
|
+
visitColumn: () => {
|
|
81
|
+
const optimizedCondition = this.conditionOptimizer.optimize(value as Input.Condition)
|
|
82
|
+
|
|
83
|
+
if (typeof optimizedCondition === 'boolean') {
|
|
84
|
+
return optimizedCondition
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { [key]: optimizedCondition }
|
|
88
|
+
},
|
|
89
|
+
visitRelation: (entity, relation, targetEntity) => {
|
|
90
|
+
const optimizedWhere = this.optimizeWhere(value as Input.Where, targetEntity)
|
|
91
|
+
|
|
92
|
+
if (typeof optimizedWhere === 'boolean') {
|
|
93
|
+
return optimizedWhere
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { [key]: optimizedWhere }
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Input, Writable } from '@contember/schema'
|
|
2
|
+
import deepEqual from 'fast-deep-equal'
|
|
3
|
+
|
|
4
|
+
export const replaceWhere = (subject: Input.Where, find: Input.Where, replace: Input.Where): Input.Where => {
|
|
5
|
+
if (deepEqual(subject, find)) {
|
|
6
|
+
return replace
|
|
7
|
+
}
|
|
8
|
+
const result: Writable<Input.Where> = {}
|
|
9
|
+
for (const [key, value] of Object.entries(subject)) {
|
|
10
|
+
if (key === 'not') {
|
|
11
|
+
result['not'] = replaceWhere(value as Input.Where, find, replace)
|
|
12
|
+
|
|
13
|
+
} else if (key === 'and' || key === 'or') {
|
|
14
|
+
result[key] = (value as Input.Where[]).map(it => replaceWhere(it, find, replace))
|
|
15
|
+
|
|
16
|
+
} else {
|
|
17
|
+
result[key] = value
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
return result
|
|
22
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const optimizeOr = <P extends Record<string, unknown>>(operands: readonly (P | boolean | undefined)[]): P | { or?: P[] } | boolean => {
|
|
2
|
+
const normalized: P[] = []
|
|
3
|
+
let hasNever = false
|
|
4
|
+
for (const operand of operands) {
|
|
5
|
+
if (operand === true) {
|
|
6
|
+
return true
|
|
7
|
+
} else if (operand === false) {
|
|
8
|
+
hasNever = true
|
|
9
|
+
} else if (operand !== undefined) {
|
|
10
|
+
normalized.push(...Array.isArray(operand.or) ? operand.or : [operand])
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (normalized.length > 1) {
|
|
15
|
+
return { or: normalized }
|
|
16
|
+
} else if (normalized.length === 1) {
|
|
17
|
+
return normalized[0]
|
|
18
|
+
} else if (hasNever) {
|
|
19
|
+
return false
|
|
20
|
+
} else {
|
|
21
|
+
return {}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const optimizeAnd = <P extends Record<string, unknown>>(operands: readonly (P | boolean | undefined)[]): P | { and?: P[] } | boolean => {
|
|
26
|
+
const normalized: P[] = []
|
|
27
|
+
let hasAlways = false
|
|
28
|
+
|
|
29
|
+
for (const operand of operands) {
|
|
30
|
+
if (operand === true) {
|
|
31
|
+
hasAlways = true
|
|
32
|
+
} else if (operand === false) {
|
|
33
|
+
return false
|
|
34
|
+
} else if (operand !== undefined) {
|
|
35
|
+
normalized.push(...Array.isArray(operand.and) ? operand.and : [operand])
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (normalized.length > 1) {
|
|
40
|
+
return { and: normalized }
|
|
41
|
+
} else if (normalized.length === 1) {
|
|
42
|
+
return normalized[0]
|
|
43
|
+
} else if (hasAlways) {
|
|
44
|
+
return true
|
|
45
|
+
} else {
|
|
46
|
+
return {}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const optimizeNot = <P extends Record<string, unknown>>(operand: P | boolean): P['not'] | { not: P } | boolean => {
|
|
51
|
+
if (typeof operand === 'boolean') {
|
|
52
|
+
return !operand
|
|
53
|
+
} else if (operand.not) {
|
|
54
|
+
return operand.not as P['not']
|
|
55
|
+
} else {
|
|
56
|
+
return { not: operand }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
GraphQLResolveInfo,
|
|
8
8
|
isListType,
|
|
9
9
|
isNonNullType,
|
|
10
|
-
isObjectType,
|
|
10
|
+
isObjectType, Kind,
|
|
11
11
|
} from 'graphql'
|
|
12
12
|
import { SelectionSetNode } from 'graphql/language/ast'
|
|
13
13
|
import { getArgumentValues } from 'graphql/execution/values'
|
|
@@ -67,13 +67,13 @@ export class GraphQlQueryAstFactory {
|
|
|
67
67
|
): AnyNode[] {
|
|
68
68
|
const fields: ObjectNode | FieldNode[] = []
|
|
69
69
|
for (const subNode of selectionSet.selections) {
|
|
70
|
-
if (isIt<GraphQlFieldNode>(subNode, 'kind',
|
|
70
|
+
if (isIt<GraphQlFieldNode>(subNode, 'kind', Kind.FIELD)) {
|
|
71
71
|
const field = this.createFromNode(info, parentType, subNode, path, filter)
|
|
72
72
|
if (field === null) {
|
|
73
73
|
continue
|
|
74
74
|
}
|
|
75
75
|
fields.push(field)
|
|
76
|
-
} else if (isIt<FragmentSpreadNode>(subNode, 'kind',
|
|
76
|
+
} else if (isIt<FragmentSpreadNode>(subNode, 'kind', Kind.FRAGMENT_SPREAD)) {
|
|
77
77
|
const fragmentDefinition = info.fragments[subNode.name.value]
|
|
78
78
|
if (!fragmentDefinition) {
|
|
79
79
|
throw new Error(`GraphQlQueryAstFactory: Fragment definition ${subNode.name.value} not found`)
|
|
@@ -457,7 +457,7 @@ export class MutationResolver {
|
|
|
457
457
|
throw new Error('MutationResolver: expected ObjectNode')
|
|
458
458
|
}
|
|
459
459
|
const objectWithArgs = singleNodeQuery.withArgs({ by: where })
|
|
460
|
-
nodes[singleNodeQuery.alias] = await mapper.selectUnique(entity, objectWithArgs)
|
|
460
|
+
nodes[singleNodeQuery.alias] = await mapper.selectUnique(entity, objectWithArgs, null)
|
|
461
461
|
}
|
|
462
462
|
return nodes
|
|
463
463
|
}
|
|
@@ -15,7 +15,7 @@ export const paginate = async (
|
|
|
15
15
|
const totalCount = paginationHelper.requiresTotalCount
|
|
16
16
|
? await mapper.count(entity, queryAst.args.filter || {})
|
|
17
17
|
: undefined
|
|
18
|
-
const nodes = paginationHelper.nodeField ? await mapper.select(entity, paginationHelper.nodeField) : undefined
|
|
18
|
+
const nodes = paginationHelper.nodeField ? await mapper.select(entity, paginationHelper.nodeField, null) : undefined
|
|
19
19
|
|
|
20
20
|
return paginationHelper.createResponse(totalCount, nodes)
|
|
21
21
|
}
|
|
@@ -37,9 +37,9 @@ export const executeReadOperations = async (
|
|
|
37
37
|
trxResult[field.alias] = await (() => {
|
|
38
38
|
switch (meta.operation) {
|
|
39
39
|
case Operation.get:
|
|
40
|
-
return mapper.selectUnique(meta.entity, field)
|
|
40
|
+
return mapper.selectUnique(meta.entity, field, null)
|
|
41
41
|
case Operation.list:
|
|
42
|
-
return mapper.select(meta.entity, field)
|
|
42
|
+
return mapper.select(meta.entity, field, null)
|
|
43
43
|
case Operation.paginate:
|
|
44
44
|
return paginate(mapper, meta.entity, field)
|
|
45
45
|
case Operation.create:
|
|
@@ -33,12 +33,12 @@ export class ReadResolver {
|
|
|
33
33
|
|
|
34
34
|
public async resolveListQuery(entity: Model.Entity, info: GraphQLResolveInfo) {
|
|
35
35
|
const queryAst: ObjectNode<Input.ListQueryInput> = this.queryAstFactory.create(info)
|
|
36
|
-
return await this.mapperFactory(this.db).select(entity, queryAst)
|
|
36
|
+
return await this.mapperFactory(this.db).select(entity, queryAst, null)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
public async resolveGetQuery(entity: Model.Entity, info: GraphQLResolveInfo) {
|
|
40
40
|
const queryAst: ObjectNode<Input.UniqueQueryInput> = this.queryAstFactory.create(info)
|
|
41
|
-
return await this.mapperFactory(this.db).selectUnique(entity, queryAst)
|
|
41
|
+
return await this.mapperFactory(this.db).selectUnique(entity, queryAst, null)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
public async resolvePaginationQuery(entity: Model.Entity, info: GraphQLResolveInfo) {
|
package/src/utils/object.ts
CHANGED
|
@@ -9,18 +9,18 @@ function filterObject<Input extends {}, Result extends { [Key in keyof Input]: I
|
|
|
9
9
|
object: Input,
|
|
10
10
|
callback: TypeGuard<Input, Result> | Filter<Input>,
|
|
11
11
|
): Result {
|
|
12
|
-
return (Object.entries(object)
|
|
13
|
-
.filter(
|
|
14
|
-
|
|
15
|
-
)
|
|
16
|
-
.reduce((result: Result, [key, value]: [string, any]) => ({ ...(result as any), [key]: value }), {} as Result)
|
|
12
|
+
return Object.fromEntries(Object.entries(object)
|
|
13
|
+
.filter(([key, value]) => (callback as any)(key, value, object)),
|
|
14
|
+
) as Result
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
function mapObject<Input, Result>(
|
|
20
18
|
input: { [key: string]: Input },
|
|
21
19
|
callback: (value: Input, key: string) => Result,
|
|
22
20
|
): { [key: string]: Result } {
|
|
23
|
-
return Object.
|
|
21
|
+
return Object.fromEntries(
|
|
22
|
+
Object.entries(input).map(([key, value]) => [key, callback(value, key)]),
|
|
23
|
+
)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export { filterObject, mapObject }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test } from 'vitest'
|
|
2
2
|
import { execute, sqlDeferred, sqlTransaction } from '../../../../src/test'
|
|
3
3
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
4
|
-
import { Model } from '@contember/schema'
|
|
4
|
+
import { Acl, Model } from '@contember/schema'
|
|
5
5
|
import { GQL, SQL } from '../../../../src/tags'
|
|
6
6
|
import { testUuid } from '../../../../src/testUuid'
|
|
7
7
|
|
|
@@ -32,7 +32,7 @@ test('delete post with acl', async () => {
|
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
variables: {
|
|
35
|
-
locale_variable: ['cs'],
|
|
35
|
+
locale_variable: { in: ['cs'] },
|
|
36
36
|
},
|
|
37
37
|
executes: [
|
|
38
38
|
...sqlTransaction([
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test } from 'vitest'
|
|
2
2
|
import { execute, failedTransaction, sqlTransaction } from '../../../../../src/test'
|
|
3
3
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
4
|
-
import { Model } from '@contember/schema'
|
|
4
|
+
import { Acl, Model } from '@contember/schema'
|
|
5
5
|
import { GQL, SQL } from '../../../../../src/tags'
|
|
6
6
|
import { testUuid } from '../../../../../src/testUuid'
|
|
7
7
|
|
|
@@ -34,7 +34,7 @@ test('set a name - allowed', async () => {
|
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
36
|
variables: {
|
|
37
|
-
name_variable: ['John', 'Jack'],
|
|
37
|
+
name_variable: { in: ['John', 'Jack'] },
|
|
38
38
|
},
|
|
39
39
|
executes: [
|
|
40
40
|
...sqlTransaction([
|
|
@@ -89,7 +89,7 @@ test('set a name - denied', async () => {
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
variables: {
|
|
92
|
-
name_variable: ['John', 'Jack'],
|
|
92
|
+
name_variable: { in: ['John', 'Jack'] },
|
|
93
93
|
},
|
|
94
94
|
executes: [
|
|
95
95
|
...failedTransaction([
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test } from 'vitest'
|
|
2
2
|
import { execute, sqlTransaction } from '../../../../src/test'
|
|
3
3
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
4
|
-
import { Model } from '@contember/schema'
|
|
4
|
+
import { Acl, Model } from '@contember/schema'
|
|
5
5
|
import { GQL, SQL } from '../../../../src/tags'
|
|
6
6
|
import { testUuid } from '../../../../src/testUuid'
|
|
7
7
|
|
|
@@ -27,7 +27,7 @@ test('insert author (with acl)', async () => {
|
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
variables: {
|
|
30
|
-
name_variable: ['John', 'Jack'],
|
|
30
|
+
name_variable: { in: ['John', 'Jack'] },
|
|
31
31
|
},
|
|
32
32
|
query: GQL`
|
|
33
33
|
mutation {
|
|
@@ -7,7 +7,7 @@ import { testUuid } from '../../../../../src/testUuid'
|
|
|
7
7
|
|
|
8
8
|
const schema = new SchemaBuilder()
|
|
9
9
|
.enum('locale', ['cs', 'en'])
|
|
10
|
-
.entity('Post', entityBuilder => entityBuilder.oneHasMany('locales', c => c.target('PostLocale')))
|
|
10
|
+
.entity('Post', entityBuilder => entityBuilder.oneHasMany('locales', c => c.target('PostLocale').ownedBy('post')))
|
|
11
11
|
.entity('PostLocale', entity =>
|
|
12
12
|
entity
|
|
13
13
|
.column('title', column => column.type(Model.ColumnType.String))
|
|
@@ -34,6 +34,7 @@ const permissions: Acl.Permissions = {
|
|
|
34
34
|
operations: {
|
|
35
35
|
read: {
|
|
36
36
|
id: true,
|
|
37
|
+
post: true,
|
|
37
38
|
title: 'localePredicate',
|
|
38
39
|
},
|
|
39
40
|
},
|
|
@@ -45,7 +46,7 @@ test('querying id and title', async () => {
|
|
|
45
46
|
schema: schema,
|
|
46
47
|
permissions: permissions,
|
|
47
48
|
variables: {
|
|
48
|
-
localeVariable: ['cs'],
|
|
49
|
+
localeVariable: { in: ['cs'] },
|
|
49
50
|
},
|
|
50
51
|
query: GQL`
|
|
51
52
|
query {
|
|
@@ -121,7 +122,7 @@ test('querying with extra where', async () => {
|
|
|
121
122
|
schema: schema,
|
|
122
123
|
permissions: permissions,
|
|
123
124
|
variables: {
|
|
124
|
-
localeVariable: ['cs'],
|
|
125
|
+
localeVariable: { in: ['cs'] },
|
|
125
126
|
},
|
|
126
127
|
query: GQL`
|
|
127
128
|
query {
|
|
@@ -167,7 +168,7 @@ test('querying only id', async () => {
|
|
|
167
168
|
schema: schema,
|
|
168
169
|
permissions: permissions,
|
|
169
170
|
variables: {
|
|
170
|
-
localeVariable: ['cs'],
|
|
171
|
+
localeVariable: { in: ['cs'] },
|
|
171
172
|
},
|
|
172
173
|
query: GQL`
|
|
173
174
|
query {
|
|
@@ -239,7 +240,7 @@ test('querying on nested field', async () => {
|
|
|
239
240
|
schema: schema,
|
|
240
241
|
permissions: permissions,
|
|
241
242
|
variables: {
|
|
242
|
-
localeVariable: ['cs'],
|
|
243
|
+
localeVariable: { in: ['cs'] },
|
|
243
244
|
},
|
|
244
245
|
query: GQL`
|
|
245
246
|
query {
|
|
@@ -274,7 +275,7 @@ test('querying on nested field', async () => {
|
|
|
274
275
|
"root_"."id" as "root_id",
|
|
275
276
|
case when "root_"."locale" in (?) then "root_"."title" else null end as "root_title"
|
|
276
277
|
from "public"."post_locale" as "root_"
|
|
277
|
-
where "root_"."post_id" in (?, ?)
|
|
278
|
+
where "root_"."post_id" in (?, ?)`,
|
|
278
279
|
parameters: ['cs', testUuid(1), testUuid(2)],
|
|
279
280
|
response: {
|
|
280
281
|
rows: [
|