ts-sql
Version:
An SQL builder in Typescript. This project is heavily inspired by [XQL](/extjs/xql). A big shout out to @exjs and @kobalicek for this amazing project.
164 lines • 7.28 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const queryVisitor_1 = require("./queryVisitor");
class CompilationContext {
constructor(currentNode) {
this.currentNode = currentNode;
this.parentNode = undefined;
this.queryString = "";
}
}
exports.CompilationContext = CompilationContext;
class QueryCompiler extends queryVisitor_1.QueryVisitor {
constructor(dialect, query, contextBuilder = CompilationContext) {
super(dialect, query, contextBuilder);
this.dialect = dialect;
this.visitSqlRoot = (context, node) => {
context.queryString = node.statements.map(s => this.visitNode(context, s).queryString).join(this.delimiter + " ");
return context;
};
this.visitQueryExpression = (context, node) => {
let query = "SELECT ";
let elementStrings = [];
if (node.selectAll) {
elementStrings.push("*");
}
query += elementStrings.concat(node.elements.map(v => this.visitNode(context, v).queryString)).join(", ");
if (node.from) {
query += " " + this.visitNode(context, node.from).queryString;
}
if (node.orderBy) {
query += " " + this.visitNode(context, node.orderBy).queryString;
}
if (node.limit) {
query += " " + this.visitNode(context, node.limit).queryString;
}
context.queryString = query;
return context;
};
this.visitConstant = (context, node) => {
if (node.value !== "NULL" && node.value !== "NOT NULL" && typeof node.value === "string") {
context.queryString = "'" + node.value + "'";
}
else {
context.queryString = node.value.toString();
}
return context;
};
this.visitFromClause = (context, node) => {
let fromClause = node.tables.map(t => this.visitNode(context, t).queryString).join(", ");
fromClause = "FROM " + fromClause;
if (node.where) {
fromClause += " " + this.visitNode(context, node.where).queryString;
}
if (node.groupBy) {
fromClause += " " + this.visitNode(context, node.groupBy).queryString;
}
if (node.having) {
fromClause += " HAVING " + this.visitNode(context, node.having).queryString;
}
context.queryString = fromClause;
return context;
};
this.visitTableSource = (context, node) => {
let table = this.visitNode(context, node.tableSourceItem).queryString;
let joins = node.joins ? node.joins.map(j => this.visitNode(context, j).queryString) : [];
joins = [table].concat(joins);
context.queryString = joins.join(" ");
return context;
};
this.visitJoinClause = (context, node) => {
let joinClause = (node.joinType ? node.joinType + " " : "") + "JOIN ";
joinClause += this.visitNode(context, node.joinWith).queryString;
if (node.on) {
joinClause += " ON " + this.visitNode(context, node.on).queryString;
}
context.queryString = joinClause;
return context;
};
this.visitTableSpec = (context, node) => {
context.queryString = node.tableName.toString();
return context;
};
this.visitGroupByClause = (context, node) => {
let groupByClause = "GROUP BY " + node.items.map(i => this.visitNode(context, i).queryString).join(", ");
context.queryString = groupByClause;
return context;
};
this.visitAliasedTerm = (context, node) => {
let termQuery = this.visitNode(context, node.term).queryString;
context.queryString = node.alias ? termQuery + " AS " + node.alias : termQuery;
return context;
};
this.visitSimpleFunctionCall = (context, node) => {
let func = node.name + "(" + (node.args || []).map(a => this.visitNode(context, a).queryString).join(", ") + ")";
context.queryString = func;
return context;
};
this.visitBinaryPredicate = (context, node) => {
context.queryString =
"("
+ this.visitNode(context, node.left).queryString
+ " "
+ node.operator.toString()
+ " "
+ this.visitNode(context, node.right).queryString
+ ")";
return context;
};
this.visitLikePredicate = (context, node) => {
context.queryString =
"("
+ this.visitNode(context, node.left).queryString
+ (node.negate ? " NOT LIKE " : " LIKE ")
+ this.visitNode(context, node.right).queryString
+ ")";
return context;
};
this.visitColumnName = (context, node) => {
context.queryString = node.table ? node.table.toString() + "." + node.name.toString() : node.name.toString();
return context;
};
this.visitWhereClause = (context, node) => {
context.queryString = "WHERE " + this.visitNode(context, node.expression).queryString;
return context;
};
this.visitOrderByClause = (context, node) => {
context.queryString = "ORDER BY " + node.expressions.map(oe => this.visitNode(context, oe).queryString).join(", ");
return context;
};
this.visitOrderByExpression = (context, node) => {
context.queryString = this.visitNode(context, node.expression).queryString + (node.descending ? " DESC " : " ASC ");
return context;
};
this.visitLimitClause = (context, node) => {
context.queryString = "LIMIT " + node.limit.toString() + (node.offset ? node.offset.toString() : "");
return context;
};
this.visitBinaryExpression = (context, node) => {
context.queryString =
"("
+ this.visitNode(context, node.left).queryString
+ " "
+ node.operator.toString()
+ " "
+ this.visitNode(context, node.right).queryString
+ ")";
return context;
};
this.delimiter = ";";
}
compile() {
let context = this.visit();
return context.queryString;
}
}
exports.QueryCompiler = QueryCompiler;
class MySQLQueryCompiler extends QueryCompiler {
constructor(query) {
super("MySQL", query, CompilationContext);
// Customize any other instance properties here, e.g. this.delimiter = "GO"; // For SQL Server (T-SQL)
}
}
exports.MySQLQueryCompiler = MySQLQueryCompiler;
//# sourceMappingURL=queryCompiler.js.map