@powersync/service-sync-rules 0.29.10 → 0.31.0
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/BaseSqlDataQuery.d.ts +3 -9
- package/dist/BaseSqlDataQuery.js +11 -21
- package/dist/BaseSqlDataQuery.js.map +1 -1
- package/dist/BucketParameterQuerier.d.ts +42 -9
- package/dist/BucketParameterQuerier.js +30 -7
- package/dist/BucketParameterQuerier.js.map +1 -1
- package/dist/BucketSource.d.ts +94 -25
- package/dist/BucketSource.js +67 -0
- package/dist/BucketSource.js.map +1 -1
- package/dist/ExpressionType.d.ts +4 -2
- package/dist/ExpressionType.js.map +1 -1
- package/dist/HydratedSyncRules.d.ts +46 -0
- package/dist/HydratedSyncRules.js +88 -0
- package/dist/HydratedSyncRules.js.map +1 -0
- package/dist/HydrationState.d.ts +45 -0
- package/dist/HydrationState.js +41 -0
- package/dist/HydrationState.js.map +1 -0
- package/dist/SqlBucketDescriptor.d.ts +31 -28
- package/dist/SqlBucketDescriptor.js +89 -112
- package/dist/SqlBucketDescriptor.js.map +1 -1
- package/dist/SqlDataQuery.d.ts +4 -4
- package/dist/SqlDataQuery.js +5 -6
- package/dist/SqlDataQuery.js.map +1 -1
- package/dist/SqlParameterQuery.d.ts +17 -9
- package/dist/SqlParameterQuery.js +49 -23
- package/dist/SqlParameterQuery.js.map +1 -1
- package/dist/SqlSyncRules.d.ts +11 -53
- package/dist/SqlSyncRules.js +11 -376
- package/dist/SqlSyncRules.js.map +1 -1
- package/dist/StaticSqlParameterQuery.d.ts +13 -3
- package/dist/StaticSqlParameterQuery.js +38 -4
- package/dist/StaticSqlParameterQuery.js.map +1 -1
- package/dist/SyncConfig.d.ts +43 -0
- package/dist/SyncConfig.js +102 -0
- package/dist/SyncConfig.js.map +1 -0
- package/dist/TablePattern.d.ts +22 -4
- package/dist/TablePattern.js +57 -19
- package/dist/TablePattern.js.map +1 -1
- package/dist/TableValuedFunctionSqlParameterQuery.d.ts +14 -4
- package/dist/TableValuedFunctionSqlParameterQuery.js +41 -7
- package/dist/TableValuedFunctionSqlParameterQuery.js.map +1 -1
- package/dist/compatibility.d.ts +7 -0
- package/dist/compatibility.js +34 -0
- package/dist/compatibility.js.map +1 -1
- package/dist/compiler/bucket_resolver.d.ts +70 -0
- package/dist/compiler/bucket_resolver.js +131 -0
- package/dist/compiler/bucket_resolver.js.map +1 -0
- package/dist/compiler/compatibility.d.ts +16 -0
- package/dist/compiler/compatibility.js +12 -0
- package/dist/compiler/compatibility.js.map +1 -0
- package/dist/compiler/compiler.d.ts +110 -0
- package/dist/compiler/compiler.js +130 -0
- package/dist/compiler/compiler.js.map +1 -0
- package/dist/compiler/equality.d.ts +99 -0
- package/dist/compiler/equality.js +284 -0
- package/dist/compiler/equality.js.map +1 -0
- package/dist/compiler/expression.d.ts +77 -0
- package/dist/compiler/expression.js +122 -0
- package/dist/compiler/expression.js.map +1 -0
- package/dist/compiler/filter.d.ts +71 -0
- package/dist/compiler/filter.js +110 -0
- package/dist/compiler/filter.js.map +1 -0
- package/dist/compiler/filter_simplifier.d.ts +26 -0
- package/dist/compiler/filter_simplifier.js +119 -0
- package/dist/compiler/filter_simplifier.js.map +1 -0
- package/dist/compiler/ir_to_sync_plan.d.ts +37 -0
- package/dist/compiler/ir_to_sync_plan.js +163 -0
- package/dist/compiler/ir_to_sync_plan.js.map +1 -0
- package/dist/compiler/parser.d.ts +99 -0
- package/dist/compiler/parser.js +556 -0
- package/dist/compiler/parser.js.map +1 -0
- package/dist/compiler/querier_graph.d.ts +42 -0
- package/dist/compiler/querier_graph.js +365 -0
- package/dist/compiler/querier_graph.js.map +1 -0
- package/dist/compiler/rows.d.ts +113 -0
- package/dist/compiler/rows.js +156 -0
- package/dist/compiler/rows.js.map +1 -0
- package/dist/compiler/scope.d.ts +22 -0
- package/dist/compiler/scope.js +47 -0
- package/dist/compiler/scope.js.map +1 -0
- package/dist/compiler/sqlite.d.ts +77 -0
- package/dist/compiler/sqlite.js +412 -0
- package/dist/compiler/sqlite.js.map +1 -0
- package/dist/compiler/table.d.ts +66 -0
- package/dist/compiler/table.js +67 -0
- package/dist/compiler/table.js.map +1 -0
- package/dist/errors.d.ts +4 -2
- package/dist/errors.js +16 -1
- package/dist/errors.js.map +1 -1
- package/dist/events/SqlEventDescriptor.js +1 -1
- package/dist/events/SqlEventDescriptor.js.map +1 -1
- package/dist/events/SqlEventSourceQuery.d.ts +1 -1
- package/dist/events/SqlEventSourceQuery.js +1 -2
- package/dist/events/SqlEventSourceQuery.js.map +1 -1
- package/dist/from_yaml.d.ts +28 -0
- package/dist/from_yaml.js +411 -0
- package/dist/from_yaml.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/json_schema.js +17 -1
- package/dist/json_schema.js.map +1 -1
- package/dist/request_functions.js.map +1 -1
- package/dist/schema-generators/DartSchemaGenerator.d.ts +3 -3
- package/dist/schema-generators/DartSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/DotNetSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/DotNetSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/JsLegacySchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/JsLegacySchemaGenerator.js.map +1 -1
- package/dist/schema-generators/KotlinSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/KotlinSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/RoomSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/RoomSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/SchemaGenerator.d.ts +8 -3
- package/dist/schema-generators/SchemaGenerator.js +21 -14
- package/dist/schema-generators/SchemaGenerator.js.map +1 -1
- package/dist/schema-generators/SqlSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/SqlSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/SwiftSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/SwiftSchemaGenerator.js.map +1 -1
- package/dist/schema-generators/TsSchemaGenerator.d.ts +2 -2
- package/dist/schema-generators/TsSchemaGenerator.js.map +1 -1
- package/dist/sql_functions.d.ts +4 -3
- package/dist/sql_functions.js +1 -1
- package/dist/sql_functions.js.map +1 -1
- package/dist/streams/filter.d.ts +34 -4
- package/dist/streams/filter.js +93 -23
- package/dist/streams/filter.js.map +1 -1
- package/dist/streams/from_sql.js +2 -5
- package/dist/streams/from_sql.js.map +1 -1
- package/dist/streams/parameter.d.ts +7 -6
- package/dist/streams/stream.d.ts +25 -15
- package/dist/streams/stream.js +59 -87
- package/dist/streams/stream.js.map +1 -1
- package/dist/streams/variant.d.ts +14 -21
- package/dist/streams/variant.js +68 -46
- package/dist/streams/variant.js.map +1 -1
- package/dist/sync_plan/engine/javascript.d.ts +6 -0
- package/dist/sync_plan/engine/javascript.js +208 -0
- package/dist/sync_plan/engine/javascript.js.map +1 -0
- package/dist/sync_plan/engine/scalar_expression_engine.d.ts +48 -0
- package/dist/sync_plan/engine/scalar_expression_engine.js +99 -0
- package/dist/sync_plan/engine/scalar_expression_engine.js.map +1 -0
- package/dist/sync_plan/engine/sqlite.d.ts +12 -0
- package/dist/sync_plan/engine/sqlite.js +53 -0
- package/dist/sync_plan/engine/sqlite.js.map +1 -0
- package/dist/sync_plan/evaluator/bucket_data_source.d.ts +24 -0
- package/dist/sync_plan/evaluator/bucket_data_source.js +139 -0
- package/dist/sync_plan/evaluator/bucket_data_source.js.map +1 -0
- package/dist/sync_plan/evaluator/bucket_source.d.ts +19 -0
- package/dist/sync_plan/evaluator/bucket_source.js +145 -0
- package/dist/sync_plan/evaluator/bucket_source.js.map +1 -0
- package/dist/sync_plan/evaluator/index.d.ts +17 -0
- package/dist/sync_plan/evaluator/index.js +32 -0
- package/dist/sync_plan/evaluator/index.js.map +1 -0
- package/dist/sync_plan/evaluator/parameter_evaluator.d.ts +138 -0
- package/dist/sync_plan/evaluator/parameter_evaluator.js +359 -0
- package/dist/sync_plan/evaluator/parameter_evaluator.js.map +1 -0
- package/dist/sync_plan/evaluator/parameter_index_lookup_creator.d.ts +20 -0
- package/dist/sync_plan/evaluator/parameter_index_lookup_creator.js +64 -0
- package/dist/sync_plan/evaluator/parameter_index_lookup_creator.js.map +1 -0
- package/dist/sync_plan/expression.d.ts +109 -0
- package/dist/sync_plan/expression.js +85 -0
- package/dist/sync_plan/expression.js.map +1 -0
- package/dist/sync_plan/expression_to_sql.d.ts +43 -0
- package/dist/sync_plan/expression_to_sql.js +190 -0
- package/dist/sync_plan/expression_to_sql.js.map +1 -0
- package/dist/sync_plan/expression_visitor.d.ts +57 -0
- package/dist/sync_plan/expression_visitor.js +181 -0
- package/dist/sync_plan/expression_visitor.js.map +1 -0
- package/dist/sync_plan/plan.d.ts +196 -0
- package/dist/sync_plan/plan.js +2 -0
- package/dist/sync_plan/plan.js.map +1 -0
- package/dist/sync_plan/schema_inference.d.ts +16 -0
- package/dist/sync_plan/schema_inference.js +123 -0
- package/dist/sync_plan/schema_inference.js.map +1 -0
- package/dist/sync_plan/serialize.d.ts +82 -0
- package/dist/sync_plan/serialize.js +214 -0
- package/dist/sync_plan/serialize.js.map +1 -0
- package/dist/types/custom_sqlite_value.d.ts +1 -1
- package/dist/types.d.ts +72 -29
- package/dist/types.js +30 -5
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +10 -3
- package/dist/utils.js +26 -3
- package/dist/utils.js.map +1 -1
- package/package.json +4 -3
- package/schema/sync_rules.json +19 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/compiler/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Or } from './filter.js';
|
|
2
|
+
import { NodeLocations } from './expression.js';
|
|
3
|
+
import { BinaryOperator, SqlExpression } from '../sync_plan/expression.js';
|
|
4
|
+
export declare class FilterConditionSimplifier {
|
|
5
|
+
simplifyOr(or: Or): Or;
|
|
6
|
+
private simplifyAnd;
|
|
7
|
+
/**
|
|
8
|
+
* Re-orders terms based on their dependencies, and then uses the given operator to merge expressions with the same
|
|
9
|
+
* dependency set.
|
|
10
|
+
*
|
|
11
|
+
* This is used to push boolean expressions down if they can be evaluated on the same table. For instance, the and
|
|
12
|
+
* terms `[row.foo, row.bar]` can be represented as a single base term `row.foo AND row.bar`. Pushing operators down
|
|
13
|
+
* into the expression generally reduces the complexity of the sync plan. In particular for `OR` terms, it can also
|
|
14
|
+
* reduce the amount of buckets since each term in an `OR` is implemented as another bucket.
|
|
15
|
+
*/
|
|
16
|
+
private mergeByCommonDependencies;
|
|
17
|
+
private simplifyBase;
|
|
18
|
+
/**
|
|
19
|
+
* Reduces expressions through a chain of binary operators.
|
|
20
|
+
*
|
|
21
|
+
* For instance, `composeExpressions('AND', a, b, c)` returns `a AND b AND c` as a single expression. All expressions
|
|
22
|
+
* must have compatible dependencies.
|
|
23
|
+
*/
|
|
24
|
+
private composeExpressions;
|
|
25
|
+
}
|
|
26
|
+
export declare function composeExpressionNodes<T>(locations: NodeLocations, operator: BinaryOperator, terms: SqlExpression<T>[]): SqlExpression<T>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { EqualsClause, isBaseTerm, SingleDependencyExpression } from './filter.js';
|
|
2
|
+
import { SyncExpression } from './expression.js';
|
|
3
|
+
import { expandNodeLocations } from '../errors.js';
|
|
4
|
+
export class FilterConditionSimplifier {
|
|
5
|
+
simplifyOr(or) {
|
|
6
|
+
const andTerms = [];
|
|
7
|
+
let baseTerms = [];
|
|
8
|
+
for (const term of or.terms) {
|
|
9
|
+
const simplified = this.simplifyAnd(term);
|
|
10
|
+
if (isBaseTerm(simplified)) {
|
|
11
|
+
baseTerms.push(simplified);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
andTerms.push(simplified);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
baseTerms = this.mergeByCommonDependencies('or', baseTerms);
|
|
18
|
+
for (const term of baseTerms) {
|
|
19
|
+
andTerms.push({ terms: [term] });
|
|
20
|
+
}
|
|
21
|
+
return { terms: andTerms };
|
|
22
|
+
}
|
|
23
|
+
simplifyAnd(and) {
|
|
24
|
+
const merged = this.mergeByCommonDependencies('and', and.terms);
|
|
25
|
+
if (merged.length == 1) {
|
|
26
|
+
return merged[0];
|
|
27
|
+
}
|
|
28
|
+
return { terms: merged };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Re-orders terms based on their dependencies, and then uses the given operator to merge expressions with the same
|
|
32
|
+
* dependency set.
|
|
33
|
+
*
|
|
34
|
+
* This is used to push boolean expressions down if they can be evaluated on the same table. For instance, the and
|
|
35
|
+
* terms `[row.foo, row.bar]` can be represented as a single base term `row.foo AND row.bar`. Pushing operators down
|
|
36
|
+
* into the expression generally reduces the complexity of the sync plan. In particular for `OR` terms, it can also
|
|
37
|
+
* reduce the amount of buckets since each term in an `OR` is implemented as another bucket.
|
|
38
|
+
*/
|
|
39
|
+
mergeByCommonDependencies(operator, baseTerms) {
|
|
40
|
+
const byResultSet = new Map();
|
|
41
|
+
const noResultSet = [];
|
|
42
|
+
const rest = [];
|
|
43
|
+
for (const term of baseTerms) {
|
|
44
|
+
const simplified = this.simplifyBase(term);
|
|
45
|
+
if (simplified instanceof SingleDependencyExpression) {
|
|
46
|
+
if (simplified.resultSet != null) {
|
|
47
|
+
if (byResultSet.has(simplified.resultSet)) {
|
|
48
|
+
byResultSet.get(simplified.resultSet).push(simplified);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
byResultSet.set(simplified.resultSet, [simplified]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
noResultSet.push(simplified);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
rest.push(term);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const addMerged = (elements) => {
|
|
63
|
+
if (elements.length == 0) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
rest.push(this.composeExpressions(operator, ...elements));
|
|
67
|
+
};
|
|
68
|
+
addMerged(noResultSet);
|
|
69
|
+
for (const terms of byResultSet.values()) {
|
|
70
|
+
addMerged(terms);
|
|
71
|
+
}
|
|
72
|
+
return rest;
|
|
73
|
+
}
|
|
74
|
+
simplifyBase(base) {
|
|
75
|
+
if (base instanceof EqualsClause) {
|
|
76
|
+
// If the left and right terms have shared dependencies, we shouldn't represent this as an equals clause. For
|
|
77
|
+
// instance, terms like `notes.state = 'public'` are generated as an equals clause initially but they can just be
|
|
78
|
+
// a row condition that is much cheaper to compute than a static bucket parameter. Similarly, `row.foo = row.bar`
|
|
79
|
+
// must be a row condition since it can't be represented as parameters that could be instantiated.
|
|
80
|
+
if (SingleDependencyExpression.extractSingleDependency([
|
|
81
|
+
...base.left.expression.instantiation,
|
|
82
|
+
...base.right.expression.instantiation
|
|
83
|
+
])) {
|
|
84
|
+
return this.composeExpressions('=', base.left, base.right);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return base;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reduces expressions through a chain of binary operators.
|
|
91
|
+
*
|
|
92
|
+
* For instance, `composeExpressions('AND', a, b, c)` returns `a AND b AND c` as a single expression. All expressions
|
|
93
|
+
* must have compatible dependencies.
|
|
94
|
+
*/
|
|
95
|
+
composeExpressions(operator, ...terms) {
|
|
96
|
+
if (terms.length == 0) {
|
|
97
|
+
throw new Error("Can't compose zero expressions");
|
|
98
|
+
}
|
|
99
|
+
const locations = terms[0].expression.locations;
|
|
100
|
+
const inner = composeExpressionNodes(locations, operator, terms.map((t) => t.expression.node));
|
|
101
|
+
return new SingleDependencyExpression(new SyncExpression(inner, locations));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function composeExpressionNodes(locations, operator, terms) {
|
|
105
|
+
if (terms.length == 0) {
|
|
106
|
+
throw new Error("Can't compose zero expressions");
|
|
107
|
+
}
|
|
108
|
+
const [first, ...rest] = terms;
|
|
109
|
+
let inner = first;
|
|
110
|
+
for (const additional of rest) {
|
|
111
|
+
inner = { type: 'binary', operator, left: inner, right: additional };
|
|
112
|
+
}
|
|
113
|
+
const location = expandNodeLocations(terms.map((e) => locations.locationFor(e)));
|
|
114
|
+
if (location) {
|
|
115
|
+
locations.sourceForNode.set(inner, location);
|
|
116
|
+
}
|
|
117
|
+
return inner;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=filter_simplifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter_simplifier.js","sourceRoot":"","sources":["../../src/compiler/filter_simplifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as plan from '../sync_plan/plan.js';
|
|
2
|
+
import { CompiledStreamQueries } from './compiler.js';
|
|
3
|
+
export declare class CompilerModelToSyncPlan {
|
|
4
|
+
private static readonly evaluatorHash;
|
|
5
|
+
private mappedObjects;
|
|
6
|
+
private buckets;
|
|
7
|
+
/**
|
|
8
|
+
* Mapping of row evaluators to buckets.
|
|
9
|
+
*
|
|
10
|
+
* One might expect one stream to result in one bucket, but that is not generally the case. First, a stream might
|
|
11
|
+
* define multiple buckets. For instance, `SELECT * FROM notes WHERE notes.is_public OR auth.parameter('admin')`
|
|
12
|
+
* requires two buckets since there are different ways a row in `notes` might be synced (we have one bucket with
|
|
13
|
+
* public notes and one bucket of all notes, and then decide which ones a given user has access to by inspecting the
|
|
14
|
+
* token).
|
|
15
|
+
*
|
|
16
|
+
* Further, a stream might have multiple evaluators but only a single bucket. A stream with queries
|
|
17
|
+
* `SELECT * FROM foo` and `SELECT * FROM bar` is an example for that, we want to merge `foo` and `bar` into the same
|
|
18
|
+
* bucket in this case. This is represented by a {@link resolver.StreamResolver} having multiple evaluators attached
|
|
19
|
+
* to it.
|
|
20
|
+
*
|
|
21
|
+
* Finally, we may even be able to re-use buckets between streams. This is not possible in many cases, but can be done
|
|
22
|
+
* if e.g. one stream is `SELECT * FROM profiles WHERE user = auth.user_id()` and another one is
|
|
23
|
+
* `SELECT * FROM profiles WHERE user IN (SELECT member FROM orgs WHERE id = auth.parameter('org'))`. Because the
|
|
24
|
+
* partitioning on `profiles` is the same in both cases, it doesn't matter how the buckets are instantiated.
|
|
25
|
+
*/
|
|
26
|
+
private evaluatorsToBuckets;
|
|
27
|
+
private translateStatefulObject;
|
|
28
|
+
translate(source: CompiledStreamQueries): plan.SyncPlan;
|
|
29
|
+
private createBucketSource;
|
|
30
|
+
private translatePartitionKey;
|
|
31
|
+
private translateRowEvaluator;
|
|
32
|
+
private translatePointLookup;
|
|
33
|
+
private translateExpression;
|
|
34
|
+
private translateStreamResolver;
|
|
35
|
+
private translateExpandingLookup;
|
|
36
|
+
private translateParameterValue;
|
|
37
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as resolver from './bucket_resolver.js';
|
|
2
|
+
import { HashMap, StableHasher, unorderedEquality } from './equality.js';
|
|
3
|
+
import { ColumnInRow } from './expression.js';
|
|
4
|
+
import * as rows from './rows.js';
|
|
5
|
+
import { MapSourceVisitor, visitExpr } from '../sync_plan/expression_visitor.js';
|
|
6
|
+
export class CompilerModelToSyncPlan {
|
|
7
|
+
static evaluatorHash = unorderedEquality({
|
|
8
|
+
hash: (hasher, value) => value.buildBehaviorHashCode(hasher),
|
|
9
|
+
equals: (a, b) => a.behavesIdenticalTo(b)
|
|
10
|
+
});
|
|
11
|
+
mappedObjects = new Map();
|
|
12
|
+
buckets = [];
|
|
13
|
+
/**
|
|
14
|
+
* Mapping of row evaluators to buckets.
|
|
15
|
+
*
|
|
16
|
+
* One might expect one stream to result in one bucket, but that is not generally the case. First, a stream might
|
|
17
|
+
* define multiple buckets. For instance, `SELECT * FROM notes WHERE notes.is_public OR auth.parameter('admin')`
|
|
18
|
+
* requires two buckets since there are different ways a row in `notes` might be synced (we have one bucket with
|
|
19
|
+
* public notes and one bucket of all notes, and then decide which ones a given user has access to by inspecting the
|
|
20
|
+
* token).
|
|
21
|
+
*
|
|
22
|
+
* Further, a stream might have multiple evaluators but only a single bucket. A stream with queries
|
|
23
|
+
* `SELECT * FROM foo` and `SELECT * FROM bar` is an example for that, we want to merge `foo` and `bar` into the same
|
|
24
|
+
* bucket in this case. This is represented by a {@link resolver.StreamResolver} having multiple evaluators attached
|
|
25
|
+
* to it.
|
|
26
|
+
*
|
|
27
|
+
* Finally, we may even be able to re-use buckets between streams. This is not possible in many cases, but can be done
|
|
28
|
+
* if e.g. one stream is `SELECT * FROM profiles WHERE user = auth.user_id()` and another one is
|
|
29
|
+
* `SELECT * FROM profiles WHERE user IN (SELECT member FROM orgs WHERE id = auth.parameter('org'))`. Because the
|
|
30
|
+
* partitioning on `profiles` is the same in both cases, it doesn't matter how the buckets are instantiated.
|
|
31
|
+
*/
|
|
32
|
+
evaluatorsToBuckets = new HashMap(CompilerModelToSyncPlan.evaluatorHash);
|
|
33
|
+
translateStatefulObject(source, map) {
|
|
34
|
+
const mapped = map();
|
|
35
|
+
this.mappedObjects.set(source, mapped);
|
|
36
|
+
return mapped;
|
|
37
|
+
}
|
|
38
|
+
translate(source) {
|
|
39
|
+
const queriersByStream = Object.groupBy(source.resolvers, (r) => r.options.name);
|
|
40
|
+
return {
|
|
41
|
+
dataSources: source.evaluators.map((e) => this.translateRowEvaluator(e)),
|
|
42
|
+
parameterIndexes: source.pointLookups.map((p, i) => this.translatePointLookup(p, i)),
|
|
43
|
+
// Note: data sources and parameter indexes must be translated first because we reference them in stream
|
|
44
|
+
// resolvers.
|
|
45
|
+
streams: Object.values(queriersByStream).map((resolvers) => {
|
|
46
|
+
return {
|
|
47
|
+
stream: resolvers[0].options,
|
|
48
|
+
queriers: resolvers.map((e) => this.translateStreamResolver(e))
|
|
49
|
+
};
|
|
50
|
+
}),
|
|
51
|
+
buckets: this.buckets
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
createBucketSource(evaluators, uniqueName) {
|
|
55
|
+
return this.evaluatorsToBuckets.putIfAbsent(evaluators, () => {
|
|
56
|
+
const hash = StableHasher.hashWith(CompilerModelToSyncPlan.evaluatorHash, evaluators);
|
|
57
|
+
const source = {
|
|
58
|
+
hashCode: hash,
|
|
59
|
+
sources: evaluators.map((e) => this.mappedObjects.get(e)),
|
|
60
|
+
uniqueName
|
|
61
|
+
};
|
|
62
|
+
this.buckets.push(source);
|
|
63
|
+
return source;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
translatePartitionKey(value) {
|
|
67
|
+
return { expr: this.translateExpression(value.expression.expression) };
|
|
68
|
+
}
|
|
69
|
+
translateRowEvaluator(value) {
|
|
70
|
+
return this.translateStatefulObject(value, () => {
|
|
71
|
+
const hasher = new StableHasher();
|
|
72
|
+
value.buildBehaviorHashCode(hasher);
|
|
73
|
+
const mapped = {
|
|
74
|
+
sourceTable: value.tablePattern,
|
|
75
|
+
hashCode: hasher.buildHashCode(),
|
|
76
|
+
columns: value.columns.map((e) => {
|
|
77
|
+
if (e instanceof rows.StarColumnSource) {
|
|
78
|
+
return 'star';
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return { expr: this.translateExpression(e.expression.expression), alias: e.alias ?? null };
|
|
82
|
+
}
|
|
83
|
+
}),
|
|
84
|
+
outputTableName: value.outputName,
|
|
85
|
+
filters: value.filters.map((e) => this.translateExpression(e.expression)),
|
|
86
|
+
parameters: value.partitionBy.map((e) => this.translatePartitionKey(e))
|
|
87
|
+
};
|
|
88
|
+
return mapped;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
translatePointLookup(value, index) {
|
|
92
|
+
return this.translateStatefulObject(value, () => {
|
|
93
|
+
const hasher = new StableHasher();
|
|
94
|
+
value.buildBehaviorHashCode(hasher);
|
|
95
|
+
return {
|
|
96
|
+
sourceTable: value.tablePattern,
|
|
97
|
+
defaultLookupScope: {
|
|
98
|
+
// This just needs to be unique, and isn't visible to users (unlike bucket names). We might want to use a
|
|
99
|
+
// more stable naming scheme in the future.
|
|
100
|
+
lookupName: 'lookup',
|
|
101
|
+
queryId: index.toString()
|
|
102
|
+
},
|
|
103
|
+
hashCode: hasher.buildHashCode(),
|
|
104
|
+
outputs: value.result.map((e) => this.translateExpression(e.expression)),
|
|
105
|
+
filters: value.filters.map((e) => this.translateExpression(e.expression)),
|
|
106
|
+
parameters: value.partitionBy.map((e) => this.translatePartitionKey(e))
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
translateExpression(expression) {
|
|
111
|
+
const mapper = new MapSourceVisitor((value) => {
|
|
112
|
+
if (value instanceof ColumnInRow) {
|
|
113
|
+
return { column: value.column };
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return { request: value.source };
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return visitExpr(mapper, expression.node, null);
|
|
120
|
+
}
|
|
121
|
+
translateStreamResolver(value) {
|
|
122
|
+
return {
|
|
123
|
+
requestFilters: value.requestFilters.map((e) => this.translateExpression(e.expression)),
|
|
124
|
+
lookupStages: value.lookupStages.map((stage) => {
|
|
125
|
+
return stage.map((e) => this.translateExpandingLookup(e));
|
|
126
|
+
}),
|
|
127
|
+
bucket: this.createBucketSource([...value.resolvedBucket.evaluators], value.uniqueName),
|
|
128
|
+
sourceInstantiation: value.resolvedBucket.instantiation.map((e) => this.translateParameterValue(e))
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
translateExpandingLookup(value) {
|
|
132
|
+
return this.translateStatefulObject(value, () => {
|
|
133
|
+
if (value instanceof resolver.ParameterLookup) {
|
|
134
|
+
return {
|
|
135
|
+
type: 'parameter',
|
|
136
|
+
lookup: this.mappedObjects.get(value.lookup),
|
|
137
|
+
instantiation: value.instantiation.map((e) => this.translateParameterValue(e))
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
return {
|
|
142
|
+
type: 'table_valued',
|
|
143
|
+
functionName: value.tableValuedFunction.tableValuedFunctionName,
|
|
144
|
+
functionInputs: value.tableValuedFunction.parameters.map((e) => this.translateExpression(e.expression)),
|
|
145
|
+
outputs: value.outputs.map((e) => this.translateExpression(e.expression)),
|
|
146
|
+
filters: value.filters.map((e) => this.translateExpression(e.expression))
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
translateParameterValue(value) {
|
|
152
|
+
if (value instanceof resolver.RequestParameterValue) {
|
|
153
|
+
return { type: 'request', expr: this.translateExpression(value.expression.expression) };
|
|
154
|
+
}
|
|
155
|
+
else if (value instanceof resolver.LookupResultParameterValue) {
|
|
156
|
+
return { type: 'lookup', resultIndex: value.resultIndex, lookup: this.mappedObjects.get(value.lookup) };
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
return { type: 'intersection', values: value.inner.map((e) => this.translateParameterValue(e)) };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=ir_to_sync_plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ir_to_sync_plan.js","sourceRoot":"","sources":["../../src/compiler/ir_to_sync_plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Statement } from 'pgsql-ast-parser';
|
|
2
|
+
import { PhysicalSourceResultSet, SourceResultSet } from './table.js';
|
|
3
|
+
import { ColumnSource } from './rows.js';
|
|
4
|
+
import { NodeLocations } from './expression.js';
|
|
5
|
+
import { Or } from './filter.js';
|
|
6
|
+
import { PreparedSubquery } from './sqlite.js';
|
|
7
|
+
import { SqlScope } from './scope.js';
|
|
8
|
+
import { ParsingErrorListener, SyncStreamsCompiler } from './compiler.js';
|
|
9
|
+
/**
|
|
10
|
+
* A parsed stream query in its canonical form.
|
|
11
|
+
*
|
|
12
|
+
* The canonical form of stream queries is as follows:
|
|
13
|
+
*
|
|
14
|
+
* ```SQL
|
|
15
|
+
* SELECT <expr>* FROM sourceTable a
|
|
16
|
+
* JOIN table2 b
|
|
17
|
+
* -- ... additional joins
|
|
18
|
+
* WHERE <expr>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Expressions in the result set must all refer to columns in the {@link sourceTable}.
|
|
22
|
+
*
|
|
23
|
+
* Additionally, the where clause is in disjunctive normal form. Inner terms are either scalar expressions only
|
|
24
|
+
* depending on data from a single source result set, or match clauses.
|
|
25
|
+
*
|
|
26
|
+
* Subqueries are not allowed in the canonical form. Instead, they are lowered into joins. So e.g. the query:
|
|
27
|
+
*
|
|
28
|
+
* ```SQL
|
|
29
|
+
* SELECT * FROM users WHERE id IN (SELECT user FROM org WHERE id = auth.user_id())
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* would get lowered to:
|
|
33
|
+
* ```SQL
|
|
34
|
+
* SELECT tmp0.* FROM users tmp0
|
|
35
|
+
* JOIN org tmp1
|
|
36
|
+
* WHERE tmp0.id = tmp1.user AND tmp1.id = (:auth_token) ->> '$.sub';
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* Unlike shown here, this lowering doesn't generate aliases that would have to be applied to expressions though.
|
|
40
|
+
* References in expressions would get resolved earlier, and they continue being valid after the transformation.
|
|
41
|
+
*/
|
|
42
|
+
export interface ParsedStreamQuery {
|
|
43
|
+
resultColumns: ColumnSource[];
|
|
44
|
+
sourceTable: PhysicalSourceResultSet;
|
|
45
|
+
joined: SourceResultSet[];
|
|
46
|
+
/**
|
|
47
|
+
* All filters, in disjunctive normal form (an OR of ANDs).
|
|
48
|
+
*/
|
|
49
|
+
where: Or;
|
|
50
|
+
}
|
|
51
|
+
export interface StreamQueryParserOptions {
|
|
52
|
+
compiler: SyncStreamsCompiler;
|
|
53
|
+
originalText: string;
|
|
54
|
+
errors: ParsingErrorListener;
|
|
55
|
+
parentScope: SqlScope;
|
|
56
|
+
locations: NodeLocations;
|
|
57
|
+
}
|
|
58
|
+
export declare class StreamQueryParser {
|
|
59
|
+
readonly errors: ParsingErrorListener;
|
|
60
|
+
private readonly compiler;
|
|
61
|
+
readonly originalText: string;
|
|
62
|
+
private readonly statementScope;
|
|
63
|
+
private readonly resultSets;
|
|
64
|
+
private readonly subqueryResultSets;
|
|
65
|
+
private readonly resultColumns;
|
|
66
|
+
private where;
|
|
67
|
+
/** The result set for which rows are synced. Set when analyzing result columns. */
|
|
68
|
+
private primaryResultSet?;
|
|
69
|
+
private syntheticSubqueryCounter;
|
|
70
|
+
private nodeLocations;
|
|
71
|
+
private exprParser;
|
|
72
|
+
constructor(options: StreamQueryParserOptions);
|
|
73
|
+
parse(stmt: Statement): ParsedStreamQuery | null;
|
|
74
|
+
parseAsSubquery(stmt: Statement, columnNames?: string[]): PreparedSubquery | null;
|
|
75
|
+
private nestedParser;
|
|
76
|
+
/**
|
|
77
|
+
* Process the AST of a statement, returning whether it's close enough to a valid select statement to be supported for
|
|
78
|
+
* sync streams (allowing us to process an invalid statement further to perhaps collect more errors).
|
|
79
|
+
*/
|
|
80
|
+
private processAst;
|
|
81
|
+
private addAndTermToWhereClause;
|
|
82
|
+
private addSubquery;
|
|
83
|
+
private processFrom;
|
|
84
|
+
private resolveTableValued;
|
|
85
|
+
private inferColumnName;
|
|
86
|
+
private processResultColumns;
|
|
87
|
+
private parseExpression;
|
|
88
|
+
private resolveTableName;
|
|
89
|
+
private resolveSoure;
|
|
90
|
+
private warnUnsupported;
|
|
91
|
+
private compileFilterClause;
|
|
92
|
+
private mapBaseExpression;
|
|
93
|
+
/**
|
|
94
|
+
* Emit diagnostics if the expression references data from more than one table, otherwise returns it as a
|
|
95
|
+
* single-dependency expression.
|
|
96
|
+
*/
|
|
97
|
+
private mustBeSingleDependency;
|
|
98
|
+
private extractBooleanOperators;
|
|
99
|
+
}
|