add basic schema support on queries

This commit is contained in:
Daniel Teixeira 2015-08-09 20:22:39 -03:00
parent 441675d4db
commit 17df5c6542
9 changed files with 65 additions and 16 deletions

View File

@ -73,6 +73,12 @@ assign(Builder.prototype, {
return this;
},
// Prepends the `schemaName` on `tableName` defined by `.table` and `.join`.
using: function using(schemaName) {
this._single.schema = schemaName;
return this;
},
// Sets the `tableName` on the query.
// Alias to "from" for select and "into" for insert statements
// e.g. builder.insert({a: value}).into('tableName')
@ -96,14 +102,15 @@ assign(Builder.prototype, {
// function(table, first, operator, second)
join: function join(table, first) {
var join;
var schema = this._single.schema;
var joinType = this._joinType();
if (typeof first === 'function') {
join = new JoinClause(table, joinType);
join = new JoinClause(table, joinType, schema);
first.call(join, join);
} else if (joinType === 'raw') {
join = new JoinClause(this.client.raw(table, first), 'raw');
} else {
join = new JoinClause(table, joinType);
join = new JoinClause(table, joinType, schema);
if (arguments.length > 1) {
join.on.apply(join, _.toArray(arguments).slice(1));
}

View File

@ -153,11 +153,12 @@ assign(QueryCompiler.prototype, {
if (!joins) return '';
while (++i < joins.length) {
var join = joins[i];
var table = join.schema ? join.schema + '.' + join.table : join.table;
if (i > 0) sql += ' ';
if (join.joinType === 'raw') {
sql += this.formatter.unwrapRaw(join.table);
} else {
sql += join.joinType + ' join ' + this.formatter.wrap(join.table);
sql += join.joinType + ' join ' + this.formatter.wrap(table);
var ii = -1;
while (++ii < join.clauses.length) {
var clause = join.clauses[ii];
@ -417,7 +418,12 @@ Object.defineProperty(QueryCompiler.prototype, 'tableName', {
get: function get() {
if (!this._tableName) {
// Only call this.formatter.wrap() the first time this property is accessed.
this._tableName = this.single.table ? this.formatter.wrap(this.single.table) : '';
var tableName = this.single.table;
var schemaName = this.single.schema;
if (tableName && schemaName) tableName = schemaName + '.' + tableName;
this._tableName = tableName ? this.formatter.wrap(tableName) : '';
}
return this._tableName;
}

View File

@ -7,7 +7,8 @@ var assign = require('lodash/object/assign');
// The "JoinClause" is an object holding any necessary info about a join,
// including the type, and any associated tables & columns being joined.
function JoinClause(table, type) {
function JoinClause(table, type, schema) {
this.schema = schema;
this.table = table;
this.joinType = type;
this.and = this;
@ -48,8 +49,8 @@ assign(JoinClause.prototype, {
},
// Adds a "using" clause to the current join.
using: function using(table) {
return this.clauses.push([this._bool(), 'using', table]);
using: function using(column) {
return this.clauses.push([this._bool(), 'using', column]);
},
// Adds an "and on" clause to the current join object.

View File

@ -3,4 +3,4 @@
// from the `knex` object, e.g. `knex.select('*').from(...`
'use strict';
module.exports = ['select', 'as', 'columns', 'column', 'from', 'fromJS', 'into', 'table', 'distinct', 'join', 'joinRaw', 'innerJoin', 'leftJoin', 'leftOuterJoin', 'rightJoin', 'rightOuterJoin', 'outerJoin', 'fullOuterJoin', 'crossJoin', 'where', 'andWhere', 'orWhere', 'whereNot', 'orWhereNot', 'whereRaw', 'whereWrapped', 'havingWrapped', 'orWhereRaw', 'whereExists', 'orWhereExists', 'whereNotExists', 'orWhereNotExists', 'whereIn', 'orWhereIn', 'whereNotIn', 'orWhereNotIn', 'whereNull', 'orWhereNull', 'whereNotNull', 'orWhereNotNull', 'whereBetween', 'whereNotBetween', 'orWhereBetween', 'orWhereNotBetween', 'groupBy', 'groupByRaw', 'orderBy', 'orderByRaw', 'union', 'unionAll', 'having', 'havingRaw', 'orHaving', 'orHavingRaw', 'offset', 'limit', 'count', 'min', 'max', 'sum', 'avg', 'increment', 'decrement', 'first', 'debug', 'pluck', 'insert', 'update', 'returning', 'del', 'delete', 'truncate', 'transacting', 'connection'];
module.exports = ['select', 'as', 'columns', 'column', 'from', 'fromJS', 'into', 'using', 'table', 'distinct', 'join', 'joinRaw', 'innerJoin', 'leftJoin', 'leftOuterJoin', 'rightJoin', 'rightOuterJoin', 'outerJoin', 'fullOuterJoin', 'crossJoin', 'where', 'andWhere', 'orWhere', 'whereNot', 'orWhereNot', 'whereRaw', 'whereWrapped', 'havingWrapped', 'orWhereRaw', 'whereExists', 'orWhereExists', 'whereNotExists', 'orWhereNotExists', 'whereIn', 'orWhereIn', 'whereNotIn', 'orWhereNotIn', 'whereNull', 'orWhereNull', 'whereNotNull', 'orWhereNotNull', 'whereBetween', 'whereNotBetween', 'orWhereBetween', 'orWhereNotBetween', 'groupBy', 'groupByRaw', 'orderBy', 'orderByRaw', 'union', 'unionAll', 'having', 'havingRaw', 'orHaving', 'orHavingRaw', 'offset', 'limit', 'count', 'min', 'max', 'sum', 'avg', 'increment', 'decrement', 'first', 'debug', 'pluck', 'insert', 'update', 'returning', 'del', 'delete', 'truncate', 'transacting', 'connection'];

View File

@ -71,6 +71,12 @@ assign(Builder.prototype, {
return this;
},
// Prepends the `schemaName` on `tableName` defined by `.table` and `.join`.
using: function(schemaName) {
this._single.schema = schemaName;
return this;
},
// Sets the `tableName` on the query.
// Alias to "from" for select and "into" for insert statements
// e.g. builder.insert({a: value}).into('tableName')
@ -94,14 +100,15 @@ assign(Builder.prototype, {
// function(table, first, operator, second)
join: function(table, first) {
var join;
var schema = this._single.schema;
var joinType = this._joinType();
if (typeof first === 'function') {
join = new JoinClause(table, joinType);
join = new JoinClause(table, joinType, schema);
first.call(join, join);
} else if (joinType === 'raw') {
join = new JoinClause(this.client.raw(table, first), 'raw');
} else {
join = new JoinClause(table, joinType);
join = new JoinClause(table, joinType, schema);
if (arguments.length > 1) {
join.on.apply(join, _.toArray(arguments).slice(1));
}

View File

@ -153,12 +153,13 @@ assign(QueryCompiler.prototype, {
var sql = '', i = -1, joins = this.grouped.join;
if (!joins) return '';
while (++i < joins.length) {
var join = joins[i]
var join = joins[i];
var table = join.schema ? `${join.schema}.${join.table}` : join.table;
if (i > 0) sql += ' '
if (join.joinType === 'raw') {
sql += this.formatter.unwrapRaw(join.table)
} else {
sql += join.joinType + ' join ' + this.formatter.wrap(join.table)
sql += join.joinType + ' join ' + this.formatter.wrap(table)
var ii = -1
while (++ii < join.clauses.length) {
var clause = join.clauses[ii]
@ -425,7 +426,12 @@ Object.defineProperty(QueryCompiler.prototype, 'tableName', {
get: function() {
if(!this._tableName) {
// Only call this.formatter.wrap() the first time this property is accessed.
this._tableName = this.single.table ? this.formatter.wrap(this.single.table) : '';
var tableName = this.single.table;
var schemaName = this.single.schema;
if (tableName && schemaName) tableName = `${schemaName}.${tableName}`;
this._tableName = tableName ? this.formatter.wrap(tableName) : '';
}
return this._tableName;
}

View File

@ -6,7 +6,8 @@ var assign = require('lodash/object/assign');
// The "JoinClause" is an object holding any necessary info about a join,
// including the type, and any associated tables & columns being joined.
function JoinClause(table, type) {
function JoinClause(table, type, schema) {
this.schema = schema;
this.table = table;
this.joinType = type;
this.and = this;
@ -42,8 +43,8 @@ assign(JoinClause.prototype, {
},
// Adds a "using" clause to the current join.
using: function(table) {
return this.clauses.push([this._bool(), 'using', table]);
using: function(column) {
return this.clauses.push([this._bool(), 'using', column]);
},
// Adds an "and on" clause to the current join object.

View File

@ -9,6 +9,7 @@ module.exports = [
'from',
'fromJS',
'into',
'using',
'table',
'distinct',
'join',

View File

@ -118,6 +118,14 @@ describe("QueryBuilder", function() {
});
});
it("basic table wrapping with declared schema", function() {
testsql(qb().using('myschema').select('*').from('users'), {
mysql: 'select * from `myschema`.`users`',
postgres: 'select * from "myschema"."users"',
default: 'select * from "myschema"."users"'
});
});
it("basic wheres", function() {
testsql(qb().select('*').from('users').where('id', '=', 1), {
mysql: {
@ -1219,6 +1227,18 @@ describe("QueryBuilder", function() {
});
});
it("joins with schema", function() {
testsql(qb().using('myschema').select('*').from('users').join('contacts', 'users.id', '=', 'contacts.id').leftJoin('photos', 'users.id', '=', 'photos.id'), {
mysql: {
sql: 'select * from `myschema`.`users` inner join `myschema`.`contacts` on `users`.`id` = `contacts`.`id` left join `myschema`.`photos` on `users`.`id` = `photos`.`id`',
bindings: []
},
default: {
sql: 'select * from "myschema"."users" inner join "myschema"."contacts" on "users"."id" = "contacts"."id" left join "myschema"."photos" on "users"."id" = "photos"."id"',
bindings: []
}
});
});
it("raw expressions in select", function() {
testsql(qb().select(raw('substr(foo, 6)')).from('users'), {
mysql: {