Implement COALESCE function
This commit is contained in:
1 parent
6cbd59c6ec
commit
2a85d768a5
3 files changed
+38
-3
No files matched your search
@@ -586,6 +586,13 @@ function normalizeCallback(exp: Expression): Expression {
|
|||||||
if (!Array.isArray(exp)) return exp;
|
if (!Array.isArray(exp)) return exp;
|
||||||
const op = exp[0];
|
const op = exp[0];
|
||||||
|
|
||||||
|
if (op === "FUNC" && exp[1] === "COALESCE") {
|
||||||
|
const res: Expression[] = ["CASE"];
|
||||||
|
for (let i = 2; i < exp.length; ++i)
|
||||||
|
res.push(normalizeCallback(["IS NOT NULL", exp[i]]), exp[i]);
|
||||||
|
return normalizeCallback(res);
|
||||||
|
}
|
||||||
|
|
||||||
if (op === "CASE") {
|
if (op === "CASE") {
|
||||||
const res = [] as [Expression, Expression][];
|
const res = [] as [Expression, Expression][];
|
||||||
for (let i = 1; i < exp.length; i += 2) {
|
for (let i = 1; i < exp.length; i += 2) {
|
||||||
@@ -765,7 +772,13 @@ function normalizeCallback(exp: Expression): Expression {
|
|||||||
|
|
||||||
export function normalize(expr: Expression): Expression {
|
export function normalize(expr: Expression): Expression {
|
||||||
expr = map(expr, normalizeCallback);
|
expr = map(expr, normalizeCallback);
|
||||||
if (expr instanceof Polynomial) expr = JSON.parse(expr.toString());
|
if (expr instanceof Polynomial) {
|
||||||
|
expr = JSON.parse(expr.toString());
|
||||||
|
} else if (Array.isArray(expr) && expr[0] === "CASE") {
|
||||||
|
expr = expr.map((e) =>
|
||||||
|
e instanceof Polynomial ? JSON.parse(e.toString()) : e
|
||||||
|
);
|
||||||
|
}
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ const lang = parsimmon.createLanguage({
|
|||||||
.regexp(/([a-zA-Z0-9_]+)/, 1)
|
.regexp(/([a-zA-Z0-9_]+)/, 1)
|
||||||
.skip(parsimmon.optWhitespace)
|
.skip(parsimmon.optWhitespace)
|
||||||
.desc("function"),
|
.desc("function"),
|
||||||
r.ValueExpression.sepBy(
|
r.Expression.sepBy(
|
||||||
parsimmon.string(",").skip(parsimmon.optWhitespace)
|
parsimmon.string(",").skip(parsimmon.optWhitespace)
|
||||||
).wrap(
|
).wrap(
|
||||||
parsimmon.string("(").skip(parsimmon.optWhitespace),
|
parsimmon.string("(").skip(parsimmon.optWhitespace),
|
||||||
|
|||||||
@@ -93,6 +93,17 @@ function toNumber(a: boolean | number | string): number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toString(a: boolean | number | string): string {
|
||||||
|
switch (typeof a) {
|
||||||
|
case "string":
|
||||||
|
return a;
|
||||||
|
case "number":
|
||||||
|
return a.toString();
|
||||||
|
case "boolean":
|
||||||
|
return (+a).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function evaluateCallback(exp: Expression): Expression {
|
export function evaluateCallback(exp: Expression): Expression {
|
||||||
if (!Array.isArray(exp)) return exp;
|
if (!Array.isArray(exp)) return exp;
|
||||||
if (exp[0] === "CASE") {
|
if (exp[0] === "CASE") {
|
||||||
@@ -101,6 +112,17 @@ export function evaluateCallback(exp: Expression): Expression {
|
|||||||
if (exp[i]) return exp[i + 1];
|
if (exp[i]) return exp[i + 1];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
} else if (exp[0] === "FUNC" && exp[1] === "COALESCE") {
|
||||||
|
const args: Expression[] = [];
|
||||||
|
for (let i = 2; i < exp.length; ++i) {
|
||||||
|
const e = exp[i];
|
||||||
|
if (e == null) continue;
|
||||||
|
args.push(e);
|
||||||
|
if (!Array.isArray(e)) break;
|
||||||
|
}
|
||||||
|
if (!args.length) return null;
|
||||||
|
if (args.length === 1) return args[0];
|
||||||
|
return ["FUNC", "COALESCE", ...args];
|
||||||
} else if (exp[0] === "AND") {
|
} else if (exp[0] === "AND") {
|
||||||
for (let i = 1; i < exp.length; ++i)
|
for (let i = 1; i < exp.length; ++i)
|
||||||
if (!Array.isArray(exp[i]) && exp[i] != null && !exp[i]) return false;
|
if (!Array.isArray(exp[i]) && exp[i] != null && !exp[i]) return false;
|
||||||
@@ -223,7 +245,7 @@ export function evaluateCallback(exp: Expression): Expression {
|
|||||||
} else if (exp[0] === "||") {
|
} else if (exp[0] === "||") {
|
||||||
return reduce(exp, (a, b) => {
|
return reduce(exp, (a, b) => {
|
||||||
if (a == null || b == null) return null;
|
if (a == null || b == null) return null;
|
||||||
if (!isArray(a) && !isArray(b)) return `${a}${b}`;
|
if (!isArray(a) && !isArray(b)) return toString(a) + toString(b);
|
||||||
return REDUCE_SKIP;
|
return REDUCE_SKIP;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user