jaydata
Version:
Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)
265 lines (216 loc) • 12.4 kB
JavaScript
;
var _core = require('../../../../core.js');
var _core2 = _interopRequireDefault(_core);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
//"use strict"; // suspicious code
(0, _core.$C)('$data.storageProviders.Facebook.FacebookCompiler', _core2.default.Expressions.EntityExpressionVisitor, null, {
constructor: function constructor() {
this.provider = {};
},
compile: function compile(query) {
this.provider = query.context.storageProvider;
var context = {
filterSql: { sql: '' },
projectionSql: { sql: '' },
orderSql: { sql: '' },
skipSql: { sql: '' },
takeSql: { sql: '' },
tableName: ''
};
this.Visit(query.expression, context);
var autoGeneratedSelect = false;
if (!context.projectionSql.sql) {
context.projectionSql = this.autoGenerateProjection(query);
autoGeneratedSelect = true;
}
if (context.filterSql.sql == '') _core.Guard.raise(new _core.Exception('Filter/where statement is required', 'invalid operation'));
return {
queryText: context.projectionSql.sql + ' FROM ' + context.tableName + context.filterSql.sql + context.orderSql.sql + context.takeSql.sql + (context.takeSql.sql ? context.skipSql.sql : ''),
selectMapping: autoGeneratedSelect == false ? context.projectionSql.selectFields : null,
params: []
};
},
autoGenerateProjection: function autoGenerateProjection(query) {
var entitySet = query.context.getEntitySetFromElementType(query.defaultType);
var newQueryable = new _core2.default.Queryable(query.context, entitySet.expression);
//newQueryable._checkRootExpression(entitySet.collectionName);
var codeExpression = _core.Container.createCodeExpression(this.generateProjectionFunc(query));
var exp = _core.Container.createProjectionExpression(newQueryable.expression, codeExpression);
var q = _core.Container.createQueryable(newQueryable, exp);
var expression = q.expression;
var preparator = _core.Container.createQueryExpressionCreator(query.context);
expression = preparator.Visit(expression);
var databaseQuery = {
projectionSql: { sql: '' }
};
this.Visit(expression, databaseQuery);
return databaseQuery.projectionSql;
},
generateProjectionFunc: function generateProjectionFunc(query) {
var isAuthenticated = this.provider.AuthenticationProvider.Authenticated || this.provider.providerConfiguration.Access_Token;
var publicMemberDefinitions = query.defaultType.memberDefinitions.getPublicMappedProperties();
if (!isAuthenticated && publicMemberDefinitions.some(function (memDef) {
return memDef.isPublic == true;
})) {
publicMemberDefinitions = publicMemberDefinitions.filter(function (memDef) {
return memDef.isPublic == true;
});
}
var selectStr = 'function (s){ return {';
publicMemberDefinitions.forEach(function (memDef, i) {
if (i != 0) selectStr += ', ';
selectStr += memDef.name + ': s.' + memDef.name;
});
selectStr += '}; }';
//var projectionFunc = null;
//eval(selectStr);
return selectStr;
},
VisitFilterExpression: function VisitFilterExpression(expression, context) {
///<param name="expression" type="$data.Expressions.FilterExpression" />
this.Visit(expression.source, context);
context.filterSql.type = expression.nodeType;
if (context.filterSql.sql == '') context.filterSql.sql = ' WHERE ';else context.filterSql.sql += ' AND ';
this.Visit(expression.selector, context.filterSql);
},
VisitProjectionExpression: function VisitProjectionExpression(expression, context) {
///<param name="expression" type="$data.Expressions.ProjectionExpression" />
this.Visit(expression.source, context);
context.projectionSql.type = expression.nodeType;
if (context.projectionSql.sql == '') context.projectionSql.sql = 'SELECT ';else _core.Guard.raise(new _core.Exception('Multiple select error'));
this.Visit(expression.selector, context.projectionSql);
},
VisitOrderExpression: function VisitOrderExpression(expression, context) {
///<param name="expression" type="$data.Expressions.OrderExpression" />
this.Visit(expression.source, context);
context.orderSql.type = expression.nodeType;
if (context.orderSql.sql == '') context.orderSql.sql = ' ORDER BY ';else _core.Guard.raise(new _core.Exception('Multiple sorting not supported', 'not supported'));
this.Visit(expression.selector, context.orderSql);
context.orderSql.sql += expression.nodeType == _core2.default.Expressions.ExpressionType.OrderByDescending ? " DESC" : " ASC";
},
VisitPagingExpression: function VisitPagingExpression(expression, context) {
///<param name="expression" type="$data.Expressions.PagingExpression" />
this.Visit(expression.source, context);
if (expression.nodeType == _core2.default.Expressions.ExpressionType.Skip) {
context.skipSql.type = expression.nodeType;
context.skipSql.sql = ' OFFSET ';
this.Visit(expression.amount, context.skipSql);
} else if (expression.nodeType == _core2.default.Expressions.ExpressionType.Take) {
context.takeSql.type = expression.nodeType;
context.takeSql.sql = ' LIMIT ';
this.Visit(expression.amount, context.takeSql);
}
},
VisitSimpleBinaryExpression: function VisitSimpleBinaryExpression(expression, context) {
context.sql += "(";
var left = this.Visit(expression.left, context);
context.sql += expression.resolution.mapTo;
if (expression.resolution.resolvableType && !_core.Guard.requireType(expression.resolution.mapTo + ' expression.right.value', expression.right.value, expression.resolution.resolvableType)) {
_core.Guard.raise(new _core.Exception(expression.right.type + " not allowed in '" + expression.resolution.mapTo + "' statement", "invalid operation"));
}
if (expression.resolution.name === 'in' && expression.right.value instanceof Array) {
var self = this;
context.sql += "(";
expression.right.value.forEach(function (item, i) {
if (i > 0) context.sql += ", ";
self.Visit(item, context);
});
context.sql += ")";
} else {
var right = this.Visit(expression.right, context);
}
context.sql += ")";
},
VisitEntityFieldExpression: function VisitEntityFieldExpression(expression, context) {
var source = this.Visit(expression.selector, context);
},
VisitMemberInfoExpression: function VisitMemberInfoExpression(expression, context) {
var memberName = expression.memberName;
context.sql += memberName;
//context.fieldName = memberName;
context.fieldData = { name: memberName, dataType: expression.memberDefinition.dataType };
if (context.type == 'Projection' && !context.selectFields) {
if (context.fieldOperation === true) context.selectFields = [{ from: 'anon' }];else context.selectFields = [{ from: memberName, dataType: expression.memberDefinition.dataType }];
}
},
VisitConstantExpression: function VisitConstantExpression(expression, context) {
if (context.type == 'Projection') _core.Guard.raise(new _core.Exception('Constant value is not supported in Projection.', 'Not supported!'));
this.VisitQueryParameterExpression(expression, context);
},
VisitQueryParameterExpression: function VisitQueryParameterExpression(expression, context) {
if (expression.value instanceof _core2.default.storageProviders.Facebook.EntitySets.Command) {
context.sql += "" + expression.value + "";
} else if (expression.value instanceof _core2.default.Queryable) {
context.sql += '(' + expression.value.toTraceString().queryText + ')';
} else {
var expressionValueType = _core.Container.resolveType(expression.type);
if (this.provider.supportedDataTypes.indexOf(expressionValueType) != -1) context.sql += this.provider.fieldConverter.toDb[_core.Container.resolveName(expressionValueType)](expression.value);else {
context.sql += "" + expression.value + "";
}
}
},
VisitParametricQueryExpression: function VisitParametricQueryExpression(expression, context) {
var exp = this.Visit(expression.expression, context);
context.parameters = expression.parameters;
},
VisitEntitySetExpression: function VisitEntitySetExpression(expression, context) {
context.tableName = expression.instance.tableName;
},
VisitObjectLiteralExpression: function VisitObjectLiteralExpression(expression, context) {
var self = this;
context.selectFields = context.selectFields || [];
expression.members.forEach(function (member) {
if (member.expression instanceof _core2.default.Expressions.ObjectLiteralExpression) {
context.mappingPrefix = context.mappingPrefix || [];
context.mappingPrefix.push(member.fieldName);
self.Visit(member, context);
context.mappingPrefix.pop();
} else {
if (context.selectFields.length > 0) context.sql += ', ';
self.Visit(member, context);
var toProperty = context.mappingPrefix instanceof Array ? context.mappingPrefix.join('.') + '.' + member.fieldName : member.fieldName;
context.selectFields.push({ from: context.fieldData.name, to: toProperty, dataType: context.fieldData.dataType });
}
});
},
VisitObjectFieldExpression: function VisitObjectFieldExpression(expression, context) {
return this.Visit(expression.expression, context);
},
VisitEntityFieldOperationExpression: function VisitEntityFieldOperationExpression(expression, context) {
_core.Guard.requireType("expression.operation", expression.operation, _core2.default.Expressions.MemberInfoExpression);
var opDef = expression.operation.memberDefinition;
var opName = opDef.mapTo || opDef.name;
context.sql += '(';
if (opDef.expressionInParameter == false) this.Visit(expression.source, context);
context.sql += opName;
context.sql += "(";
var paramCounter = 0;
var params = opDef.parameters || [];
var args = params.map(function (item, index) {
var result = { dataType: item.dataType };
if (item.value) {
result.value = item.value;
} else if (item.name === "@expression") {
result.value = expression.source;
} else {
result.value = expression.parameters[paramCounter];
result.itemType = expression.parameters[paramCounter++].type;
};
return result;
});
args.forEach(function (arg, index) {
var itemType = arg.itemType ? _core.Container.resolveType(arg.itemType) : null;
if (!itemType || arg.dataType instanceof Array && arg.dataType.indexOf(itemType) != -1 || arg.dataType == itemType) {
if (index > 0) {
context.sql += ", ";
};
if (context.type == 'Projection') context.fieldOperation = true;
this.Visit(arg.value, context);
if (context.type == 'Projection') context.fieldOperation = undefined;
} else _core.Guard.raise(new _core.Exception(arg.dataType + " not allowed in '" + expression.operation.memberName + "' statement", "invalid operation"));
}, this);
if (context.fieldData && context.fieldData.name) context.fieldData.name = 'anon';
if (opDef.rigthValue) context.sql += opDef.rigthValue;else context.sql += ")";
context.sql += ')';
}
}, null);