UNPKG

morsel-sql.db

Version:

Morsel, advanced SQL database for Node.js

313 lines (284 loc) 11.5 kB
const mysql = require('mysql2/promise'); class morselSQL { constructor(config) { this.config = config; this.pool = mysql.createPool({ ...config, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); } async connect() { try { this.connection = await this.pool.getConnection(); console.log('Connected to the database.'); } catch (error) { console.error('Connection error:', error.message); throw new Error(`Connection error: ${error.message}`); } } async disconnect() { try { if (this.connection) { await this.connection.release(); console.log('Database connection closed.'); } } catch (error) { console.error('Disconnection error:', error.message); throw new Error(`Disconnection error: ${error.message}`); } } async query(sql, params) { try { const [rows] = await this.connection.execute(sql, params); return rows; } catch (error) { console.error('Query error:', error.message); throw new Error(`Query error: ${error.message}`); } } async transaction(queries) { try { await this.connection.beginTransaction(); const results = []; for (const { sql, params } of queries) { const result = await this.query(sql, params); results.push(result); } await this.connection.commit(); return results; } catch (error) { await this.connection.rollback(); console.error('Transaction error:', error.message); throw new Error(`Transaction error: ${error.message}`); } } async insert(table, data) { try { const keys = Object.keys(data).join(', '); const values = Object.values(data).map(() => '?').join(', '); const sql = `INSERT INTO ${table} (${keys}) VALUES (${values})`; return await this.query(sql, Object.values(data)); } catch (error) { console.error('Insert error:', error.message); throw new Error(`Insert error: ${error.message}`); } } async bulkInsert(table, rows) { try { if (rows.length === 0) return; const keys = Object.keys(rows[0]).join(', '); const values = rows.map(row => `(${Object.values(row).map(() => '?').join(', ')})`).join(', '); const sql = `INSERT INTO ${table} (${keys}) VALUES ${values}`; const params = rows.reduce((acc, row) => [...acc, ...Object.values(row)], []); return await this.query(sql, params); } catch (error) { console.error('Bulk insert error:', error.message); throw new Error(`Bulk insert error: ${error.message}`); } } async select(table, conditions = {}, columns = '*') { try { const keys = Object.keys(conditions).map(key => `${key} = ?`).join(' AND '); const sql = `SELECT ${columns} FROM ${table}` + (keys ? ` WHERE ${keys}` : ''); return await this.query(sql, Object.values(conditions)); } catch (error) { console.error('Select error:', error.message); throw new Error(`Select error: ${error.message}`); } } async selectWithJoin(table, joinType, joinTable, joinCondition, conditions = {}, columns = '*') { try { const keys = Object.keys(conditions).map(key => `${table}.${key} = ?`).join(' AND '); const sql = `SELECT ${columns} FROM ${table} ${joinType} JOIN ${joinTable} ON ${joinCondition}` + (keys ? ` WHERE ${keys}` : ''); return await this.query(sql, Object.values(conditions)); } catch (error) { console.error('Join operation error:', error.message); throw new Error(`Join operation error: ${error.message}`); } } async update(table, data, conditions) { try { const set = Object.keys(data).map(key => `${key} = ?`).join(', '); const where = Object.keys(conditions).map(key => `${key} = ?`).join(' AND '); const sql = `UPDATE ${table} SET ${set} WHERE ${where}`; return await this.query(sql, [...Object.values(data), ...Object.values(conditions)]); } catch (error) { console.error('Update error:', error.message); throw new Error(`Update error: ${error.message}`); } } async delete(table, conditions) { try { const where = Object.keys(conditions).map(key => `${key} = ?`).join(' AND '); const sql = `DELETE FROM ${table} WHERE ${where}`; return await this.query(sql, Object.values(conditions)); } catch (error) { console.error('Delete error:', error.message); throw new Error(`Delete error: ${error.message}`); } } async count(table, conditions = {}) { try { const keys = Object.keys(conditions).map(key => `${key} = ?`).join(' AND '); const sql = `SELECT COUNT(*) as count FROM ${table}` + (keys ? ` WHERE ${keys}` : ''); const result = await this.query(sql, Object.values(conditions)); return result[0].count; } catch (error) { console.error('Count error:', error.message); throw new Error(`Count error: ${error.message}`); } } async exists(table, conditions = {}) { try { const keys = Object.keys(conditions).map(key => `${key} = ?`).join(' AND '); const sql = `SELECT EXISTS(SELECT 1 FROM ${table} WHERE ${keys}) as exists`; const result = await this.query(sql, Object.values(conditions)); return result[0].exists; } catch (error) { console.error('Existence check error:', error.message); throw new Error(`Existence check error: ${error.message}`); } } async truncate(table) { try { const sql = `TRUNCATE TABLE ${table}`; return await this.query(sql); } catch (error) { console.error('Truncate error:', error.message); throw new Error(`Truncate error: ${error.message}`); } } async dropTable(table) { try { const sql = `DROP TABLE IF EXISTS ${table}`; return await this.query(sql); } catch (error) { console.error('Drop table error:', error.message); throw new Error(`Drop table error: ${error.message}`); } } async createTable(table, columns) { try { const cols = Object.keys(columns) .map(key => `${key} ${columns[key]}`) .join(', '); const sql = `CREATE TABLE IF NOT EXISTS ${table} (${cols})`; return await this.query(sql); } catch (error) { console.error('Create table error:', error.message); throw new Error(`Create table error: ${error.message}`); } } async getTableColumns(table) { try { const sql = `SHOW COLUMNS FROM ${table}`; return await this.query(sql); } catch (error) { console.error('Get table columns error:', error.message); throw new Error(`Get table columns error: ${error.message}`); } } async getTables() { try { const sql = `SHOW TABLES`; return await this.query(sql); } catch (error) { console.error('Get tables error:', error.message); throw new Error(`Get tables error: ${error.message}`); } } async getDatabaseSize() { try { const sql = `SELECT table_schema AS database_name, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb FROM information_schema.tables WHERE table_schema = ? GROUP BY table_schema`; const result = await this.query(sql, [this.config.database]); return result[0]?.size_mb || 0; } catch (error) { console.error('Get database size error:', error.message); throw new Error(`Get database size error: ${error.message}`); } } async optimizeTable(table) { try { const sql = `OPTIMIZE TABLE ${table}`; return await this.query(sql); } catch (error) { console.error('Optimize table error:', error.message); throw new Error(`Optimize table error: ${error.message}`); } } async repairTable(table) { try { const sql = `REPAIR TABLE ${table}`; return await this.query(sql); } catch (error) { console.error('Repair table error:', error.message); throw new Error(`Repair table error: ${error.message}`); } } async showProcessList() { try { const sql = `SHOW PROCESSLIST`; return await this.query(sql); } catch (error) { console.error('Get process list error:', error.message); throw new Error(`Get process list error: ${error.message}`); } } async showStatus() { try { const sql = `SHOW STATUS`; return await this.query(sql); } catch (error) { console.error('Get status error:', error.message); throw new Error(`Get status error: ${error.message}`); } } async showVariables() { try { const sql = `SHOW VARIABLES`; return await this.query(sql); } catch (error) { console.error('Get variables error:', error.message); throw new Error(`Get variables error: ${error.message}`); } } async setVariable(name, value) { try { const sql = `SET ${name} = ?`; return await this.query(sql, [value]); } catch (error) { console.error('Set variable error:', error.message); throw new Error(`Set variable error: ${error.message}`); } } async getUserPrivileges(user) { try { const sql = `SHOW GRANTS FOR '${user}'@'%'`; return await this.query(sql); } catch (error) { console.error('Get user privileges error:', error.message); throw new Error(`Get user privileges error: ${error.message}`); } } async grantPrivileges(user, privileges, database = '*') { try { const sql = `GRANT ${privileges} ON ${database}.* TO '${user}'@'%'`; return await this.query(sql); } catch (error) { console.error('Grant privileges error:', error.message); throw new Error(`Grant privileges error: ${error.message}`); } } async revokePrivileges(user, privileges, database = '*') { try { const sql = `REVOKE ${privileges} ON ${database}.* FROM '${user}'@'%'`; return await this.query(sql); } catch (error) { console.error('Revoke privileges error:', error.message); throw new Error(`Revoke privileges error: ${error.message}`); } } } module.exports = morselSQL;