Skip to content

Instantly share code, notes, and snippets.

@Aracturat
Last active November 8, 2017 14:53
Show Gist options
  • Save Aracturat/4077e70292ffa995b37da78a35a1410b to your computer and use it in GitHub Desktop.
Save Aracturat/4077e70292ffa995b37da78a35a1410b to your computer and use it in GitHub Desktop.
Function To SQL
import * as ts from 'typescript';
class Test {
public ParamString: string;
public ParamInt: number;
public ParamString2: string;
}
class Collection<T> {
private selectQuery: (t: T) => any;
private whereQuery: (t: T) => boolean;
private orderByQuery: (t: T) => any;
public where(query: (t: T) => boolean): Collection<T> {
this.whereQuery = query;
return this;
}
public orderBy(query: (t: T) => any): Collection<T> {
this.orderByQuery = query;
return this;
}
public select(query: (t: T) => any): Collection<T> {
this.selectQuery = query;
return this;
}
public getSql(): string {
var selectString = this.queryToSql(this.selectQuery);
var whereString = this.queryToSql(this.whereQuery);
var orderByString = this.queryToSql(this.orderByQuery);
var ret = "SELECT\n" + selectString + "\nFROM Table e\n";
if (whereString.length > 0) {
ret += "WHERE " + whereString +"\n";
}
if (orderByString.length > 0) {
ret += "ORDER BY " + orderByString;
}
return ret;
}
private queryToSql(query: (t: T) => boolean): string {
if (query) {
let src = ts.createSourceFile("test.ts", query.toString(), ts.ScriptTarget.ES2016, false);
var expr = <ts.ExpressionStatement> src.statements[0];
var arrFunc = <ts.ArrowFunction> expr.expression;
return this.toSql(arrFunc.body);
}
return "";
}
private toSql(expr: ts.Node): string {
switch(expr.kind) {
case ts.SyntaxKind.PropertyAccessExpression:
var paExpr = <ts.PropertyAccessExpression> expr;
var idObject = <ts.Identifier> paExpr.expression;
return idObject.text + "." + paExpr.name.text;
case ts.SyntaxKind.ParenthesizedExpression:
var parExpr = <ts.ParenthesizedExpression> expr;
if (parExpr.expression.kind != ts.SyntaxKind.ObjectLiteralExpression) {
return "(" + this.toSql(parExpr.expression) + ")";
}
else {
return this.toSql(parExpr.expression);
}
case ts.SyntaxKind.BinaryExpression:
var bExpr = <ts.BinaryExpression> expr;
var op = "";
switch (bExpr.operatorToken.kind) {
case ts.SyntaxKind.EqualsEqualsToken:
op = "=";
break;
case ts.SyntaxKind.GreaterThanToken:
op = ">";
break;
case ts.SyntaxKind.GreaterThanEqualsToken:
op = ">=";
break;
case ts.SyntaxKind.LessThanToken:
op = "<";
break;
case ts.SyntaxKind.LessThanEqualsToken:
op = "<=";
break;
case ts.SyntaxKind.AmpersandAmpersandToken:
op = "and";
break;
case ts.SyntaxKind.BarBarToken:
op = "or";
break;
default:
op = "[UndefinedOperator]";
}
return this.toSql(bExpr.left) + " " + op + " " + this.toSql(bExpr.right);
case ts.SyntaxKind.NumericLiteral:
var nlExpr = <ts.NumericLiteral> expr;
return nlExpr.text;
case ts.SyntaxKind.StringLiteral:
var slExpr = <ts.StringLiteral> expr;
return "'" + slExpr.text + "'";
case ts.SyntaxKind.CallExpression:
var cExpr = <ts.CallExpression> expr;
if (cExpr.expression.kind == ts.SyntaxKind.PropertyAccessExpression) {
var cpaExpr = <ts.PropertyAccessExpression> cExpr.expression;
var funcName = "";
var args = "";
switch (cpaExpr.name.text) {
case "toUpperCase":
funcName = "UPPER";
break;
case "toLowerCase":
funcName = "LOWER";
break;
case "substring":
funcName = "SUBSTRING"
args = ", " + cExpr.arguments.map(e => this.toSql(e)).join(", ");
break;
default:
funcName = "[UndefinedFunction]";
break;
}
return funcName + "(" + this.toSql(cpaExpr.expression) + args + ")";
}
case ts.SyntaxKind.ObjectLiteralExpression:
var olExpr = <ts.ObjectLiteralExpression> expr;
return olExpr.properties.map(pr => {
switch (pr.kind) {
case ts.SyntaxKind.PropertyAssignment:
var prAs = <ts.PropertyAssignment> pr;
var prNameObject = <ts.Identifier> prAs.name;
return this.toSql(prAs.initializer) + " as " + prNameObject.text;
default:
return "[undefined]";
}
}).join(",\n");
default:
debugger;
return "[undefined]";
}
}
}
/*
return
SELECT
e.ParamInt as IntParam,
UPPER(e.ParamString) as StringParam
FROM Table e
WHERE (LOWER(UPPER(e.ParamString)) = SUBSTRING(LOWER('3'), 0, 10) or e.ParamInt >= 4) and e.ParamString2 <= '2'
ORDER BY e.ParamInt
*/
var result = new Collection<Test>()
.where(e => (e.ParamString.toUpperCase().toLowerCase() == "3".toLowerCase().substring(0, 10) || e.ParamInt >= 4) && e.ParamString2 <= "2")
.orderBy(e => e.ParamInt)
.select(e => <any> {
IntParam: e.ParamInt,
StringParam: e.ParamString.toUpperCase()
})
.getSql();
console.log(result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment