不要怂,就是干,撸起袖子干!

Commit 2b4195cb by Matt Liszewski

make schema a property on the model independent of prototype

1 parent 46a3cd42
...@@ -202,6 +202,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -202,6 +202,7 @@ var BelongsToMany = function(source, target, options) {
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false
* @param {String} [options.schema] Apply a schema on the related model
* @return {Promise<Array<Instance>>} * @return {Promise<Array<Instance>>}
* @method getAssociations * @method getAssociations
*/ */
...@@ -466,6 +467,10 @@ BelongsToMany.prototype.injectGetter = function(obj) { ...@@ -466,6 +467,10 @@ BelongsToMany.prototype.injectGetter = function(obj) {
} }
} }
if (options.hasOwnProperty('schema')) {
model = model.schema(options.schema, options.schemaDelimiter);
}
return model.findAll(options); return model.findAll(options);
}; };
......
...@@ -76,6 +76,7 @@ var BelongsTo = function(source, target, options) { ...@@ -76,6 +76,7 @@ var BelongsTo = function(source, target, options) {
* *
* @param {Object} [options] * @param {Object} [options]
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false. * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false.
* @param {String} [options.schema] Apply a schema on the related model
* @return {Promise<Instance>} * @return {Promise<Instance>}
* @method getAssociation * @method getAssociation
*/ */
...@@ -159,6 +160,10 @@ BelongsTo.prototype.injectGetter = function(instancePrototype) { ...@@ -159,6 +160,10 @@ BelongsTo.prototype.injectGetter = function(instancePrototype) {
} }
} }
if (options.hasOwnProperty('schema')) {
model = model.schema(options.schema, options.schemaDelimiter);
}
return model.find(options); return model.find(options);
}; };
......
...@@ -97,6 +97,7 @@ var HasMany = function(source, target, options) { ...@@ -97,6 +97,7 @@ var HasMany = function(source, target, options) {
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false
* @param {String} [options.schema] Apply a schema on the related model
* @return {Promise<Array<Instance>>} * @return {Promise<Array<Instance>>}
* @method getAssociations * @method getAssociations
*/ */
...@@ -312,6 +313,11 @@ HasMany.prototype.get = function(instances, options) { ...@@ -312,6 +313,11 @@ HasMany.prototype.get = function(instances, options) {
} }
} }
if (options.hasOwnProperty('schema')) {
Model = Model.schema(options.schema, options.schemaDelimiter);
}
return Model.findAll(options).then(function (results) { return Model.findAll(options).then(function (results) {
if (instance) return results; if (instance) return results;
......
...@@ -70,6 +70,7 @@ var HasOne = function(srcModel, targetModel, options) { ...@@ -70,6 +70,7 @@ var HasOne = function(srcModel, targetModel, options) {
* *
* @param {Object} [options] * @param {Object} [options]
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false
* @param {String} [options.schema] Apply a schema on the related model
* @return {Promise<Instance>} * @return {Promise<Instance>}
* @method getAssociation * @method getAssociation
*/ */
...@@ -153,6 +154,10 @@ HasOne.prototype.injectGetter = function(instancePrototype) { ...@@ -153,6 +154,10 @@ HasOne.prototype.injectGetter = function(instancePrototype) {
} }
} }
if (options.hasOwnProperty('schema')) {
model = model.schema(options.schema, options.schemaDelimiter);
}
return model.find(options); return model.find(options);
}; };
......
...@@ -24,14 +24,12 @@ function addForeignKeyConstraints (newAttribute, source, target, options, key) { ...@@ -24,14 +24,12 @@ function addForeignKeyConstraints (newAttribute, source, target, options, key) {
.map(function($key) { return source.rawAttributes[$key].field || $key; }).value(); .map(function($key) { return source.rawAttributes[$key].field || $key; }).value();
if (primaryKeys.length === 1) { if (primaryKeys.length === 1) {
if (!!source.options.schema) { if (!!source.$schema) {
newAttribute.references = { newAttribute.references = {
model: source.modelManager.sequelize.queryInterface.QueryGenerator.addSchema({ model: source.modelManager.sequelize.queryInterface.QueryGenerator.addSchema({
tableName: source.tableName, tableName: source.tableName,
options: { $schema: source.$schema,
schema: source.options.schema, $schemaDelimiter: source.$schemaDelimiter
schemaDelimiter: source.options.schemaDelimiter
}
}) })
}; };
} else { } else {
......
...@@ -20,18 +20,16 @@ var QueryGenerator = { ...@@ -20,18 +20,16 @@ var QueryGenerator = {
options: {}, options: {},
addSchema: function(param) { addSchema: function(param) {
var self = this var self = this;
, schema = (!param.options && param.schema) || (param.options && param.options.schema ? param.options.schema : undefined)
, schemaDelimiter = (param.options && param.options.schemaDelimiter ? param.options.schemaDelimiter : undefined);
if (!schema) return param.tableName || param; if (!param.$schema) return param.tableName || param;
return { return {
tableName: param.tableName || param, tableName: param.tableName || param,
table: param.tableName || param, table: param.tableName || param,
name: param.name || param, name: param.name || param,
schema: schema, schema: param.$schema,
delimiter: schemaDelimiter || '.', delimiter: param.$schemaDelimiter || '.',
toString: function() { toString: function() {
return self.quoteTable(this); return self.quoteTable(this);
} }
...@@ -69,10 +67,8 @@ var QueryGenerator = { ...@@ -69,10 +67,8 @@ var QueryGenerator = {
var table = this.quoteTable( var table = this.quoteTable(
this.addSchema({ this.addSchema({
tableName: tableName, tableName: tableName,
options: { $schema: schema,
schema: schema, $schemaDelimiter: schemaDelimiter
schemaDelimiter: schemaDelimiter
}
}) })
); );
...@@ -1588,7 +1584,7 @@ var QueryGenerator = { ...@@ -1588,7 +1584,7 @@ var QueryGenerator = {
left.rawAttributes[left.primaryKeyAttribute].field left.rawAttributes[left.primaryKeyAttribute].field
/* Attributes for the right side */ /* Attributes for the right side */
, right = association.target , right = include.model
, asRight = include.as , asRight = include.as
, tableRight = right.getTableName() , tableRight = right.getTableName()
, fieldRight = association instanceof BelongsTo ? , fieldRight = association instanceof BelongsTo ?
......
...@@ -293,13 +293,13 @@ var QueryGenerator = { ...@@ -293,13 +293,13 @@ var QueryGenerator = {
}, },
describeTableQuery: function(tableName, schema, schemaDelimiter) { describeTableQuery: function(tableName, schema, schemaDelimiter) {
var options = {}; var table = {};
options.schema = schema; table.$schema = schema;
options.schemaDelimiter = schemaDelimiter; table.$schemaDelimiter = schemaDelimiter;
options.quoted = false; table.tableName = tableName;
var sql = 'PRAGMA TABLE_INFO(<%= tableName %>);'; var sql = 'PRAGMA TABLE_INFO(<%= tableName %>);';
return Utils._.template(sql)({ tableName: this.addSchema({tableName: this.quoteIdentifiers(tableName), options: options})}); return Utils._.template(sql)({tableName: this.quoteTable(this.addSchema(table))});
}, },
removeColumnQuery: function(tableName, attributes) { removeColumnQuery: function(tableName, attributes) {
......
...@@ -641,14 +641,14 @@ Instance.prototype.save = function(options) { ...@@ -641,14 +641,14 @@ Instance.prototype.save = function(options) {
if (self.isNewRecord) { if (self.isNewRecord) {
query = 'insert'; query = 'insert';
args = [self, self.Model.getTableName(options), values, options]; args = [self, self.$Model.getTableName(options), values, options];
} else { } else {
var where = this.where(); var where = this.where();
where = Utils.mapValueFieldNames(where, Object.keys(where), this.Model); where = Utils.mapValueFieldNames(where, Object.keys(where), this.Model);
query = 'update'; query = 'update';
args = [self, self.Model.getTableName(options), values, where, options]; args = [self, self.$Model.getTableName(options), values, where, options];
} }
return self.sequelize.getQueryInterface()[query].apply(self.sequelize.getQueryInterface(), args) return self.sequelize.getQueryInterface()[query].apply(self.sequelize.getQueryInterface(), args)
...@@ -832,9 +832,9 @@ Instance.prototype.destroy = function(options) { ...@@ -832,9 +832,9 @@ Instance.prototype.destroy = function(options) {
this.setDataValue(field, values[field]); this.setDataValue(field, values[field]);
return this.sequelize.getQueryInterface().update(this, this.Model.getTableName(options), values, where, _.defaults({ hooks: false }, options)); return this.sequelize.getQueryInterface().update(this, this.$Model.getTableName(options), values, where, _.defaults({ hooks: false }, options));
} else { } else {
return this.sequelize.getQueryInterface().delete(this, this.Model.getTableName(options), where, _.assign({ type: QueryTypes.DELETE, limit: null }, options)); return this.sequelize.getQueryInterface().delete(this, this.$Model.getTableName(options), where, _.assign({ type: QueryTypes.DELETE, limit: null }, options));
} }
}).tap(function() { }).tap(function() {
// Run after hook // Run after hook
...@@ -943,7 +943,7 @@ Instance.prototype.increment = function(fields, options) { ...@@ -943,7 +943,7 @@ Instance.prototype.increment = function(fields, options) {
} }
}, this); }, this);
return this.sequelize.getQueryInterface().increment(this, this.Model.getTableName(options), values, where, options).return(this); return this.sequelize.getQueryInterface().increment(this, this.$Model.getTableName(options), values, where, options).return(this);
}; };
/** /**
......
...@@ -60,6 +60,9 @@ var Model = function(name, attributes, options) { ...@@ -60,6 +60,9 @@ var Model = function(name, attributes, options) {
this.tableName = this.options.tableName; this.tableName = this.options.tableName;
} }
this.$schema = this.options.schema;
this.$schemaDelimiter = this.options.schemaDelimiter;
// error check options // error check options
Utils._.each(options.validate, function(validator, validatorType) { Utils._.each(options.validate, function(validator, validatorType) {
if (Utils._.contains(Utils._.keys(attributes), validatorType)) { if (Utils._.contains(Utils._.keys(attributes), validatorType)) {
...@@ -271,8 +274,6 @@ function conformInclude(include, self) { ...@@ -271,8 +274,6 @@ function conformInclude(include, self) {
include = { model: model, association: include, as: include.as }; include = { model: model, association: include, as: include.as };
} else if (include instanceof Model) { } else if (include instanceof Model) {
model = include;
include = { model: include }; include = { model: include };
} else if (_.isPlainObject(include)) { } else if (_.isPlainObject(include)) {
if (include.association) { if (include.association) {
...@@ -1033,19 +1034,28 @@ Model.prototype.dropSchema = function(schema) { ...@@ -1033,19 +1034,28 @@ Model.prototype.dropSchema = function(schema) {
* @return {this} * @return {this}
*/ */
Model.prototype.schema = function(schema, options) { // testhint options:none Model.prototype.schema = function(schema, options) { // testhint options:none
this.options.schema = schema; var self = this;
var clone = Object.create(self);
clone.$schema = schema;
if (!!options) { if (!!options) {
if (typeof options === 'string') { if (typeof options === 'string') {
this.options.schemaDelimiter = options; clone.$schemaDelimiter = options;
} else { } else {
if (!!options.schemaDelimiter) { if (!!options.schemaDelimiter) {
this.options.schemaDelimiter = options.schemaDelimiter; clone.$schemaDelimiter = options.schemaDelimiter;
} }
} }
} }
return this; clone.Instance = function() {
self.Instance.apply(this, arguments);
};
clone.Instance.prototype = Object.create(self.Instance.prototype);
clone.Instance.prototype.$Model = clone;
return clone;
}; };
/** /**
...@@ -1711,7 +1721,9 @@ Model.prototype.build = function(values, options) { // testhint options:none ...@@ -1711,7 +1721,9 @@ Model.prototype.build = function(values, options) { // testhint options:none
return this.bulkBuild(values, options); return this.bulkBuild(values, options);
} }
options = _.extend({ options = _.extend({
isNewRecord: true isNewRecord: true,
$schema: this.$schema,
$schemaDelimiter: this.$schemaDelimiter
}, options || {}); }, options || {});
if (options.attributes) { if (options.attributes) {
...@@ -2557,7 +2569,7 @@ Model.prototype.update = function(values, options) { ...@@ -2557,7 +2569,7 @@ Model.prototype.update = function(values, options) {
* @return {Promise} * @return {Promise}
*/ */
Model.prototype.describe = function(schema, options) { Model.prototype.describe = function(schema, options) {
return this.QueryInterface.describeTable(this.tableName, _.assign({schema: schema || this.options.schema || undefined}, options)); return this.QueryInterface.describeTable(this.tableName, _.assign({schema: schema || this.$schema || undefined}, options));
}; };
Model.prototype.$getDefaultTimestamp = function(attr) { Model.prototype.$getDefaultTimestamp = function(attr) {
......
...@@ -156,10 +156,11 @@ QueryInterface.prototype.createTable = function(tableName, attributes, options, ...@@ -156,10 +156,11 @@ QueryInterface.prototype.createTable = function(tableName, attributes, options,
} }
} }
if (!tableName.schema && options.schema) { if (!tableName.schema &&
(options.schema || (!!model && model.$schema))) {
tableName = self.QueryGenerator.addSchema({ tableName = self.QueryGenerator.addSchema({
tableName: tableName, tableName: tableName,
schema: options.schema $schema: (!!model && model.$schema) || options.schema
}); });
} }
...@@ -173,10 +174,11 @@ QueryInterface.prototype.createTable = function(tableName, attributes, options, ...@@ -173,10 +174,11 @@ QueryInterface.prototype.createTable = function(tableName, attributes, options,
}); });
}); });
} else { } else {
if (!tableName.schema && options.schema) { if (!tableName.schema &&
(options.schema || (!!model && model.$schema))) {
tableName = self.QueryGenerator.addSchema({ tableName = self.QueryGenerator.addSchema({
tableName: tableName, tableName: tableName,
schema: options.schema $schema: (!!model && model.$schema) || options.schema
}); });
} }
...@@ -693,7 +695,7 @@ QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelec ...@@ -693,7 +695,7 @@ QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelec
if (options.schema) { if (options.schema) {
tableName = this.QueryGenerator.addSchema({ tableName = this.QueryGenerator.addSchema({
tableName: tableName, tableName: tableName,
schema: options.schema $schema: options.schema
}); });
} }
......
...@@ -206,7 +206,12 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -206,7 +206,12 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
return self.sequelize.dropAllSchemas().then(function() { return self.sequelize.dropAllSchemas().then(function() {
return self.sequelize.createSchema('acme'); return self.sequelize.createSchema('acme');
}).then(function() { }).then(function() {
return self.sequelize.sync({force: true}); return Promise.all([
AcmeUser.sync({force: true}),
AcmeProject.sync({force: true})
]);
}).then(function() {
return AcmeProjectUsers.sync({force: true});
}).bind({}).then(function() { }).bind({}).then(function() {
return AcmeUser.create(); return AcmeUser.create();
}).then(function(u) { }).then(function(u) {
......
...@@ -110,7 +110,9 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() { ...@@ -110,7 +110,9 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() {
return self.sequelize.dropAllSchemas().then(function() { return self.sequelize.dropAllSchemas().then(function() {
return self.sequelize.createSchema('archive'); return self.sequelize.createSchema('archive');
}).then(function() { }).then(function() {
return self.sequelize.sync({force: true }); return User.sync({force: true });
}).then(function() {
return Task.sync({force: true });
}).then(function() { }).then(function() {
return Promise.all([ return Promise.all([
User.create({ username: 'foo', gender: 'male' }), User.create({ username: 'foo', gender: 'male' }),
......
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, current = Support.sequelize;
describe(Support.getTestDialectTeaser('Model') + 'Schemas', function() {
if (current.dialect.supports.schemas) {
var Project = current.define('project'),
Company = current.define('company', {}, {
schema: 'default',
schemaDelimiter: '&'
});
describe('schema', function() {
it('should work with no default schema', function() {
expect(Project.$schema).to.be.null;
});
it('should apply default schema from define', function() {
expect(Company.$schema).to.equal('default');
});
it('should be able to override the default schema', function() {
expect(Company.schema('newSchema').$schema).to.equal('newSchema');
});
it('should be able nullify schema', function() {
expect(Company.schema(null).$schema).to.be.null;
});
it('should support multiple, coexistent schema models', function() {
var schema1 = Company.schema('schema1')
, schema2 = Company.schema('schema1');
expect(schema1.$schema).to.equal('schema1');
expect(schema2.$schema).to.equal('schema1');
});
});
describe('schema delimiter', function() {
it('should work with no default schema delimiter', function() {
expect(Project.$schemaDelimiter).to.equal('');
});
it('should apply default schema delimiter from define', function() {
expect(Company.$schemaDelimiter).to.equal('&');
});
it('should be able to override the default schema delimiter', function() {
expect(Company.schema(Company.$schema,'^').$schemaDelimiter).to.equal('^');
});
it('should support multiple, coexistent schema delimiter models', function() {
var schema1 = Company.schema(Company.$schema,'$')
, schema2 = Company.schema(Company.$schema,'#');
expect(schema1.$schemaDelimiter).to.equal('$');
expect(schema2.$schemaDelimiter).to.equal('#');
});
});
}
});
...@@ -29,7 +29,7 @@ suite(Support.getTestDialectTeaser('SQL'), function() { ...@@ -29,7 +29,7 @@ suite(Support.getTestDialectTeaser('SQL'), function() {
}); });
expectsql(sql.addIndexQuery(sql.quoteTable(sql.addSchema({ expectsql(sql.addIndexQuery(sql.quoteTable(sql.addSchema({
schema: 'schema', $schema: 'schema',
tableName: 'table' tableName: 'table'
})), ['column1', 'column2'], {}), { })), ['column1', 'column2'], {}), {
default: 'CREATE INDEX [schema_table_column1_column2] ON [schema].[table] ([column1], [column2])' default: 'CREATE INDEX [schema_table_column1_column2] ON [schema].[table] ([column1], [column2])'
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!