Skip to content

Commit

Permalink
Add Flavor escapeUnion method
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubknejzlik committed Apr 22, 2024
1 parent aeb4377 commit 5c0a6c8
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 85 deletions.
2 changes: 2 additions & 0 deletions src/Flavor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ConditionValue } from "./Condition";
import { FunctionExpression, OperationExpression } from "./Expression";
import { UnionType } from "./Query";

export interface ISQLFlavor {
escapeColumn(name: string, legacy?: boolean): string;
Expand All @@ -8,4 +9,5 @@ export interface ISQLFlavor {
escapeLimitAndOffset(limit?: number, offset?: number): string;
escapeFunction(fn: FunctionExpression): string;
escapeOperation(fn: OperationExpression): string;
escapeUnion(unionType: UnionType, leftSQL: string, rightSQL: string): string;
}
7 changes: 5 additions & 2 deletions src/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,11 @@ export class SelectQuery extends SelectBaseQuery implements ISerializable {
sql += flavor.escapeLimitAndOffset(this._limit, this._offset);

this._unionQueries.forEach((unionQuery) => {
sql =
`(` + sql + `) ${unionQuery.type} (${unionQuery.query.toSQL(flavor)})`;
sql = flavor.escapeUnion(
unionQuery.type,
sql,
unionQuery.query.toSQL(flavor)
);
});
return sql;
}
Expand Down
4 changes: 2 additions & 2 deletions src/flavors/aws-timestream.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MySQLFlavor } from "./mysql";
import { DefaultFlavor } from "./default";

export class AWSTimestreamFlavor extends MySQLFlavor {
export class AWSTimestreamFlavor extends DefaultFlavor {
protected columnQuotes = `"`;
protected stringQuotes = `'`;
escapeLimitAndOffset(limit?: number, offset?: number): string {
Expand Down
86 changes: 86 additions & 0 deletions src/flavors/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { isDayjs } from "dayjs";
import { ConditionValue } from "../Condition";
import {
Expression,
FunctionExpression,
OperationExpression,
} from "../Expression";
import { ISQLFlavor } from "../Flavor";
import { UnionType } from "../Query";

export class DefaultFlavor implements ISQLFlavor {
protected columnQuotes = "`";
protected stringQuotes = `"`;

escapeColumn(name: string, legacyParsing?: boolean): string {
if (name === "NULL") {
return name;
}
if (legacyParsing) {
const columnMatch = name.match(/^[\.a-zA-Z0-9_]+$/);
if (columnMatch) {
return `${this.columnQuotes}${name
.replace(
new RegExp(`/${this.columnQuotes}/`, "g"),
`${this.columnQuotes}${this.columnQuotes}`
)
.split(".")
.join(`${this.columnQuotes}.${this.columnQuotes}`)}${
this.columnQuotes
}`;
}
return `${name}`;
}
return `${this.columnQuotes}${name
.split(".")
.join(`${this.columnQuotes}.${this.columnQuotes}`)}${this.columnQuotes}`;
}

escapeTable(table: string): string {
if (table.indexOf("-") !== -1) {
return `${this.columnQuotes}${table}${this.columnQuotes}`;
}
return this.escapeColumn(table);
}

escapeValue(value: ConditionValue): string {
if (isDayjs(value)) {
return `${this.stringQuotes}${value.format("YYYY-MM-DD HH:mm:ss")}${
this.stringQuotes
}`;
}
if (typeof value === "string") {
return `${this.stringQuotes}${value}${this.stringQuotes}`;
}
return `${value}`;
}

escapeLimitAndOffset(limit?: number, offset?: number): string {
let str = "";
if (limit !== undefined) {
str += ` LIMIT ${limit}`;
}
if (offset !== undefined) {
str += ` OFFSET ${offset}`;
}
return str;
}
escapeFunction(fn: FunctionExpression): string {
const args = fn.value
.map((x) => Expression.deserialize(x).toSQL(this))
.join(",");
return `${fn.name}(${args})`;
}
escapeOperation(fn: OperationExpression): string {
return (
"(" +
fn.value
.map((x) => Expression.deserialize(x).toSQL(this))
.join(` ${fn.operation} `) +
")"
);
}
escapeUnion(unionType: UnionType, leftSQL: string, rightSQL: string): string {
return `(${leftSQL}) ${unionType} (${rightSQL})`;
}
}
83 changes: 2 additions & 81 deletions src/flavors/mysql.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,3 @@
import { isDayjs } from "dayjs";
import { ConditionValue } from "../Condition";
import {
Expression,
FunctionExpression,
OperationExpression,
} from "../Expression";
import { ISQLFlavor } from "../Flavor";
import { DefaultFlavor } from "./default";

export class MySQLFlavor implements ISQLFlavor {
protected columnQuotes = "`";
protected stringQuotes = `"`;

escapeColumn(name: string, legacyParsing?: boolean): string {
if (name === "NULL") {
return name;
}
if (legacyParsing) {
const columnMatch = name.match(/^[\.a-zA-Z0-9_]+$/);
if (columnMatch) {
return `${this.columnQuotes}${name
.replace(
new RegExp(`/${this.columnQuotes}/`, "g"),
`${this.columnQuotes}${this.columnQuotes}`
)
.split(".")
.join(`${this.columnQuotes}.${this.columnQuotes}`)}${
this.columnQuotes
}`;
}
return `${name}`;
}
return `${this.columnQuotes}${name
.split(".")
.join(`${this.columnQuotes}.${this.columnQuotes}`)}${this.columnQuotes}`;
}

escapeTable(table: string): string {
if (table.indexOf("-") !== -1) {
return `${this.columnQuotes}${table}${this.columnQuotes}`;
}
return this.escapeColumn(table);
}

escapeValue(value: ConditionValue): string {
if (isDayjs(value)) {
return `${this.stringQuotes}${value.format("YYYY-MM-DD HH:mm:ss")}${
this.stringQuotes
}`;
}
if (typeof value === "string") {
return `${this.stringQuotes}${value}${this.stringQuotes}`;
}
return `${value}`;
}

escapeLimitAndOffset(limit?: number, offset?: number): string {
let str = "";
if (limit !== undefined) {
str += ` LIMIT ${limit}`;
}
if (offset !== undefined) {
str += ` OFFSET ${offset}`;
}
return str;
}
escapeFunction(fn: FunctionExpression): string {
const args = fn.value
.map((x) => Expression.deserialize(x).toSQL(this))
.join(",");
return `${fn.name}(${args})`;
}
escapeOperation(fn: OperationExpression): string {
return (
"(" +
fn.value
.map((x) => Expression.deserialize(x).toSQL(this))
.join(` ${fn.operation} `) +
")"
);
}
}
export class MySQLFlavor extends DefaultFlavor {}

0 comments on commit 5c0a6c8

Please sign in to comment.