UNPKG

globalstorage

Version:

Global Storage is a Global Distributed Data Warehouse

267 lines (215 loc) 8.84 kB
'use strict'; function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _typeof(obj) { 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); } var _require = require('metaschema'), extractDecorator = _require.extractDecorator; var transformations = require('./transformations'); var escapeString = function escapeString(value) { var backslash = false; var escaped = "'"; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = value[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var character = _step.value; if (character === "'") { escaped += "''"; } else if (character === '\\') { escaped += '\\\\'; backslash = true; } else { escaped += character; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } escaped += "'"; return backslash ? " E".concat(escaped) : escaped; }; var escapeIdentifier = function escapeIdentifier(name) { return "\"".concat(name, "\""); }; var escapeKey = function escapeKey(key) { return key.split('.').map(function (k) { return k === '*' ? '*' : escapeIdentifier(k); }).join('.'); }; var escapeValue = function escapeValue(value) { var type = _typeof(value); if (type === 'number') return value; if (type === 'string') return escapeString(value); if (value instanceof Date) return "'".concat(value.toISOString(), "'"); throw new TypeError('Unsupported value (${value}) type'); }; var PREDEFINED_DOMAINS = { Time: 'time with time zone', DateDay: 'date', DateTime: 'timestamp with time zone', JSON: 'jsonb', Money: 'money' }; var IGNORED_DOMAINS = ['List', 'Enum', 'HashMap', 'HashSet']; // https://tools.ietf.org/html/rfc3629#section-3 var utf8bytesLastCodePoints = { 1: 0x007f, 2: 0x07ff, 3: 0xffff }; var utf8codePointSize = function utf8codePointSize(codePoint) { for (var byteCount = 1; byteCount <= 3; byteCount++) { if (codePoint <= utf8bytesLastCodePoints[byteCount]) { return byteCount; } } return 4; }; var asciiCP = { aToZLower: ['a'.codePointAt(0), 'z'.codePointAt(0)], aToZUpper: ['A'.codePointAt(0), 'Z'.codePointAt(0)], underscore: '_'.codePointAt(0), numbers: ['0'.codePointAt(0), '9'.codePointAt(0)], dollar: '$'.codePointAt(0) }; var classMapping = { Uint8Array: 'bytea', Date: 'timestamp with time zone', Uint64: 'bigint' }; // https://github.com/postgres/postgres/blob/5f6b0e6d69f1087847c8456b3f69761c950d52c6/src/backend/utils/adt/misc.c#L723 var isValidIdentifierStart = function isValidIdentifierStart(cp) { return cp === asciiCP.underscore || cp >= asciiCP.aToZLower[0] && cp <= asciiCP.aToZLower[1] || cp >= asciiCP.aToZUpper[0] && cp <= asciiCP.aToZUpper[1] || cp >= 0x80; }; // https://github.com/postgres/postgres/blob/5f6b0e6d69f1087847c8456b3f69761c950d52c6/src/backend/utils/adt/misc.c#L741 var isValidIdentifierCont = function isValidIdentifierCont(cp) { return cp >= asciiCP.numbers[0] && cp <= asciiCP.numbers[1] || cp === asciiCP.dollar || isValidIdentifierStart(cp); }; var singleUnitUtf16 = (1 << 16) - 1; // https://www.postgresql.org/docs/10/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS var isValidIdentifier = function isValidIdentifier(name) { var length = 0; for (var i = 0; i < name.length; i++) { var codePoint = name.codePointAt(i); if (i === 0) { if (!isValidIdentifierStart(codePoint)) { return false; } } else if (!isValidIdentifierCont(codePoint)) { return false; } length += utf8codePointSize(codePoint); if (codePoint > singleUnitUtf16) i++; } return length < 64; }; var validateIdentifier = function validateIdentifier(name, type) { var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; if (!isValidIdentifier(name)) { throw new Error("Cannot create ".concat(type, " ").concat(prefix).concat(name, " ") + 'because it is not a valid identifier'); } }; var generateQueryParams = function generateQueryParams(count) { var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var params = ''; for (var i = start; i < start + count; i++) { if (i !== start) { params += ', '; } params += "$".concat(i); } return params; }; var generateLinkQueryParams = function generateLinkQueryParams(count) { var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var params = ''; for (var i = start + 1; i < start + 1 + count; i++) { if (i !== start + 1) { params += ', '; } params += "($".concat(start, ", $").concat(i, ")"); } return params; }; var buildWhere = function buildWhere(query) { var constraints = transformations.constraints(query); var constraintsKeys = Object.keys(constraints); if (constraintsKeys.length === 0) { return ['', []]; } var params = new Array(constraintsKeys.length); return [' WHERE ' + constraintsKeys.map(function (key, i) { var _constraints$key = _slicedToArray(constraints[key], 2), cond = _constraints$key[0], value = _constraints$key[1]; params[i] = value; return "".concat(escapeKey(key), " ").concat(cond === '!' ? '!=' : cond, " $").concat(i + 1); }).join(' AND '), params]; }; var generateDeleteQuery = function generateDeleteQuery(category, includedCategories, query) { var escapedCategory = escapeIdentifier(category); var deleteQuery = "WITH ToDelete AS (SELECT ".concat(escapedCategory, ".\"Id\"") + " FROM ".concat(escapedCategory); includedCategories.forEach(function (category) { var includedCategory = escapeIdentifier(category); deleteQuery += " INNER JOIN ".concat(includedCategory, " ON") + " ".concat(escapedCategory, ".\"Id\" = ").concat(includedCategory, ".\"Id\""); }); var _buildWhere = buildWhere(query), _buildWhere2 = _slicedToArray(_buildWhere, 2), where = _buildWhere2[0], whereParams = _buildWhere2[1]; deleteQuery += where + ')'; includedCategories.forEach(function (category) { var includedCategory = escapeIdentifier(category); deleteQuery += ", ".concat(category, " AS (DELETE FROM ").concat(includedCategory) + ' WHERE "Id" IN (SELECT "Id" FROM ToDelete))'; }); deleteQuery += " DELETE FROM ".concat(escapedCategory) + ' WHERE "Id" IN (SELECT "Id" FROM ToDelete)'; return [deleteQuery, whereParams]; }; var fitInSchema = function fitInSchema(object, schema) { var result = {}; if (object.Id) { result.Id = object.Id; } for (var prop in schema) { var field = schema[prop]; var value = object[prop]; if (value !== undefined) { result[prop] = value; } else if (extractDecorator(field) === 'Include') { result[prop] = fitInSchema(object, field.definition); } } return result; }; var recreateIdTrigger = Symbol('recreateIdTrigger'); var uploadMetadata = Symbol('uploadMetadata'); module.exports = { escapeString: escapeString, escapeValue: escapeValue, escapeIdentifier: escapeIdentifier, escapeKey: escapeKey, PREDEFINED_DOMAINS: PREDEFINED_DOMAINS, IGNORED_DOMAINS: IGNORED_DOMAINS, isValidIdentifier: isValidIdentifier, validateIdentifier: validateIdentifier, generateQueryParams: generateQueryParams, generateLinkQueryParams: generateLinkQueryParams, buildWhere: buildWhere, generateDeleteQuery: generateDeleteQuery, classMapping: classMapping, fitInSchema: fitInSchema, symbols: { recreateIdTrigger: recreateIdTrigger, uploadMetadata: uploadMetadata } };