Skip to content

Commit f793fab

Browse files
committed
Smaller fixes, more tests
1 parent 52677d1 commit f793fab

File tree

5 files changed

+50
-24
lines changed

5 files changed

+50
-24
lines changed

packages/sync-rules/src/compiler/sqlite.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ export class PostgresToSqlite {
247247
let rightHandSideOfIs: SqlExpression<ExpressionInput>;
248248

249249
switch (expr.op) {
250-
case '+':
251250
case '-':
251+
return this.invalidExpression(expr, 'Unary minus is not currently supported');
252+
case '+':
252253
return { type: 'unary', operator: expr.op, operand: this.translateNodeWithLocation(expr.operand) };
253254
case 'NOT':
254255
return { type: 'unary', operator: 'not', operand: this.translateNodeWithLocation(expr.operand) };

packages/sync-rules/src/sync_plan/engine/javascript.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ class ExpressionToJavaScriptFunction
151151
return operand;
152152
case 'not':
153153
return (input) => sqliteNot(operand(input));
154-
case '~':
155-
case '-':
156-
throw new Error(`unary operator not supported: ${expr.operator}`);
154+
// case '~':
155+
// case '-':
156+
// throw new Error(`unary operator not supported: ${expr.operator}`);
157157
}
158158
}
159159

@@ -173,10 +173,13 @@ class ExpressionToJavaScriptFunction
173173
return (input) => {
174174
const evaluatedValue = value(input);
175175

176-
return (
177-
sqliteBool(evaluateOperator('>=', evaluatedValue, low(input))) &&
178-
sqliteBool(evaluateOperator('<=', evaluatedValue, high(input)))
179-
);
176+
const geqLow = evaluateOperator('>=', evaluatedValue, low(input));
177+
const leqHigh = evaluateOperator('<=', evaluatedValue, high(input));
178+
if (geqLow == null || leqHigh == null) {
179+
return null;
180+
}
181+
182+
return sqliteBool(geqLow) && sqliteBool(leqHigh);
180183
};
181184
}
182185

packages/sync-rules/src/sync_plan/expression.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export type SqlExpression<Data> =
2626
*/
2727
export type ExternalData<Data> = { type: 'data'; source: Data };
2828

29-
export type UnaryOperator = 'not' | '~' | '+' | '-';
29+
export type UnaryOperator = 'not' | '+'; //| '-' | '~';
3030

3131
export type UnaryExpression<Data> = {
3232
type: 'unary';

packages/sync-rules/src/sync_plan/expression_to_sql.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ const binaryPrecedence: Record<BinaryOperator, Precedence> = {
221221

222222
const unaryPrecedence: Record<UnaryOperator, Precedence> = {
223223
not: Precedence.not,
224-
'~': Precedence.unary,
225-
'+': Precedence.unary,
226-
'-': Precedence.unary
224+
//'~': Precedence.unary,
225+
'+': Precedence.unary
226+
//'-': Precedence.unary
227227
};

packages/sync-rules/test/src/sync_plan/engine/engine.test.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as sqlite from 'node:sqlite';
33
import { describe, expect, onTestFinished, test } from 'vitest';
44
import {
55
CompatibilityContext,
6+
CompatibilityEdition,
67
javaScriptExpressionEngine,
78
nodeSqliteExpressionEngine,
89
SqliteValue
@@ -14,19 +15,22 @@ import {
1415
} from '../../../../src/sync_plan/engine/scalar_expression_engine.js';
1516
import { BinaryOperator } from '../../../../src/sync_plan/expression.js';
1617

17-
const compatibility = CompatibilityContext.FULL_BACKWARDS_COMPATIBILITY;
18-
1918
describe('sqlite', () => {
20-
defineEngineTests(false, () => nodeSqliteExpressionEngine(sqlite, compatibility));
19+
defineEngineTests(false, (c) => nodeSqliteExpressionEngine(sqlite, c));
2120
});
2221

2322
describe('javascript', () => {
24-
defineEngineTests(true, () => javaScriptExpressionEngine(compatibility));
23+
defineEngineTests(true, javaScriptExpressionEngine);
2524
});
2625

27-
function defineEngineTests(isJavaScript: boolean, createEngine: () => ScalarExpressionEngine) {
26+
function defineEngineTests(
27+
isJavaScript: boolean,
28+
createEngine: (compatibility: CompatibilityContext) => ScalarExpressionEngine
29+
) {
30+
let compatibility = CompatibilityContext.FULL_BACKWARDS_COMPATIBILITY;
31+
2832
function prepare(stmt: ScalarStatement) {
29-
const engine = createEngine();
33+
const engine = createEngine(compatibility);
3034
onTestFinished(() => engine.close());
3135
return engine.prepareEvaluator(stmt);
3236
}
@@ -60,6 +64,12 @@ function defineEngineTests(isJavaScript: boolean, createEngine: () => ScalarExpr
6064
expect(prepare({ outputs: [{ type: 'lit_null' }] }).evaluate([])).toStrictEqual([[null]]);
6165
});
6266

67+
test('not null', () => {
68+
expect(
69+
prepare({ outputs: [{ type: 'unary', operator: 'not', operand: { type: 'lit_null' } }] }).evaluate([])
70+
).toStrictEqual([[isJavaScript ? 1n : null]]);
71+
});
72+
6373
test('literal double', () => {
6474
expect(prepare({ outputs: [{ type: 'lit_double', value: 3 }] }).evaluate([])).toStrictEqual([[3]]);
6575
});
@@ -125,6 +135,10 @@ function defineEngineTests(isJavaScript: boolean, createEngine: () => ScalarExpr
125135
expect(stmt.evaluate([1, 2, 3])).toStrictEqual([[0n]]);
126136
expect(stmt.evaluate([4, 2, 3])).toStrictEqual([[0n]]);
127137
expect(stmt.evaluate([1, 1, 1])).toStrictEqual([[1n]]);
138+
139+
expect(stmt.evaluate([null, 3, 4])).toStrictEqual([[null]]);
140+
expect(stmt.evaluate([4, null, 4])).toStrictEqual([[null]]);
141+
expect(stmt.evaluate([4, 3, null])).toStrictEqual([[null]]);
128142
});
129143

130144
test('scalar in', () => {
@@ -261,12 +275,6 @@ function defineEngineTests(isJavaScript: boolean, createEngine: () => ScalarExpr
261275
expectFunction('unixepoch', ['now'], null);
262276
expectFunction('datetime', ['now'], null);
263277

264-
const jsonObject = JSON.stringify({ foo: { bar: ['baz'] } });
265-
266-
// Legacy JSON behavior, support paths without $. prefix
267-
expectFunction('->', [jsonObject, 'foo.bar'], '["baz"]');
268-
expectFunction('->>', [jsonObject, 'foo.bar.0'], 'baz');
269-
270278
const point = '010100000097900F7A36FB40C0F4FDD478E9D63240';
271279
expectFunction('st_x', [point], -33.9626);
272280
expectFunction('st_y', [point], 18.8395);
@@ -275,4 +283,18 @@ function defineEngineTests(isJavaScript: boolean, createEngine: () => ScalarExpr
275283
expectFunction('st_asgeojson', [geography], '{"type":"Point","coordinates":[-33.9626,18.8395]}');
276284
expectFunction('st_astext', [geography], 'POINT(-33.9626 18.8395)');
277285
});
286+
287+
test('legacy and fixed JSON behavior', () => {
288+
const jsonObject = JSON.stringify({ foo: { bar: ['baz'] }, 'foo.bar': ['another'] });
289+
compatibility = CompatibilityContext.FULL_BACKWARDS_COMPATIBILITY;
290+
291+
// Legacy JSON behavior, support paths without $. prefix
292+
expectFunction('->', [jsonObject, 'foo.bar'], '["baz"]');
293+
expectFunction('->>', [jsonObject, 'foo.bar.0'], 'baz');
294+
295+
// New JSON behavior, require $. syntax.
296+
compatibility = new CompatibilityContext({ edition: CompatibilityEdition.SYNC_STREAMS });
297+
expectFunction('->', [jsonObject, 'foo.bar'], '["another"]');
298+
expectFunction('->>', [jsonObject, 'foo.bar.0'], null);
299+
});
278300
}

0 commit comments

Comments
 (0)