lupdo
Version:
Database Abstraction Layer for Node js
309 lines (308 loc) • 10.9 kB
JavaScript
"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;