@jakub.knejzlik/ts-query
Version:
TypeScript implementation of SQL builder
171 lines (164 loc) • 4.29 kB
text/typescript
import dayjs, { Dayjs } from "dayjs";
import { Cond, Condition } from "./Condition";
import {
Expression,
ExpressionValue,
FunctionExpression,
OperationExpression,
} from "./Expression";
import { Q } from "./Query";
const formatDayjs = (d: Dayjs | string) =>
dayjs(d).format("YYYY-MM-DD HH:mm:ss");
const ifFn = (
condition: Condition,
trueValue: ExpressionValue,
falseValue: ExpressionValue
) => {
return new FunctionExpression("IF", condition, trueValue, falseValue);
};
const dateAddFn = (
date: ExpressionValue,
value: ExpressionValue,
interval: "year" | "month" | "day"
) => {
return new FunctionExpression(
"DATEADD",
date,
Q.value(value),
Q.value(interval)
);
};
export const Function = {
count: (column: ExpressionValue) => {
return new FunctionExpression("COUNT", column);
},
add: (...columns: ExpressionValue[]) => {
return new OperationExpression("+", ...columns);
},
subtract: (...columns: ExpressionValue[]) => {
return new OperationExpression("-", ...columns);
},
divide: (...columns: ExpressionValue[]) => {
return new OperationExpression("/", ...columns);
},
multiply: (...columns: ExpressionValue[]) => {
return new OperationExpression("*", ...columns);
},
sum: (column: ExpressionValue) => {
return new FunctionExpression("SUM", column);
},
year: (column: ExpressionValue) => {
return new FunctionExpression("YEAR", column);
},
month: (column: ExpressionValue) => {
return new FunctionExpression("MONTH", column);
},
min: (column: ExpressionValue) => {
return new FunctionExpression("MIN", column);
},
max: (column: ExpressionValue) => {
return new FunctionExpression("MAX", column);
},
avg: (column: ExpressionValue) => {
return new FunctionExpression("AVG", column);
},
abs: (column: ExpressionValue) => {
return new FunctionExpression("ABS", column);
},
dateDiff: (
interval: "year" | "month" | "day" | "hour" | "minute" | "second",
date1: ExpressionValue,
date2: ExpressionValue
) => {
if (interval === "month") {
return Q.expr(
`TIMESTAMPDIFF(MONTH, ${Expression.escapeExpressionValue(
date1
)}, ${Expression.escapeExpressionValue(date2)})`
);
} else if (interval === "day") {
return new FunctionExpression("DATEDIFF", date1, date2);
} else {
return new OperationExpression(
"-",
Function.year(date1),
Function.year(date2)
);
}
},
formatDate: (date: Dayjs) => {
return Q.expr(`'${formatDayjs(date)}'`);
},
substring: (
string: string,
start: ExpressionValue,
length: ExpressionValue
) => {
return new FunctionExpression(
"SUBSTRING",
string,
Q.value(start),
Q.value(length)
);
},
string: (value: string) => {
return Q.expr(Expression.escapeString(`${value}`));
},
null: () => {
return Q.expr(`NULL`);
},
ifnull: (name: ExpressionValue, value: ExpressionValue) => {
return new FunctionExpression("IFNULL", name, value);
},
concat: (...values: ExpressionValue[]) => {
return new FunctionExpression("CONCAT", ...values);
},
if: ifFn,
dateAdd: dateAddFn,
dateRangeSumField: ({
dateColumn,
valueColumn,
start,
end,
}: {
dateColumn: string;
valueColumn: string;
start: Dayjs | string;
end: Dayjs | string;
}) => {
return new FunctionExpression(
"SUM",
new FunctionExpression(
"IF",
Cond.between(dateColumn, [dayjs(start), dayjs(end)]),
valueColumn,
Q.value(0)
)
);
},
priceCurrentAndPreviousDiffField: ({
thisYearColumn,
lastYearColumn,
}: {
thisYearColumn: ExpressionValue;
lastYearColumn: ExpressionValue;
}) =>
ifFn(
Cond.and([Cond.equal(thisYearColumn, 0), Cond.equal(lastYearColumn, 0)]),
Q.expr(`+0`),
ifFn(
Cond.equal(lastYearColumn, 0),
Q.expr("NULL"),
ifFn(
Cond.equal(thisYearColumn, 0),
Q.expr(`-1`),
new OperationExpression(
"/",
new OperationExpression("-", thisYearColumn, lastYearColumn),
lastYearColumn
)
)
)
),
};
export { Function as Fn };