UNPKG

libpiggy

Version:

Use a PostgreSQL database like a JSON document store.

122 lines (88 loc) 3.16 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _assert = require('assert'); var _assert2 = _interopRequireDefault(_assert); var _isNumber = require('lodash/isNumber'); var _isNumber2 = _interopRequireDefault(_isNumber); var _map = require('lodash/fp/map'); var _map2 = _interopRequireDefault(_map); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const getFieldParts = function (fieldName) { // E.g., foo.bar.baz[0] -> ['foo', 'bar', 'baz', 0] return fieldName.split(/[.|[]/).map(v => v.search(']') > -1 ? Number(v.replace(']', '')) : v); }; const getIndexPath = function (field) { const fieldParts = getFieldParts(field); return fieldParts.join('_'); }; const getJsonPath = function (field, type, columnNames) { // Quote the strings const fieldPartsRaw = getFieldParts(field); const fieldParts = fieldPartsRaw.map(p => (0, _isNumber2.default)(p) ? p : `'${p}'`); let jsonPath; if (type === 'object') { jsonPath = `("${columnNames.val}" -> ${fieldParts.join(' -> ')})`; } if (type === 'text' || type === 'integer') { const fieldLast = fieldParts.pop(); if (fieldParts.length) { jsonPath = `("${columnNames.val}" -> ${fieldParts.join(' -> ')} ->> ${fieldLast})`; } else { jsonPath = `("${columnNames.val}" ->> ${fieldLast})`; } } if (type === 'integer') { jsonPath = `(${jsonPath}::integer)`; } return jsonPath; }; const getIndexesQueryText = function ({ table, columnNames, indexes }) { const text = (0, _map2.default)(index => { const { field, type, unique, lower } = index; if (field === 'key' || field === 'val') { _assert2.default.fail(false, `'key' and 'val' are not valid indexes`); } const indexPath = getIndexPath(field); let jsonPath = getJsonPath(field, type, columnNames); if (lower) { jsonPath = `lower(${jsonPath})`; } const indexName = `${table}_${columnNames.val}_${indexPath}_idx`; return ` CREATE ${unique ? 'UNIQUE' : ''} INDEX IF NOT EXISTS "${indexName}" ON "${table}" (${jsonPath}); `; }, indexes); return text.join(''); }; const createIndexes = (() => { var _ref = (0, _asyncToGenerator3.default)(function* (options = {}) { const { client, table, indexes, columnNames } = options; try { // The primary gin index with jsonb_path_ops let text = ` CREATE INDEX IF NOT EXISTS "${table}_${columnNames.val}_idx" ON "${table}" USING gin ("${columnNames.val}" jsonb_path_ops); `; // Secondary indexes if (indexes && indexes.length) { text += getIndexesQueryText({ table, columnNames, indexes }); } const results = yield client.query({ text }); return { client, results }; } catch (error) { throw error; } }); return function createIndexes() { return _ref.apply(this, arguments); }; })(); exports.default = createIndexes;