feat: add LIKE-Compare DC set relationships

Detect contradictions between LIKE patterns and comparison operators
(=, <, >) on the same field. For prefix patterns like 'abc%', use
range bounds to identify impossible combinations such as
(string < 'abc') AND (string LIKE 'abc%').
This commit is contained in:
Zaid Humaimidi committed 2026-03-13 13:15:52 -07:00
1 parent 6f3ce6f7c8
commit f39e2ce7cf
2 files changed
+218

No files matched your search

+64
View File
@@ -4,6 +4,10 @@ import initSqlJs from "sql.js/dist/sql-asm.js";
import { covers, minimize, unionDiff } from "../lib/common/expression/synth.ts";
import Expression from "../lib/common/expression.ts";
function isFalse(expr: Expression): boolean {
return expr instanceof Expression.Literal && expr.value === false;
}
const STRING_VALUES = [null, "", "a", "ab", "ab10", "ab-10"];
const DECIMAL_VALUES = [null, 0, -10, 10];
@@ -169,3 +173,63 @@ void test("covers", async () => {
);
}
});
void test("LIKE-Compare DC set relationships", () => {
const likeExpr = Expression.parse("string LIKE 'a%'");
const eqExpr = Expression.parse("string = 'a'");
const conjExpr: Expression = new Expression.Binary("AND", eqExpr, likeExpr);
assert.strictEqual(
isFalse(minimize(conjExpr, true)),
false,
"(string = 'a') AND (string LIKE 'a%') should NOT minimize to false",
);
const nonMatchingExpr = Expression.parse("string = 'b'");
const conjNonMatch: Expression = new Expression.Binary(
"AND",
nonMatchingExpr,
likeExpr,
);
assert.strictEqual(
isFalse(minimize(conjNonMatch, true)),
true,
"(string = 'b') AND (string LIKE 'a%') should minimize to false",
);
});
void test("LIKE-Compare DC set with range operators", () => {
const likeExpr = Expression.parse("string LIKE 'abc%'");
const ltExpr = Expression.parse("string < 'abc'");
const ltConj: Expression = new Expression.Binary("AND", ltExpr, likeExpr);
assert.strictEqual(
isFalse(minimize(ltConj, true)),
true,
"(string < 'abc') AND (string LIKE 'abc%') should be false",
);
const ltExpr2 = Expression.parse("string < 'abd'");
const ltConj2: Expression = new Expression.Binary("AND", ltExpr2, likeExpr);
assert.strictEqual(
isFalse(minimize(ltConj2, true)),
false,
"(string < 'abd') AND (string LIKE 'abc%') should NOT be false",
);
const gtExpr = Expression.parse("string > 'abd'");
const gtConj: Expression = new Expression.Binary("AND", gtExpr, likeExpr);
assert.strictEqual(
isFalse(minimize(gtConj, true)),
true,
"(string > 'abd') AND (string LIKE 'abc%') should be false",
);
const gtExpr2 = Expression.parse("string > 'abc'");
const gtConj2: Expression = new Expression.Binary("AND", gtExpr2, likeExpr);
assert.strictEqual(
isFalse(minimize(gtConj2, true)),
false,
"(string > 'abc') AND (string LIKE 'abc%') should NOT be false",
);
});