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.
84 lines • 3.15 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ast = require("./astsql");
class GenericQueryContext {
constructor(currentNode) {
this.currentNode = currentNode;
}
}
class QueryVisitor {
constructor(dialect, query, contextBuilder) {
this.dialect = dialect;
this.query = query;
this.visitStarted = false;
this._contextBuilder = contextBuilder || GenericQueryContext;
if (this.dialect !== query.dialect) {
throw Error("Mismatched query dialects.");
}
}
// Derived classes must call this to start the visiting process
visit() {
if (this.visitStarted) {
throw Error("Visit already initiated");
}
this.visitStarted = true;
let context = this.buildContext();
context = this.visitNode(context, this.query);
return context;
}
// Dispatcher
visitNode(context, node) {
let previousParent = context.parentNode;
let previousCurrent = context.currentNode;
if (context.currentNode !== node) {
context.parentNode = context.currentNode;
context.currentNode = node;
}
context = this.doVisitNode(context, node);
context.parentNode = previousParent;
context.currentNode = previousCurrent;
return context;
}
// Generic visit method. The visiting process falls back to this if it doesn't find a visit<NodeType> method
// e.g. visitSelectStatement or visitQueryExpression
visitGenericNode(context, node) {
let anyNode = node;
for (let p in anyNode) {
if (this.shouldVisitNode(anyNode[p])) {
context = this.visitNode(context, anyNode[p]);
}
else if (Array.isArray(anyNode[p])) {
for (let elem of anyNode[p]) {
if (this.shouldVisitNode(elem)) {
context = this.visitNode(context, elem);
}
}
}
else {
// throw Error("Unknown element requested to be visited");
// console.log(`WARNING: Skipping visiting unknown element ${p}`);
}
}
return context;
}
// Context builder
buildContext() {
return new this._contextBuilder(this.query);
}
// Determines whether this object should be visited
shouldVisitNode(node) {
return node && (node instanceof ast.SqlAstNode || node.nodeType);
}
// Determines which visit method to call and calls here
doVisitNode(context, node) {
let nodeType = ast.SqlAstNode.getNodeType(node);
let visitorMethod = "visit" + nodeType;
let visitor = this;
if (visitor[visitorMethod] && typeof visitor[visitorMethod] === "function") {
return visitor[visitorMethod](context, node);
}
return this.visitGenericNode(context, node);
}
}
exports.QueryVisitor = QueryVisitor;
//# sourceMappingURL=queryVisitor.js.map