columnInfo, adapted code from @johanneslumpe in #190

This commit is contained in:
Tim Griesser 2014-04-21 23:08:59 -04:00
parent 9c21af25c9
commit c1ee0f5708
8 changed files with 111 additions and 8 deletions

View File

@ -45,4 +45,9 @@ Client.prototype.releaseConnection = function(connection) {
});
};
// Return the database being used by this client.
Client.prototype.database = function() {
return this.connectionSettings.database;
};
module.exports = Client;

View File

@ -2,6 +2,7 @@
// ------
module.exports = function(client) {
var _ = require('lodash');
var inherits = require('inherits');
var QueryBuilder = require('../../query/builder');
var QueryCompiler = require('../../query/compiler');
@ -53,6 +54,24 @@ QueryCompiler_MySQL.prototype.forShare = function() {
return 'lock in share mode';
};
// Compiles a `columnInfo` query.
QueryCompiler_MySQL.prototype.columnInfo = function() {
return {
sql: 'select column_name, data_type, character_maximum_length ' +
'from information_schema.columns where table_name = ? and table_schema = ?',
bindings: [this.single.table, client.database()],
output: function(resp) {
return _.reduce(resp, function(columns, val) {
columns[val.column_name] = {
type: val.data_type,
length: val.character_maximum_length
};
return columns;
}, {});
}
};
};
// Set the QueryBuilder & QueryCompiler on the client object,
// incase anyone wants to modify things to suit their own purposes.
client.QueryBuilder = QueryBuilder_MySQL;

View File

@ -2,6 +2,7 @@
// ------
module.exports = function(client) {
var _ = require('lodash');
var inherits = require('inherits');
var QueryBuilder = require('../../query/builder');
@ -78,6 +79,24 @@ QueryCompiler_PG.prototype.forShare = function() {
return 'for share';
};
// Compiles a columnInfo query
QueryCompiler_PG.prototype.columnInfo = function() {
return {
sql: 'select column_name, data_type, character_maximum_length from information_schema.columns' +
' where table_name = ? and table_catalog = ?',
bindings: [this.single.table, client.database()],
output: function(resp) {
return _.reduce(resp.rows, function (columns, val) {
columns[val.column_name] = {
type: val.data_type,
length: val.character_maximum_length
};
return columns;
}, {});
}
};
};
client.QueryBuilder = QueryBuilder_PG;
client.QueryCompiler = QueryCompiler_PG;

View File

@ -86,6 +86,26 @@ QueryCompiler_SQLite3.prototype.truncate = function() {
};
};
// Compiles a `columnInfo` query
QueryCompiler_SQLite3.prototype.columnInfo = function() {
return {
sql: 'PRAGMA table_info(' + this.single.table +')',
output: function(resp) {
var maxLengthRegex = /.*\((\d+)\)/;
return _.reduce(resp, function (columns, val) {
var type = val.type;
var maxLength = (maxLength = type.match(maxLengthRegex)) && maxLength[1];
type = maxLength ? type.split('(')[0] : type;
columns[val.name] = {
type: type.toLowerCase(),
length: maxLength
};
return columns;
}, {});
}
};
};
client.QueryBuilder = QueryBuilder_SQLite3;
client.QueryCompiler = QueryCompiler_SQLite3;

View File

@ -589,6 +589,12 @@ QueryBuilder.prototype.truncate = function() {
return this;
};
// Retrieves columns for the table specified by `knex(tableName)`
QueryBuilder.prototype.columnInfo = function() {
this._method = 'columnInfo';
return this;
};
// Set a lock for update constraint.
QueryBuilder.prototype.forUpdate = function() {
this._single.lock = 'forUpdate';

View File

@ -13,8 +13,8 @@ var QueryCompiler = function(queryBuilder) {
this.options = queryBuilder._options;
this.single = queryBuilder._single;
this.transacting = queryBuilder._transacting;
this.grouped = _.groupBy(queryBuilder._statements, 'grouping');
this.tableName = this.single.table ? this.formatter.wrap(this.single.table) : '';
this.grouped = _.groupBy(queryBuilder._statements, 'grouping');
this.tableName = this.single.table ? this.formatter.wrap(this.single.table) : '';
};
// Collapse the builder into a single object

View File

@ -26,23 +26,57 @@ module.exports = function(knex) {
});
it('should allow raw queries directly with `knex.raw`', function() {
var tables = {
mysql: 'SHOW TABLES',
postgresql: "SELECT table_name FROM information_schema.tables WHERE table_schema='public'",
sqlite3: "SELECT name FROM sqlite_master WHERE type='table';"
};
return knex.raw(tables[knex.client.dialect]).testSql(function(tester) {
tester(knex.client.dialect, tables[knex.client.dialect]);
});
});
it('should allow using the primary table as a raw statement', function() {
expect(knex(knex.raw("raw_table_name")).toQuery()).to.equal('select * from raw_table_name');
});
it('gets the columnInfo', function() {
return knex('datatype_test').columnInfo().testSql(function(tester) {
tester('mysql',
'select column_name, data_type, character_maximum_length from information_schema.columns where table_name = ? and table_schema = ?',
[ 'datatype_test', 'db_test' ], {
"enum_value": {
"length": 1,
"type": "enum"
},
"uuid": {
"length": 36,
"type": "char"
}
});
tester('postgresql', 'select column_name, data_type, character_maximum_length from information_schema.columns where table_name = ? and table_catalog = ?',
[ 'datatype_test', 'db_test' ],
{
"enum_value": {
"length": null,
"type": "text"
},
"uuid": {
"length": null,
"type": "uuid"
}
});
tester('sqlite3', 'PRAGMA table_info(datatype_test)', [], {
"enum_value": {
"length": null,
"type": "varchar"
},
"uuid": {
"length": "36",
"type": "char"
}
});
});
});
it('should allow renaming a column', function() {

View File

@ -62,13 +62,13 @@ module.exports = function(pgclient, mysqlclient, sqlite3client) {
});
it("raw wheres", function() {
chain = sql().select('*').from('users').whereRaw('id = ? or email = ?', [1, 'foo']).toSQL();
chain = sql().select('*').from('users').where(raw('id = ? or email = ?', [1, 'foo'])).toSQL();
expect(chain.sql).to.equal('select * from "users" where id = ? or email = ?');
expect(chain.bindings).to.eql([1, 'foo']);
});
it("raw or wheres", function() {
chain = sql().select('*').from('users').where('id', '=', 1).orWhereRaw('email = ?', ['foo']).toSQL();
chain = sql().select('*').from('users').where('id', '=', 1).orWhere(raw('email = ?', ['foo'])).toSQL();
expect(chain.sql).to.equal('select * from "users" where "id" = ? or email = ?');
expect(chain.bindings).to.eql([1, 'foo']);
});