Skip to content
Open
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
1 change: 1 addition & 0 deletions lib/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Column.iface = [
'getDataType',
'getMaxLength',
'isPrimaryKey',
'isForeignKey',
'getDefaultValue',
'isUnique',
'isAutoIncrementing'
Expand Down
4 changes: 4 additions & 0 deletions lib/mysql/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Column.prototype.isPrimaryKey = function () {
return this.meta.column_key === 'PRI';
};

Column.prototype.isForeignKey = function () {
return this.meta.foreign_key === true;
};

Column.prototype.getDefaultValue = function () {
return this.meta.column_default;
};
Expand Down
40 changes: 38 additions & 2 deletions lib/mysql/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ var mysql = require('mysql');
var Table = require('../table');
var Column = require('./column');
var Index = require('./index');
var metaUtils = require('../util');
var arrayContains = metaUtils.arrayContains;

exports.connect = function (options, callback) {
try {
var client = mysql.createClient(options);
var client;
if (typeof(mysql.createConnection) === 'undefined') {
client = new mysql.createClient(options);
} else {
client = new mysql.createConnection(options);
}

callback(null, new Driver(client));
} catch (err) {
callback(err);
Expand Down Expand Up @@ -39,9 +47,37 @@ Driver.prototype.getTables = function (callback) {
};

Driver.prototype.getColumns = function (tableName, callback) {
var handler = handleResults.bind(this, Column, callback);
var handler = handleResults.bind(this, Column, findForeignKeys.bind(this));
var db = getClientDatabase(this.client);
this.client.query("select * from information_schema.columns where table_schema = ? and table_name = ?", [db, tableName], handler);

function findForeignKeys(err, columns) {
if(err) {
return callback(err);
}

this.client.query("select * from information_schema.key_column_usage " +
"WHERE table_schema = ? AND table_name = ? AND referenced_column_name IS NOT NULL",
[db, tableName], onForeignKeysResult.bind(this, columns, this.client));
}

function onForeignKeysResult(columns, client, err, result) {
if(err) {
return callback(err);
}

var foreignKeys = result.map(function (row) {
return row.COLUMN_NAME;
});

columns.forEach(function (column) {
if (arrayContains(foreignKeys, column.getName())) {
column.meta.foreign_key = true;
}
});

callback(null, columns);
}
};

Driver.prototype.getIndexes = function(tableName, callback) {
Expand Down
4 changes: 4 additions & 0 deletions lib/pg/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Column.prototype.isPrimaryKey = function () {
return this.meta.primary_key === true;
};

Column.prototype.isForeignKey = function () {
return this.meta.foreign_key === true;
};

Column.prototype.getDefaultValue = function () {
return this.meta.column_default;
};
Expand Down
49 changes: 38 additions & 11 deletions lib/pg/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var pg = require('pg');
var Table = require('../table');
var Column = require('./column');
var Index = require('./index');
var arrayContains = require('../util').arrayContains;

exports.connect = function (options, callback) {
var client = new pg.Client(options);
Expand All @@ -12,7 +13,6 @@ exports.connect = function (options, callback) {
};

exports.connectToExistingConnection = function(client, callback){
// console.log("connecting to existing connection");
callback(null, new Driver(client));
};

Expand Down Expand Up @@ -105,10 +105,45 @@ Driver.prototype.getColumns = function (tableName, callback) {
column.meta.unique = true;
}
});
findForeignKeys(null, columns, client);
}

function findForeignKeys(err, columns, client) {
if(err) {
return callback(err);
}

client.query("select cu.column_name " +
"from information_schema.key_column_usage cu, " +
"information_schema.table_constraints tc " +
"where tc.table_name = cu.table_name " +
"and tc.constraint_type = 'FOREIGN KEY' " +
"and tc.constraint_name = cu.constraint_name " +
"and tc.table_name = $1",
[tableName],
onForeignKeysResult.bind(this, columns, client)
);
}

function onForeignKeysResult(columns, client, err, result) {
if(err) {
return callbacke(err);
}

var foreignKeys = result.rows.map(function (row) {
return row.column_name;
});

columns.forEach(function (column) {
if (arrayContains(foreignKeys, column.getName())) {
column.meta.foreign_key = true;
}
});

checkAutoincrement(null, columns, client);
}

function checkAutoincrement(err, columns, client) {
function checkAutoincrement(err, columns, client) {
if (err) {
return callback(err);
}
Expand All @@ -135,6 +170,7 @@ function checkAutoincrement(err, columns, client) {
column.meta.autoincrement = true;
}
});

callback(null, columns);
}
};
Expand Down Expand Up @@ -171,12 +207,3 @@ function handleResults(obj, callback, err, result) {

callback(null, objects);
}

function arrayContains(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
return true;
}
}
return false;
}
8 changes: 6 additions & 2 deletions lib/sqlite3/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ Column.prototype.isNullable = function () {

Column.prototype.getMaxLength = function () {
var match = this.getDataType().match(/\((\d+)\)$/);
if (match[1]) {
if (match && match[1]) {
return parseInt(match[1]);
}
return -1;
return null;
};

Column.prototype.getDataType = function() {
Expand All @@ -33,6 +33,10 @@ Column.prototype.isPrimaryKey = function () {
return this.meta.pk === 1;
};

Column.prototype.isForeignKey = function () {
return this.meta.fk === 1;
};

Column.prototype.getDefaultValue = function () {
return this.meta.dflt_value;
};
Expand Down
27 changes: 26 additions & 1 deletion lib/sqlite3/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var sqlite3 = require('sqlite3');
var Table = require('../table');
var Column = require('./column');
var Index = require('./index');
var arrayContains = require('../util').arrayContains;

exports.connect = function (options, callback) {
try {
Expand Down Expand Up @@ -71,7 +72,31 @@ Driver.prototype.getColumns = function (tableName, callback) {
}
colNumber++;
});
callback(err,previous);

findForeignKeys(previous, this.client);
}

function findForeignKeys(columns, client) {
client.all('PRAGMA foreign_key_list(' + tableName + ');',
onForeignKeysResult.bind(this, columns, client));
}

function onForeignKeysResult(columns, client, err, result) {
if(err) {
return callback(err);
}

var foreignKeys = result.map(function (row) {
return row.from;
});

columns.forEach(function (column) {
if (arrayContains(foreignKeys, column.getName())) {
column.meta.fk = 1;
}
});

callback(err, columns);
}

};
Expand Down
11 changes: 10 additions & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@ exports.lowercaseKeys = function (obj) {
newObj[key.toLowerCase()] = obj[key];
});
return newObj;
};
};

exports.arrayContains = function(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
return true;
}
}
return false;
}
10 changes: 9 additions & 1 deletion test/mysql/column-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var expect = require('chai').expect;
var Column = require('../../lib/mysql/column');
var iface = require('../../lib/column').iface;

describe('pg column', function () {
describe('mysql column', function () {
it('should implement all the methods defined in the base column interface', function (done) {
var c = new Column({ column_name: 'col', data_type: 'integer' });
iface.forEach(function (method) {
Expand Down Expand Up @@ -52,6 +52,14 @@ describe('pg column', function () {
expect(c.isPrimaryKey()).to.be.false;
done();
});

it('should implement the isForeignKey method', function(done) {
var c = new Column({ column_name: 'col', foreign_key: true });
expect(c.isForeignKey()).to.be.true;
var c = new Column({ column_name: 'col', foreign_key: false });
expect(c.isForeignKey()).to.be.false;
done();
});

it('should implement the getDefaultValue method', function(done) {
var c = new Column({ column_name: 'col', column_default: '30' });
Expand Down
32 changes: 25 additions & 7 deletions test/mysql/driver-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ describe('mysql driver', function() {
mysql.connect({ database: 'db_meta_test' }, onConnect);

function onConnect(err, dbDriver) {
if(err) {
return done(err);
}

driver = dbDriver;
driver.client.query('CREATE TABLE person (id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(100) UNIQUE, age INTEGER DEFAULT 30);', createIndex);
driver.client.query('CREATE TABLE person (id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(100) UNIQUE, age INTEGER DEFAULT 30, ref INTEGER, CONSTRAINT FOREIGN KEY (ref) REFERENCES person(id));', createIndex);
}

function createIndex(err) {
if(err) {
return done(err);
}

driver.client.query('CREATE INDEX person_name_idx ON person (name, age)', done);
}
});
Expand Down Expand Up @@ -50,7 +58,7 @@ describe('mysql driver', function() {
function onResult(err, columns) {
expect(err).to.be.null;
expect(columns).not.to.be.empty;
expect(columns.length).to.equal(4);
expect(columns.length).to.equal(5);

var idColumn = getColumnByName(columns, 'id');
expect(idColumn).not.to.be.null;
Expand All @@ -59,6 +67,7 @@ describe('mysql driver', function() {
expect(idColumn.getMaxLength()).to.be.null;
expect(idColumn.getDataType()).to.equal('INT');
expect(idColumn.isPrimaryKey()).to.be.true;
expect(idColumn.isForeignKey()).to.be.false;
expect(idColumn.isUnique()).to.be.true;
expect(idColumn.isAutoIncrementing()).to.be.true;

Expand Down Expand Up @@ -87,6 +96,15 @@ describe('mysql driver', function() {
expect(ageColumn.isUnique()).to.be.false;
expect(ageColumn.isAutoIncrementing()).to.be.false;

var refColumn = getColumnByName(columns, 'ref');
expect(refColumn).to.be.not.null;
expect(refColumn.meta).not.to.be.empty;
expect(refColumn.isForeignKey(), 'FK').to.be.true;
expect(refColumn.isPrimaryKey()).to.be.false;
expect(refColumn.getDataType()).to.equal('INT');
expect(refColumn.getMaxLength()).to.be.null;
expect(refColumn.isAutoIncrementing()).to.be.false;

done();
}
});
Expand All @@ -95,19 +113,19 @@ describe('mysql driver', function() {
driver.getIndexes('person', onResult);

function onResult(err, indexes) {
expect(indexes.length).to.equal(4);
expect(indexes.length).to.equal(5);
expect(indexes[0].getName()).to.equal('PRIMARY');
expect(indexes[0].getTableName()).to.equal('person');
expect(indexes[0].getColumnName()).to.equal('id');
expect(indexes[1].getName()).to.equal('email');
expect(indexes[1].getTableName()).to.equal('person');
expect(indexes[1].getColumnName()).to.equal('email');
expect(indexes[2].getName()).to.equal('person_name_idx');
expect(indexes[2].getTableName()).to.equal('person');
expect(indexes[2].getColumnName()).to.equal('name');
expect(indexes[3].getName()).to.equal('person_name_idx');
expect(indexes[3].getTableName()).to.equal('person');
expect(indexes[3].getColumnName()).to.equal('age');
expect(indexes[3].getColumnName()).to.equal('name');
expect(indexes[4].getName()).to.equal('person_name_idx');
expect(indexes[4].getTableName()).to.equal('person');
expect(indexes[4].getColumnName()).to.equal('age');
done();
}
});
Expand Down
8 changes: 8 additions & 0 deletions test/pg/column-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ describe('pg column', function () {
done();
});

it('should implement the isForeignKey method', function(done) {
var c = new Column({ column_name: 'col', foreign_key: true });
expect(c.isForeignKey()).to.be.true;
c = new Column({ column_name: 'col', foreign_key: false });
expect(c.isForeignKey()).to.be.false;
done();
});

it('should implement the getDefaultValue method', function(done) {
var c = new Column({ column_name: 'col', column_default: '30' });
expect(c.getDefaultValue()).to.equal('30');
Expand Down
Loading