UNPKG

refql

Version:

A Node.js and Deno library for composing and running SQL queries.

129 lines (128 loc) 5.31 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const consts_1 = require("../common/consts"); const Raw_1 = __importDefault(require("../SQLTag/Raw")); const sql_1 = require("../SQLTag/sql"); const Values_1 = __importDefault(require("../SQLTag/Values")); const Table_1 = require("../Table"); const RefField_1 = __importDefault(require("./RefField")); const RQLNode_1 = require("./RQLNode"); const type = "refql/RefNode"; const prototype = Object.assign({}, RQLNode_1.rqlNodePrototype, { [consts_1.refqlType]: type, joinLateral }); function RefNode(tag, refProp, parent, options) { let refNode = Object.create(prototype); const { as, rel, child, refInput } = refProp; const refOf = RefField_1.default.refFieldOf(as); let info = { parent, as }; let single = false; function getRef(refs, table, type, fallback) { return refs && refs.length > 0 ? refs.map((ref, idx) => refOf(table, type + (idx + 1), ref)) : [refOf(table, type + "1", options.toCase(fallback))]; } switch (rel) { case "BelongsTo": info.lRef = getRef(refInput.lRef, parent, "lref", `${child.name}_id`); info.rRef = getRef(refInput.rRef, child, "rref", "id"); single = true; break; case "HasOne": info.lRef = getRef(refInput.lRef, parent, "lref", "id"); info.rRef = getRef(refInput.rRef, child, "rref", `${parent.name}_id`); single = true; break; case "HasMany": info.lRef = getRef(refInput.lRef, parent, "lref", "id"); info.rRef = getRef(refInput.rRef, child, "rref", `${parent.name}_id`); break; case "BelongsToMany": const btmInput = refInput; const xTable = typeof btmInput.xTable === "undefined" ? (0, Table_1.TableX)(parent.name < child.name ? `${parent.name}_${child.name}` : `${child.name}_${parent.name}`, []) : (0, Table_1.TableX)(btmInput.xTable, []); Object.assign(info, { xTable, lRef: getRef(btmInput.lRef, parent, "lref", "id"), rRef: getRef(btmInput.rRef, child, "rref", "id"), lxRef: getRef(btmInput.lxRef, xTable, "lxref", `${parent.name}_id`), rxRef: getRef(btmInput.rxRef, xTable, "rxref", `${child.name}_id`) }); break; } refNode.info = info; refNode.single = single; refNode.tag = tag; return refNode; } function joinLateral() { if (this.info.xTable) { const { rRef, lRef, xTable, rxRef, lxRef, parent } = this.info; const l1 = lRef.reduce((acc, lr, idx) => { const kw = idx === 0 ? "where" : "and"; return acc.concat((0, sql_1.sqlX) ` ${(0, Raw_1.default)(`${kw} ${lr.name}`)} in ${(0, Values_1.default)(p => [...new Set(p.refQLRows.map(r => r[lr.as]))])} `); }, (0, sql_1.sqlX) ` select distinct ${(0, Raw_1.default)(lRef.join(", "))} from ${(0, Raw_1.default)(parent)} `); const l2Join = rRef.reduce((acc, rr, idx) => { const kw = idx === 0 ? "on" : "and"; const rxr = rxRef[idx]; return acc.concat((0, sql_1.sqlX) ` ${(0, Raw_1.default)(`${kw} ${rxr.name} = ${rr.name}`)} `); }, (0, sql_1.sqlX) `join ${(0, Raw_1.default)(xTable)}`); const l2where = lRef.reduce((acc, lr, idx) => { const kw = idx === 0 ? "where" : "and"; const lxr = lxRef[idx]; return acc.concat((0, sql_1.sqlX) ` ${(0, Raw_1.default)(`${kw} ${lxr.name} = refqll1.${lr.as}`)} `); }, (0, sql_1.sqlX) ``); const { tag: l2, next } = this.tag.interpret(l2Join.concat(l2where)); const joined = (0, sql_1.sqlX) ` select * from (${l1}) refqll1, lateral (${l2}) refqll2 `; this.tag.interpreted = { tag: joined, next }; return this.tag; } else { const { rRef, lRef, parent } = this.info; const l1 = lRef.reduce((acc, lr, idx) => { const kw = idx === 0 ? "where" : "and"; return acc.concat((0, sql_1.sqlX) ` ${(0, Raw_1.default)(`${kw} ${lr.name}`)} in ${(0, Values_1.default)(p => [...new Set(p.refQLRows.map(r => r[lr.as]))])} `); }, (0, sql_1.sqlX) ` select distinct ${(0, Raw_1.default)(lRef.join(", "))} from ${(0, Raw_1.default)(parent)} `); const { tag: l2, next } = this.tag.interpret(lRef.reduce((acc, lr, idx) => { const rr = rRef[idx]; const kw = idx === 0 ? "where" : "and"; return acc.concat((0, sql_1.sqlX) ` ${(0, Raw_1.default)(`${kw} ${rr.name} = refqll1.${lr.as}`)} `); }, (0, sql_1.sqlX) ``)); const joined = (0, sql_1.sqlX) ` select * from (${l1}) refqll1, lateral (${l2}) refqll2 `; this.tag.interpreted = { tag: joined, next }; return this.tag; } } RefNode.isRefNode = function (x) { return x != null && x[consts_1.refqlType] === type; }; exports.default = RefNode;