UNPKG

@odatnurd/d1-query

Version:
1,500 lines (1,469 loc) 886 kB
// node-sql-parser (sqlite) - v5.3.12-62e472f - 2025-09-24T21:38:56.717Z function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { writable: false }), e; } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var n = 0, F = function () {}; return { s: F, n: function () { return n >= r.length ? { done: true } : { done: false, value: r[n++] }; }, e: function (r) { throw r; }, 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 o, a = true, u = false; return { s: function () { t = t.call(r); }, n: function () { var r = t.next(); return a = r.done, r; }, e: function (r) { u = true, o = r; }, f: function () { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e; } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } // const escapeMap = { // '\0' : '\\0', // '\'' : '\\\'', // '"' : '\\"', // '\b' : '\\b', // '\n' : '\\n', // '\r' : '\\r', // '\t' : '\\t', // '\x1a' : '\\Z', // // '\\' : '\\\\', // } var DEFAULT_OPT = { database: "sqlite", type: 'table', trimQuery: true, parseOptions: { includeLocations: false } }; var parserOpt = DEFAULT_OPT; function commonOptionConnector(keyword, action, opt) { if (!opt) return; if (!keyword) return action(opt); return "".concat(keyword.toUpperCase(), " ").concat(action(opt)); } function connector(keyword, str) { if (!str) return; return "".concat(keyword.toUpperCase(), " ").concat(str); } /** * @param {(Array|boolean|string|number|null)} value * @return {Object} */ function createValueExpr(value) { var type = _typeof(value); if (Array.isArray(value)) return { type: 'expr_list', value: value.map(createValueExpr) }; if (value === null) return { type: 'null', value: null }; switch (type) { case 'boolean': return { type: 'bool', value: value }; case 'string': return { type: 'string', value: value }; case 'number': return { type: 'number', value: value }; default: throw new Error("Cannot convert value \"".concat(type, "\" to SQL")); } } /** * @param operator * @param left * @param right * @return {Object} */ function createBinaryExpr(operator, left, right) { var expr = { operator: operator, type: 'binary_expr' }; expr.left = left.type ? left : createValueExpr(left); if (operator === 'BETWEEN' || operator === 'NOT BETWEEN') { expr.right = { type: 'expr_list', value: [createValueExpr(right[0]), createValueExpr(right[1])] }; return expr; } expr.right = right.type ? right : createValueExpr(right); return expr; } /** * Replace param expressions * * @param {Object} ast - AST object * @param {Object} keys - Keys = parameter names, values = parameter values * @return {Object} - Newly created AST object */ function replaceParamsInner(ast, keys) { Object.keys(ast).filter(function (key) { var value = ast[key]; return Array.isArray(value) || _typeof(value) === 'object' && value !== null; }).forEach(function (key) { var expr = ast[key]; if (!(_typeof(expr) === 'object' && expr.type === 'param')) return replaceParamsInner(expr, keys); if (typeof keys[expr.value] === 'undefined') throw new Error("no value for parameter :".concat(expr.value, " found")); ast[key] = createValueExpr(keys[expr.value]); return null; }); return ast; } function escape(str) { return str; // const res = [] // for (let i = 0, len = str.length; i < len; ++i) { // let char = str[i] // const escaped = escapeMap[char] // if (escaped) char = escaped // res.push(char) // } // return res.join('') } function getParserOpt() { return parserOpt; } function setParserOpt(opt) { parserOpt = opt; } function topToSQL(opt) { if (!opt) return; var value = opt.value, percent = opt.percent, parentheses = opt.parentheses; var val = parentheses ? "(".concat(value, ")") : value; var prefix = "TOP ".concat(val); if (!percent) return prefix; return "".concat(prefix, " ").concat(percent.toUpperCase()); } function columnIdentifierToSql(ident) { var _getParserOpt = getParserOpt(), database = _getParserOpt.database; if (!ident) return; switch (database && database.toLowerCase()) { case 'athena': case 'db2': case 'postgresql': case 'redshift': case 'snowflake': case 'noql': case 'trino': case 'sqlite': return "\"".concat(ident, "\""); case 'transactsql': return "[".concat(ident, "]"); case 'mysql': case 'mariadb': case 'bigquery': default: return "`".concat(ident, "`"); } } function identifierToSql(ident, isDual, surround) { if (isDual === true) return "'".concat(ident, "'"); if (!ident) return; if (ident === '*') return ident; if (surround) return "".concat(surround).concat(ident).concat(surround); var _getParserOpt2 = getParserOpt(), database = _getParserOpt2.database; switch (database && database.toLowerCase()) { case 'mysql': case 'mariadb': return "`".concat(ident, "`"); case 'athena': case 'postgresql': case 'redshift': case 'snowflake': case 'trino': case 'noql': case 'sqlite': return "\"".concat(ident, "\""); case 'transactsql': return "[".concat(ident, "]"); case 'bigquery': case 'db2': return ident; default: return "`".concat(ident, "`"); } } function toUpper(val) { if (!val) return; return val.toUpperCase(); } function hasVal(val) { return val; } function literalToSQL(literal) { if (!literal) return; var prefix = literal.prefix; var type = literal.type, parentheses = literal.parentheses, suffix = literal.suffix, value = literal.value; var str = _typeof(literal) === 'object' ? value : literal; switch (type) { case 'backticks_quote_string': str = "`".concat(escape(value), "`"); break; case 'string': str = "'".concat(escape(value), "'"); break; case 'regex_string': str = "r\"".concat(escape(value), "\""); break; case 'hex_string': str = "X'".concat(escape(value), "'"); break; case 'full_hex_string': str = "0x".concat(escape(value)); break; case 'natural_string': str = "N'".concat(escape(value), "'"); break; case 'bit_string': str = "b'".concat(escape(value), "'"); break; case 'double_quote_string': str = "\"".concat(escape(value), "\""); break; case 'single_quote_string': str = "'".concat(value, "'"); break; case 'boolean': case 'bool': str = value ? 'TRUE' : 'FALSE'; break; case 'null': str = 'NULL'; break; case 'star': str = '*'; break; case 'param': str = "".concat(prefix || ':').concat(value); prefix = null; break; case 'origin': str = value.toUpperCase(); break; case 'date': case 'datetime': case 'time': case 'timestamp': str = "".concat(type.toUpperCase(), " '").concat(value, "'"); break; case 'var_string': str = "N'".concat(escape(value), "'"); break; case 'unicode_string': str = "U&'".concat(escape(value), "'"); break; } var result = []; if (prefix) result.push(toUpper(prefix)); result.push(str); if (suffix) { if (typeof suffix === 'string') result.push(suffix); if (_typeof(suffix) === 'object') { if (suffix.collate) result.push(collateToSQL(suffix.collate));else result.push(literalToSQL(suffix)); } } str = result.join(' '); return parentheses ? "(".concat(str, ")") : str; } function commonTypeValue(opt) { if (!opt) return []; var type = opt.type, symbol = opt.symbol, value = opt.value; return [type.toUpperCase(), symbol, typeof value === 'string' ? value.toUpperCase() : literalToSQL(value)].filter(hasVal); } function replaceParams(ast, params) { return replaceParamsInner(JSON.parse(JSON.stringify(ast)), params); } function onPartitionsToSQL(expr) { var type = expr.type, partitions = expr.partitions; var result = [toUpper(type), "(".concat(partitions.map(function (partition) { var partitionType = partition.type; if (!(partitionType === 'range')) return literalToSQL(partition); var start = partition.start, end = partition.end, symbol = partition.symbol; return "".concat(literalToSQL(start), " ").concat(toUpper(symbol), " ").concat(literalToSQL(end)); }).join(', '), ")")]; return result.join(' '); } function dataTypeToSQL(expr) { var schema = expr.schema, dataType = expr.dataType, length = expr.length, parentheses = expr.parentheses, scale = expr.scale, suffix = expr.suffix; var str = ''; if (length != null) str = scale ? "".concat(length, ", ").concat(scale) : length; if (parentheses) str = "(".concat(str, ")"); if (suffix && suffix.length) str += " ".concat(suffix.join(' ')); var prefix = schema ? "".concat(schema, ".") : ''; return "".concat(prefix).concat(dataType).concat(str); } function arrayStructTypeToSQL(expr) { if (!expr) return; var dataType = expr.dataType, definition = expr.definition, anglebracket = expr.anglebracket; var dataTypeUpper = toUpper(dataType); var isNotArrayOrStruct = dataTypeUpper !== 'ARRAY' && dataTypeUpper !== 'STRUCT'; if (isNotArrayOrStruct) return dataTypeUpper; var result = definition && definition.map(function (field) { var fieldName = field.field_name, fieldType = field.field_type; var fieldResult = [fieldName, arrayStructTypeToSQL(fieldType)]; return fieldResult.filter(hasVal).join(' '); }).join(', '); return anglebracket ? "".concat(dataTypeUpper, "<").concat(result, ">") : "".concat(dataTypeUpper, " ").concat(result); } function commentToSQL(comment) { if (!comment) return; var result = []; var keyword = comment.keyword, symbol = comment.symbol, value = comment.value; result.push(keyword.toUpperCase()); if (symbol) result.push(symbol); result.push(literalToSQL(value)); return result.join(' '); } function triggerEventToSQL(events) { return events.map(function (event) { var eventKw = event.keyword, args = event.args; var result = [toUpper(eventKw)]; if (args) { var kwArgs = args.keyword, columns = args.columns; result.push(toUpper(kwArgs), columns.map(columnRefToSQL).join(', ')); } return result.join(' '); }).join(' OR '); } function returningToSQL(returning) { if (!returning) return ''; var columns = returning.columns; return ['RETURNING', columns.map(columnToSQL).filter(hasVal).join(', ')].join(' '); } function commonKeywordArgsToSQL(kwArgs) { if (!kwArgs) return []; return [toUpper(kwArgs.keyword), toUpper(kwArgs.args)]; } function autoIncrementToSQL(autoIncrement) { if (!autoIncrement) return; if (typeof autoIncrement === 'string') { var _getParserOpt3 = getParserOpt(), database = _getParserOpt3.database; switch (database && database.toLowerCase()) { case 'sqlite': return 'AUTOINCREMENT'; default: return 'AUTO_INCREMENT'; } } var keyword = autoIncrement.keyword, seed = autoIncrement.seed, increment = autoIncrement.increment, parentheses = autoIncrement.parentheses; var result = toUpper(keyword); if (parentheses) result += "(".concat(literalToSQL(seed), ", ").concat(literalToSQL(increment), ")"); return result; } function columnOrderListToSQL(columnOrderList) { if (!columnOrderList) return; return columnOrderList.map(columnOrderToSQL).filter(hasVal).join(', '); } var util = /*#__PURE__*/Object.freeze({ __proto__: null, DEFAULT_OPT: DEFAULT_OPT, arrayStructTypeToSQL: arrayStructTypeToSQL, autoIncrementToSQL: autoIncrementToSQL, columnIdentifierToSql: columnIdentifierToSql, columnOrderListToSQL: columnOrderListToSQL, commentToSQL: commentToSQL, commonKeywordArgsToSQL: commonKeywordArgsToSQL, commonOptionConnector: commonOptionConnector, commonTypeValue: commonTypeValue, connector: connector, createBinaryExpr: createBinaryExpr, createValueExpr: createValueExpr, dataTypeToSQL: dataTypeToSQL, escape: escape, getParserOpt: getParserOpt, hasVal: hasVal, identifierToSql: identifierToSql, literalToSQL: literalToSQL, onPartitionsToSQL: onPartitionsToSQL, replaceParams: replaceParams, returningToSQL: returningToSQL, setParserOpt: setParserOpt, toUpper: toUpper, topToSQL: topToSQL, triggerEventToSQL: triggerEventToSQL }); function indexTypeToSQL(indexType) { if (!indexType) return []; var keyword = indexType.keyword, type = indexType.type; return [keyword.toUpperCase(), toUpper(type)]; } function indexOptionToSQL(indexOpt) { if (!indexOpt) return; var type = indexOpt.type, expr = indexOpt.expr, symbol = indexOpt.symbol; var upperType = type.toUpperCase(); var indexOptArray = []; indexOptArray.push(upperType); switch (upperType) { case 'KEY_BLOCK_SIZE': if (symbol) indexOptArray.push(symbol); indexOptArray.push(literalToSQL(expr)); break; case 'BTREE': case 'HASH': indexOptArray.length = 0; indexOptArray.push.apply(indexOptArray, _toConsumableArray(indexTypeToSQL(indexOpt))); break; case 'WITH PARSER': indexOptArray.push(expr); break; case 'VISIBLE': case 'INVISIBLE': break; case 'COMMENT': indexOptArray.shift(); indexOptArray.push(commentToSQL(indexOpt)); break; case 'DATA_COMPRESSION': indexOptArray.push(symbol, toUpper(expr.value), onPartitionsToSQL(expr.on)); break; default: indexOptArray.push(symbol, literalToSQL(expr)); break; } return indexOptArray.filter(hasVal).join(' '); } function indexOptionListToSQL(indexOptList) { if (!indexOptList) return []; return indexOptList.map(indexOptionToSQL); } function indexTypeAndOptionToSQL(indexDefinition) { var constraintType = indexDefinition.constraint_type, indexType = indexDefinition.index_type, _indexDefinition$inde = indexDefinition.index_options, indexOptions = _indexDefinition$inde === void 0 ? [] : _indexDefinition$inde, definition = indexDefinition.definition, on = indexDefinition.on, withExpr = indexDefinition["with"]; var dataType = []; dataType.push.apply(dataType, _toConsumableArray(indexTypeToSQL(indexType))); if (definition && definition.length) { var definitionSQL = toUpper(constraintType) === 'CHECK' ? "(".concat(exprToSQL(definition[0]), ")") : "(".concat(definition.map(function (col) { return exprToSQL(col); }).join(', '), ")"); dataType.push(definitionSQL); } dataType.push(indexOptionListToSQL(indexOptions).join(' ')); if (withExpr) dataType.push("WITH (".concat(indexOptionListToSQL(withExpr).join(', '), ")")); if (on) dataType.push("ON [".concat(on, "]")); return dataType; } function indexDefinitionToSQL(indexDefinition) { var indexSQL = []; var keyword = indexDefinition.keyword, index = indexDefinition.index; indexSQL.push(toUpper(keyword)); indexSQL.push(index); indexSQL.push.apply(indexSQL, _toConsumableArray(indexTypeAndOptionToSQL(indexDefinition))); return indexSQL.filter(hasVal).join(' '); } function binaryToSQL(expr) { var operator = expr.operator || expr.op; var rstr = exprToSQL(expr.right); var isBetween = false; if (Array.isArray(rstr)) { switch (operator) { case '=': operator = 'IN'; break; case '!=': operator = 'NOT IN'; break; case 'BETWEEN': case 'NOT BETWEEN': isBetween = true; rstr = "".concat(rstr[0], " AND ").concat(rstr[1]); break; } if (!isBetween) rstr = "(".concat(rstr.join(', '), ")"); } var escape = expr.right.escape || {}; var leftPart = Array.isArray(expr.left) ? expr.left.map(exprToSQL).join(', ') : exprToSQL(expr.left); var str = [leftPart, operator, rstr, toUpper(escape.type), exprToSQL(escape.value)].filter(hasVal).join(operator === '.' ? '' : ' '); var result = [expr.parentheses ? "(".concat(str, ")") : str]; return result.join(' '); } function analyzeToSQL(stmt) { var type = stmt.type, table = stmt.table; var action = toUpper(type); var tableName = tableToSQL(table); return [action, tableName].join(' '); } function attachToSQL(stmt) { var type = stmt.type, database = stmt.database, expr = stmt.expr, as = stmt.as, schema = stmt.schema; return [toUpper(type), toUpper(database), exprToSQL(expr), toUpper(as), identifierToSql(schema)].filter(hasVal).join(' '); } function commentOptionToSQL(stmt) { var name = stmt.name, type = stmt.type; switch (type) { case 'table': case 'view': var fullTableName = [identifierToSql(name.db), identifierToSql(name.table)].filter(hasVal).join('.'); return "".concat(toUpper(type), " ").concat(fullTableName); case 'column': return "COLUMN ".concat(columnRefToSQL(name)); default: return "".concat(toUpper(type), " ").concat(literalToSQL(name)); } } function commentIsExprToSQL(stmt) { var keyword = stmt.keyword, expr = stmt.expr; return [toUpper(keyword), literalToSQL(expr)].filter(hasVal).join(' '); } function commentOnToSQL(stmt) { var expr = stmt.expr, keyword = stmt.keyword, target = stmt.target, type = stmt.type; var result = [toUpper(type), toUpper(keyword), commentOptionToSQL(target), commentIsExprToSQL(expr)]; return result.filter(hasVal).join(' '); } function composePrefixValSuffix(stmt) { if (!stmt) return []; return [stmt.prefix.map(literalToSQL).join(' '), exprToSQL(stmt.value), stmt.suffix.map(literalToSQL).join(' ')]; } function fetchOffsetToSQL(stmt) { var fetch = stmt.fetch, offset = stmt.offset; var result = [].concat(_toConsumableArray(composePrefixValSuffix(offset)), _toConsumableArray(composePrefixValSuffix(fetch))); return result.filter(hasVal).join(' '); } function limitOffsetToSQL(limit) { var seperator = limit.seperator, value = limit.value; if (value.length === 1 && seperator === 'offset') return connector('OFFSET', exprToSQL(value[0])); return connector('LIMIT', value.map(exprToSQL).join("".concat(seperator === 'offset' ? ' ' : '').concat(toUpper(seperator), " "))); } function limitToSQL(limit) { if (!limit) return ''; if (limit.fetch || limit.offset) return fetchOffsetToSQL(limit); return limitOffsetToSQL(limit); } /** * @param {Array<Object>} withExpr */ function withToSQL(withExpr) { if (!withExpr || withExpr.length === 0) return; var isRecursive = withExpr[0].recursive ? 'RECURSIVE ' : ''; var withExprStr = withExpr.map(function (cte) { var name = cte.name, stmt = cte.stmt, columns = cte.columns; var column = Array.isArray(columns) ? "(".concat(columns.map(columnRefToSQL).join(', '), ")") : ''; var expr = commonOptionConnector(stmt.type === 'values' ? 'VALUES' : '', exprToSQL, stmt); return "".concat(name.type === 'default' ? identifierToSql(name.value) : literalToSQL(name)).concat(column, " AS (").concat(expr, ")"); }).join(', '); return "WITH ".concat(isRecursive).concat(withExprStr); } function distinctToSQL(distinct) { if (!distinct) return; if (typeof distinct === 'string') return distinct; var type = distinct.type, columns = distinct.columns; var result = [toUpper(type)]; if (columns) result.push("(".concat(columns.map(exprToSQL).join(', '), ")")); return result.filter(hasVal).join(' '); } function selectIntoToSQL(into) { if (!into) return; var position = into.position; if (!position) return; var keyword = into.keyword, expr = into.expr; var result = []; var intoType = toUpper(keyword); switch (intoType) { case 'VAR': result.push(expr.map(varToSQL).join(', ')); break; default: result.push(intoType, typeof expr === 'string' ? identifierToSql(expr) : exprToSQL(expr)); } return result.filter(hasVal).join(' '); } /** * @param {Object} stmt * @param {?Array} stmt.with * @param {?Array} stmt.options * @param {?string} stmt.distinct * @param {?Array|string} stmt.columns * @param {?Array} stmt.from * @param {?Object} stmt.where * @param {?Array} stmt.groupby * @param {?Object} stmt.having * @param {?Array} stmt.orderby * @param {?Array} stmt.limit * @return {string} */ function forXmlToSQL(stmt) { if (!stmt) return; var expr = stmt.expr, keyword = stmt.keyword, type = stmt.type; var result = [toUpper(type), toUpper(keyword)]; if (!expr) return result.join(' '); return "".concat(result.join(' '), "(").concat(exprToSQL(expr), ")"); } function selectToSQL(stmt) { var asStructVal = stmt.as_struct_val, columns = stmt.columns, collate = stmt.collate, distinct = stmt.distinct, forXml = stmt["for"], from = stmt.from, _stmt$for_sys_time_as = stmt.for_sys_time_as_of, forSystem = _stmt$for_sys_time_as === void 0 ? {} : _stmt$for_sys_time_as, lockingRead = stmt.locking_read, groupby = stmt.groupby, having = stmt.having, _stmt$into = stmt.into, into = _stmt$into === void 0 ? {} : _stmt$into, isolation = stmt.isolation, limit = stmt.limit, options = stmt.options, orderby = stmt.orderby, parentheses = stmt.parentheses_symbol, qualify = stmt.qualify, top = stmt.top, windowInfo = stmt.window, withInfo = stmt["with"], where = stmt.where; var clauses = [withToSQL(withInfo), 'SELECT', toUpper(asStructVal)]; if (Array.isArray(options)) clauses.push(options.join(' ')); clauses.push(distinctToSQL(distinct), topToSQL(top), columnsToSQL(columns, from)); var position = into.position; var intoSQL = ''; if (position) intoSQL = commonOptionConnector('INTO', selectIntoToSQL, into); if (position === 'column') clauses.push(intoSQL); // FROM + joins clauses.push(commonOptionConnector('FROM', tablesToSQL, from)); if (position === 'from') clauses.push(intoSQL); var _ref = forSystem || {}, keyword = _ref.keyword, expr = _ref.expr; clauses.push(commonOptionConnector(keyword, exprToSQL, expr)); clauses.push(commonOptionConnector('WHERE', exprToSQL, where)); if (groupby) { clauses.push(connector('GROUP BY', getExprListSQL(groupby.columns).join(', '))); clauses.push(getExprListSQL(groupby.modifiers).join(', ')); } clauses.push(commonOptionConnector('HAVING', exprToSQL, having)); clauses.push(commonOptionConnector('QUALIFY', exprToSQL, qualify)); clauses.push(commonOptionConnector('WINDOW', exprToSQL, windowInfo)); clauses.push(orderOrPartitionByToSQL(orderby, 'order by')); clauses.push(collateToSQL(collate)); clauses.push(limitToSQL(limit)); if (isolation) clauses.push(commonOptionConnector(isolation.keyword, literalToSQL, isolation.expr)); clauses.push(toUpper(lockingRead)); if (position === 'end') clauses.push(intoSQL); clauses.push(forXmlToSQL(forXml)); var sql = clauses.filter(hasVal).join(' '); return parentheses ? "(".concat(sql, ")") : sql; } function explainToSQL(stmt) { var type = stmt.type, expr = stmt.expr; return [toUpper(type), selectToSQL(expr)].join(' '); } function deleteToSQL(stmt) { var columns = stmt.columns, from = stmt.from, table = stmt.table, where = stmt.where, orderby = stmt.orderby, withInfo = stmt["with"], limit = stmt.limit, returning = stmt.returning; var clauses = [withToSQL(withInfo), 'DELETE']; var columnInfo = columnsToSQL(columns, from); clauses.push(columnInfo); if (Array.isArray(table)) { if (!(table.length === 1 && table[0].addition === true)) clauses.push(tablesToSQL(table)); } clauses.push(commonOptionConnector('FROM', tablesToSQL, from)); clauses.push(commonOptionConnector('WHERE', exprToSQL, where)); clauses.push(orderOrPartitionByToSQL(orderby, 'order by')); clauses.push(limitToSQL(limit)); clauses.push(returningToSQL(returning)); return clauses.filter(hasVal).join(' '); } /** * @param {Array} sets * @return {string} */ function setToSQL(sets) { if (!sets || sets.length === 0) return ''; var clauses = []; var _iterator = _createForOfIteratorHelper(sets), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var set = _step.value; var column = {}; var value = set.value; for (var key in set) { if (key === 'value' || key === 'keyword') continue; column[key] = set[key]; } var str = columnRefToSQL(column); var setItem = [str]; var val = ''; if (value) { val = exprToSQL(value); setItem.push('=', val); } clauses.push(setItem.filter(hasVal).join(' ')); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return clauses.join(', '); } function updateToSQL(stmt) { var from = stmt.from, table = stmt.table, set = stmt.set, where = stmt.where, orderby = stmt.orderby, withInfo = stmt["with"], limit = stmt.limit, returning = stmt.returning; var clauses = [withToSQL(withInfo), 'UPDATE', tablesToSQL(table), commonOptionConnector('SET', setToSQL, set), commonOptionConnector('FROM', tablesToSQL, from), commonOptionConnector('WHERE', exprToSQL, where), orderOrPartitionByToSQL(orderby, 'order by'), limitToSQL(limit), returningToSQL(returning)]; return clauses.filter(hasVal).join(' '); } function execVariablesToSQL(stmt) { var name = stmt.name, value = stmt.value; var result = ["@".concat(name), '=', exprToSQL(value)]; return result.filter(hasVal).join(' '); } function execToSQL(stmt) { var keyword = stmt.keyword, module = stmt.module, parameters = stmt.parameters; var result = [toUpper(keyword), tableToSQL(module), (parameters || []).map(execVariablesToSQL).filter(hasVal).join(', ')]; return result.filter(hasVal).join(' '); } function loadDataFields(expr) { if (!expr) return ''; var keyword = expr.keyword, terminated = expr.terminated, enclosed = expr.enclosed, escaped = expr.escaped; return [toUpper(keyword), literalToSQL(terminated), literalToSQL(enclosed), literalToSQL(escaped)].filter(hasVal).join(' '); } function loadDataLines(expr) { if (!expr) return ''; var keyword = expr.keyword, starting = expr.starting, terminated = expr.terminated; return [toUpper(keyword), literalToSQL(starting), literalToSQL(terminated)].filter(hasVal).join(' '); } function loadDataIgnore(expr) { if (!expr) return ''; var count = expr.count, suffix = expr.suffix; return ['IGNORE', literalToSQL(count), suffix].filter(hasVal).join(' '); } function loadDataToSQL(expr) { if (!expr) return ''; var mode = expr.mode, local = expr.local, file = expr.file, replace_ignore = expr.replace_ignore, table = expr.table, partition = expr.partition, character_set = expr.character_set, column = expr.column, fields = expr.fields, lines = expr.lines, set = expr.set, ignore = expr.ignore; var result = ['LOAD DATA', toUpper(mode), toUpper(local), 'INFILE', literalToSQL(file), toUpper(replace_ignore), 'INTO TABLE', tableToSQL(table), partitionToSQL(partition), commonOptionConnector('CHARACTER SET', literalToSQL, character_set), loadDataFields(fields), loadDataLines(lines), loadDataIgnore(ignore), columnsToSQL(column), commonOptionConnector('SET', setToSQL, set)]; return result.filter(hasVal).join(' '); } function assignToSQL(expr) { /** @type {Object} */ var left = expr.left, right = expr.right, symbol = expr.symbol, keyword = expr.keyword; left.keyword = keyword; var leftVar = exprToSQL(left); var rightVal = exprToSQL(right); return [leftVar, toUpper(symbol), rightVal].filter(hasVal).join(' '); } function returnToSQL(stmt) { var type = stmt.type, expr = stmt.expr; return [toUpper(type), exprToSQL(expr)].join(' '); } function procToSQL(expr) { var stmt = expr.stmt; switch (stmt.type) { case 'assign': return assignToSQL(stmt); case 'return': return returnToSQL(stmt); } } function transactionToSQL(stmt) { var _stmt$expr = stmt.expr, action = _stmt$expr.action, keyword = _stmt$expr.keyword, modes = _stmt$expr.modes; var result = [literalToSQL(action), toUpper(keyword)]; if (modes) result.push(modes.map(literalToSQL).join(', ')); return result.filter(hasVal).join(' '); } function showEventToSQL(showEventExpr) { var inClause = showEventExpr["in"], from = showEventExpr.from, limit = showEventExpr.limit; return [commonOptionConnector('IN', literalToSQL, inClause && inClause.right), commonOptionConnector('FROM', tablesToSQL, from), limitToSQL(limit)].filter(hasVal).join(' '); } function showLikeAndWhereToSQL(showCharacterSetExpr) { var expr = showCharacterSetExpr.expr; if (!expr) return; var op = expr.op; if (toUpper(op) === 'LIKE') return commonOptionConnector('LIKE', literalToSQL, expr.right); return commonOptionConnector('WHERE', exprToSQL, expr); } function showGrantsForUser(showGrantsForExpr) { var forExpr = showGrantsForExpr["for"]; if (!forExpr) return; var user = forExpr.user, host = forExpr.host, role_list = forExpr.role_list; var userAndHost = "'".concat(user, "'"); if (host) userAndHost += "@'".concat(host, "'"); return ['FOR', userAndHost, role_list && 'USING', role_list && role_list.map(function (role) { return "'".concat(role, "'"); }).join(', ')].filter(hasVal).join(' '); } function showToSQL(showExpr) { var keyword = showExpr.keyword; var suffix = showExpr.suffix; var str = ''; switch (toUpper(keyword)) { case 'BINLOG': str = showEventToSQL(showExpr); break; case 'CHARACTER': case 'COLLATION': str = showLikeAndWhereToSQL(showExpr); break; case 'COLUMNS': case 'INDEXES': case 'INDEX': str = commonOptionConnector('FROM', tablesToSQL, showExpr.from); break; case 'GRANTS': str = showGrantsForUser(showExpr); break; case 'CREATE': str = commonOptionConnector('', tableToSQL, showExpr[suffix]); break; case 'VAR': str = varToSQL(showExpr["var"]); keyword = ''; break; } return ['SHOW', toUpper(keyword), toUpper(suffix), str].filter(hasVal).join(' '); } var typeToSQLFn = { alter: alterToSQL, analyze: analyzeToSQL, attach: attachToSQL, create: createToSQL, comment: commentOnToSQL, select: selectToSQL, deallocate: deallocateToSQL, "delete": deleteToSQL, exec: execToSQL, execute: executeToSQL, explain: explainToSQL, "for": forLoopToSQL, update: updateToSQL, "if": ifToSQL, insert: insertToSQL, load_data: loadDataToSQL, drop: commonCmdToSQL, truncate: commonCmdToSQL, replace: insertToSQL, declare: declareToSQL, use: useToSQL, rename: renameToSQL, call: callToSQL, desc: descToSQL, set: setVarToSQL, lock: lockUnlockToSQL, unlock: lockUnlockToSQL, show: showToSQL, grant: grantAndRevokeToSQL, revoke: grantAndRevokeToSQL, proc: procToSQL, raise: raiseToSQL, transaction: transactionToSQL }; function unionToSQL(stmt) { if (!stmt) return ''; var fun = typeToSQLFn[stmt.type]; var _stmt = stmt, _parentheses = _stmt._parentheses, _orderby = _stmt._orderby, _limit = _stmt._limit; var res = [_parentheses && '(', fun(stmt)]; while (stmt._next) { var nextFun = typeToSQLFn[stmt._next.type]; var unionKeyword = toUpper(stmt.set_op); res.push(unionKeyword, nextFun(stmt._next)); stmt = stmt._next; } res.push(_parentheses && ')', orderOrPartitionByToSQL(_orderby, 'order by'), limitToSQL(_limit)); return res.filter(hasVal).join(' '); } function multipleToSQL(stmt) { var res = []; for (var i = 0, len = stmt.length; i < len; ++i) { var astInfo = stmt[i] && stmt[i].ast ? stmt[i].ast : stmt[i]; var sql = unionToSQL(astInfo); if (i === len - 1 && astInfo.type === 'transaction') sql = "".concat(sql, " ;"); res.push(sql); } return res.join(' ; '); } /** * @param {Array} stmt * @return {string} */ function valuesToSQL(stmt) { var type = stmt.type; if (type === 'select') return unionToSQL(stmt); var values = type === 'values' ? stmt.values : stmt; var clauses = values.map(function (value) { var sql = exprToSQL(value); return [toUpper(value.prefix), "(".concat(sql, ")")].filter(hasVal).join(''); }); return clauses.join(', '); } function partitionToSQL(partition) { if (!partition) return ''; var partitionArr = ['PARTITION', '(']; if (Array.isArray(partition)) { partitionArr.push(partition.map(function (partitionItem) { return identifierToSql(partitionItem); }).join(', ')); } else { var value = partition.value; partitionArr.push(value.map(exprToSQL).join(', ')); } partitionArr.push(')'); return partitionArr.filter(hasVal).join(''); } function conflictTargetToSQL(conflictTarget) { if (!conflictTarget) return ''; var type = conflictTarget.type; switch (type) { case 'column': return "(".concat(conflictTarget.expr.map(columnRefToSQL).join(', '), ")"); } } function conflictActionToSQL(conflictAction) { var expr = conflictAction.expr, keyword = conflictAction.keyword; var type = expr.type; var result = [toUpper(keyword)]; switch (type) { case 'origin': result.push(literalToSQL(expr)); break; case 'update': result.push('UPDATE', commonOptionConnector('SET', setToSQL, expr.set), commonOptionConnector('WHERE', exprToSQL, expr.where)); break; } return result.filter(hasVal).join(' '); } function conflictToSQL(conflict) { if (!conflict) return ''; var action = conflict.action, target = conflict.target; var result = [conflictTargetToSQL(target), conflictActionToSQL(action)]; return result.filter(hasVal).join(' '); } function insertToSQL(stmt) { var table = stmt.table, type = stmt.type, _stmt$or = stmt.or, orExpr = _stmt$or === void 0 ? [] : _stmt$or, _stmt$prefix = stmt.prefix, prefix = _stmt$prefix === void 0 ? 'into' : _stmt$prefix, columns = stmt.columns, conflict = stmt.conflict, values = stmt.values, where = stmt.where, onDuplicateUpdate = stmt.on_duplicate_update, partition = stmt.partition, returning = stmt.returning, set = stmt.set; var _ref = onDuplicateUpdate || {}, keyword = _ref.keyword, duplicateSet = _ref.set; var clauses = [toUpper(type), orExpr.map(literalToSQL).join(' '), toUpper(prefix), tablesToSQL(table), partitionToSQL(partition)]; if (Array.isArray(columns)) clauses.push("(".concat(columns.map(literalToSQL).join(', '), ")")); clauses.push(commonOptionConnector(values && values.type === 'values' ? 'VALUES' : '', valuesToSQL, values)); clauses.push(commonOptionConnector('ON CONFLICT', conflictToSQL, conflict)); clauses.push(commonOptionConnector('SET', setToSQL, set)); clauses.push(commonOptionConnector('WHERE', exprToSQL, where)); clauses.push(commonOptionConnector(keyword, setToSQL, duplicateSet)); clauses.push(returningToSQL(returning)); return clauses.filter(hasVal).join(' '); } function intervalToSQL(intervalExpr) { var expr = intervalExpr.expr, unit = intervalExpr.unit, suffix = intervalExpr.suffix; var result = ['INTERVAL', exprToSQL(expr), toUpper(unit), exprToSQL(suffix)]; return result.filter(hasVal).join(' '); } function unnestToSQL(unnestExpr) { var type = unnestExpr.type, as = unnestExpr.as, expr = unnestExpr.expr, withOffset = unnestExpr.with_offset; var result = ["".concat(toUpper(type), "(").concat(expr && exprToSQL(expr) || '', ")"), commonOptionConnector('AS', typeof as === 'string' ? identifierToSql : exprToSQL, as), commonOptionConnector(toUpper(withOffset && withOffset.keyword), identifierToSql, withOffset && withOffset.as)]; return result.filter(hasVal).join(' '); } function pivotOperatorToSQL(operator) { var as = operator.as, column = operator.column, expr = operator.expr, in_expr = operator.in_expr, type = operator.type; var result = [exprToSQL(expr), 'FOR', columnRefToSQL(column), binaryToSQL(in_expr)]; var sql = ["".concat(toUpper(type), "(").concat(result.join(' '), ")")]; if (as) sql.push('AS', identifierToSql(as)); return sql.join(' '); } function operatorToSQL(operator) { if (!operator) return; var type = operator.type; switch (type) { case 'pivot': case 'unpivot': return pivotOperatorToSQL(operator); default: return ''; } } function tableHintToSQL(tableHintExpr) { if (!tableHintExpr) return; var keyword = tableHintExpr.keyword, expr = tableHintExpr.expr, index = tableHintExpr.index, index_columns = tableHintExpr.index_columns, parentheses = tableHintExpr.parentheses, prefix = tableHintExpr.prefix; var result = []; switch (keyword.toLowerCase()) { case 'forceseek': result.push(toUpper(keyword), "(".concat(identifierToSql(index)), "(".concat(index_columns.map(exprToSQL).filter(hasVal).join(', '), "))")); break; case 'spatial_window_max_cells': result.push(toUpper(keyword), '=', exprToSQL(expr)); break; case 'index': result.push(toUpper(prefix), toUpper(keyword), parentheses ? "(".concat(expr.map(function (indexItem) { return identifierToSql(indexItem); }).join(', '), ")") : "= ".concat(identifierToSql(expr))); break; default: result.push(exprToSQL(expr)); } return result.filter(hasVal).join(' '); } function tableTumbleArgsToSQL(param, expr) { var name = param.name, symbol = param.symbol; return [toUpper(name), symbol, expr].filter(hasVal).join(' '); } function tableTumbleToSQL(tumble) { if (!tumble) return ''; var tableInfo = tumble.data, timecol = tumble.timecol, offset = tumble.offset, size = tumble.size; var fullTableName = [identifierToSql(tableInfo.expr.db), identifierToSql(tableInfo.expr.schema), identifierToSql(tableInfo.expr.table)].filter(hasVal).join('.'); var timeColSQL = "DESCRIPTOR(".concat(columnRefToSQL(timecol.expr), ")"); var result = ["TABLE(TUMBLE(TABLE ".concat(tableTumbleArgsToSQL(tableInfo, fullTableName)), tableTumbleArgsToSQL(timecol, timeColSQL)]; var sizeSQL = tableTumbleArgsToSQL(size, intervalToSQL(size.expr)); if (offset && offset.expr) result.push(sizeSQL, "".concat(tableTumbleArgsToSQL(offset, intervalToSQL(offset.expr)), "))"));else result.push("".concat(sizeSQL, "))")); return result.filter(hasVal).join(', '); } function temporalTableOptionToSQL(stmt) { var keyword = stmt.keyword; var result = []; switch (keyword) { case 'as': result.push('AS', 'OF', exprToSQL(stmt.of)); break; case 'from_to': result.push('FROM', exprToSQL(stmt.from), 'TO', exprToSQL(stmt.to)); break; case 'between_and': result.push('BETWEEN', exprToSQL(stmt.between), 'AND', exprToSQL(stmt.and)); break; case 'contained': result.push('CONTAINED', 'IN', exprToSQL(stmt["in"])); break; } return result.filter(hasVal).join(' '); } function temporalTableToSQL(stmt) { if (!stmt) return; var keyword = stmt.keyword, expr = stmt.expr; return [toUpper(keyword), temporalTableOptionToSQL(expr)].filter(hasVal).join(' '); } function generateVirtualTable(stmt) { var keyword = stmt.keyword, type = stmt.type, generators = stmt.generators; var generatorSQL = generators.map(function (generator) { return commonTypeValue(generator).join(' '); }).join(', '); return "".concat(toUpper(keyword), "(").concat(toUpper(type), "(").concat(generatorSQL, "))"); } function tableToSQL(tableInfo) { if (toUpper(tableInfo.type) === 'UNNEST') return unnestToSQL(tableInfo); var table = tableInfo.table, db = tableInfo.db, as = tableInfo.as, expr = tableInfo.expr, operator = tableInfo.operator, prefixStr = tableInfo.prefix, schema = tableInfo.schema, server = tableInfo.server, suffix = tableInfo.suffix, tablesample = tableInfo.tablesample, temporal_table = tableInfo.temporal_table, table_hint = tableInfo.table_hint, _tableInfo$surround = tableInfo.surround, surround = _tableInfo$surround === void 0 ? {} : _tableInfo$surround; var serverName = identifierToSql(server, false, surround.server); var database = identifierToSql(db, false, surround.db); var schemaStr = identifierToSql(schema, false, surround.schema); var tableName = table && identifierToSql(table, false, surround.table); if (expr) { var exprType = expr.type; switch (exprType) { case 'values': var parentheses = expr.parentheses, values = expr.values, prefix = expr.prefix; var valueSQL = [parentheses && '(', '', parentheses && ')']; var valuesExpr = valuesToSQL(values); if (prefix) valuesExpr = valuesExpr.split('(').slice(1).map(function (val) { return "".concat(toUpper(prefix), "(").concat(val); }).join(''); valueSQL[1] = "VALUES ".concat(valuesExpr); tableName = valueSQL.filter(hasVal).join(''); break; case 'tumble': tableName = tableTumbleToSQL(expr); break; case 'generator': tableName = generateVirtualTable(expr); break; default: tableName = exprToSQL(expr); } } tableName = [toUpper(prefixStr), tableName, toUpper(suffix)].filter(hasVal).join(' '); var str = [serverName, database, schemaStr, tableName].filter(hasVal).join('.'); var result = [str]; if (tablesample) { var tableSampleSQL = ['TABLESAMPLE', exprToSQL(tablesample.expr), literalToSQL(tablesample.repeatable)].filter(hasVal).join(' '); result.push(tableSampleSQL); } result.push(temporalTableToSQL(temporal_table), commonOptionConnector('AS', typeof as === 'string' ? identifierToSql : exprToSQL, as), operatorToSQL(operator)); if (table_hint) result.push(toUpper(table_hint.keyword), "(".concat(table_hint.expr.map(tableHintToSQL).filter(hasVal).join(', '), ")")); var tableSQL = result.filter(hasVal).join(' '); return tableInfo.parentheses ? "(".concat(tableSQL, ")") : tableSQL; } /** * @param {Array} tables * @return {string} */ function tablesToSQL(tables) { if (!tables) return ''; if (!Array.isArray(tables)) { var expr = tables.expr, parentheses = tables.parentheses, joins = tables.joins; var sql = tablesToSQL(expr); if (parentheses) { var leftParentheses = []; var rightParentheses = []; var parenthesesNumber = parentheses === true ? 1 : parentheses.length; var i = 0; while (i++ < parenthesesNumber) { leftParentheses.push('('); rightParentheses.push(')'); } var joinsSQL = joins && joins.length > 0 ? tablesToSQL([''].concat(_toConsumableArray(joins))) : ''; return leftParentheses.join('') + sql + rightParentheses.join('') + joinsSQL; } return sql; } var baseTable = tables[0]; var clauses = []; if (baseTable.type === 'dual') return 'DUAL'; clauses.push(tableToSQL(baseTable)); for (var _i = 1; _i < tables.length; ++_i) { var joinExpr = tables[_i]; var on = joinExpr.on, using = joinExpr.using, join = joinExpr.join; var str = []; var isTables = Array.isArray(joinExpr) || Object.hasOwnProperty.call(joinExpr, 'joins'); str.push(join ? " ".concat(toUpper(join)) : ','); str.push(isTables ? tablesToSQL(joinExpr) : tableToSQL(joinExpr)); str.push(commonOptionConnector('ON', exprToSQL, on)); if (using) str.push("USING (".concat(using.map(literalToSQL).join(', '), ")")); clauses.push(str.filter(hasVal).join(' ')); } return clauses.filter(hasVal).join(''); } function tableOptionToSQL(tableOption) { var keyword = tableOption.keyword, symbol = tableOption.symbol, value = tableOption.value; var sql = [keyword.toUpperCase()]; if (symbol) sql.push(symbol); var val = literalToSQL(value); switch (keyword) { case 'partition by': case 'default collate': val = exprToSQL(value); break; case 'options': val = "(".concat(value.map(function (tableOptionItem) { return [tableOptionItem.keyword, tableOptionItem.symbol, exprToSQL(tableOptionItem.value)].join(' '); }).join(', '), ")"); break; case 'cluster by': val = value.map(exprToSQL).join(', '); break; } sql.push(val); return sql.filter(hasVal).join(' '); } var supportedTypes = ['analyze', 'attach', 'select', 'deallocate', 'delete', 'exec', 'update', 'insert', 'drop', 'rename', 'truncate', 'call', 'desc', 'use', 'alter', 'set', 'create', 'lock', 'unlock', 'declare', 'show', 'replace', 'if', 'grant', 'revoke', 'proc', 'raise', 'execute', 'transaction', 'explain', 'comment', 'load_data']; function checkSupported(expr) { var ast = expr && expr.ast ? expr.ast : expr; if (!supportedTypes.includes(ast.type)) throw new Error("".concat(ast.type, " statements not supported at the moment")); } function toSQL(ast) { if (Array.isArray(ast)) { ast.forEach(checkSupported); return multipleToSQL(ast); } checkSupported(ast); return unionToSQL(ast); } function goToSQL(stmt) { if (!stmt || stmt.length === 0) return ''; var res = [toSQL(stmt.ast)]; if (stmt.go_next) res.push(stmt.go.toUpperCase(), goToSQL(stmt.go_next)); return res.filter(function (sqlItem) { return sqlItem; }).join(' '); } function astToSQL(ast) { var sql = ast.go === 'go' ? goToSQL(ast) : toSQL(ast); return sql; } function callToSQL(stmt) { var type = 'CALL'; var storeProcessCall = exprToSQL(stmt.expr); return "".concat(type, " ").concat(storeProcessCall); } function commonCmdToSQL(stmt) { var type = stmt.type, keyword = stmt.keyword, name = stmt.name, prefix = stmt.prefix, suffix = stmt.suffix; var clauses = [toUpper(type), toUpper(keyword), toUpper(prefix)]; switch (keyword) { case 'table': clauses.push(tablesToSQL(name)); break; case 'trigger': clauses.push([name[0].schema ? "".concat(identifierToSql(name[0].schema), ".") : '', identifierToSql(name[0].trigger)].filter(hasVal).join('')); break; case 'database': case 'schema': case 'procedure': clauses.push(identifierToSql(name)); break; case 'view': clauses.push(tablesToSQL(name), stmt.options && stmt.options.map(exprToSQL).filter(hasVal).join(' ')); break; case 'index': clauses.push.apply(clauses, [columnRefToSQL(name)].concat(_toConsumableArray(stmt.table ? ['ON', tableToSQL(stmt.table)] : []), [stmt.options && stmt.options.map(exprToSQL).filter(hasVal).join(' ')])); break; case 'type': clauses.push(name.map(columnRefToSQL).join(', '), stmt.options && stmt.options.map(exprToSQL).filter(hasVal).join(' ')); bre