UNPKG

lupdo

Version:

Database Abstraction Layer for Node js

309 lines (308 loc) 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PdoStatement = void 0; const constants_1 = require("../constants"); const pdo_error_1 = require("../errors/pdo-error"); const utils_1 = require("../utils"); class PdoStatement { constructor(connection, rawSql, affectingResults, selectResults, columns) { this.connection = connection; this.rawSql = rawSql; this.affectingResults = affectingResults; this.rawParams = null; this.params = null; this.cursor = null; this.rowset = 0; this.isRowset = false; this.currentSelectResults = []; this.currentColumns = []; this.sql = this.rawSql; this.columns = columns; this.selectResults = selectResults; this.resetRowset(); this.resetCursor(); this.setCurrentColumns(); this.setCurrentSelectResults(); } columnCount() { return this.currentColumns.length; } debug() { return `SQL: ${this.rawSql}\nPARAMS:${(0, utils_1.paramsToString)(this.rawParams ?? [], 2)}`; } debugSent() { return `PROCESSED SQL: ${this.sql}\nPARAMS:${(0, utils_1.paramsToString)(this.params ?? [], 2)}`; } getColumnMeta(column) { return this.currentColumns.length > column ? this.currentColumns[column] : null; } rowCount() { if (typeof this.affectingResults.affectedRows !== 'undefined') { return this.affectingResults.affectedRows; } return 0; } async lastInsertId(name) { return await this.connection.lastInsertId({ affectingResults: this.affectingResults, selectResults: this.currentSelectResults, columns: this.currentColumns, }, name); } getAttribute(attribute) { return this.connection.getAttribute(attribute); } setAttribute(attribute, value) { return this.connection.setAttribute(attribute, value); } fetchDictionary() { return this.fetched((row, columns) => { return row.reduce((carry, val, currentIndex) => { carry[columns[currentIndex]] = val; return carry; }, {}); }); } fetchArray() { return this.fetched((row) => { return row; }); } fetchBoth() { return this.fetched((row, columns) => { return row.reduce((carry, val, currentIndex) => { carry[currentIndex] = val; carry[columns[currentIndex]] = val; return carry; }, {}); }); } fetchColumn(column) { return this.fetched((row) => { if (row.length - 1 < column) { throw new pdo_error_1.default(`Column ${column} does not exists.`); } return row[column]; }); } fetchObject(abstract, constructorArgs) { return this.fetched((row, columns) => { const obj = new abstract(...(constructorArgs ?? [])); this.assignPropsToObj(obj, row, columns); return obj; }); } fetchClosure(fn) { return this.fetched((row) => { return fn(...row); }); } fecthNamed() { return this.fetched((row, columns, duplicatedColumns) => { return row.reduce((carry, val, currentIndex) => { const columnKey = columns[currentIndex]; if (duplicatedColumns.includes(columnKey)) { if (!(columnKey in carry)) { carry[columnKey] = []; } carry[columnKey].push(val); } else { carry[columnKey] = val; } return carry; }, {}); }, true); } fetchPair() { const columns = this.getCasedColumnsName(); if (columns.length !== 2) { throw new pdo_error_1.default(`With fetchPair(), query results must return 2 columns, [${columns.length}] provided`); } const map = new Map(); for (const row of this.fetchAll()) { map.set(row[0], row[1]); } return map; } resetCursor() { this.setCursor(null); } fetched(callable, withDuplicated = false) { return { get: () => { const row = this.fetch(); if (row === null) { return undefined; } return callable(this.getRowNulled(row), this.getCasedColumnsName(), withDuplicated ? this.getDuplicatedColumns() : []); }, all: () => { return this.fetchAll().map((row) => { return callable(this.getRowNulled(row), this.getCasedColumnsName(), withDuplicated ? this.getDuplicatedColumns() : []); }); }, group: () => { const columns = this.getCasedColumnsName(); const duplicated = this.getDuplicatedColumns(); const map = new Map(); for (const row of this.fetchAll()) { const key = row.shift(); const values = map.get(key) ?? []; values.push(callable(this.getRowNulled(row), columns, duplicated)); map.set(key, values); } return map; }, unique: () => { const columns = this.getCasedColumnsName(); const duplicated = this.getDuplicatedColumns(); const map = new Map(); for (const row of this.fetchAll()) { map.set(row.shift(), callable(this.getRowNulled(row), columns, duplicated)); } return map; }, [Symbol.iterator]() { return { next: () => { const row = this.get(); if (row == null) { return { done: true, value: undefined }; } return { done: false, value: row }; }, return: () => { return { done: true, value: undefined }; }, }; }, }; } getRowNulled(row) { const nullType = this.getAttribute(constants_1.ATTR_NULLS); return nullType === constants_1.NULL_NATURAL ? row : row.map((val) => { return val === null || (typeof val === 'string' && val === '') ? nullType === constants_1.NULL_EMPTY_STRING ? null : '' : val; }); } getCasedColumnsName() { const columnCase = this.getAttribute(constants_1.ATTR_CASE); return this.currentColumns.map((column) => { return (columnCase & constants_1.CASE_NATURAL) !== 0 ? column.name : (columnCase & constants_1.CASE_LOWER) !== 0 ? column.name.toLowerCase() : column.name.toUpperCase(); }); } getDuplicatedColumns() { return this.getCasedColumnsName().filter((element, index, array) => array.indexOf(element) !== index); } assignPropsToObj(obj, row, columns) { for (let x = 0; x < row.length; x++) { const key = columns[x]; if (key in obj) { const desc = Object.getOwnPropertyDescriptor(obj, key); if (desc === undefined) { if (typeof obj[key] === 'function') { throw new pdo_error_1.default(`[${obj.constructor.name}.prototype.${key}()] conflict with column name [${key}].`); } } } try { obj[key] = row[x]; } catch (error) { throw new pdo_error_1.default(error); } } } fetch() { const cursorOrientation = this.getAttribute(constants_1.ATTR_FETCH_DIRECTION); const cursor = this.getTempCursorForFetch(cursorOrientation); if (!this.isValidCursor(cursor, cursorOrientation)) { if (cursorOrientation === constants_1.FETCH_BACKWARD) { this.setCursorToStart(); } else { this.setCursorToEnd(); } return null; } this.setCursor(cursor); return this.currentSelectResults[cursor]; } fetchAll() { const cursorOrientation = this.getAttribute(constants_1.ATTR_FETCH_DIRECTION); const cursor = this.getTempCursorForFetch(cursorOrientation); if (cursorOrientation === constants_1.FETCH_BACKWARD) { this.setCursorToStart(); return this.currentSelectResults.slice(0, cursor + 1).reverse(); } this.setCursorToEnd(); return this.currentSelectResults.slice(cursor); } setCursor(cursor) { this.cursor = cursor; } setCursorToEnd() { this.setCursor(this.currentSelectResults.length); } setCursorToStart() { this.setCursor(-1); } getTempCursorForFetch(cursorOrientation) { let cursor = this.cursor; if (cursor === null) { cursor = cursorOrientation === constants_1.FETCH_BACKWARD ? this.currentSelectResults.length : -1; } return cursorOrientation === constants_1.FETCH_BACKWARD ? cursor - 1 : cursor + 1; } isValidCursor(cursor, cursorOrientation) { return cursorOrientation === constants_1.FETCH_BACKWARD ? cursor > -1 : cursor < this.currentSelectResults.length; } resetRowset() { this.rowset = 0; this.isRowset = Array.isArray(this.columns[0]); } setCurrentColumns() { this.currentColumns = this.isRowset ? this.columns[this.rowset] : this.columns; } setCurrentSelectResults() { this.currentSelectResults = this.isRowset ? this.selectResults[this.rowset] : this.selectResults; } nextRowset() { if (!this.isRowset) { return false; } else { if (this.selectResults.length > this.rowset + 1) { this.rowset++; this.resetCursor(); this.setCurrentColumns(); this.setCurrentSelectResults(); return true; } return false; } } } exports.PdoStatement = PdoStatement; exports.default = PdoStatement;