UNPKG

sqlpad

Version:

Web app. Write SQL and visualize the results. Supports Postgres, MySQL, SQL Server, Crate, Vertica and SAP HANA.

174 lines (159 loc) 4.01 kB
const mysql = require('mysql'); const { formatSchemaQueryResults } = require('../utils'); const id = 'mysql'; const name = 'MySQL'; function getSchemaSql(database) { const whereSql = database ? `WHERE t.table_schema = '${database}'` : `WHERE t.table_schema NOT IN ( 'mysql', 'performance_schema', 'information_schema' )`; return ` SELECT t.table_schema, t.table_name, c.column_name, c.data_type FROM INFORMATION_SCHEMA.TABLES t JOIN INFORMATION_SCHEMA.COLUMNS c ON t.table_schema = c.table_schema AND t.table_name = c.table_name ${whereSql} ORDER BY t.table_schema, t.table_name, c.ordinal_position `; } /** * Run query for connection * Should return { rows, incomplete } * @param {string} query * @param {object} connection */ function runQuery(query, connection) { const myConnection = mysql.createConnection({ multipleStatements: true, host: connection.host, port: connection.port ? connection.port : 3306, user: connection.username, password: connection.password, database: connection.database, insecureAuth: connection.mysqlInsecureAuth, timezone: 'Z', supportBigNumbers: true }); return new Promise((resolve, reject) => { let incomplete = false; const rows = []; myConnection.connect(err => { if (err) { return reject(err); } let queryError; let resultsSent = false; function continueOn() { if (!resultsSent) { resultsSent = true; if (queryError) { return reject(queryError); } return resolve({ rows, incomplete }); } } const myQuery = myConnection.query(query); myQuery .on('error', function(err) { // Handle error, // an 'end' event will be emitted after this as well // so we'll call the callback there. queryError = err; }) .on('result', function(row) { // If we haven't hit the max yet add row to results if (rows.length < connection.maxRows) { return rows.push(row); } // Too many rows incomplete = true; // Stop the query stream myConnection.pause(); // Destroy the underlying connection // Calling end() will wait and eventually time out myConnection.destroy(); continueOn(); }) .on('end', function() { // all rows have been received // This will not fire if we end the connection early // myConnection.end() // myConnection.destroy() myConnection.end(error => { if (error) { console.error('Error ending MySQL connection', error); } continueOn(); }); }); }); }); } /** * Test connectivity of connection * @param {*} connection */ function testConnection(connection) { const query = "SELECT 'success' AS TestQuery;"; return runQuery(query, connection); } /** * Get schema for connection * @param {*} connection */ function getSchema(connection) { const schemaSql = getSchemaSql(connection.database); return runQuery(schemaSql, connection).then(queryResult => formatSchemaQueryResults(queryResult) ); } const fields = [ { key: 'host', formType: 'TEXT', label: 'Host/Server/IP Address' }, { key: 'port', formType: 'TEXT', label: 'Port (optional)' }, { key: 'database', formType: 'TEXT', label: 'Database' }, { key: 'username', formType: 'TEXT', label: 'Database Username' }, { key: 'password', formType: 'PASSWORD', label: 'Database Password' }, { key: 'mysqlInsecureAuth', formType: 'CHECKBOX', label: 'Use old/insecure pre 4.1 Auth System' } ]; module.exports = { id, name, fields, getSchema, runQuery, testConnection };