UNPKG

artmapper

Version:

A simple and intuitive ORM for Node.js with TypeScript and JavaScript support

248 lines 8.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueryBuilder = void 0; class QueryBuilder { constructor(definition, databaseType) { this.definition = definition; this.databaseType = databaseType; } /** * Build SELECT query */ buildSelect(options) { const { select, where, orderBy, limit, offset } = options || {}; const params = []; let sql = 'SELECT '; // Select fields if (select && select.length > 0) { sql += select.map(field => this.quoteField(field)).join(', '); } else { sql += '*'; } sql += ` FROM ${this.quoteTable(this.definition.table)}`; // WHERE clause if (where) { const whereClause = this.buildWhereClause(where, params); if (whereClause) { sql += ` WHERE ${whereClause}`; } } // ORDER BY if (orderBy) { sql += this.buildOrderByClause(orderBy); } // LIMIT and OFFSET if (limit) { sql += ` LIMIT ${limit}`; if (offset) { sql += ` OFFSET ${offset}`; } } return { sql, params }; } /** * Build INSERT query */ buildInsert(data) { const fields = Object.keys(data); const values = Object.values(data); const placeholders = this.getPlaceholders(fields.length); const sql = `INSERT INTO ${this.quoteTable(this.definition.table)} (${fields.map(field => this.quoteField(field)).join(', ')}) VALUES (${placeholders})`; return { sql, params: values }; } /** * Build UPDATE query */ buildUpdate(id, data) { const params = []; const setClause = Object.keys(data) .map(field => `${this.quoteField(field)} = ${this.getPlaceholder()}`) .join(', '); params.push(...Object.values(data)); params.push(id); const sql = `UPDATE ${this.quoteTable(this.definition.table)} SET ${setClause} WHERE ${this.quoteField('id')} = ${this.getPlaceholder()}`; return { sql, params }; } /** * Build DELETE query */ buildDelete(id) { const sql = `DELETE FROM ${this.quoteTable(this.definition.table)} WHERE ${this.quoteField('id')} = ${this.getPlaceholder()}`; return { sql, params: [id] }; } /** * Build COUNT query */ buildCount(options) { const { where } = options || {}; const params = []; let sql = `SELECT COUNT(*) as count FROM ${this.quoteTable(this.definition.table)}`; if (where) { const whereClause = this.buildWhereClause(where, params); if (whereClause) { sql += ` WHERE ${whereClause}`; } } return { sql, params }; } /** * Build CREATE TABLE query */ buildCreateTable() { const fields = Object.entries(this.definition.fields) .map(([name, field]) => this.buildFieldDefinition(name, field)) .join(',\n '); return `CREATE TABLE IF NOT EXISTS ${this.quoteTable(this.definition.table)} (\n ${fields}\n)`; } /** * Build DROP TABLE query */ buildDropTable() { return `DROP TABLE IF EXISTS ${this.quoteTable(this.definition.table)}`; } /** * Build WHERE clause */ buildWhereClause(where, params) { const conditions = []; for (const [field, value] of Object.entries(where)) { if (value === null) { conditions.push(`${this.quoteField(field)} IS NULL`); } else { conditions.push(`${this.quoteField(field)} = ${this.getPlaceholder()}`); params.push(value); } } return conditions.join(' AND '); } /** * Build ORDER BY clause */ buildOrderByClause(orderBy) { const clauses = Object.entries(orderBy) .map(([field, direction]) => `${this.quoteField(field)} ${direction}`) .join(', '); return ` ORDER BY ${clauses}`; } /** * Build field definition for CREATE TABLE */ buildFieldDefinition(name, field) { let definition = `${this.quoteField(name)} ${this.mapFieldType(field.type)}`; if (field.length) { definition += `(${field.length})`; } if (!field.nullable || field.notNull) { definition += ' NOT NULL'; } if (field.unique) { definition += ' UNIQUE'; } if (field.primary || field.primaryKey) { definition += ' PRIMARY KEY'; } if (field.autoIncrement) { // SQLite uses AUTOINCREMENT, others use AUTO_INCREMENT if (this.databaseType === 'sqlite') { definition += ' AUTOINCREMENT'; } else { definition += ' AUTO_INCREMENT'; } } if (field.default !== undefined) { definition += ` DEFAULT ${this.quoteValue(field.default)}`; } return definition; } /** * Map field type to database-specific type */ mapFieldType(type) { const typeMap = { 'string': this.databaseType === 'sqlite' ? 'TEXT' : 'VARCHAR', 'text': 'TEXT', 'int': this.databaseType === 'sqlite' ? 'INTEGER' : 'INT', 'integer': this.databaseType === 'sqlite' ? 'INTEGER' : 'INT', 'bigint': this.databaseType === 'sqlite' ? 'INTEGER' : 'BIGINT', 'float': this.databaseType === 'sqlite' ? 'REAL' : 'FLOAT', 'double': this.databaseType === 'sqlite' ? 'REAL' : 'DOUBLE', 'decimal': this.databaseType === 'sqlite' ? 'REAL' : 'DECIMAL', 'boolean': this.databaseType === 'sqlite' ? 'INTEGER' : 'BOOLEAN', 'datetime': this.databaseType === 'sqlite' ? 'TEXT' : 'DATETIME', 'timestamp': this.databaseType === 'sqlite' ? 'TEXT' : 'TIMESTAMP', 'date': this.databaseType === 'sqlite' ? 'TEXT' : 'DATE', 'json': this.databaseType === 'sqlite' ? 'TEXT' : 'JSON' }; return typeMap[type.toLowerCase()] || type.toUpperCase(); } /** * Get placeholders for parameterized queries */ getPlaceholders(count) { switch (this.databaseType) { case 'postgresql': return Array.from({ length: count }, (_, i) => `$${i + 1}`).join(', '); case 'mysql': case 'sqlite': default: return Array.from({ length: count }, () => '?').join(', '); } } /** * Get single placeholder */ getPlaceholder() { switch (this.databaseType) { case 'postgresql': return '$1'; case 'mysql': case 'sqlite': default: return '?'; } } /** * Quote table name */ quoteTable(table) { switch (this.databaseType) { case 'postgresql': return `"${table}"`; case 'mysql': return `\`${table}\``; case 'sqlite': return `"${table}"`; default: return table; } } /** * Quote field name */ quoteField(field) { switch (this.databaseType) { case 'postgresql': return `"${field}"`; case 'mysql': return `\`${field}\``; case 'sqlite': return `"${field}"`; default: return field; } } /** * Quote value for default */ quoteValue(value) { if (typeof value === 'string') { return `'${value.replace(/'/g, "''")}'`; } return String(value); } } exports.QueryBuilder = QueryBuilder; //# sourceMappingURL=query.js.map