A comprehensive MySQL database driver for Node.js providing connection management, query execution, connection pooling, and cluster support.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive query execution system supporting parameterized queries, streaming results, and event-driven processing. Includes full transaction support, prepared statements, and advanced query options for optimal performance and security.
Creates a new query object for execution.
/**
* Create a new Query instance
* @param {string} sql - The SQL for the query
* @param {array} [values] - Any values to insert into placeholders in sql
* @param {function} [callback] - The callback to use when query is complete
* @returns {Query} New query object
*/
function createQuery(sql, values, callback);
// Query options object
interface QueryOptions {
sql: string; // SQL query string
values?: any[]; // Parameter values for placeholders
timeout?: number; // Query timeout in milliseconds
nestTables?: boolean | string; // Nest result tables by table name
typeCast?: boolean | function; // Enable/disable or custom type casting
}Usage Examples:
const mysql = require('mysql');
// Create query with SQL string
const query1 = mysql.createQuery('SELECT * FROM users');
// Create query with parameters
const query2 = mysql.createQuery('SELECT * FROM users WHERE id = ?', [1]);
// Create query with callback
const query3 = mysql.createQuery('SELECT * FROM users', (error, results) => {
if (error) throw error;
console.log(results);
});
// Create query with options object
const query4 = mysql.createQuery({
sql: 'SELECT * FROM users WHERE active = ?',
values: [true],
timeout: 30000,
nestTables: true
});Queries can be executed using connections, pools, or directly on query objects.
Execute query on a specific connection.
/**
* Executes a SQL query on connection
* @param {string|object} sql - SQL query string or query object
* @param {array} [values] - Parameter values for prepared statements
* @param {function} [callback] - Callback function (err, results, fields)
* @returns {Query} Query object for event-based processing
*/
connection.query(sql, values, callback);Execute query using pool connection.
/**
* Executes query using pool connection
* @param {string|object} sql - SQL query string or query object
* @param {array} [values] - Parameter values for prepared statements
* @param {function} [callback] - Callback function (err, results, fields)
* @returns {Query} Query object for event-based processing
*/
pool.query(sql, values, callback);Basic Query Examples:
// Simple SELECT query
connection.query('SELECT * FROM users', (error, results, fields) => {
if (error) throw error;
console.log('Users:', results);
console.log('Field info:', fields);
});
// Parameterized query (prevents SQL injection)
connection.query('SELECT * FROM users WHERE id = ? AND active = ?', [userId, true], (error, results) => {
if (error) throw error;
console.log('User:', results[0]);
});
// INSERT query
connection.query('INSERT INTO users SET ?', {
name: 'John Doe',
email: 'john@example.com',
active: true
}, (error, results) => {
if (error) throw error;
console.log('Inserted user with ID:', results.insertId);
});
// UPDATE query
connection.query('UPDATE users SET ? WHERE id = ?', [{name: 'Jane Doe'}, userId], (error, results) => {
if (error) throw error;
console.log('Updated rows:', results.affectedRows);
});
// DELETE query
connection.query('DELETE FROM users WHERE id = ?', [userId], (error, results) => {
if (error) throw error;
console.log('Deleted rows:', results.affectedRows);
});Organize results by table name when joining multiple tables.
// Query with nested tables
connection.query({
sql: 'SELECT u.*, p.* FROM users u LEFT JOIN profiles p ON u.id = p.user_id',
nestTables: true
}, (error, results) => {
if (error) throw error;
results.forEach(row => {
console.log('User:', row.u); // User table data
console.log('Profile:', row.p); // Profile table data
});
});
// Nested tables with separator
connection.query({
sql: 'SELECT u.*, p.* FROM users u LEFT JOIN profiles p ON u.id = p.user_id',
nestTables: '_'
}, (error, results) => {
if (error) throw error;
results.forEach(row => {
// Fields will be named like: u_id, u_name, p_bio, etc.
console.log(row);
});
});Control how MySQL types are converted to JavaScript types.
// Disable type casting (return raw buffer data)
connection.query({
sql: 'SELECT * FROM users',
typeCast: false
}, (error, results) => {
if (error) throw error;
console.log(results); // Raw buffer data
});
// Custom type casting function
connection.query({
sql: 'SELECT * FROM users',
typeCast: function (field, next) {
if (field.type === 'TINY' && field.length === 1) {
return (field.string() === '1'); // Convert TINYINT(1) to boolean
}
if (field.type === 'DATETIME') {
return new Date(field.string()); // Convert to Date object
}
return next(); // Use default type casting
}
}, (error, results) => {
if (error) throw error;
console.log(results);
});Set timeout for individual queries.
connection.query({
sql: 'SELECT * FROM large_table',
timeout: 30000 // 30 seconds
}, (error, results) => {
if (error) {
if (error.code === 'PROTOCOL_SEQUENCE_TIMEOUT') {
console.error('Query timed out');
}
throw error;
}
console.log(results);
});Queries return EventEmitter objects for advanced result handling.
// Query event handlers
const query = connection.query('SELECT * FROM users');
query.on('result', (row, index) => {
console.log('Row %d:', index, row);
});
query.on('fields', (fields, index) => {
console.log('Fields for result set %d:', index, fields);
});
query.on('error', (err) => {
console.error('Query error:', err);
});
query.on('end', () => {
console.log('Query completed');
});Large Result Set Handling:
const query = connection.query('SELECT * FROM large_table');
let rowCount = 0;
query.on('result', (row) => {
// Pause connection to prevent memory overflow
connection.pause();
rowCount++;
// Process row asynchronously
processRow(row, () => {
// Resume connection after processing
connection.resume();
});
});
query.on('end', () => {
console.log('Processed %d rows', rowCount);
});
function processRow(row, callback) {
// Simulate async processing
setTimeout(() => {
console.log('Processed row:', row.id);
callback();
}, 10);
}Convert query results to readable streams for memory-efficient processing.
/**
* Returns query results as a readable stream
* @param {object} [options] - Stream options
* @param {number} [options.highWaterMark] - Stream buffer size (default: 16)
* @param {string} [options.encoding] - Stream encoding (default: null)
* @param {boolean} [options.objectMode] - Object mode (default: true for MySQL streams)
* @returns {ReadableStream} Readable stream of query results
*/
query.stream(options);
// Stream options interface
interface StreamOptions {
highWaterMark?: number; // Buffer size for stream backpressure control
encoding?: string; // Stream encoding (usually null for object streams)
objectMode?: boolean; // Whether stream operates in object mode
}Streaming Example:
const query = connection.query('SELECT * FROM large_table');
const stream = query.stream({highWaterMark: 5});
stream.on('data', (row) => {
console.log('Stream row:', row);
});
stream.on('end', () => {
console.log('Stream ended');
});
stream.on('error', (err) => {
console.error('Stream error:', err);
});MySQL package supports prepared statements through parameterized queries.
// Prepared statement with single parameter
const stmt1 = 'SELECT * FROM users WHERE id = ?';
connection.query(stmt1, [userId], callback);
// Prepared statement with multiple parameters
const stmt2 = 'SELECT * FROM users WHERE age > ? AND city = ?';
connection.query(stmt2, [25, 'New York'], callback);
// Prepared statement with object parameters
const stmt3 = 'INSERT INTO users SET ?';
connection.query(stmt3, [{name: 'John', email: 'john@example.com'}], callback);
// Prepared statement with mixed parameters
const stmt4 = 'UPDATE users SET ? WHERE id = ?';
connection.query(stmt4, [{name: 'Jane'}, userId], callback);Execute multiple SQL statements in a single query (requires multipleStatements: true).
// Enable multiple statements in connection config
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb',
multipleStatements: true
});
// Execute multiple statements
connection.query('SELECT 1; SELECT 2; SELECT 3', (error, results) => {
if (error) throw error;
console.log('First result:', results[0]); // SELECT 1 results
console.log('Second result:', results[1]); // SELECT 2 results
console.log('Third result:', results[2]); // SELECT 3 results
});// Query instance properties
interface Query extends EventEmitter {
sql: string; // SQL query string
values: any[]; // Parameter values
// Methods
stream(options?: StreamOptions): ReadableStream;
}
// Query result structure
interface QueryResult {
// For SELECT queries
results?: any[]; // Result rows
fields?: FieldInfo[]; // Field metadata
// For INSERT queries
insertId?: number; // Auto-increment ID of inserted row
affectedRows?: number; // Number of affected rows
// For UPDATE/DELETE queries
affectedRows?: number; // Number of affected rows
changedRows?: number; // Number of actually changed rows
// General properties
fieldCount?: number; // Number of fields
serverStatus?: number; // Server status flags
warningCount?: number; // Number of warnings
message?: string; // Server message
}
// Field information
interface FieldInfo {
catalog: string; // Catalog name
db: string; // Database name
table: string; // Table name
orgTable: string; // Original table name
name: string; // Column name
orgName: string; // Original column name
charsetNr: number; // Character set number
length: number; // Column length
type: number; // Column type (see Types constants)
flags: number; // Column flags
decimals: number; // Decimal places
default?: any; // Default value
zeroFill: boolean; // Zero fill flag
protocol41: boolean; // Protocol 4.1 flag
}Queries within transactions follow the same patterns but require proper transaction management.
function performTransaction(callback) {
connection.beginTransaction((err) => {
if (err) return callback(err);
// First query
connection.query('INSERT INTO users SET ?', {name: 'John'}, (error, results) => {
if (error) {
return connection.rollback(() => {
callback(error);
});
}
const userId = results.insertId;
// Second query
connection.query('INSERT INTO profiles SET ?', {user_id: userId, bio: 'Developer'}, (error, results) => {
if (error) {
return connection.rollback(() => {
callback(error);
});
}
// Commit transaction
connection.commit((err) => {
if (err) {
return connection.rollback(() => {
callback(err);
});
}
callback(null, {userId, profileId: results.insertId});
});
});
});
});
}