UNPKG

jaydata

Version:

Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)

302 lines (275 loc) 13.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SqlStatementBlocks = undefined; var _core = require("jaydata/core"); var _core2 = _interopRequireDefault(_core); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var SqlStatementBlocks = exports.SqlStatementBlocks = { beginGroup: "(", endGroup: ")", nameSeparator: ".", valueSeparator: ", ", select: "SELECT ", where: " WHERE ", from: " FROM ", skip: " OFFSET ", take: " LIMIT ", parameter: "?", order: " ORDER BY ", as: " AS ", scalarFieldName: 'd', rowIdName: 'rowid$$', count: 'select count(*) cnt from (' }; (0, _core.$C)('$data.sqLite.SqlBuilder', _core2.default.queryBuilder, null, { constructor: function constructor(sets, context) { this.sets = sets; this.entityContext = context; }, getExpressionAlias: function getExpressionAlias(setExpression) { var idx = this.sets.indexOf(setExpression); if (idx == -1) { idx = this.sets.push(setExpression) - 1; } return "T" + idx; } }); (0, _core.$C)('$data.sqLite.SqlCompiler', _core2.default.Expressions.EntityExpressionVisitor, null, { constructor: function constructor(queryExpression, context) { this.queryExpression = queryExpression; this.sets = context.sets; this.infos = context.infos; this.entityContext = context.entityContext; this.associations = []; this.filters = []; this.newFilters = {}; this.sortedFilterPart = ['projection', 'from', 'filter', 'order', 'take', 'skip']; }, compile: function compile() { var sqlBuilder = _core2.default.sqLite.SqlBuilder.create(this.sets, this.entityContext); this.Visit(this.queryExpression, sqlBuilder); if (sqlBuilder.getTextPart('projection') === undefined) { this.VisitDefaultProjection(sqlBuilder); } sqlBuilder.selectTextPart("result"); this.sortedFilterPart.forEach(function (part) { var part = sqlBuilder.getTextPart(part); if (part) { sqlBuilder.addText(part.text); sqlBuilder.selectedFragment.params = sqlBuilder.selectedFragment.params.concat(part.params); } }, this); var countPart = sqlBuilder.getTextPart('count'); if (countPart !== undefined) { sqlBuilder.selectedFragment.text = countPart.text + sqlBuilder.selectedFragment.text; sqlBuilder.addText(SqlStatementBlocks.endGroup); sqlBuilder.selectedFragment.params = sqlBuilder.selectedFragment.params.concat(countPart.params); } sqlBuilder.resetModelBinderProperty(); this.filters.push(sqlBuilder); }, VisitToArrayExpression: function VisitToArrayExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); }, VisitCountExpression: function VisitCountExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); sqlBuilder.selectTextPart('count'); sqlBuilder.addText(SqlStatementBlocks.count); }, VisitFilterExpression: function VisitFilterExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); sqlBuilder.selectTextPart('filter'); sqlBuilder.addText(SqlStatementBlocks.where); var filterCompiler = _core2.default.sqLite.SqlFilterCompiler.create(); filterCompiler.Visit(expression.selector, sqlBuilder); return expression; }, VisitOrderExpression: function VisitOrderExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); sqlBuilder.selectTextPart('order'); if (this.addOrders) { sqlBuilder.addText(SqlStatementBlocks.valueSeparator); } else { this.addOrders = true; sqlBuilder.addText(SqlStatementBlocks.order); } var orderCompiler = _core2.default.sqLite.SqlOrderCompiler.create(); orderCompiler.Visit(expression, sqlBuilder); return expression; }, VisitPagingExpression: function VisitPagingExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); switch (expression.nodeType) { case _core2.default.Expressions.ExpressionType.Skip: sqlBuilder.selectTextPart('skip'); sqlBuilder.addText(SqlStatementBlocks.skip);break; case _core2.default.Expressions.ExpressionType.Take: sqlBuilder.selectTextPart('take'); sqlBuilder.addText(SqlStatementBlocks.take);break; default: _core.Guard.raise("Not supported nodeType");break; } var pagingCompiler = _core2.default.sqLite.SqlPagingCompiler.create(); pagingCompiler.Visit(expression, sqlBuilder); return expression; }, VisitProjectionExpression: function VisitProjectionExpression(expression, sqlBuilder) { this.Visit(expression.source, sqlBuilder); sqlBuilder.selectTextPart('projection'); this.hasProjection = true; sqlBuilder.addText(SqlStatementBlocks.select); var projectonCompiler = _core2.default.sqLite.SqlProjectionCompiler.create(); projectonCompiler.Visit(expression, sqlBuilder); }, VisitEntitySetExpression: function VisitEntitySetExpression(expression, sqlBuilder) { sqlBuilder.selectTextPart('from'); sqlBuilder.addText(SqlStatementBlocks.from); sqlBuilder.sets.forEach(function (es, setIndex) { if (setIndex > 0) { sqlBuilder.addText(" \n\tLEFT OUTER JOIN "); } var alias = sqlBuilder.getExpressionAlias(es); sqlBuilder.addText(es.instance.tableName + ' '); sqlBuilder.addText(alias); if (setIndex > 0) { sqlBuilder.addText(" ON ("); var toSet = this.infos[setIndex]; var toPrefix = "T" + toSet.AliasNumber; var fromSetName = toSet.NavigationPath.substring(0, toSet.NavigationPath.lastIndexOf('.')); var temp = this.infos.filter(function (inf) { return inf.NavigationPath == fromSetName; }, this); var fromPrefix = "T0"; if (temp.length > 0) { fromPrefix = "T" + temp[0].AliasNumber; } toSet.Association.associationInfo.ReferentialConstraint.forEach(function (constrain, index) { if (index > 0) { sqlBuilder.addText(" AND "); } sqlBuilder.addText(fromPrefix + "." + constrain[toSet.Association.associationInfo.From]); sqlBuilder.addText(" = "); sqlBuilder.addText(toPrefix + "." + constrain[toSet.Association.associationInfo.To]); }, this); sqlBuilder.addText(")"); } }, this); }, VisitDefaultProjection: function VisitDefaultProjection(sqlBuilder) { sqlBuilder.selectTextPart('projection'); var needAlias = this.infos.filter(function (i) { return i.IsMapped; }).length > 1; if (sqlBuilder.sets.length > 1) { sqlBuilder.addText(SqlStatementBlocks.select); sqlBuilder.sets.forEach(function (set, masterIndex) { if (this.infos[masterIndex].IsMapped) { var alias = sqlBuilder.getExpressionAlias(set); set.storageModel.PhysicalType.memberDefinitions.getPublicMappedProperties().forEach(function (memberDef, index) { if (index > 0 || masterIndex > 0) { sqlBuilder.addText(SqlStatementBlocks.valueSeparator); } sqlBuilder.addText(alias + "."); sqlBuilder.addText(memberDef.name); if (needAlias) { sqlBuilder.addText(SqlStatementBlocks.as); sqlBuilder.addText(alias + "__" + memberDef.name); } }, this); } }, this); } else { sqlBuilder.addText("SELECT *"); } } }); _core2.default.Expressions.ExpressionNode.prototype.monitor = function (monitorDefinition, context) { var m = _core2.default.sqLite.SqlExpressionMonitor.create(monitorDefinition); return m.Visit(this, context); }; (0, _core.$C)('$data.storageProviders.sqLite.SQLiteCompiler', null, null, { compile: function compile(query) { /// <param name="query" type="$data.Query" /> var expression = query.expression; var context = { sets: [], infos: [], entityContext: query.context }; var optimizedIncludeExpression = expression.monitor({ MonitorEntitySetExpression: function MonitorEntitySetExpression(expression, context) { if (expression.source instanceof _core2.default.Expressions.EntityContextExpression && context.sets.indexOf(expression) == -1) { this.backupEntitySetExpression = expression; } }, VisitCountExpression: function VisitCountExpression(expression, context) { context.hasCountFrameOperator = true; return expression; }, MutateIncludeExpression: function MutateIncludeExpression(expression, context) { var result = null; if (context.hasCountFrameOperator) { result = expression.source; } else { var origSelector = expression.selector.value; _core.Container.createCodeExpression("function(it){return it." + origSelector + ";}", null); var jsCodeTree = _core.Container.createCodeParser(this.backupEntitySetExpression.source.instance).createExpression("function(it){return it." + origSelector + ";}"); var code2entity = _core.Container.createCodeToEntityConverter(this.backupEntitySetExpression.source.instance); var includeSelector = code2entity.Visit(jsCodeTree, { queryParameters: undefined, lambdaParameters: [this.backupEntitySetExpression] }); result = _core.Container.createIncludeExpression(expression.source, includeSelector); } return result; } }, context); var optimizedExpression = optimizedIncludeExpression.monitor({ MonitorEntitySetExpression: function MonitorEntitySetExpression(expression, context) { if (expression.source instanceof _core2.default.Expressions.EntityContextExpression && context.sets.indexOf(expression) == -1) { context.sets.push(expression); context.infos.push({ AliasNumber: 0, Association: null, FromType: null, FromPropertyName: null, IsMapped: true }); } }, MutateEntitySetExpression: function MutateEntitySetExpression(expression, context) { if (expression.source instanceof _core2.default.Expressions.EntityContextExpression) { this.backupContextExpression = expression.source; this.path = ""; return expression; } if (expression.selector.associationInfo.FromMultiplicity == "0..1" && expression.selector.associationInfo.FromMultiplicity == "*") { _core.Guard.raise("Not supported query on this navigation property: " + expression.selector.associationInfo.From + " " + expression.selector.associationInfo.FromPropertyName); } this.path += '.' + expression.selector.associationInfo.FromPropertyName; var info = context.infos.filter(function (inf) { return inf.NavigationPath == this.path; }, this); if (info.length > 0) { return context.sets[info[0].AliasNumber]; } var memberDefinitions = this.backupContextExpression.instance.getType().memberDefinitions.getMember(expression.storageModel.ItemName); if (!memberDefinitions) { _core.Guard.raise("Context schema error"); } var mi = _core.Container.createMemberInfoExpression(memberDefinitions); var result = _core.Container.createEntitySetExpression(this.backupContextExpression, mi); result.instance = this.backupContextExpression.instance[expression.storageModel.ItemName]; var aliasNum = context.sets.push(result); context.infos.push({ AliasNumber: aliasNum - 1, Association: expression.selector, NavigationPath: this.path, IsMapped: this.isMapped }); return result; } }, context); var compiler = _core2.default.sqLite.SqlCompiler.create(optimizedExpression, context); compiler.compile(); var sqlBuilder = _core2.default.sqLite.SqlBuilder.create(this.sets, this.entityContext); query.modelBinderConfig = {}; var modelBinder = _core2.default.sqLite.sqLite_ModelBinderCompiler.create(query, context); modelBinder.Visit(optimizedExpression); var result = { sqlText: compiler.filters[0].selectedFragment.text, params: compiler.filters[0].selectedFragment.params, modelBinderConfig: query.modelBinderConfig }; return result; } }, null);