Skip to content
This repository has been archived by the owner on Mar 15, 2021. It is now read-only.

Add getVersion function to db clients to get version details #104

Merged
merged 8 commits into from
Aug 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions spec/db.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { db } from '../src';
import config from './databases/config';
import setupSQLite from './databases/sqlite/setup';
import setupCassandra from './databases/cassandra/setup';
import { versionCompare } from '../src/utils';

chai.use(chaiAsPromised);

Expand Down Expand Up @@ -93,9 +94,27 @@ describe('db', () => {
});

describe('.version', () => {
it('should return a version', async () => {
expect(dbConn.version()).to.be.a('string');
expect(dbConn.version()).to.not.be.empty;
it('should return version string', () => {
const version = dbConn.version();
expect(version).to.be.a('string').and.not.be.empty;
});
});

describe('.getVersion', () => {
it('should return version details', () => {
const version = dbConn.getVersion();
expect(dbConn.getVersion()).to.be.a('object');
const expectedName = {
postgresql: 'PostgreSQL',
mysql: 'MySQL',
mariadb: 'MariaDB',
sqlite: 'SQLite',
sqlserver: 'SQL Server',
cassandra: 'Cassandra',
};
expect(version).to.have.property('name').to.contain(expectedName[dbClient]);
expect(version).to.have.property('version').to.be.a('string').and.to.match(/(?:[0-9]\.?)+/);
expect(version).to.have.property('string').to.be.a('string').and.to.be.not.empty;
});
});

Expand Down Expand Up @@ -311,7 +330,7 @@ describe('db', () => {
it('should return table create script', async () => {
const [createScript] = await dbConn.getTableCreateScript('users');

if (dbClient === 'mysql' && parseInt(dbConn.version()[0], 10) >= '8') {
if (dbClient === 'mysql' && versionCompare(dbConn.getVersion().version, '8') >= 0) {
expect(createScript).to.contain('CREATE TABLE `users` (\n' +
' `id` int NOT NULL AUTO_INCREMENT,\n' +
' `username` varchar(45) DEFAULT NULL,\n' +
Expand Down Expand Up @@ -689,7 +708,7 @@ describe('db', () => {
}
} catch (err) {
if (dbClient === 'cassandra') {
if (dbConn.version().split('.')[0] === '2') {
if (versionCompare(dbConn.getVersion().version, '2') === 0) {
expect(err.message).to.eql('line 0:-1 no viable alternative at input \'<EOF>\'');
} else {
expect(err.message).to.eql('line 1:13 mismatched character \'<EOF>\' expecting set null');
Expand Down Expand Up @@ -794,7 +813,7 @@ describe('db', () => {
expect(secondResult).to.have.deep.property('rowCount').to.eql(1);
} catch (err) {
if (dbClient === 'cassandra') {
if (parseFloat(dbConn.version().split('.').slice(0, 2).join('.')) >= 3.10) {
if (versionCompare(dbConn.getVersion().version, '3.10') >= 0) {
expect(err.message).to.match(/mismatched input 'select' expecting EOF/);
} else {
expect(err.message).to.match(/missing EOF at 'select'/);
Expand Down Expand Up @@ -874,7 +893,7 @@ describe('db', () => {
}
} catch (err) {
if (dbClient === 'cassandra') {
if (parseFloat(dbConn.version().split('.').slice(0, 2).join('.')) >= 3.10) {
if (versionCompare(dbConn.getVersion().version, '3.10') >= 0) {
expect(err.message).to.match(/mismatched input 'insert' expecting EOF/);
} else {
expect(err.message).to.match(/missing EOF at 'insert'/);
Expand Down Expand Up @@ -950,7 +969,7 @@ describe('db', () => {
}
} catch (err) {
if (dbClient === 'cassandra') {
if (parseFloat(dbConn.version().split('.').slice(0, 2).join('.')) >= 3.10) {
if (versionCompare(dbConn.getVersion().version, '3.10') >= 0) {
expect(err.message).to.match(/mismatched input 'delete' expecting EOF/);
} else {
expect(err.message).to.match(/missing EOF at 'delete'/);
Expand Down Expand Up @@ -1026,7 +1045,7 @@ describe('db', () => {
}
} catch (err) {
if (dbClient === 'cassandra') {
if (parseFloat(dbConn.version().split('.').slice(0, 2).join('.')) >= 3.10) {
if (versionCompare(dbConn.getVersion().version, '3.10') >= 0) {
expect(err.message).to.match(/mismatched input 'update' expecting EOF/);
} else {
expect(err.message).to.match(/missing EOF at 'update'/);
Expand Down
9 changes: 9 additions & 0 deletions src/db/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function createConnection(server, database) {
connect: connect.bind(null, server, database),
disconnect: disconnect.bind(null, server, database),
version: version.bind(null, server, database),
getVersion: getVersion.bind(null, server, database),
listTables: listTables.bind(null, server, database),
listViews: listViews.bind(null, server, database),
listRoutines: listRoutines.bind(null, server, database),
Expand Down Expand Up @@ -120,11 +121,19 @@ function disconnect(server, database) {
}
}

/**
* @deprecated
*/
function version(server, database) {
checkIsConnected(server, database);
return database.connection.version;
}

function getVersion(server, database) {
checkIsConnected(server, database);
return database.connection.getVersion();
}

function listSchemas(server, database, filter) {
checkIsConnected(server, database);
return database.connection.listSchemas(database.database, filter);
Expand Down
15 changes: 11 additions & 4 deletions src/db/clients/cassandra.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ export default function (server, database) {
return reject(err);
}

client.version = client.getState().getConnectedHosts()[0].cassandraVersion;
client.version = client.getState().getConnectedHosts()[0].getCassandraVersion();

client.versionData = {
name: 'Cassandra',
version: client.getState().getConnectedHosts()[0].cassandraVersion,
string: `Cassandra ${client.getState().getConnectedHosts()[0].cassandraVersion}`,
};

logger().debug('connected');
resolve({
wrapIdentifier,
version: client.version,
version: client.getState().getConnectedHosts()[0].cassandraVersion,
getVersion: () => client.versionData,
disconnect: () => disconnect(client),
listTables: (db) => listTables(client, db),
listViews: () => listViews(client),
Expand Down Expand Up @@ -60,7 +67,7 @@ export function disconnect(client) {
export function listTables(client, database) {
return new Promise((resolve, reject) => {
let sql;
if (client.version.split('.')[0] === '2') {
if (client.version[0] === 2) {
sql = `
SELECT columnfamily_name as name
FROM system.schema_columnfamilies
Expand Down Expand Up @@ -91,7 +98,7 @@ export function listRoutines() {
}

export function listTableColumns(client, database, table) {
const cassandra2 = client.version.split('.')[0] === '2';
const cassandra2 = client.version[0] === 2;
return new Promise((resolve, reject) => {
let sql;
if (cassandra2) {
Expand Down
42 changes: 38 additions & 4 deletions src/db/clients/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,43 @@ export default async function (server, database) {
pool: mysql.createPool(dbConfig),
};

// light solution to test connection with with the server
const version = (await driverExecuteQuery(conn, { query: 'select version() as version;' })).data[0].version;
const versionInfo = (await driverExecuteQuery(conn, {
query: "SHOW VARIABLES WHERE variable_name='version' OR variable_name='version_comment';",
})).data;

let version;
let versionComment;
for (let i = 0; i < versionInfo.length; i++) {
const item = versionInfo[i];
if (item.Variable_name === 'version') {
version = item.Value;
} else if (item.Variable_name === 'version_comment') {
versionComment = item.Value;
}
}

conn.versionData = {
name: versionComment,
version: version.split('-')[0],
string: `${versionComment} ${version}`,
};

// normalize the name as depending on where the server is installed from, it
// could be just "MySQL" or "MariaDB", or it could be a longer string like
// "mariadb.org binary distribution"
const lowerComment = versionComment.toLowerCase();
if (lowerComment.includes('mysql')) {
conn.versionData.name = 'MySQL';
} else if (lowerComment.includes('mariadb')) {
conn.versionData.name = 'MariaDB';
} else if (lowerComment.includes('percona')) {
conn.versionData.name = 'Percona';
}

return {
wrapIdentifier,
version,
version: conn.versionData.version,
getVersion: () => conn.versionData,
disconnect: () => disconnect(conn),
listTables: () => listTables(conn),
listViews: () => listViews(conn),
Expand Down Expand Up @@ -172,7 +203,10 @@ export async function getTableReferences(conn, table) {

export async function getTableKeys(conn, database, table) {
const sql = `
SELECT constraint_name as 'constraint_name', column_name as 'column_name', referenced_table_name as 'referenced_table_name',
SELECT
constraint_name as 'constraint_name',
column_name as 'column_name',
referenced_table_name as 'referenced_table_name',
CASE WHEN (referenced_table_name IS NOT NULL) THEN 'FOREIGN'
ELSE constraint_name
END as key_type
Expand Down
8 changes: 8 additions & 0 deletions src/db/clients/postgresql.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,19 @@ export default async function (server, database) {
const defaultSchema = await getSchema(conn);

const version = (await driverExecuteQuery(conn, { query: 'select version()' })).rows[0].version;
const splitVersion = version.split(' ');

conn.versionData = {
name: splitVersion[0],
version: splitVersion[1],
string: version,
};

return {
/* eslint max-len:0 */
wrapIdentifier,
version,
getVersion: () => conn.versionData,
disconnect: () => disconnect(conn),
listTables: (db, filter) => listTables(conn, filter),
listViews: (filter) => listViews(conn, filter),
Expand Down
6 changes: 6 additions & 0 deletions src/db/clients/sqlite.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ export default async function (server, database) {

// light solution to test connection with with the server
const version = (await driverExecuteQuery(conn, { query: 'SELECT sqlite_version() as version' })).data[0].version;
conn.versionData = {
name: 'SQLite',
version,
string: `SQLite ${version}`,
};

return {
wrapIdentifier,
version,
getVersion: () => conn.versionData,
disconnect: () => disconnect(conn),
listTables: () => listTables(conn),
listViews: () => listViews(conn),
Expand Down
7 changes: 7 additions & 0 deletions src/db/clients/sqlserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@ export default async function (server, database) {
// light solution to test connection with with the server
const version = (await driverExecuteQuery(conn, { query: 'SELECT @@version as \'version\'' })).data[0].version;

conn.versionData = {
name: 'SQL Server',
version: version.match(/^Microsoft SQL Server ([0-9]{4})/)[1],
string: version,
};

return {
wrapIdentifier,
version,
getVersion: () => conn.versionData,
disconnect: () => disconnect(conn),
listTables: (db, filter) => listTables(conn, filter),
listViews: (filter) => listViews(conn, filter),
Expand Down