Skip to content

Commit

Permalink
Add raw expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubknejzlik committed Feb 26, 2024
1 parent 062f867 commit ad0d5db
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/Condition-serialization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("Condition Serialization and Deserialization", () => {
);
});
it("should serialize and deserialize between with expressions", () => {
const condition = Conditions.between("foo", ["abcd", Q.expr("now()")]);
const condition = Conditions.between("foo", ["abcd", Q.raw("now()")]);
const json = condition.toJSON();
expect(Condition.fromJSON(json).toSQL(flavor)).toEqual(
condition.toSQL(flavor)
Expand All @@ -78,7 +78,7 @@ describe("Condition Serialization and Deserialization", () => {
// AND
it("should serialize and deserialize and condition", () => {
const condition1 = Conditions.equal("foo", 123);
const condition2 = Conditions.greaterThan("bar", Q.expr("a"));
const condition2 = Conditions.greaterThan("bar", Q.raw("a"));
const condition = Conditions.and([condition1, condition2]);
const serialized = condition.toJSON();
const deserialized = Condition.fromJSON(serialized);
Expand Down
4 changes: 2 additions & 2 deletions src/Condition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,8 @@ export const Conditions = {
between: (key: ExpressionValue, values: [ExpressionValue, ExpressionValue]) =>
new BetweenCondition(
key,
ValueExpression.deserialize(values[0]),
ValueExpression.deserialize(values[1])
Expression.deserializeValue(values[0]),
Expression.deserializeValue(values[1])
),
in: (key: string, values: ExpressionValue[]) => new InCondition(key, values),
notIn: (key: ExpressionValue, values: ExpressionValue[]) =>
Expand Down
54 changes: 44 additions & 10 deletions src/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ export type ExpressionValue =
| Condition;

export class ExpressionBase implements ISerializable, ISequelizable {
static deserialize(value: ExpressionValue, exact = false): ExpressionBase {
static deserialize(value: ExpressionValue): ExpressionBase {
const valueIsString = typeof value === "string";
if (valueIsString && RawExpression.isValueString(value)) {
return RawExpression.deserialize(value);
}
if (valueIsString && ValueExpression.isValueString(value)) {
return ValueExpression.deserialize(value);
}
Expand All @@ -22,6 +25,9 @@ export class ExpressionBase implements ISerializable, ISequelizable {
if (valueIsString && OperationExpression.isValidString(value)) {
return OperationExpression.deserialize(value);
}
if (value instanceof RawExpression) {
return value;
}
if (
valueIsString ||
(value instanceof Expression && typeof value.value === "string")
Expand All @@ -35,7 +41,6 @@ export class ExpressionBase implements ISerializable, ISequelizable {
}
if (valueIsString || typeof value === "number") {
const expr = new Expression(value);
expr.setExact(exact);
return expr;
}
if (value instanceof Condition) {
Expand All @@ -50,8 +55,17 @@ export class ExpressionBase implements ISerializable, ISequelizable {
if (value instanceof ValueExpression) {
return value;
}
if (value instanceof RawExpression) {
return value;
}
if (typeof value === "string" && RawExpression.isValueString(value)) {
return RawExpression.deserialize(value);
}
return ValueExpression.deserialize(value);
}
static deserializeRaw(value: ExpressionValue): RawExpression {
return RawExpression.deserialize(value);
}
toSQL(flavor: ISQLFlavor): string {
throw new Error("Method not implemented.");
}
Expand All @@ -64,10 +78,6 @@ export class Expression<T = ExpressionValue> extends ExpressionBase {
super();
}

setExact(exact: boolean): this {
return this;
}

toSQL(flavor: ISQLFlavor): string {
if (this.value instanceof Expression) {
return this.value.toSQL(flavor);
Expand Down Expand Up @@ -133,17 +143,41 @@ export class ValueExpression extends Expression {
return `!!!` + JSON.stringify(this.value);
}
static deserialize(value: ExpressionValue): ValueExpression {
if (typeof value === "string" && value.startsWith("!!!")) {
const isStringValue = typeof value === "string";
if (isStringValue && ValueExpression.isValueString(value)) {
const res = new ValueExpression(JSON.parse(value.substring(3)));
return res;
}
if (value instanceof Expression) {
return new ValueExpression(value.value);
}

return new ValueExpression(value);
}
}

export class RawExpression extends Expression {
static isValueString(str: string): boolean {
return str.startsWith("!!") && str.endsWith("!!");
}
toSQL(flavor: ISQLFlavor): string {
return `${this.value}`;
}
serialize(): string {
return `!!` + JSON.stringify(this.value) + "!!";
}
static deserialize(value: ExpressionValue): ValueExpression {
if (
typeof value === "string" &&
value.startsWith("!!") &&
value.endsWith("!!")
) {
const res = new RawExpression(
JSON.parse(value.substring(2, value.length - 2))
);
return res;
}
throw new Error(`Invalid raw expression: '${value}'`);
}
}

export class FunctionExpression extends Expression<ExpressionValue[]> {
constructor(public name: string, ...args: ExpressionValue[]) {
super(args);
Expand Down
2 changes: 2 additions & 0 deletions src/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ExpressionBase,
ExpressionRawValue,
ExpressionValue,
RawExpression,
} from "./Expression";
import { ISQLFlavor } from "./Flavor";
import { AWSTimestreamFlavor } from "./flavors/aws-timestream";
Expand Down Expand Up @@ -523,6 +524,7 @@ export const Query = {
new CreateViewAsSelect(table, select, true),
deserialize,
flavors,
raw: (val: ExpressionValue) => new RawExpression(val),
expr: (val: ExpressionValue) => ExpressionBase.deserialize(val),
exprValue: (val: ExpressionValue) => ExpressionBase.deserializeValue(val),
value: (val: ExpressionValue) => ExpressionBase.deserializeValue(val),
Expand Down

0 comments on commit ad0d5db

Please sign in to comment.