UNPKG

fxsql

Version:

Functional query builder based on fxjs

213 lines (186 loc) 8.96 kB
"use strict"; var _mapInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/map"); var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter"); var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports.default = load_ljoin; var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/assign")); var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of")); var _fxjs = require("fxjs"); var _pluralize = _interopRequireDefault(require("pluralize")); const { singular } = _pluralize.default; async function load_ljoin({ ready_sqls, add_column, tag, connection_info, QUERY, IN, EQ, COLUMN, CL, TB, SQL, SQLS }) { const table_columns = {}; const add_as_join = (me, as) => { var _context; return COLUMN(...(0, _fxjs.go)((0, _concat.default)(_context = me.column.originals).call(_context, (0, _fxjs.pluck)('left_key', me.left_joins)), (0, _mapInstanceProperty(_fxjs))(c => me.as + '.' + c + ' AS ' + `${as}>_<${c}`), _fxjs.uniq)); }; (0, _assign.default)(table_columns, await (0, _fxjs.go)(QUERY` SELECT table_name, column_name FROM information_schema.columns WHERE table_name in ( SELECT tablename FROM pg_tables WHERE tableowner=${connection_info.user || process.env.PGUSER} ) ORDER BY table_name;`, (0, _fxjs.groupBy)(v => v.table_name), (0, _mapInstanceProperty(_fxjs))(v => (0, _fxjs.pluck)('column_name', v))), await (0, _fxjs.go)(QUERY` SELECT * FROM INFORMATION_SCHEMA.view_column_usage WHERE view_catalog=${connection_info.database || process.env.PGDATABASE} ;`, (0, _fxjs.groupBy)(v => v.view_name), (0, _mapInstanceProperty(_fxjs))(v => (0, _fxjs.pluck)('column_name', v)))); function where_in_query(left, where_in, QUERY) { var _context2; const colums = (0, _fxjs.uniq)((0, _concat.default)(_context2 = add_column(left).originals).call(_context2, left.key)); const query = left.query(); if (query && query.text) query.text = query.text.replace(/^\s*WHERE/i, 'AND'); return left.row_number.length == 2 ? QUERY` SELECT * FROM ( SELECT ${COLUMN(...colums)}, ROW_NUMBER() OVER (PARTITION BY ${CL(left.key)} ORDER BY ${left.row_number[1]}) as "--row_number--" FROM ${TB(left.table)} AS ${TB(left.as)} ${where_in || tag()} ) AS "--row_number_table--" WHERE "--row_number_table--"."--row_number--"<=${left.row_number[0]}` : QUERY` SELECT ${CL(...colums)} FROM ${TB(left.table)} AS ${TB(left.as)} ${where_in || tag()} ${tag(query)} `; } function left_join_query(left, where_in, QUERY) { var _context3; let i = 0; left.lj_as = 'lj' + i++ + '//' + left.depth; const first_col = (0, _concat.default)(_context3 = add_as_join(left, left.lj_as).originals).call(_context3, left.as + '.id' + ' AS ' + `${left.lj_as}>_<id`); if (left.key) first_col.push(left.as + '.' + left.key + ' AS ' + `${left.lj_as}>_<${left.key}`); const join_columns = [first_col]; const join_sqls = []; return (0, _fxjs.go)(left, function recur(me) { me.left_join_over = true; (0, _fxjs.each)(right => { var _context4, _context5; const query = right.query(); right.lj_as = 'lj' + i++ + '//' + right.depth; if (query && query.text) query.text = query.text.replace(/^\s*WHERE/i, 'AND'); join_columns.push((0, _fxjs.uniq)((0, _concat.default)(_context4 = (0, _concat.default)(_context5 = add_as_join(right, right.lj_as).originals).call(_context5, right.as + '.' + right.key + ' AS ' + `${right.lj_as}>_<${right.key}`)).call(_context4, right.as + '.id' + ' AS ' + `${right.lj_as}>_<id`))); join_sqls.push(SQL` LEFT JOIN ${TB(right.table)} AS ${TB(right.as)} ON ${EQ({ [me.as + '.' + right.left_key]: COLUMN(right.as + '.' + right.key) })} ${tag(query)} `); recur(right); }, me.left_joins); }, () => { const query = left.query(); if (!query) return query; query.text = query.text.replace(/^\s*WHERE/i, where_in ? 'AND' : 'WHERE'); return query; }, query => left.row_number.length == 2 ? QUERY` SELECT "--row_number_table--".* FROM ( SELECT ${COLUMN(...(0, _fxjs.flatten)(join_columns))}, ROW_NUMBER() OVER (PARTITION BY ${CL(left.as + '.' + left.key)} ORDER BY ${left.row_number[1]}) as "--row_number--" FROM ${TB(left.table)} AS ${TB(left.as)} ${SQLS(join_sqls)} ${where_in || tag()} ${tag(query)} ) AS "--row_number_table--" WHERE "--row_number_table--"."--row_number--"<=${left.row_number[0]}` : QUERY` SELECT ${COLUMN(...(0, _fxjs.flatten)(join_columns))} FROM ${TB(left.table)} AS ${TB(left.as)} ${SQLS(join_sqls)} ${where_in || tag()} ${tag(query)}`, left.row_number.length == 2 ? (0, _mapInstanceProperty(_fxjs))(r => delete r['--row_number--'] && r) : r => r, (0, _mapInstanceProperty(_fxjs))(row => { const before_result_obj = {}; const result_obj = {}; for (const as in row) { if ((0, _indexOf.default)(as).call(as, '>_<') == -1) return; const split_as = as.split('>_<'); var tas = split_as[0]; before_result_obj[tas] = before_result_obj[tas] || { _: {} }; before_result_obj[tas][split_as[1]] = row[as]; } !function recur(me, memo) { memo[me.as] = before_result_obj[me.lj_as]; (0, _fxjs.each)(right => recur(right, memo[me.as]._), me.left_joins); }(left, result_obj); return result_obj[left.as]; })); } return function (QUERY) { return async function ljoin(strs, ...tails) { return (0, _fxjs.go)(ready_sqls(strs, tails), _fxjs.flatten, (0, _filterInstanceProperty(_fxjs))(t => t.as), (0, _fxjs.each)(option => { option.query = option.query || tag(); option.table = option.table || (option.rel_type == '-' ? option.as + 's' : option.as); option.column = option.column || CL(...table_columns[option.table]); option.left_joins = []; option.rels = []; option.row_number = option.row_number || []; }), ([left, ...rest]) => { const cur = [left]; (0, _fxjs.each)(me => { while (!((0, _fxjs.last)(cur).depth < me.depth)) cur.pop(); const left = (0, _fxjs.last)(cur); if (me.rel_type == '-') { me.left_key = me.left_key || (me.is_poly ? 'id' : singular(me.table) + '_id'); me.key = me.key || (me.is_poly ? 'attached_id' : 'id'); left.left_joins.push(me); } else { me.left_key = me.left_key || 'id'; me.key = me.key || (me.is_poly ? 'attached_id' : singular(left.table) + '_id'); } left.rels.push(me); me.poly_type = me.is_poly ? SQL`AND ${EQ((0, _fxjs.isString)(me.poly_type) ? { attached_type: me.poly_type || left.table } : me.poly_type)}` : tag(); cur.push(me); }, rest); return left; }, async left => [left, left.left_joins.length ? await left_join_query(left, null, QUERY) : await QUERY` SELECT ${add_column(left)} FROM ${TB(left.table)} AS ${TB(left.as)} ${left.query}`], function recur([left, results]) { if ((0, _fxjs.reject)(r => r, results).length) return; return (0, _fxjs.go)(left.rels, (0, _fxjs.mapC)(async function (me) { const f_key_ids = (0, _fxjs.uniq)((0, _filterInstanceProperty(_fxjs))(r => !!r, (0, _fxjs.pluck)(me.left_key, results))); if (me.rel_type == '-' || !f_key_ids.length) return recur([me, (0, _fxjs.flatten)((0, _mapInstanceProperty(_fxjs))(r => r._ ? r._[me.as] : null, results))]); return (0, _fxjs.go)((!me.left_join_over && me.left_joins.length ? left_join_query : where_in_query)(me, SQL`WHERE ${IN(me.as + '.' + me.key, f_key_ids)}`, QUERY), (0, _fxjs.groupBy)(v => v[me.key]), function (groups) { (0, _fxjs.each)(function (result) { result._ = result._ || {}; result._[me.as] = groups[result[me.left_key]] || []; }, results); return recur([me, (0, _fxjs.flatten)((0, _mapInstanceProperty(_fxjs))(r => r._ ? r._[me.as] : null, results))]); }); }), () => results); }); }; }; }