@jitterbit/soql-parser-js
Version:
Salesforce.com SOQL parser and composer
296 lines (295 loc) • 12.9 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Compose = exports.composeQuery = exports.formatQuery = void 0;
var utils = require("../utils");
var formatter_1 = require("../formatter/formatter");
var visitor_1 = require("../parser/visitor");
function formatQuery(soql, formatOptions, parseOptions) {
return composeQuery((0, visitor_1.parseQuery)(soql, parseOptions), { format: true, formatOptions: formatOptions });
}
exports.formatQuery = formatQuery;
function composeQuery(soql, config) {
if (config === void 0) { config = {}; }
if (!soql) {
return '';
}
config = config || {};
config.format = config.format ? true : false;
if (config.logging) {
console.time('composer');
console.log('Composing Query:', soql);
console.log('Format output:', config.format);
}
var query = new Compose(soql, config).query;
if (config.logging) {
console.timeEnd('composer');
}
return query;
}
exports.composeQuery = composeQuery;
var Compose = (function () {
function Compose(soql, config) {
if (config === void 0) { config = {}; }
this.soql = soql;
this.logging = false;
this.format = false;
config = __assign({ autoCompose: true }, config);
var logging = config.logging, format = config.format;
this.logging = !!logging;
this.format = !!format;
this.query = '';
this.formatter = new formatter_1.Formatter(this.format, __assign({ logging: this.logging }, config.formatOptions));
if (config.autoCompose) {
this.start();
}
}
Compose.prototype.start = function () {
this.query = this.parseQuery(this.soql);
};
Compose.prototype.log = function (soql) {
if (this.logging) {
console.log('Current SOQL:', soql);
}
};
Compose.prototype.parseFn = function (fn) {
var _this = this;
var output;
if (fn.rawValue) {
output = fn.rawValue;
}
else {
output = fn.functionName;
output += "(".concat((fn.parameters || []).map(function (param) { return (utils.isString(param) ? param : _this.parseFn(param)); }).join(', '), ")");
}
if (fn.alias) {
output += " ".concat(fn.alias);
}
return output;
};
Compose.prototype.parseQuery = function (query) {
var _this = this;
var fieldData = {
fields: this.parseFields(query.fields || []).map(function (field) { return ({
text: field.text,
typeOfClause: field.typeOfClause,
isSubquery: field.text.startsWith('('),
prefix: '',
suffix: '',
}); }),
isSubquery: utils.isSubquery(query),
lineBreaks: [],
};
var output = '';
if (query.fields) {
output += this.formatter.formatClause('SELECT').trimStart();
}
this.formatter.formatFields(fieldData);
var fieldsOutput = '';
fieldData.fields.forEach(function (field) {
if (Array.isArray(field.typeOfClause)) {
fieldsOutput += "".concat(field.prefix).concat(_this.formatter.formatTyeOfField(field.text, field.typeOfClause)).concat(field.suffix);
}
else {
fieldsOutput += "".concat(field.prefix).concat(field.text).concat(field.suffix);
}
});
output += this.formatter.formatText(fieldsOutput);
if (!!(utils.isSubquery(query) ? query.relationshipName : query.sObject)) {
output += this.formatter.formatClause('FROM');
}
if (utils.isSubquery(query)) {
var sObjectPrefix = query.sObjectPrefix || [];
sObjectPrefix.push(query.relationshipName);
output += this.formatter.formatText("".concat(sObjectPrefix.join('.')).concat(utils.get(query.sObjectAlias, '', ' ')));
}
else if (query.sObject) {
output += this.formatter.formatText("".concat(query.sObject).concat(utils.get(query.sObjectAlias, '', ' ')));
}
this.log(output);
if (query.usingScope) {
output += this.formatter.formatClause('USING SCOPE');
output += this.formatter.formatText(query.usingScope);
this.log(output);
}
if (query.where) {
output += this.formatter.formatClause('WHERE');
output += this.formatter.formatText(this.parseWhereOrHavingClause(query.where));
this.log(output);
}
if (query.groupBy) {
output += this.formatter.formatClause('GROUP BY');
output += this.formatter.formatText(this.parseGroupByClause(query.groupBy));
this.log(output);
if (query.having) {
output += this.formatter.formatClause('HAVING');
output += this.formatter.formatText(this.parseWhereOrHavingClause(query.having));
this.log(output);
}
}
if (query.orderBy && (!Array.isArray(query.orderBy) || query.orderBy.length > 0)) {
output += this.formatter.formatClause('ORDER BY');
output += this.formatter.formatText(this.parseOrderBy(query.orderBy));
this.log(output);
}
if (utils.isNumber(query.limit)) {
output += this.formatter.formatClause('LIMIT');
output += this.formatter.formatText("".concat(query.limit));
this.log(output);
}
if (utils.isNumber(query.offset)) {
output += this.formatter.formatClause('OFFSET');
output += this.formatter.formatText("".concat(query.offset));
this.log(output);
}
if (query.withDataCategory) {
output += this.formatter.formatClause('WITH DATA CATEGORY');
output += this.formatter.formatText(this.parseWithDataCategory(query.withDataCategory));
this.log(output);
}
if (query.withSecurityEnforced) {
output += this.formatter.formatClause('WITH SECURITY_ENFORCED');
this.log(output);
}
if (query.withAccessLevel) {
output += this.formatter.formatClause("WITH ".concat(query.withAccessLevel));
this.log(output);
}
if (query.for) {
output += this.formatter.formatClause('FOR');
output += this.formatter.formatText(query.for);
this.log(output);
}
if (query.update) {
output += this.formatter.formatClause('UPDATE');
output += this.formatter.formatText(query.update);
this.log(output);
}
return output.trim();
};
Compose.prototype.parseFields = function (fields) {
var _this = this;
return fields.map(function (field) {
var text = '';
var typeOfClause;
var objPrefix = field.objectPrefix ? "".concat(field.objectPrefix, ".") : '';
switch (field.type) {
case 'Field': {
text = "".concat(objPrefix).concat(field.field).concat(field.alias ? " ".concat(field.alias) : '');
break;
}
case 'FieldFunctionExpression': {
var params = '';
if (field.parameters) {
params = field.parameters
.map(function (param) { return (utils.isString(param) ? param : _this.parseFields([param]).map(function (param) { return param.text; })); })
.join(', ');
}
text = "".concat(field.functionName, "(").concat(params, ")").concat(field.alias ? " ".concat(field.alias) : '');
break;
}
case 'FieldRelationship': {
text = "".concat(objPrefix).concat(field.relationships.join('.'), ".").concat(field.field).concat(utils.hasAlias(field) ? " ".concat(field.alias) : '');
break;
}
case 'FieldSubquery': {
text = _this.formatter.formatSubquery(_this.parseQuery(field.subquery));
break;
}
case 'FieldTypeof': {
typeOfClause = _this.parseTypeOfField(field);
text = typeOfClause.join(' ');
break;
}
default:
break;
}
return { text: text, typeOfClause: typeOfClause };
});
};
Compose.prototype.parseTypeOfField = function (typeOfField) {
var _this = this;
var output = ["TYPEOF ".concat(typeOfField.field)].concat(typeOfField.conditions.map(function (condition) { return _this.formatter.formatTypeofFieldCondition(condition); }));
output.push("END");
return output;
};
Compose.prototype.parseWhereOrHavingClause = function (whereOrHaving, tabOffset, priorConditionIsNegation) {
if (tabOffset === void 0) { tabOffset = 0; }
if (priorConditionIsNegation === void 0) { priorConditionIsNegation = false; }
var output = '';
var left = whereOrHaving.left;
var trimPrecedingOutput = false;
if (left) {
output += this.formatter.formatParens(left.openParen, '(', utils.isNegationCondition(left));
if (!utils.isNegationCondition(left)) {
tabOffset = tabOffset + (left.openParen || 0) - (left.closeParen || 0);
if (priorConditionIsNegation) {
tabOffset++;
}
var expression = '';
expression += utils.isValueFunctionCondition(left) ? this.parseFn(left.fn) : left.field;
expression += " ".concat(left.operator, " ");
if (utils.isValueQueryCondition(left)) {
expression += this.formatter.formatSubquery(this.parseQuery(left.valueQuery), 1, true);
}
else {
expression += utils.getAsArrayStr(utils.getWhereValue(left.value, left.literalType, left.operator));
}
output += this.formatter.formatWithIndent(expression);
output += this.formatter.formatParens(left.closeParen, ')', priorConditionIsNegation);
}
}
if (utils.isWhereOrHavingClauseWithRightCondition(whereOrHaving)) {
var operator = utils.get(whereOrHaving.operator);
trimPrecedingOutput = operator === 'NOT';
var formattedData = this.formatter.formatWhereClauseOperators(operator, this.parseWhereOrHavingClause(whereOrHaving.right, tabOffset, utils.isNegationCondition(left)), tabOffset);
return "".concat(trimPrecedingOutput ? output.trimRight() : output).concat(formattedData).trim();
}
else {
return output.trim();
}
};
Compose.prototype.parseGroupByClause = function (groupBy) {
var _this = this;
return (Array.isArray(groupBy) ? groupBy : [groupBy])
.map(function (clause) { return (utils.isGroupByField(clause) ? clause.field : _this.parseFn(clause.fn)); })
.join(', ');
};
Compose.prototype.parseOrderBy = function (orderBy) {
var _this = this;
if (Array.isArray(orderBy)) {
return this.formatter.formatOrderByArray(orderBy.map(function (ob) { return _this.parseOrderBy(ob); }));
}
else {
var output = '';
if (utils.isOrderByField(orderBy)) {
output = "".concat(utils.get(orderBy.field, ' '));
}
else {
output += "".concat(this.parseFn(orderBy.fn), " ");
}
output += "".concat(utils.get(orderBy.order, ' ')).concat(utils.get(orderBy.nulls, '', 'NULLS '));
return output.trim();
}
};
Compose.prototype.parseWithDataCategory = function (withDataCategory) {
return withDataCategory.conditions
.map(function (condition) {
var params = condition.parameters.length > 1 ? "(".concat(condition.parameters.join(', '), ")") : "".concat(condition.parameters.join(', '));
return "".concat(condition.groupName, " ").concat(condition.selector, " ").concat(params);
})
.join(' AND ');
};
return Compose;
}());
exports.Compose = Compose;