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

Commit 0c70eb47 by Daniel Durante

Added the ability for schemas to be declared (useful for PostgreSQL). Other dial…

…ects will default to a prefix behavior. Closes #541
1 parent 0aba244e
......@@ -16,7 +16,9 @@ module.exports = (function() {
underscored: false,
syncOnAssociation: true,
paranoid: false,
whereCollection: null
whereCollection: null,
schema: null,
scheamPrefix: ''
}, options || {})
this.name = name
......@@ -116,7 +118,7 @@ module.exports = (function() {
return new Utils.CustomEventEmitter(function(emitter) {
var doQuery = function() {
self.QueryInterface
.createTable(self.tableName, self.attributes, options)
.createTable(self.QueryGenerator.addSchema(self), self.attributes, options)
.success(function() { emitter.emit('success', self) })
.error(function(err) { emitter.emit('error', err) })
.on('sql', function(sql) { emitter.emit('sql', sql) })
......@@ -134,6 +136,15 @@ module.exports = (function() {
return this.QueryInterface.dropTable(this.tableName)
}
DAOFactory.prototype.dropSchema = function(schema) {
return this.QueryInterface.dropSchema(schema)
}
DAOFactory.prototype.schema = function(schema) {
this.options.schema = schema
return this
}
// alias for findAll
DAOFactory.prototype.all = function(options) {
return this.findAll(options)
......@@ -170,7 +181,7 @@ module.exports = (function() {
// whereCollection is used for non-primary key updates
this.options.whereCollection = optcpy.where || null;
return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: 'SELECT' })
return this.QueryInterface.select(this, [this.QueryGenerator.addSchema(this), joinTableName], optcpy, { type: 'SELECT' })
}
/**
......@@ -232,7 +243,7 @@ module.exports = (function() {
options.limit = 1
return this.QueryInterface.select(this, this.tableName, options, {
return this.QueryInterface.select(this, this.QueryGenerator.addSchema(this), options, {
plain: true,
type: 'SELECT',
hasJoin: hasJoin
......@@ -244,7 +255,7 @@ module.exports = (function() {
options.attributes.push(['count(*)', 'count'])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, 'count')
return this.QueryInterface.rawSelect(this.QueryGenerator.addSchema(this), options, 'count')
}
DAOFactory.prototype.max = function(field, options) {
......@@ -252,14 +263,14 @@ module.exports = (function() {
options.attributes.push(['max(' + field + ')', 'max'])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, 'max')
return this.QueryInterface.rawSelect(this.QueryGenerator.addSchema(this), options, 'max')
}
DAOFactory.prototype.min = function(field, options) {
options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push(['min(' + field + ')', 'min'])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, 'min')
return this.QueryInterface.rawSelect(this.QueryGenerator.addSchema(this), options, 'min')
}
DAOFactory.prototype.build = function(values, options) {
......
......@@ -136,7 +136,7 @@ module.exports = (function() {
}
if (this.isNewRecord) {
return this.QueryInterface.insert(this, this.__factory.tableName, values)
return this.QueryInterface.insert(this, this.QueryInterface.QueryGenerator.addSchema(this.__factory), values)
} else {
var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id;
......@@ -144,7 +144,7 @@ module.exports = (function() {
identifier = this.__options.whereCollection;
}
var tableName = this.__factory.tableName
var tableName = this.QueryInterface.QueryGenerator.addSchema(this.__factory)
, query = this.QueryInterface.update(this, tableName, values, identifier)
return query
......@@ -281,7 +281,7 @@ module.exports = (function() {
return this.save()
} else {
var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id
return this.QueryInterface.delete(this, this.__factory.tableName, identifier)
return this.QueryInterface.delete(this, this.QueryInterface.QueryGenerator.addSchema(this.__factory.tableName, this.__factory.options.schema), identifier)
}
}
......@@ -301,7 +301,7 @@ module.exports = (function() {
values = fields;
}
return this.QueryInterface.increment(this, this.__factory.tableName, values, identifier)
return this.QueryInterface.increment(this, this.QueryInterface.QueryGenerator.addSchema(this.__factory.tableName, this.__factory.options.schema), values, identifier)
}
DAO.prototype.decrement = function (fields, count) {
......
......@@ -4,6 +4,39 @@ var Utils = require("../../utils")
module.exports = (function() {
var QueryGenerator = {
addSchema: function(opts) {
var tableName = undefined
var schema = (!!opts && !!opts.options && !!opts.options.schema ? opts.options.schema : undefined)
var schemaPrefix = (!!opts && !!opts.options && !!opts.options.schemaPrefix ? opts.options.schemaPrefix : undefined)
if (!!opts && !!opts.tableName) {
tableName = opts.tableName
}
else if (typeof opts === "string") {
tableName = opts
}
if (!schema || schema.toString().trim() === "") {
return tableName
}
return QueryGenerator.addQuotes(schema + (!schemaPrefix ? '.' : schemaPrefix) + tableName)
},
createSchema: function() {
var query = "SHOW TABLES"
return Utils._.template(query)({})
},
dropSchema: function() {
var query = "SHOW TABLES"
return Utils._.template(query)({})
},
showSchemasQuery: function() {
return "SHOW TABLES"
},
createTableQuery: function(tableName, attributes, options) {
options = Utils._.extend({
engine: 'InnoDB',
......
......@@ -8,6 +8,39 @@ module.exports = (function() {
var QueryGenerator = {
options: {},
addSchema: function(opts) {
var tableName = undefined
var schema = (!!opts.options && !!opts.options.schema ? opts.options.schema : undefined)
var schemaPrefix = (!!opts.options && !!opts.options.schemaPrefix ? opts.options.schemaPrefix : undefined)
if (!!opts.tableName) {
tableName = opts.tableName
}
else if (typeof opts === "string") {
tableName = opts
}
if (!schema || schema.toString().trim() === "") {
return tableName
}
return QueryGenerator.addQuotes(schema) + '.' + QueryGenerator.addQuotes(tableName)
},
createSchema: function(schema) {
var query = "CREATE SCHEMA <%= schema%>;"
return Utils._.template(query)({schema: schema})
},
dropSchema: function(schema) {
var query = "DROP SCHEMA <%= schema%> CASCADE;"
return Utils._.template(query)({schema: schema})
},
showSchemasQuery: function() {
return "SELECT schema_name FROM information_schema.schemata WHERE schema_name <> 'information_schema' AND schema_name != 'public' AND schema_name !~ E'^pg_';"
},
createTableQuery: function(tableName, attributes, options) {
options = Utils._.extend({
}, options || {})
......
module.exports = (function() {
var QueryGenerator = {
addSchema: function(opts) {
throwMethodUndefined('addSchema')
},
/*
Returns a query for creating a table.
Parameters:
......
......@@ -24,6 +24,43 @@ module.exports = (function() {
var QueryGenerator = {
options: {},
addQuotes: function(s, quoteChar) {
return Utils.addTicks(s, quoteChar)
},
addSchema: function(opts) {
var tableName = undefined
var schema = (!!opts && !!opts.options && !!opts.options.schema ? opts.options.schema : undefined)
var schemaPrefix = (!!opts && !!opts.options && !!opts.options.schemaPrefix ? opts.options.schemaPrefix : undefined)
if (!!opts && !!opts.tableName) {
tableName = opts.tableName
}
else if (typeof opts === "string") {
tableName = opts
}
if (!schema || schema.toString().trim() === "") {
return tableName
}
return QueryGenerator.addQuotes(schema + (!schemaPrefix ? '.' : schemaPrefix) + tableName)
},
createSchema: function() {
var query = "SELECT name FROM sqlite_master WHERE type='table' and name!='sqlite_sequence';"
return Utils._.template(query)({})
},
dropSchema: function() {
var query = "SELECT name FROM sqlite_master WHERE type='table' and name!='sqlite_sequence';"
return Utils._.template(query)({})
},
showSchemasQuery: function() {
return "SELECT name FROM sqlite_master WHERE type='table' and name!='sqlite_sequence';"
},
createTableQuery: function(tableName, attributes, options) {
options = options || {}
......
......@@ -10,6 +10,58 @@ module.exports = (function() {
}
Utils.addEventEmitter(QueryInterface)
QueryInterface.prototype.createSchema = function(schema) {
var sql = this.QueryGenerator.createSchema(schema)
return queryAndEmit.call(this, sql, 'createSchema')
}
QueryInterface.prototype.dropSchema = function(schema) {
var sql = this.QueryGenerator.dropSchema(schema)
return queryAndEmit.call(this, sql, 'dropSchema')
}
QueryInterface.prototype.dropAllSchemas = function() {
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
self.showAllSchemas().success(function(schemaNames) {
schemaNames.forEach(function(schemaName) {
chainer.add(self.dropSchema(schemaName))
})
chainer
.run()
.success(function() {
self.emit('dropAllSchemas', null)
emitter.emit('success', null)
})
.error(function(err) {
self.emit('dropAllSchemas', err)
emitter.emit('error', err)
})
}).error(function(err) {
self.emit('dropAllSchemas', err)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.showAllSchemas = function() {
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
var showSchemasSql = self.QueryGenerator.showSchemasQuery()
self.sequelize.query(showSchemasSql, null, { raw: true }).success(function(schemaNames) {
self.emit('showAllSchemas', null)
emitter.emit('success', Utils._.flatten(Utils._.map(schemaNames, function(value){ return value.schema_name })))
}).error(function(err) {
self.emit('showAllSchemas', err)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.createTable = function(tableName, attributes, options) {
var attributeHashes = {}
......
......@@ -210,6 +210,38 @@ module.exports = (function() {
return this.connectorManager.query(sql, callee, options)
}
Sequelize.prototype.createSchema = function(schema) {
var chainer = new Utils.QueryChainer()
chainer.add(this.getQueryInterface().createSchema(schema))
return chainer.run()
}
Sequelize.prototype.showAllSchemas = function() {
var chainer = new Utils.QueryChainer()
chainer.add(this.getQueryInterface().showAllSchemas())
return chainer.run()
}
Sequelize.prototype.dropSchema = function(schema) {
var chainer = new Utils.QueryChainer()
chainer.add(this.getQueryInterface().dropSchema(schema))
return chainer.run()
}
Sequelize.prototype.dropAllSchemas = function() {
var self = this
var chainer = new Utils.QueryChainer()
chainer.add(self.getQueryInterface().dropAllSchemas())
return chainer.run()
}
Sequelize.prototype.sync = function(options) {
options = options || {}
......
......@@ -1076,4 +1076,82 @@ describe(Helpers.getTestDialectTeaser("DAOFactory"), function() {
})
})
}) //- describe: max
describe('schematic support', function() {
before(function(done){
var self = this;
this.UserPublic = this.sequelize.define('UserPublic', {
age: Sequelize.INTEGER
})
this.UserSpecial = this.sequelize.define('UserSpecial', {
age: Sequelize.INTEGER
})
self.sequelize.dropAllSchemas().success(function(){
self.sequelize.createSchema('schema_test').success(function(){
self.sequelize.createSchema('special').success(function(){
self.UserSpecial.schema('special').sync({force: true}).success(function(UserSpecialSync){
self.UserSpecialSync = UserSpecialSync;
done()
})
})
})
})
})
it("should be able to list schemas", function(done){
this.sequelize.showAllSchemas().success(function(schemas){
expect(schemas).toBeDefined()
expect(schemas[0]).toBeArray()
expect(schemas[0].length).toEqual(2)
done()
})
})
if (dialect === "mysql") {
it("should take schemaPrefix into account if applicable", function(done){
var UserSpecialUnderscore = this.sequelize.define('UserSpecialUnderscore', {age: Sequelize.INTEGER}, {schema: 'hello', schemaPrefix: '_'})
UserSpecialUnderscore.sync({force: true}).success(function(User){
User.create({age: 3}).on('sql', function(sql){
expect(sql).toBeDefined()
expect(sql.indexOf('INSERT INTO `hello_UserSpecialUnderscores`')).toBeGreaterThan(-1)
done()
})
})
})
}
it("should be able to create and update records under any valid schematic", function(done){
this.UserPublic.sync({ force: true }).success(function(UserPublicSync){
UserPublicSync.create({age: 3}).on('sql', function(UserPublic){
this.UserSpecialSync.schema('special').create({age: 3})
.on('sql', function(UserSpecial){
expect(UserSpecial).toBeDefined()
expect(UserPublic).toBeDefined()
if (dialect === "postgres") {
expect(UserSpecial.indexOf('INSERT INTO "special"."UserSpecials"')).toBeGreaterThan(-1)
expect(UserPublic.indexOf('INSERT INTO "UserPublics"')).toBeGreaterThan(-1)
} else {
expect(UserSpecial.indexOf('INSERT INTO `special.UserSpecials`')).toBeGreaterThan(-1)
expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).toBeGreaterThan(-1)
}
})
.success(function(UserSpecial){
UserSpecial.updateAttributes({age: 5})
.on('sql', function(user){
expect(user).toBeDefined()
if (dialect === "postgres") {
expect(user.indexOf('UPDATE "special"."UserSpecials"')).toBeGreaterThan(-1)
} else {
expect(user.indexOf('UPDATE `special.UserSpecials`')).toBeGreaterThan(-1)
}
done()
})
}.bind(this))
}.bind(this))
}.bind(this))
})
})
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!