@powersync/service-sync-rules 0.29.9 → 0.30.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.
Files changed (170) hide show
  1. package/dist/BaseSqlDataQuery.d.ts +3 -9
  2. package/dist/BaseSqlDataQuery.js +11 -21
  3. package/dist/BaseSqlDataQuery.js.map +1 -1
  4. package/dist/BucketParameterQuerier.d.ts +42 -9
  5. package/dist/BucketParameterQuerier.js +30 -7
  6. package/dist/BucketParameterQuerier.js.map +1 -1
  7. package/dist/BucketSource.d.ts +94 -25
  8. package/dist/BucketSource.js +67 -0
  9. package/dist/BucketSource.js.map +1 -1
  10. package/dist/ExpressionType.d.ts +4 -2
  11. package/dist/ExpressionType.js.map +1 -1
  12. package/dist/HydratedSyncRules.d.ts +46 -0
  13. package/dist/HydratedSyncRules.js +88 -0
  14. package/dist/HydratedSyncRules.js.map +1 -0
  15. package/dist/HydrationState.d.ts +45 -0
  16. package/dist/HydrationState.js +41 -0
  17. package/dist/HydrationState.js.map +1 -0
  18. package/dist/SqlBucketDescriptor.d.ts +31 -28
  19. package/dist/SqlBucketDescriptor.js +89 -112
  20. package/dist/SqlBucketDescriptor.js.map +1 -1
  21. package/dist/SqlDataQuery.d.ts +4 -4
  22. package/dist/SqlDataQuery.js +5 -6
  23. package/dist/SqlDataQuery.js.map +1 -1
  24. package/dist/SqlParameterQuery.d.ts +17 -9
  25. package/dist/SqlParameterQuery.js +49 -23
  26. package/dist/SqlParameterQuery.js.map +1 -1
  27. package/dist/SqlSyncRules.d.ts +13 -29
  28. package/dist/SqlSyncRules.js +48 -77
  29. package/dist/SqlSyncRules.js.map +1 -1
  30. package/dist/StaticSqlParameterQuery.d.ts +13 -3
  31. package/dist/StaticSqlParameterQuery.js +38 -4
  32. package/dist/StaticSqlParameterQuery.js.map +1 -1
  33. package/dist/TablePattern.d.ts +4 -1
  34. package/dist/TablePattern.js +11 -0
  35. package/dist/TablePattern.js.map +1 -1
  36. package/dist/TableValuedFunctionSqlParameterQuery.d.ts +14 -4
  37. package/dist/TableValuedFunctionSqlParameterQuery.js +41 -7
  38. package/dist/TableValuedFunctionSqlParameterQuery.js.map +1 -1
  39. package/dist/compatibility.d.ts +23 -1
  40. package/dist/compatibility.js +32 -4
  41. package/dist/compatibility.js.map +1 -1
  42. package/dist/compiler/bucket_resolver.d.ts +70 -0
  43. package/dist/compiler/bucket_resolver.js +131 -0
  44. package/dist/compiler/bucket_resolver.js.map +1 -0
  45. package/dist/compiler/compatibility.d.ts +16 -0
  46. package/dist/compiler/compatibility.js +12 -0
  47. package/dist/compiler/compatibility.js.map +1 -0
  48. package/dist/compiler/compiler.d.ts +104 -0
  49. package/dist/compiler/compiler.js +113 -0
  50. package/dist/compiler/compiler.js.map +1 -0
  51. package/dist/compiler/equality.d.ts +99 -0
  52. package/dist/compiler/equality.js +284 -0
  53. package/dist/compiler/equality.js.map +1 -0
  54. package/dist/compiler/expression.d.ts +77 -0
  55. package/dist/compiler/expression.js +122 -0
  56. package/dist/compiler/expression.js.map +1 -0
  57. package/dist/compiler/filter.d.ts +71 -0
  58. package/dist/compiler/filter.js +110 -0
  59. package/dist/compiler/filter.js.map +1 -0
  60. package/dist/compiler/filter_simplifier.d.ts +26 -0
  61. package/dist/compiler/filter_simplifier.js +119 -0
  62. package/dist/compiler/filter_simplifier.js.map +1 -0
  63. package/dist/compiler/ir_to_sync_plan.d.ts +37 -0
  64. package/dist/compiler/ir_to_sync_plan.js +163 -0
  65. package/dist/compiler/ir_to_sync_plan.js.map +1 -0
  66. package/dist/compiler/parser.d.ts +99 -0
  67. package/dist/compiler/parser.js +556 -0
  68. package/dist/compiler/parser.js.map +1 -0
  69. package/dist/compiler/querier_graph.d.ts +42 -0
  70. package/dist/compiler/querier_graph.js +365 -0
  71. package/dist/compiler/querier_graph.js.map +1 -0
  72. package/dist/compiler/rows.d.ts +113 -0
  73. package/dist/compiler/rows.js +156 -0
  74. package/dist/compiler/rows.js.map +1 -0
  75. package/dist/compiler/scope.d.ts +22 -0
  76. package/dist/compiler/scope.js +47 -0
  77. package/dist/compiler/scope.js.map +1 -0
  78. package/dist/compiler/sqlite.d.ts +77 -0
  79. package/dist/compiler/sqlite.js +412 -0
  80. package/dist/compiler/sqlite.js.map +1 -0
  81. package/dist/compiler/table.d.ts +67 -0
  82. package/dist/compiler/table.js +67 -0
  83. package/dist/compiler/table.js.map +1 -0
  84. package/dist/errors.d.ts +4 -2
  85. package/dist/errors.js +16 -1
  86. package/dist/errors.js.map +1 -1
  87. package/dist/events/SqlEventDescriptor.js +1 -1
  88. package/dist/events/SqlEventDescriptor.js.map +1 -1
  89. package/dist/events/SqlEventSourceQuery.d.ts +1 -1
  90. package/dist/events/SqlEventSourceQuery.js +1 -2
  91. package/dist/events/SqlEventSourceQuery.js.map +1 -1
  92. package/dist/index.d.ts +8 -0
  93. package/dist/index.js +8 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/json_schema.js +5 -1
  96. package/dist/json_schema.js.map +1 -1
  97. package/dist/request_functions.js +1 -1
  98. package/dist/request_functions.js.map +1 -1
  99. package/dist/schema-generators/SchemaGenerator.d.ts +5 -0
  100. package/dist/schema-generators/SchemaGenerator.js +21 -14
  101. package/dist/schema-generators/SchemaGenerator.js.map +1 -1
  102. package/dist/sql_functions.d.ts +2 -1
  103. package/dist/sql_functions.js +1 -1
  104. package/dist/sql_functions.js.map +1 -1
  105. package/dist/streams/filter.d.ts +34 -4
  106. package/dist/streams/filter.js +93 -23
  107. package/dist/streams/filter.js.map +1 -1
  108. package/dist/streams/from_sql.js +2 -5
  109. package/dist/streams/from_sql.js.map +1 -1
  110. package/dist/streams/parameter.d.ts +7 -6
  111. package/dist/streams/stream.d.ts +25 -15
  112. package/dist/streams/stream.js +59 -87
  113. package/dist/streams/stream.js.map +1 -1
  114. package/dist/streams/variant.d.ts +14 -21
  115. package/dist/streams/variant.js +68 -46
  116. package/dist/streams/variant.js.map +1 -1
  117. package/dist/sync_plan/engine/javascript.d.ts +6 -0
  118. package/dist/sync_plan/engine/javascript.js +208 -0
  119. package/dist/sync_plan/engine/javascript.js.map +1 -0
  120. package/dist/sync_plan/engine/scalar_expression_engine.d.ts +48 -0
  121. package/dist/sync_plan/engine/scalar_expression_engine.js +99 -0
  122. package/dist/sync_plan/engine/scalar_expression_engine.js.map +1 -0
  123. package/dist/sync_plan/engine/sqlite.d.ts +12 -0
  124. package/dist/sync_plan/engine/sqlite.js +53 -0
  125. package/dist/sync_plan/engine/sqlite.js.map +1 -0
  126. package/dist/sync_plan/evaluator/bucket_data_source.d.ts +23 -0
  127. package/dist/sync_plan/evaluator/bucket_data_source.js +137 -0
  128. package/dist/sync_plan/evaluator/bucket_data_source.js.map +1 -0
  129. package/dist/sync_plan/evaluator/bucket_source.d.ts +19 -0
  130. package/dist/sync_plan/evaluator/bucket_source.js +145 -0
  131. package/dist/sync_plan/evaluator/bucket_source.js.map +1 -0
  132. package/dist/sync_plan/evaluator/index.d.ts +7 -0
  133. package/dist/sync_plan/evaluator/index.js +26 -0
  134. package/dist/sync_plan/evaluator/index.js.map +1 -0
  135. package/dist/sync_plan/evaluator/parameter_evaluator.d.ts +138 -0
  136. package/dist/sync_plan/evaluator/parameter_evaluator.js +359 -0
  137. package/dist/sync_plan/evaluator/parameter_evaluator.js.map +1 -0
  138. package/dist/sync_plan/evaluator/parameter_index_lookup_creator.d.ts +19 -0
  139. package/dist/sync_plan/evaluator/parameter_index_lookup_creator.js +62 -0
  140. package/dist/sync_plan/evaluator/parameter_index_lookup_creator.js.map +1 -0
  141. package/dist/sync_plan/expression.d.ts +109 -0
  142. package/dist/sync_plan/expression.js +85 -0
  143. package/dist/sync_plan/expression.js.map +1 -0
  144. package/dist/sync_plan/expression_to_sql.d.ts +43 -0
  145. package/dist/sync_plan/expression_to_sql.js +190 -0
  146. package/dist/sync_plan/expression_to_sql.js.map +1 -0
  147. package/dist/sync_plan/expression_visitor.d.ts +57 -0
  148. package/dist/sync_plan/expression_visitor.js +181 -0
  149. package/dist/sync_plan/expression_visitor.js.map +1 -0
  150. package/dist/sync_plan/plan.d.ts +196 -0
  151. package/dist/sync_plan/plan.js +2 -0
  152. package/dist/sync_plan/plan.js.map +1 -0
  153. package/dist/sync_plan/schema_inference.d.ts +15 -0
  154. package/dist/sync_plan/schema_inference.js +121 -0
  155. package/dist/sync_plan/schema_inference.js.map +1 -0
  156. package/dist/sync_plan/serialize.d.ts +82 -0
  157. package/dist/sync_plan/serialize.js +209 -0
  158. package/dist/sync_plan/serialize.js.map +1 -0
  159. package/dist/types/custom_sqlite_value.d.ts +1 -1
  160. package/dist/types/time.d.ts +24 -5
  161. package/dist/types/time.js +67 -12
  162. package/dist/types/time.js.map +1 -1
  163. package/dist/types.d.ts +52 -24
  164. package/dist/types.js +4 -1
  165. package/dist/types.js.map +1 -1
  166. package/dist/utils.d.ts +9 -2
  167. package/dist/utils.js +26 -3
  168. package/dist/utils.js.map +1 -1
  169. package/package.json +4 -3
  170. package/schema/sync_rules.json +9 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Stable value-based hashcodes for JavaScript. The sync streams compiler uses hashmaps derived from this to efficiently
3
+ * de-duplicate equivalent expressions and lookups.
4
+ *
5
+ * This is copied from Dart SDK sources, which in turn based the algorithm on Jenkins hash functions.
6
+ *
7
+ * Because hash codes are stable across restarts, they should not be used for untrusted inputs to avoid attacks
8
+ * provoking hash collisions and subpar hashmap performance. The sync rules package only uses these hashes to compile
9
+ * sync streams, but the compiled IR processing source rows does not need these hashes.
10
+ */
11
+ export declare class StableHasher {
12
+ private static readonly seed;
13
+ private hash;
14
+ addHash(value: number): void;
15
+ reset(): number;
16
+ addString(value: string): void;
17
+ add(...e: Equatable[]): void;
18
+ buildHashCode(): number;
19
+ /**
20
+ * Hashes a value under the given equality implementation.
21
+ */
22
+ static hashWith<T>(equality: Equality<T>, value: T): number;
23
+ private static readonly hasher;
24
+ /**
25
+ * The default equality for {@link Equatable} types.
26
+ */
27
+ private static readonly defaultEquality;
28
+ static readonly defaultListEquality: Equality<Iterable<Equatable>>;
29
+ }
30
+ /**
31
+ * A generic equality relation on objects.
32
+ */
33
+ export interface Equality<T> {
34
+ /**
35
+ * Checks whether a and b are equal according to this equality implementation.
36
+ *
37
+ * This must hold the usual properties for equality relations (reflexivity, symmetry and transitivety).
38
+ */
39
+ equals(a: T, b: T): boolean;
40
+ /**
41
+ * Adds a value to a stable hasher.
42
+ *
43
+ * The implementation of hashes must be compatible with {@link equals}, meaning that if values `a` and `b` are equal,
44
+ * they must also generate the same hash. Two distinct values may also generate the same hashcode though.
45
+ */
46
+ hash(hasher: StableHasher, value: T): void;
47
+ }
48
+ /**
49
+ * Interface for objects that have a logical default equality.
50
+ */
51
+ export interface Equatable {
52
+ buildHash(hasher: StableHasher): void;
53
+ equals(other: unknown): boolean;
54
+ }
55
+ /**
56
+ * Creates an equality operator matching iterables with elements compared by an inner equality.
57
+ *
58
+ * Two iterables are considered equal if they contain the same elements in the same order.
59
+ */
60
+ export declare function listEquality<E>(equality: Equality<E>): Equality<Iterable<E>>;
61
+ /**
62
+ * Creates an equality operator matching iterables with elements compared by an inner equality.
63
+ *
64
+ * Two iterables are considered equal if they contain the same elements, in any order.
65
+ */
66
+ export declare function unorderedEquality<E>(equality: Equality<E>): Equality<Iterable<E>>;
67
+ /**
68
+ * A hash map implementation based on a custom {@link Equality}.
69
+ *
70
+ * Like {@link Map}, this implementation also preserves insertion-order.
71
+ */
72
+ export declare class HashMap<K, V> {
73
+ private readonly equality;
74
+ private readonly map;
75
+ private first;
76
+ private last;
77
+ constructor(equality: Equality<K>);
78
+ private computeHashCode;
79
+ get isEmpty(): boolean;
80
+ get entries(): Iterable<[K, V]>;
81
+ private iterateEntries;
82
+ get(key: K): V | undefined;
83
+ set(key: K, value: V): void;
84
+ setOrUpdate(key: K, updater: (old: V | undefined, oldKey: K | undefined) => V): void;
85
+ putIfAbsent(key: K, ifAbsent: () => V): V;
86
+ private addEntryInBucket;
87
+ }
88
+ /**
89
+ * An insertion-order preserving hash set implementation based on {@link HashMap}.
90
+ */
91
+ export declare class HashSet<K> implements Iterable<K> {
92
+ private readonly inner;
93
+ constructor(equality: Equality<K>);
94
+ [Symbol.iterator](): Iterator<K>;
95
+ private entries;
96
+ add(element: K): boolean;
97
+ getOrInsert(element: K): [K, boolean];
98
+ private static readonly sentinel;
99
+ }
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Stable value-based hashcodes for JavaScript. The sync streams compiler uses hashmaps derived from this to efficiently
3
+ * de-duplicate equivalent expressions and lookups.
4
+ *
5
+ * This is copied from Dart SDK sources, which in turn based the algorithm on Jenkins hash functions.
6
+ *
7
+ * Because hash codes are stable across restarts, they should not be used for untrusted inputs to avoid attacks
8
+ * provoking hash collisions and subpar hashmap performance. The sync rules package only uses these hashes to compile
9
+ * sync streams, but the compiled IR processing source rows does not need these hashes.
10
+ */
11
+ export class StableHasher {
12
+ static seed = 614160925; // 'PowerSync'.hashCode on the Dart VM
13
+ hash = StableHasher.seed;
14
+ addHash(value) {
15
+ let hash = 0x1fffffff & (this.hash + value);
16
+ hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
17
+ this.hash = hash ^ (hash >> 6);
18
+ }
19
+ reset() {
20
+ const old = this.hash;
21
+ this.hash = StableHasher.seed;
22
+ return old;
23
+ }
24
+ addString(value) {
25
+ for (let i = 0; i < value.length; i++) {
26
+ this.addHash(value.charCodeAt(i));
27
+ }
28
+ }
29
+ add(...e) {
30
+ for (const param of e) {
31
+ param.buildHash(this);
32
+ }
33
+ }
34
+ buildHashCode() {
35
+ let hash = this.hash;
36
+ hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
37
+ hash = hash ^ (hash >> 11);
38
+ return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
39
+ }
40
+ /**
41
+ * Hashes a value under the given equality implementation.
42
+ */
43
+ static hashWith(equality, value) {
44
+ const saved = this.hasher.reset();
45
+ equality.hash(this.hasher, value);
46
+ const result = this.hasher.buildHashCode();
47
+ this.hasher.hash = saved;
48
+ return result;
49
+ }
50
+ static hasher = new StableHasher();
51
+ /**
52
+ * The default equality for {@link Equatable} types.
53
+ */
54
+ static defaultEquality = {
55
+ hash(hasher, value) {
56
+ value.buildHash(hasher);
57
+ },
58
+ equals(a, b) {
59
+ return a.equals(b);
60
+ }
61
+ };
62
+ static defaultListEquality = listEquality(this.defaultEquality);
63
+ }
64
+ /**
65
+ * Creates an equality operator matching iterables with elements compared by an inner equality.
66
+ *
67
+ * Two iterables are considered equal if they contain the same elements in the same order.
68
+ */
69
+ export function listEquality(equality) {
70
+ return {
71
+ equals: (a, b) => {
72
+ if (a === b)
73
+ return true;
74
+ const iteratorA = a[Symbol.iterator]();
75
+ const iteratorB = b[Symbol.iterator]();
76
+ while (true) {
77
+ let nextA = iteratorA.next();
78
+ let nextB = iteratorB.next();
79
+ if (nextA.done != nextB.done) {
80
+ return false; // Different lengths
81
+ }
82
+ else if (nextA.done) {
83
+ return true; // Both done
84
+ }
85
+ else {
86
+ const elementA = nextA.value;
87
+ const elementB = nextB.value;
88
+ if (!equality.equals(elementA, elementB)) {
89
+ return false;
90
+ }
91
+ }
92
+ }
93
+ },
94
+ hash: (hasher, value) => {
95
+ for (const e of value) {
96
+ equality.hash(hasher, e);
97
+ }
98
+ }
99
+ };
100
+ }
101
+ /**
102
+ * Creates an equality operator matching iterables with elements compared by an inner equality.
103
+ *
104
+ * Two iterables are considered equal if they contain the same elements, in any order.
105
+ */
106
+ export function unorderedEquality(equality) {
107
+ return {
108
+ equals: (a, b) => {
109
+ if (a === b)
110
+ return true;
111
+ let counts = new HashMap(equality);
112
+ let length = 0;
113
+ // Count how often each element exists in a.
114
+ for (const e of a) {
115
+ counts.setOrUpdate(e, (old) => (old ?? 0) + 1);
116
+ length++;
117
+ }
118
+ // Then compare with b.
119
+ for (const e of b) {
120
+ let matched = false;
121
+ counts.setOrUpdate(e, (old) => {
122
+ matched = old != null && old > 0;
123
+ if (matched) {
124
+ return old - 1;
125
+ }
126
+ else {
127
+ return 0;
128
+ }
129
+ });
130
+ if (!matched) {
131
+ return false;
132
+ }
133
+ length--;
134
+ }
135
+ return length == 0;
136
+ },
137
+ hash: (hasher, value) => {
138
+ // https://github.com/dart-lang/core/blob/3e55c1ce7be48b469da5be043b5931fe6405f74a/pkgs/collection/lib/src/equality.dart#L236-L248
139
+ let hash = 0;
140
+ for (const element of value) {
141
+ hash = (hash + StableHasher.hashWith(equality, element)) & 0x7fffffff;
142
+ }
143
+ hasher.addHash(hash);
144
+ }
145
+ };
146
+ }
147
+ /**
148
+ * A hash map implementation based on a custom {@link Equality}.
149
+ *
150
+ * Like {@link Map}, this implementation also preserves insertion-order.
151
+ */
152
+ export class HashMap {
153
+ equality;
154
+ // We create one bucket per unique hash, and then store collisions in an array.
155
+ map = new Map();
156
+ first;
157
+ last;
158
+ constructor(equality) {
159
+ this.equality = equality;
160
+ }
161
+ computeHashCode(key) {
162
+ return StableHasher.hashWith(this.equality, key);
163
+ }
164
+ get isEmpty() {
165
+ return this.first == null;
166
+ }
167
+ get entries() {
168
+ return this.iterateEntries();
169
+ }
170
+ *iterateEntries() {
171
+ let next = this.first;
172
+ while (next != null) {
173
+ yield [next.key, next.value];
174
+ next = next.next;
175
+ }
176
+ }
177
+ get(key) {
178
+ const hashCode = this.computeHashCode(key);
179
+ const bucket = this.map.get(hashCode);
180
+ if (bucket) {
181
+ for (const entry of bucket) {
182
+ if (this.equality.equals(entry.key, key)) {
183
+ return entry.value;
184
+ }
185
+ }
186
+ }
187
+ }
188
+ set(key, value) {
189
+ const hashCode = this.computeHashCode(key);
190
+ let bucket = this.map.get(hashCode);
191
+ if (!bucket) {
192
+ bucket = [];
193
+ this.map.set(hashCode, bucket);
194
+ }
195
+ this.addEntryInBucket(bucket, key, value);
196
+ }
197
+ setOrUpdate(key, updater) {
198
+ const hashCode = this.computeHashCode(key);
199
+ let bucket = this.map.get(hashCode);
200
+ if (!bucket) {
201
+ bucket = [];
202
+ this.map.set(hashCode, bucket);
203
+ }
204
+ else {
205
+ for (const entry of bucket) {
206
+ if (this.equality.equals(entry.key, key)) {
207
+ entry.value = updater(entry.value, entry.key);
208
+ return;
209
+ }
210
+ }
211
+ }
212
+ this.addEntryInBucket(bucket, key, updater(undefined, undefined));
213
+ }
214
+ putIfAbsent(key, ifAbsent) {
215
+ let result = undefined;
216
+ this.setOrUpdate(key, (old) => {
217
+ if (old == null) {
218
+ return (result = ifAbsent());
219
+ }
220
+ else {
221
+ return (result = old);
222
+ }
223
+ });
224
+ return result;
225
+ }
226
+ addEntryInBucket(bucket, key, value) {
227
+ const entry = new LinkedHashMapEntry(key, value);
228
+ bucket.push(entry);
229
+ if (this.first) {
230
+ this.last.next = entry;
231
+ entry.prev = this.last;
232
+ this.last = entry;
233
+ }
234
+ else {
235
+ this.first = this.last = entry;
236
+ }
237
+ }
238
+ }
239
+ /**
240
+ * An insertion-order preserving hash set implementation based on {@link HashMap}.
241
+ */
242
+ export class HashSet {
243
+ inner;
244
+ constructor(equality) {
245
+ this.inner = new HashMap(equality);
246
+ }
247
+ [Symbol.iterator]() {
248
+ return this.entries()[Symbol.iterator]();
249
+ }
250
+ *entries() {
251
+ for (const [k, _] of this.inner.entries) {
252
+ yield k;
253
+ }
254
+ }
255
+ add(element) {
256
+ return this.getOrInsert(element)[1];
257
+ }
258
+ getOrInsert(element) {
259
+ let result = null;
260
+ this.inner.setOrUpdate(element, (old, oldKey) => {
261
+ if (oldKey == null) {
262
+ result = [element, true];
263
+ return HashSet.sentinel;
264
+ }
265
+ else {
266
+ result = [oldKey, false];
267
+ return oldKey;
268
+ }
269
+ });
270
+ return result;
271
+ }
272
+ static sentinel = new Object();
273
+ }
274
+ class LinkedHashMapEntry {
275
+ key;
276
+ prev;
277
+ next;
278
+ value;
279
+ constructor(key, value) {
280
+ this.key = key;
281
+ this.value = value;
282
+ }
283
+ }
284
+ //# sourceMappingURL=equality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equality.js","sourceRoot":"","sources":["../../src/compiler/equality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,OAAO,YAAY;IACf,MAAM,CAAU,IAAI,GAAW,SAAS,CAAC,CAAC,sCAAsC;IAEhF,IAAI,GAAW,YAAY,CAAC,IAAI,CAAC;IAEzC,OAAO,CAAC,KAAa;QACnB,IAAI,IAAI,GAAG,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAC5C,IAAI,GAAG,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAG,CAAc;QACnB,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;YACtB,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,aAAa;QACX,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrB,IAAI,GAAG,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3B,OAAO,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAI,QAAqB,EAAE,KAAQ;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,MAAM,CAAU,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpD;;OAEG;IACK,MAAM,CAAU,eAAe,GAAwB;QAC7D,IAAI,CAAC,MAAM,EAAE,KAAK;YAChB,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;KACF,CAAC;IAEF,MAAM,CAAU,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;;AA+B3E;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAI,QAAqB;IACnD,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACf,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAEzB,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAEvC,OAAO,IAAI,EAAE,CAAC;gBACZ,IAAI,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC7B,IAAI,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;gBAE7B,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBAC7B,OAAO,KAAK,CAAC,CAAC,oBAAoB;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACtB,OAAO,IAAI,CAAC,CAAC,YAAY;gBAC3B,CAAC;qBAAM,CAAC;oBACN,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;oBAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;oBAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;wBACzC,OAAO,KAAK,CAAC;oBACf,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACtB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAI,QAAqB;IACxD,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACf,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAEzB,IAAI,MAAM,GAAG,IAAI,OAAO,CAAY,QAAQ,CAAC,CAAC;YAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,4CAA4C;YAC5C,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC/C,MAAM,EAAE,CAAC;YACX,CAAC;YAED,uBAAuB;YACvB,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;oBAC5B,OAAO,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;oBACjC,IAAI,OAAO,EAAE,CAAC;wBACZ,OAAO,GAAI,GAAG,CAAC,CAAC;oBAClB,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,CAAC;oBACX,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,KAAK,CAAC;gBACf,CAAC;gBACD,MAAM,EAAE,CAAC;YACX,CAAC;YAED,OAAO,MAAM,IAAI,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACtB,kIAAkI;YAClI,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;gBAC5B,IAAI,GAAG,CAAC,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC;YACxE,CAAC;YAED,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,OAAO;IAOW;IAN7B,+EAA+E;IAC9D,GAAG,GAAG,IAAI,GAAG,EAAsC,CAAC;IAE7D,KAAK,CAAuC;IAC5C,IAAI,CAAuC;IAEnD,YAA6B,QAAqB;QAArB,aAAQ,GAAR,QAAQ,CAAa;IAAG,CAAC;IAE9C,eAAe,CAAC,GAAM;QAC5B,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;IAC/B,CAAC;IAEO,CAAC,cAAc;QACrB,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACtB,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAM;QACR,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;oBACzC,OAAO,KAAK,CAAC,KAAK,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAM,EAAE,KAAQ;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,GAAM,EAAE,OAAyD;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;oBACzC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC9C,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,WAAW,CAAC,GAAM,EAAE,QAAiB;QACnC,IAAI,MAAM,GAAkB,SAAS,CAAC;QACtC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YAC5B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;gBAChB,OAAO,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,MAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAC,MAAkC,EAAE,GAAM,EAAE,KAAQ;QAC3E,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAK,CAAC,IAAI,GAAG,KAAK,CAAC;YACxB,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,OAAO;IACD,KAAK,CAAqB;IAE3C,YAAY,QAAqB;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC3C,CAAC;IAEO,CAAC,OAAO;QACd,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,GAAG,CAAC,OAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,WAAW,CAAC,OAAU;QACpB,IAAI,MAAM,GAAwB,IAAI,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC9C,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,MAAM,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACzB,OAAO,OAAO,CAAC,QAAQ,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC,MAAO,EAAE,KAAK,CAAC,CAAC;gBAC1B,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,MAAO,CAAC;IACjB,CAAC;IAEO,MAAM,CAAU,QAAQ,GAAG,IAAI,MAAM,EAAE,CAAC;;AAGlD,MAAM,kBAAkB;IAOX;IANX,IAAI,CAAuC;IAC3C,IAAI,CAAuC;IAE3C,KAAK,CAAI;IAET,YACW,GAAM,EACf,KAAQ;QADC,QAAG,GAAH,GAAG,CAAG;QAGf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,77 @@
1
+ import { Expr, NodeLocation, PGNode } from 'pgsql-ast-parser';
2
+ import { SourceResultSet } from './table.js';
3
+ import { EqualsIgnoringResultSet } from './compatibility.js';
4
+ import { StableHasher } from './equality.js';
5
+ import { ConnectionParameterSource } from '../sync_plan/plan.js';
6
+ import { SqlExpression } from '../sync_plan/expression.js';
7
+ /**
8
+ * An analyzed SQL expression tracking dependencies on non-static data (i.e. rows or connection sources).
9
+ *
10
+ * Consider the sync stream `SELECT * FROM issues WHERE is_public OR auth.param('is_admin')`. To be able to explicitly
11
+ * track dependencies referenced in expressions, we transform them into a {@link SyncExpression}. For the `WHERE` clause
12
+ * in that example, the {@link sqlExpression} would be `?1 OR (?2 ->> 'is_admin')`, where `?1` is a {@link ColumnInRow}
13
+ * and `?2` is a {@link ConnectionParameter}.
14
+ *
15
+ * Once in this form, it's easy to reason about dependencies in expressions (used to later generate parameter match
16
+ * clauses) and to evaluate expressions at runtime (by preparing them as a statement and binding external values).
17
+ */
18
+ export declare class SyncExpression implements EqualsIgnoringResultSet {
19
+ #private;
20
+ /**
21
+ * The AST node backing {@link sql}.
22
+ *
23
+ * We use this to be able to compose expressions, e.g. to possibly merge them.
24
+ */
25
+ readonly node: SqlExpression<ExpressionInput>;
26
+ readonly locations: NodeLocations;
27
+ /**
28
+ * The original expression, where references to row or connection parameters have been replaced with SQL variables
29
+ * that are tracked through {@link instantiation}.
30
+ *
31
+ * This is only used to compute hash codes and to check instances for equality. {@link node} is the canonical
32
+ * representation of this expression.
33
+ */
34
+ get sql(): string;
35
+ /**
36
+ * The values to instantiate parameters in {@link sqlExpression} with to retain original semantics of the
37
+ * expression.
38
+ */
39
+ get instantiation(): readonly ExpressionInput[];
40
+ get location(): NodeLocation;
41
+ constructor(
42
+ /**
43
+ * The AST node backing {@link sql}.
44
+ *
45
+ * We use this to be able to compose expressions, e.g. to possibly merge them.
46
+ */
47
+ node: SqlExpression<ExpressionInput>, locations: NodeLocations);
48
+ equalsAssumingSameResultSet(other: EqualsIgnoringResultSet): boolean;
49
+ assumingSameResultSetEqualityHashCode(hasher: StableHasher): void;
50
+ }
51
+ export type ExpressionInput = ColumnInRow | ConnectionParameter;
52
+ export declare class ColumnInRow implements EqualsIgnoringResultSet {
53
+ readonly syntacticOrigin: Expr;
54
+ readonly resultSet: SourceResultSet;
55
+ readonly column: string;
56
+ constructor(syntacticOrigin: Expr, resultSet: SourceResultSet, column: string);
57
+ equalsAssumingSameResultSet(other: EqualsIgnoringResultSet): boolean;
58
+ assumingSameResultSetEqualityHashCode(hasher: StableHasher): void;
59
+ }
60
+ export declare class ConnectionParameter implements EqualsIgnoringResultSet {
61
+ readonly syntacticOrigin: Expr;
62
+ readonly source: ConnectionParameterSource;
63
+ constructor(syntacticOrigin: Expr, source: ConnectionParameterSource);
64
+ equalsAssumingSameResultSet(other: EqualsIgnoringResultSet): boolean;
65
+ assumingSameResultSetEqualityHashCode(hasher: StableHasher): void;
66
+ }
67
+ /**
68
+ * Tracks the original source location for translated {@link SqlExpression} nodes.
69
+ *
70
+ * We want to serialize translated expressions for sync plan, so embedding source offsets in them expands the size of
71
+ * sync plans and is tedious. We only need access to node locations while compiling sync streams, which we store in this
72
+ * in-memory map.
73
+ */
74
+ export declare class NodeLocations {
75
+ readonly sourceForNode: Map<SqlExpression<unknown>, PGNode | NodeLocation>;
76
+ locationFor(source: SqlExpression<unknown>): NodeLocation;
77
+ }
@@ -0,0 +1,122 @@
1
+ import { equalsIgnoringResultSetList } from './compatibility.js';
2
+ import { ExpressionToSqlite } from '../sync_plan/expression_to_sql.js';
3
+ import { RecursiveExpressionVisitor } from '../sync_plan/expression_visitor.js';
4
+ import { getLocation } from '../errors.js';
5
+ /**
6
+ * An analyzed SQL expression tracking dependencies on non-static data (i.e. rows or connection sources).
7
+ *
8
+ * Consider the sync stream `SELECT * FROM issues WHERE is_public OR auth.param('is_admin')`. To be able to explicitly
9
+ * track dependencies referenced in expressions, we transform them into a {@link SyncExpression}. For the `WHERE` clause
10
+ * in that example, the {@link sqlExpression} would be `?1 OR (?2 ->> 'is_admin')`, where `?1` is a {@link ColumnInRow}
11
+ * and `?2` is a {@link ConnectionParameter}.
12
+ *
13
+ * Once in this form, it's easy to reason about dependencies in expressions (used to later generate parameter match
14
+ * clauses) and to evaluate expressions at runtime (by preparing them as a statement and binding external values).
15
+ */
16
+ export class SyncExpression {
17
+ node;
18
+ locations;
19
+ #sql;
20
+ #instantiation;
21
+ /**
22
+ * The original expression, where references to row or connection parameters have been replaced with SQL variables
23
+ * that are tracked through {@link instantiation}.
24
+ *
25
+ * This is only used to compute hash codes and to check instances for equality. {@link node} is the canonical
26
+ * representation of this expression.
27
+ */
28
+ get sql() {
29
+ return (this.#sql ??= ExpressionToSqlite.toSqlite(this.node));
30
+ }
31
+ /**
32
+ * The values to instantiate parameters in {@link sqlExpression} with to retain original semantics of the
33
+ * expression.
34
+ */
35
+ get instantiation() {
36
+ if (this.#instantiation != null) {
37
+ return this.#instantiation;
38
+ }
39
+ const instantiation = [];
40
+ FindExternalData.instance.visit(this.node, instantiation);
41
+ return (this.#instantiation = instantiation);
42
+ }
43
+ get location() {
44
+ return this.locations.locationFor(this.node);
45
+ }
46
+ constructor(
47
+ /**
48
+ * The AST node backing {@link sql}.
49
+ *
50
+ * We use this to be able to compose expressions, e.g. to possibly merge them.
51
+ */
52
+ node, locations) {
53
+ this.node = node;
54
+ this.locations = locations;
55
+ }
56
+ equalsAssumingSameResultSet(other) {
57
+ return (other instanceof SyncExpression &&
58
+ other.sql == this.sql &&
59
+ equalsIgnoringResultSetList.equals(other.instantiation, this.instantiation));
60
+ }
61
+ assumingSameResultSetEqualityHashCode(hasher) {
62
+ hasher.addString(this.sql);
63
+ equalsIgnoringResultSetList.hash(hasher, this.instantiation);
64
+ }
65
+ }
66
+ class FindExternalData extends RecursiveExpressionVisitor {
67
+ defaultExpression(expr, arg) {
68
+ this.visitChildren(expr, arg);
69
+ }
70
+ visitExternalData(expr, arg) {
71
+ arg.push(expr.source);
72
+ }
73
+ static instance = new FindExternalData();
74
+ }
75
+ export class ColumnInRow {
76
+ syntacticOrigin;
77
+ resultSet;
78
+ column;
79
+ constructor(syntacticOrigin, resultSet, column) {
80
+ this.syntacticOrigin = syntacticOrigin;
81
+ this.resultSet = resultSet;
82
+ this.column = column;
83
+ }
84
+ equalsAssumingSameResultSet(other) {
85
+ return other instanceof ColumnInRow && other.column == this.column;
86
+ }
87
+ assumingSameResultSetEqualityHashCode(hasher) {
88
+ hasher.addString(this.column);
89
+ }
90
+ }
91
+ export class ConnectionParameter {
92
+ syntacticOrigin;
93
+ source;
94
+ constructor(syntacticOrigin, source) {
95
+ this.syntacticOrigin = syntacticOrigin;
96
+ this.source = source;
97
+ }
98
+ equalsAssumingSameResultSet(other) {
99
+ return other instanceof ConnectionParameter && other.source == this.source;
100
+ }
101
+ assumingSameResultSetEqualityHashCode(hasher) {
102
+ hasher.addString(this.source);
103
+ }
104
+ }
105
+ /**
106
+ * Tracks the original source location for translated {@link SqlExpression} nodes.
107
+ *
108
+ * We want to serialize translated expressions for sync plan, so embedding source offsets in them expands the size of
109
+ * sync plans and is tedious. We only need access to node locations while compiling sync streams, which we store in this
110
+ * in-memory map.
111
+ */
112
+ export class NodeLocations {
113
+ sourceForNode = new Map();
114
+ locationFor(source) {
115
+ const location = getLocation(this.sourceForNode.get(source));
116
+ if (location == null) {
117
+ throw new Error('Missing location');
118
+ }
119
+ return location;
120
+ }
121
+ }
122
+ //# sourceMappingURL=expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.js","sourceRoot":"","sources":["../../src/compiler/expression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { NodeLocation } from 'pgsql-ast-parser';
2
+ import { ExpressionInput, SyncExpression } from './expression.js';
3
+ import { SourceResultSet } from './table.js';
4
+ import { EqualsIgnoringResultSet } from './compatibility.js';
5
+ import { StableHasher } from './equality.js';
6
+ export interface Or {
7
+ terms: And[];
8
+ }
9
+ export interface And {
10
+ terms: BaseTerm[];
11
+ }
12
+ /**
13
+ * A boolean expression that doesn't have boolean operators with subexpressions referencing different tables in it.
14
+ *
15
+ * These basic terms form a filter by being composed into a distributive normal form. For analysis, we just need to know
16
+ * how terms from different tables relate to each other. So `users.id = auth.user_id() AND issues.is_public` need to be
17
+ * two terms in an {@link And}, but `users.is_deleted OR users.is_admin` can be represented as a single base term.
18
+ */
19
+ export type BaseTerm = SingleDependencyExpression | EqualsClause;
20
+ export declare function isBaseTerm(value: unknown): value is BaseTerm;
21
+ /**
22
+ * A {@link SyncExpression} that only depends on a single result set or connection data.
23
+ */
24
+ export declare class SingleDependencyExpression implements EqualsIgnoringResultSet {
25
+ readonly expression: SyncExpression;
26
+ /**
27
+ * The single result set on which the expression depends on.
28
+ *
29
+ * If null, the expression is allowed to depend on subscription parameters instead.
30
+ */
31
+ readonly resultSet: SourceResultSet | null;
32
+ /**
33
+ * Whether this expression depends on data derived from the connection or subscription.
34
+ */
35
+ readonly dependsOnConnection: boolean;
36
+ constructor(expression: SyncExpression | SingleDependencyExpression);
37
+ equalsAssumingSameResultSet(other: EqualsIgnoringResultSet): boolean;
38
+ assumingSameResultSetEqualityHashCode(hasher: StableHasher): void;
39
+ /**
40
+ * If all inputs have a single dependency, returns either the result set they all depend on or `null` and whether they
41
+ * depend on connection data.
42
+ *
43
+ * If the inputs have more than a single distinct dependency, returns null.
44
+ */
45
+ static extractSingleDependency(inputs: Iterable<ExpressionInput>): [SourceResultSet | null, boolean] | null;
46
+ }
47
+ /**
48
+ * A {@link SyncExpression} that only depends on data from a single row.
49
+ */
50
+ export declare class RowExpression extends SingleDependencyExpression {
51
+ readonly resultSet: SourceResultSet;
52
+ constructor(expression: SyncExpression | SingleDependencyExpression);
53
+ }
54
+ /**
55
+ * A {@link SyncExpression} that only depends on connection data.
56
+ */
57
+ export declare class RequestExpression extends SingleDependencyExpression {
58
+ constructor(expression: SyncExpression | SingleDependencyExpression);
59
+ }
60
+ /**
61
+ * An expression of the form `foo = bar`, where `foo` and `bar` are expressions allowed to depend on different sources.
62
+ */
63
+ export declare class EqualsClause {
64
+ readonly left: SingleDependencyExpression;
65
+ readonly right: SingleDependencyExpression;
66
+ constructor(left: SingleDependencyExpression, right: SingleDependencyExpression);
67
+ get location(): NodeLocation | undefined;
68
+ }
69
+ export declare class InvalidExpressionError extends Error {
70
+ constructor(message: string);
71
+ }