UNPKG

@rechat/squel

Version:
1,480 lines (1,210 loc) 94.9 kB
;(function(root, factory) { if (typeof define === 'function' && define.amd) { define([], factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.squel = factory(); } }(this, function() { "use strict"; function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } // append to string if non-empty function _pad(str, pad) { return str.length ? str + pad : str; } // Extend given object's with other objects' properties, overriding existing ones if necessary function _extend(dst) { for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { sources[_key - 1] = arguments[_key]; } if (dst && sources) { var _iterator = _createForOfIteratorHelper(sources), _step; try { var _loop = function _loop() { var src = _step.value; if (_typeof(src) === 'object') { Object.getOwnPropertyNames(src).forEach(function (key) { dst[key] = src[key]; }); } }; for (_iterator.s(); !(_step = _iterator.n()).done;) { _loop(); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } return dst; } ; // get whether object is a plain object function _isPlainObject(obj) { return obj && obj.constructor.prototype === Object.prototype; } ; // get whether object is an array function _isArray(obj) { return obj && obj.constructor.prototype === Array.prototype; } ; // clone given item function _clone(src) { if (!src) { return src; } if (typeof src.clone === 'function') { return src.clone(); } else if (_isPlainObject(src) || _isArray(src)) { var ret = new src.constructor(); Object.getOwnPropertyNames(src).forEach(function (key) { if (typeof src[key] !== 'function') { ret[key] = _clone(src[key]); } }); return ret; } else { return JSON.parse(JSON.stringify(src)); } } ; /** * Register a value type handler * * Note: this will override any existing handler registered for this value type. */ function _registerValueHandler(handlers, type, handler) { var typeofType = _typeof(type); if (typeofType !== 'function' && typeofType !== 'string') { throw new Error("type must be a class constructor or string"); } if (typeof handler !== 'function') { throw new Error("handler must be a function"); } var _iterator2 = _createForOfIteratorHelper(handlers), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var typeHandler = _step2.value; if (typeHandler.type === type) { typeHandler.handler = handler; return; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } handlers.push({ type: type, handler: handler }); } ; /** * Get value type handler for given type */ function getValueHandler(value, localHandlers, globalHandlers) { return _getValueHandler(value, localHandlers) || _getValueHandler(value, globalHandlers); } ; function _getValueHandler(value, handlers) { for (var i = 0; i < handlers.length; i++) { var typeHandler = handlers[i]; // if type is a string then use `typeof` or else use `instanceof` if (_typeof(value) === typeHandler.type || typeof typeHandler.type !== 'string' && value instanceof typeHandler.type) { return typeHandler.handler; } } } ; /** * Build base squel classes and methods */ function _buildSquel() { var flavour = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var cls = { // Get whether obj is a query builder isSquelBuilder: function isSquelBuilder(obj) { return obj && !!obj._toParamString; } }; // Get whether nesting should be applied for given item var _shouldApplyNesting = function _shouldApplyNesting(obj) { return !cls.isSquelBuilder(obj) || !obj.options.rawNesting; }; // default query builder options cls.DefaultQueryBuilderOptions = { // If true then table names will be rendered inside quotes. The quote character used is configurable via the nameQuoteCharacter option. autoQuoteTableNames: false, // If true then field names will rendered inside quotes. The quote character used is configurable via the nameQuoteCharacter option. autoQuoteFieldNames: false, // If true then alias names will rendered inside quotes. The quote character used is configurable via the `tableAliasQuoteCharacter` and `fieldAliasQuoteCharacter` options. autoQuoteAliasNames: true, // If true then table alias names will rendered after AS keyword. useAsForTableAliasNames: false, // The quote character used for when quoting table and field names nameQuoteCharacter: '`', // The quote character used for when quoting table alias names tableAliasQuoteCharacter: '`', // The quote character used for when quoting table alias names fieldAliasQuoteCharacter: '"', // Custom value handlers where key is the value type and the value is the handler function valueHandlers: [], // Character used to represent a parameter value parameterCharacter: '?', // Numbered parameters returned from toParam() as $1, $2, etc. numberedParameters: false, // Numbered parameters prefix character(s) numberedParametersPrefix: '$', // Numbered parameters start at this number. numberedParametersStartAt: 1, // If true then replaces all single quotes within strings. The replacement string used is configurable via the `singleQuoteReplacement` option. replaceSingleQuotes: false, // The string to replace single quotes with in query strings singleQuoteReplacement: '\'\'', // String used to join individual blocks in a query when it's stringified separator: ' ', // Function for formatting string values prior to insertion into query string stringFormatter: null, // Whether to prevent the addition of brackets () when nesting this query builder's output rawNesting: false }; // Global custom value handlers for all instances of builder cls.globalValueHandlers = []; /* # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- # Custom value types # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- */ // Register a new value handler cls.registerValueHandler = function (type, handler) { _registerValueHandler(cls.globalValueHandlers, type, handler); }; /* # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- # Base classes # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- */ // Base class for cloneable builders cls.Cloneable = /*#__PURE__*/function () { function _class() { _classCallCheck(this, _class); } _createClass(_class, [{ key: "clone", value: /** * Clone this builder */ function clone() { var newInstance = new this.constructor(); return _extend(newInstance, _clone(_extend({}, this))); } }]); return _class; }(); // Base class for all builders cls.BaseBuilder = /*#__PURE__*/function (_cls$Cloneable) { _inherits(_class2, _cls$Cloneable); var _super = _createSuper(_class2); /** * Constructor. * this.param {Object} options Overriding one or more of `cls.DefaultQueryBuilderOptions`. */ function _class2(options) { var _this; _classCallCheck(this, _class2); _this = _super.call(this); var defaults = JSON.parse(JSON.stringify(cls.DefaultQueryBuilderOptions)); // for function values, etc we need to manually copy ['stringFormatter'].forEach(function (p) { defaults[p] = cls.DefaultQueryBuilderOptions[p]; }); _this.options = _extend({}, defaults, options); return _this; } /** * Register a custom value handler for this builder instance. * * Note: this will override any globally registered handler for this value type. */ _createClass(_class2, [{ key: "registerValueHandler", value: function registerValueHandler(type, handler) { _registerValueHandler(this.options.valueHandlers, type, handler); return this; } /** * Sanitize given expression. */ }, { key: "_sanitizeExpression", value: function _sanitizeExpression(expr) { // If it's not a base builder instance if (!cls.isSquelBuilder(expr)) { // It must then be a string if (typeof expr !== "string") { throw new Error("expression must be a string or builder instance"); } } return expr; } /** * Sanitize the given name. * * The 'type' parameter is used to construct a meaningful error message in case validation fails. */ }, { key: "_sanitizeName", value: function _sanitizeName(value, type) { if (typeof value !== "string") { throw new Error("".concat(type, " must be a string")); } return value; } }, { key: "_sanitizeField", value: function _sanitizeField(item) { if (!cls.isSquelBuilder(item)) { item = this._sanitizeName(item, "field name"); } return item; } }, { key: "_sanitizeBaseBuilder", value: function _sanitizeBaseBuilder(item) { if (cls.isSquelBuilder(item)) { return item; } throw new Error("must be a builder instance"); } }, { key: "_sanitizeTable", value: function _sanitizeTable(item) { if (typeof item !== "string") { try { item = this._sanitizeBaseBuilder(item); } catch (e) { throw new Error("table name must be a string or a builder"); } } else { item = this._sanitizeName(item, 'table'); } return item; } }, { key: "_sanitizeTableAlias", value: function _sanitizeTableAlias(item) { return this._sanitizeName(item, "table alias"); } }, { key: "_sanitizeFieldAlias", value: function _sanitizeFieldAlias(item) { return this._sanitizeName(item, "field alias"); } // Sanitize the given limit/offset value. }, { key: "_sanitizeLimitOffset", value: function _sanitizeLimitOffset(value) { value = parseInt(value); if (0 > value || isNaN(value)) { throw new Error("limit/offset must be >= 0"); } return value; } // Santize the given field value }, { key: "_sanitizeValue", value: function _sanitizeValue(item) { var itemType = _typeof(item); if (null === item) {// null is allowed } else if ("string" === itemType || "number" === itemType || "boolean" === itemType) {// primitives are allowed } else if (cls.isSquelBuilder(item)) {// Builders allowed } else { var typeIsValid = !!getValueHandler(item, this.options.valueHandlers, cls.globalValueHandlers); if (!typeIsValid) { throw new Error("field value must be a string, number, boolean, null or one of the registered custom value types"); } } return item; } // Escape a string value, e.g. escape quotes and other characters within it. }, { key: "_escapeValue", value: function _escapeValue(value) { return this.options.replaceSingleQuotes && value ? value.replace(/\'/g, this.options.singleQuoteReplacement) : value; } }, { key: "_formatTableName", value: function _formatTableName(item) { if (this.options.autoQuoteTableNames) { var quoteChar = this.options.nameQuoteCharacter; item = "".concat(quoteChar).concat(item).concat(quoteChar); } return item; } }, { key: "_formatFieldAlias", value: function _formatFieldAlias(item) { if (this.options.autoQuoteAliasNames) { var quoteChar = this.options.fieldAliasQuoteCharacter; item = "".concat(quoteChar).concat(item).concat(quoteChar); } return item; } }, { key: "_formatTableAlias", value: function _formatTableAlias(item) { if (this.options.autoQuoteAliasNames) { var quoteChar = this.options.tableAliasQuoteCharacter; item = "".concat(quoteChar).concat(item).concat(quoteChar); } return this.options.useAsForTableAliasNames ? "AS ".concat(item) : item; } }, { key: "_formatFieldName", value: function _formatFieldName(item) { var formattingOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (this.options.autoQuoteFieldNames) { var quoteChar = this.options.nameQuoteCharacter; if (formattingOptions.ignorePeriodsForFieldNameQuotes) { // a.b.c -> `a.b.c` item = "".concat(quoteChar).concat(item).concat(quoteChar); } else { // a.b.c -> `a`.`b`.`c` item = item.split('.').map(function (v) { // treat '*' as special case (#79) return '*' === v ? v : "".concat(quoteChar).concat(v).concat(quoteChar); }).join('.'); } } return item; } // Format the given custom value }, { key: "_formatCustomValue", value: function _formatCustomValue(value, asParam, formattingOptions) { // user defined custom handlers takes precedence var customHandler = getValueHandler(value, this.options.valueHandlers, cls.globalValueHandlers); // use the custom handler if available if (customHandler) { value = customHandler(value, asParam, formattingOptions); // custom value handler can instruct caller not to process returned value if (value && value.rawNesting) { return { formatted: true, rawNesting: true, value: value.value }; } } return { formatted: !!customHandler, value: value }; } /** * Format given value for inclusion into parameter values array. */ }, { key: "_formatValueForParamArray", value: function _formatValueForParamArray(value) { var _this2 = this; var formattingOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (_isArray(value)) { return value.map(function (v) { return _this2._formatValueForParamArray(v, formattingOptions); }); } else { return this._formatCustomValue(value, true, formattingOptions).value; } } /** * Format the given field value for inclusion into the query string */ }, { key: "_formatValueForQueryString", value: function _formatValueForQueryString(initialValue) { var _this3 = this; var formattingOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // maybe we have a cusotm value handler var _this$_formatCustomVa = this._formatCustomValue(initialValue, false, formattingOptions), rawNesting = _this$_formatCustomVa.rawNesting, formatted = _this$_formatCustomVa.formatted, value = _this$_formatCustomVa.value; // if formatting took place then return it directly if (formatted) { if (rawNesting) { return value; } else { return this._applyNestingFormatting(value, _shouldApplyNesting(initialValue)); } } // if it's an array then format each element separately if (_isArray(value)) { value = value.map(function (v) { return _this3._formatValueForQueryString(v); }); value = this._applyNestingFormatting(value.join(', '), _shouldApplyNesting(value)); } else { var typeofValue = _typeof(value); if (null === value) { value = "NULL"; } else if (typeofValue === "boolean") { value = value ? "TRUE" : "FALSE"; } else if (cls.isSquelBuilder(value)) { value = this._applyNestingFormatting(value.toString(), _shouldApplyNesting(value)); } else if (typeofValue !== "number") { // if it's a string and we have custom string formatting turned on then use that if ('string' === typeofValue && this.options.stringFormatter) { return this.options.stringFormatter(value); } if (formattingOptions.dontQuote) { value = "".concat(value); } else { var escapedValue = this._escapeValue(value); value = "'".concat(escapedValue, "'"); } } } return value; } }, { key: "_applyNestingFormatting", value: function _applyNestingFormatting(str) { var nesting = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (str && typeof str === 'string' && nesting && !this.options.rawNesting) { // apply brackets if they're not already existing var alreadyHasBrackets = '(' === str.charAt(0) && ')' === str.charAt(str.length - 1); if (alreadyHasBrackets) { // check that it's the form "((x)..(y))" rather than "(x)..(y)" var idx = 0, open = 1; while (str.length - 1 > ++idx) { var c = str.charAt(idx); if ('(' === c) { open++; } else if (')' === c) { open--; if (1 > open) { alreadyHasBrackets = false; break; } } } } if (!alreadyHasBrackets) { str = "(".concat(str, ")"); } } return str; } /** * Build given string and its corresponding parameter values into * output. * * @param {String} str * @param {Array} values * @param {Object} [options] Additional options. * @param {Boolean} [options.buildParameterized] Whether to build paramterized string. Default is false. * @param {Boolean} [options.nested] Whether this expression is nested within another. * @param {Boolean} [options.formattingOptions] Formatting options for values in query string. * @return {Object} */ }, { key: "_buildString", value: function _buildString(str, values) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var nested = options.nested, buildParameterized = options.buildParameterized, formattingOptions = options.formattingOptions; values = values || []; str = str || ''; var formattedStr = '', curValue = -1, formattedValues = []; var paramChar = this.options.parameterCharacter; var idx = 0; while (str.length > idx) { // param char? if (str.substr(idx, paramChar.length) === paramChar) { var value = values[++curValue]; if (buildParameterized) { if (cls.isSquelBuilder(value)) { var ret = value._toParamString({ buildParameterized: buildParameterized, nested: true }); formattedStr += ret.text; ret.values.forEach(function (value) { return formattedValues.push(value); }); } else { value = this._formatValueForParamArray(value, formattingOptions); if (_isArray(value)) { // Array(6) -> "(??, ??, ??, ??, ??, ??)" var tmpStr = value.map(function () { return paramChar; }).join(', '); formattedStr += "(".concat(tmpStr, ")"); value.forEach(function (val) { return formattedValues.push(val); }); } else { formattedStr += paramChar; formattedValues.push(value); } } } else { formattedStr += this._formatValueForQueryString(value, formattingOptions); } idx += paramChar.length; } else { formattedStr += str.charAt(idx); idx++; } } return { text: this._applyNestingFormatting(formattedStr, !!nested), values: formattedValues }; } /** * Build all given strings and their corresponding parameter values into * output. * * @param {Array} strings * @param {Array} strValues array of value arrays corresponding to each string. * @param {Object} [options] Additional options. * @param {Boolean} [options.buildParameterized] Whether to build paramterized string. Default is false. * @param {Boolean} [options.nested] Whether this expression is nested within another. * @return {Object} */ }, { key: "_buildManyStrings", value: function _buildManyStrings(strings, strValues) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var totalStr = [], totalValues = []; for (var idx = 0; strings.length > idx; ++idx) { var inputString = strings[idx], inputValues = strValues[idx]; var _this$_buildString = this._buildString(inputString, inputValues, { buildParameterized: options.buildParameterized, nested: false }), text = _this$_buildString.text, values = _this$_buildString.values; totalStr.push(text); values.forEach(function (value) { return totalValues.push(value); }); } totalStr = totalStr.join(this.options.separator); return { text: totalStr.length ? this._applyNestingFormatting(totalStr, !!options.nested) : '', values: totalValues }; } /** * Get parameterized representation of this instance. * * @param {Object} [options] Options. * @param {Boolean} [options.buildParameterized] Whether to build paramterized string. Default is false. * @param {Boolean} [options.nested] Whether this expression is nested within another. * @return {Object} */ }, { key: "_toParamString", value: function _toParamString(options) { throw new Error('Not yet implemented'); } /** * Get the expression string. * @return {String} */ }, { key: "toString", value: function toString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return this._toParamString(options).text; } /** * Get the parameterized expression string. * @return {Object} */ }, { key: "toParam", value: function toParam() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return this._toParamString(_extend({}, options, { buildParameterized: true })); } }]); return _class2; }(cls.Cloneable); /* # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- # cls.Expressions # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- */ /** * An SQL expression builder. * * SQL expressions are used in WHERE and ON clauses to filter data by various criteria. * * Expressions can be nested. Nested expression contains can themselves * contain nested expressions. When rendered a nested expression will be * fully contained within brackets. * * All the build methods in this object return the object instance for chained method calling purposes. */ cls.Expression = /*#__PURE__*/function (_cls$BaseBuilder) { _inherits(_class3, _cls$BaseBuilder); var _super2 = _createSuper(_class3); // Initialise the expression. function _class3(options) { var _this4; _classCallCheck(this, _class3); _this4 = _super2.call(this, options); _this4._nodes = []; return _this4; } // Combine the current expression with the given expression using the intersection operator (AND). _createClass(_class3, [{ key: "and", value: function and(expr) { expr = this._sanitizeExpression(expr); for (var _len2 = arguments.length, params = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { params[_key2 - 1] = arguments[_key2]; } this._nodes.push({ type: 'AND', expr: expr, para: params }); return this; } // Combine the current expression with the given expression using the union operator (OR). }, { key: "or", value: function or(expr) { expr = this._sanitizeExpression(expr); for (var _len3 = arguments.length, params = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { params[_key3 - 1] = arguments[_key3]; } this._nodes.push({ type: 'OR', expr: expr, para: params }); return this; } }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var totalStr = [], totalValues = []; var _iterator3 = _createForOfIteratorHelper(this._nodes), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var node = _step3.value; var type = node.type, expr = node.expr, para = node.para; var _ref = cls.isSquelBuilder(expr) ? expr._toParamString({ buildParameterized: options.buildParameterized, nested: true }) : this._buildString(expr, para, { buildParameterized: options.buildParameterized }), text = _ref.text, values = _ref.values; if (totalStr.length) { totalStr.push(type); } totalStr.push(text); values.forEach(function (value) { return totalValues.push(value); }); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } totalStr = totalStr.join(' '); return { text: this._applyNestingFormatting(totalStr, !!options.nested), values: totalValues }; } }]); return _class3; }(cls.BaseBuilder); /* # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- # cls.Case # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- */ /** * An SQL CASE expression builder. * * SQL cases are used to select proper values based on specific criteria. */ cls.Case = /*#__PURE__*/function (_cls$BaseBuilder2) { _inherits(_class4, _cls$BaseBuilder2); var _super3 = _createSuper(_class4); function _class4(fieldName) { var _this5; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, _class4); _this5 = _super3.call(this, options); if (_isPlainObject(fieldName)) { options = fieldName; fieldName = null; } if (fieldName) { _this5._fieldName = _this5._sanitizeField(fieldName); } _this5.options = _extend({}, cls.DefaultQueryBuilderOptions, options); _this5._cases = []; _this5._elseValue = null; return _this5; } _createClass(_class4, [{ key: "when", value: function when(expression) { for (var _len4 = arguments.length, values = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { values[_key4 - 1] = arguments[_key4]; } this._cases.unshift({ expression: expression, values: values || [] }); return this; } }, { key: "then", value: function then(result) { if (this._cases.length == 0) { throw new Error("when() needs to be called first"); } this._cases[0].result = result; return this; } }, { key: "else", value: function _else(elseValue) { this._elseValue = elseValue; return this; } }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var totalStr = '', totalValues = []; var _iterator4 = _createForOfIteratorHelper(this._cases), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _step4$value = _step4.value, expression = _step4$value.expression, values = _step4$value.values, result = _step4$value.result; totalStr = _pad(totalStr, ' '); var ret = this._buildString(expression, values, { buildParameterized: options.buildParameterized, nested: true }); totalStr += "WHEN ".concat(ret.text, " THEN ").concat(this._formatValueForQueryString(result)); ret.values.forEach(function (value) { return totalValues.push(value); }); } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } if (totalStr.length) { totalStr += " ELSE ".concat(this._formatValueForQueryString(this._elseValue), " END"); if (this._fieldName) { totalStr = "".concat(this._fieldName, " ").concat(totalStr); } totalStr = "CASE ".concat(totalStr); } else { totalStr = this._formatValueForQueryString(this._elseValue); } return { text: totalStr, values: totalValues }; } }]); return _class4; }(cls.BaseBuilder); /* # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- # Building blocks # --------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------- */ /* # A building block represents a single build-step within a query building process. # # Query builders consist of one or more building blocks which get run in a particular order. Building blocks can # optionally specify methods to expose through the query builder interface. They can access all the input data for # the query builder and manipulate it as necessary, as well as append to the final query string output. # # If you wish to customize how queries get built or add proprietary query phrases and content then it is recommended # that you do so using one or more custom building blocks. # # Original idea posted in https://github.com/hiddentao/export/issues/10#issuecomment-15016427 */ cls.Block = /*#__PURE__*/function (_cls$BaseBuilder3) { _inherits(_class5, _cls$BaseBuilder3); var _super4 = _createSuper(_class5); function _class5(options) { _classCallCheck(this, _class5); return _super4.call(this, options); } /** # Get input methods to expose within the query builder. # # By default all methods except the following get returned: # methods prefixed with _ # constructor and toString() # # @return Object key -> function pairs */ _createClass(_class5, [{ key: "exposedMethods", value: function exposedMethods() { var ret = {}; var obj = this; while (obj) { Object.getOwnPropertyNames(obj).forEach(function (prop) { if ('constructor' !== prop && typeof obj[prop] === "function" && prop.charAt(0) !== '_' && !cls.Block.prototype[prop]) { ret[prop] = obj[prop]; } }); obj = Object.getPrototypeOf(obj); } ; return ret; } }]); return _class5; }(cls.BaseBuilder); // A fixed string which always gets output cls.StringBlock = /*#__PURE__*/function (_cls$Block) { _inherits(_class6, _cls$Block); var _super5 = _createSuper(_class6); function _class6(options, str) { var _this6; _classCallCheck(this, _class6); _this6 = _super5.call(this, options); _this6._str = str; return _this6; } _createClass(_class6, [{ key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return { text: this._str, values: [] }; } }]); return _class6; }(cls.Block); // A function string block cls.FunctionBlock = /*#__PURE__*/function (_cls$Block2) { _inherits(_class7, _cls$Block2); var _super6 = _createSuper(_class7); function _class7(options) { var _this7; _classCallCheck(this, _class7); _this7 = _super6.call(this, options); _this7._strings = []; _this7._values = []; return _this7; } _createClass(_class7, [{ key: "function", value: function _function(str) { this._strings.push(str); for (var _len5 = arguments.length, values = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { values[_key5 - 1] = arguments[_key5]; } this._values.push(values); } }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return this._buildManyStrings(this._strings, this._values, options); } }]); return _class7; }(cls.Block); // value handler for FunctionValueBlock objects cls.registerValueHandler(cls.FunctionBlock, function (value) { var asParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return asParam ? value.toParam() : value.toString(); }); /* # Table specifier base class */ cls.AbstractTableBlock = /*#__PURE__*/function (_cls$Block3) { _inherits(_class8, _cls$Block3); var _super7 = _createSuper(_class8); /** * @param {Boolean} [options.singleTable] If true then only allow one table spec. * @param {String} [options.prefix] String prefix for output. */ function _class8(options, prefix) { var _this8; _classCallCheck(this, _class8); _this8 = _super7.call(this, options); _this8._tables = []; return _this8; } /** # Update given table. # # An alias may also be specified for the table. # # Concrete subclasses should provide a method which calls this */ _createClass(_class8, [{ key: "_table", value: function _table(table) { var alias = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; alias = alias ? this._sanitizeTableAlias(alias) : alias; table = this._sanitizeTable(table); if (this.options.singleTable) { this._tables = []; } this._tables.push({ table: table, alias: alias }); } // get whether a table has been set }, { key: "_hasTable", value: function _hasTable() { return 0 < this._tables.length; } /** * @override */ }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var totalStr = '', totalValues = []; if (this._hasTable()) { // retrieve the parameterised queries var _iterator5 = _createForOfIteratorHelper(this._tables), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var _step5$value = _step5.value, table = _step5$value.table, alias = _step5$value.alias; totalStr = _pad(totalStr, ', '); var tableStr = void 0; if (cls.isSquelBuilder(table)) { var _table$_toParamString = table._toParamString({ buildParameterized: options.buildParameterized, nested: true }), text = _table$_toParamString.text, values = _table$_toParamString.values; tableStr = text; values.forEach(function (value) { return totalValues.push(value); }); } else { tableStr = this._formatTableName(table); } if (alias) { tableStr += " ".concat(this._formatTableAlias(alias)); } totalStr += tableStr; } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } if (this.options.prefix) { totalStr = "".concat(this.options.prefix, " ").concat(totalStr); } } return { text: totalStr, values: totalValues }; } }]); return _class8; }(cls.Block); // target table for DELETE queries, DELETE <??> FROM cls.TargetTableBlock = /*#__PURE__*/function (_cls$AbstractTableBlo) { _inherits(_class9, _cls$AbstractTableBlo); var _super8 = _createSuper(_class9); function _class9() { _classCallCheck(this, _class9); return _super8.apply(this, arguments); } _createClass(_class9, [{ key: "target", value: function target(table) { this._table(table); } }]); return _class9; }(cls.AbstractTableBlock); // Update Table cls.UpdateTableBlock = /*#__PURE__*/function (_cls$AbstractTableBlo2) { _inherits(_class10, _cls$AbstractTableBlo2); var _super9 = _createSuper(_class10); function _class10() { _classCallCheck(this, _class10); return _super9.apply(this, arguments); } _createClass(_class10, [{ key: "table", value: function table(_table2) { var alias = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; this._table(_table2, alias); } }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (!this._hasTable()) { throw new Error("table() needs to be called"); } return _get(_getPrototypeOf(_class10.prototype), "_toParamString", this).call(this, options); } }]); return _class10; }(cls.AbstractTableBlock); // FROM table cls.FromTableBlock = /*#__PURE__*/function (_cls$AbstractTableBlo3) { _inherits(_class11, _cls$AbstractTableBlo3); var _super10 = _createSuper(_class11); function _class11(options) { _classCallCheck(this, _class11); return _super10.call(this, _extend({}, options, { prefix: 'FROM' })); } _createClass(_class11, [{ key: "from", value: function from(table) { var alias = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; this._table(table, alias); } }]); return _class11; }(cls.AbstractTableBlock); // INTO table cls.IntoTableBlock = /*#__PURE__*/function (_cls$AbstractTableBlo4) { _inherits(_class12, _cls$AbstractTableBlo4); var _super11 = _createSuper(_class12); function _class12(options) { _classCallCheck(this, _class12); return _super11.call(this, _extend({}, options, { prefix: 'INTO', singleTable: true })); } _createClass(_class12, [{ key: "into", value: function into(table) { this._table(table); } }, { key: "_toParamString", value: function _toParamString() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (!this._hasTable()) { throw new Error("into() needs to be called"); } return _get(_getPrototypeOf(_class12.prototype), "_toParamString", this).call(this, options); } }]); return _class12; }(cls.AbstractTableBlock); // (SELECT) Get field cls.GetFieldBlock = /*#__PURE__*/function (_cls$Block4) { _inherits(_class13, _cls$Block4); var _super12 = _createSuper(_class13); function _class13(options) { var _this9; _classCallCheck(this, _class13); _this9 = _super12.call(this, options); _this9._fields = []; return _this9; } /** # Add the given fields to the final result set. # # The parameter is an Object containing field names (or database functions) as the keys and aliases for the fields # as the values. If the value for a key is null then no alias is set for that field. # # Internally this method simply calls the field() method of this block to add each individual field. # # options.ignorePeriodsForFieldNameQuotes - whether to ignore period (.) when automatically quoting the field name */ _createClass(_class13, [{ key: "fields", value: function fields(_fields) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (_isArray(_fields)) { var _iterator6 = _createForOfIteratorHelper(_fields), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var field = _step6.value; this.field(field, null, options); } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } } else { for (var _field2 in _fields) { var alias = _fields[_field2]; this.field(_field2, alias, options); } } } /** # Add the given field to the final result set. # # The 'field' parameter does not necessarily have to be a fieldname. It can use database functions too, # e.g. DATE_FORMAT(a.started, "%H") # # An alias may also be specified for this field. # # options.ignorePeriodsForFieldNameQuotes - whether to ignore period (.) when automatically quoting the field name */ }, { key: "field", value: function field(_field) { var alias = arguments.length > 1 && ar