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

Commit 67762ac6 by Jan Aagaard Meier

Updated docs for raw query

1 parent ebd2b5d1
...@@ -7,5 +7,6 @@ npm-debug.log ...@@ -7,5 +7,6 @@ npm-debug.log
*~ *~
test/binary/tmp/* test/binary/tmp/*
test/tmp/* test/tmp/*
test/dialects/sqlite/test.sqlite
test/sqlite/test.sqlite test/sqlite/test.sqlite
coverage-* coverage-*
As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can utilize the function `sequelize.query`. As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can utilize the function `sequelize.query`.
By default the function will return two arguments - a results array, and an object containing metadata (affected rows etc.). Note that since this is a raw query, the metadata (property names etc.) is dialect specific. By default the function will return two arguments - a results array, and an object containing metadata (affected rows etc.). Note that since this is a raw query, the metadata (property names etc.) is dialect specific. Some dialects return the metadata "within" the results object (as properties on an array). However, two arguments will always be returned, but for MSSQL and MySQL it will be two references to the same object.
```js ```js
sequelize.query("UPDATE users SET y = 42 WHERE x = 12").spread(function(results, metadata) { sequelize.query("UPDATE users SET y = 42 WHERE x = 12").spread(function(results, metadata) {
...@@ -29,20 +29,20 @@ sequelize.query('SELECT * FROM projects', Projects).then(function(projects){ ...@@ -29,20 +29,20 @@ sequelize.query('SELECT * FROM projects', Projects).then(function(projects){
``` ```
# Replacements # Replacements
Replacements in a query can be done in two different ways, either using named parameters (starting with `:`), or unnamed, represented by a `?`. Replacements can be passed in the options object. Replacements in a query can be done in two different ways, either using named parameters (starting with `:`), or unnamed, represented by a `?`. Replacements are passed in the options object.
* If an array is passed, `?` will be replaced in the order that they appear in the array * If an array is passed, `?` will be replaced in the order that they appear in the array
* If an object is passed, `:key` will be replaced with the keys from that object. If the object contains keys not found in the query or vice verca, an exception will be thrown. * If an object is passed, `:key` will be replaced with the keys from that object. If the object contains keys not found in the query or vice verca, an exception will be thrown.
```js ```js
sequelize.query('SELECT * FROM projects WHERE status = ?', sequelize.query('SELECT * FROM projects WHERE status = ?',
{ replacements: ['active'] } { replacements: ['active'], type: sequelize.QueryTypes.SELECT }
).then(function(projects) { ).then(function(projects) {
console.log(projects) console.log(projects)
}) })
sequelize.query('SELECT * FROM projects WHERE status = :status ', sequelize.query('SELECT * FROM projects WHERE status = :status ',
{ replacements: { status: 'active' }} { replacements: { status: 'active', type: sequelize.QueryTypes.SELECT }}
).then(function(projects) { ).then(function(projects) {
console.log(projects) console.log(projects)
}) })
......
...@@ -157,6 +157,10 @@ module.exports = (function() { ...@@ -157,6 +157,10 @@ module.exports = (function() {
return this.options.type === QueryTypes.BULKDELETE; return this.options.type === QueryTypes.BULKDELETE;
}; };
AbstractQuery.prototype.isForeignKeysQuery = function() {
return this.options.type === QueryTypes.FOREIGNKEYS;
};
AbstractQuery.prototype.isUpdateQuery = function() { AbstractQuery.prototype.isUpdateQuery = function() {
if (this.options.type === QueryTypes.UPDATE) { if (this.options.type === QueryTypes.UPDATE) {
return true; return true;
......
...@@ -153,6 +153,8 @@ module.exports = (function() { ...@@ -153,6 +153,8 @@ module.exports = (function() {
result = data[0] && data[0].AFFECTEDROWS; result = data[0] && data[0].AFFECTEDROWS;
} else if (this.isVersionQuery()) { } else if (this.isVersionQuery()) {
result = data[0].version; result = data[0].version;
} else if (this.isForeignKeysQuery()) {
result = data;
} else if (this.isRawQuery()) { } else if (this.isRawQuery()) {
// MSSQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta // MSSQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta
result = [data, data]; result = [data, data];
......
...@@ -95,6 +95,8 @@ module.exports = (function() { ...@@ -95,6 +95,8 @@ module.exports = (function() {
result = data.affectedRows; result = data.affectedRows;
} else if (this.isVersionQuery()) { } else if (this.isVersionQuery()) {
result = data[0].version; result = data[0].version;
} else if (this.isForeignKeysQuery()) {
result = data;
} else if (this.isRawQuery()) { } else if (this.isRawQuery()) {
// MySQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta // MySQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta
result = [data, data]; result = [data, data];
......
...@@ -12,4 +12,5 @@ module.exports = { ...@@ -12,4 +12,5 @@ module.exports = {
SHOWINDEXES: 'SHOWINDEXES', SHOWINDEXES: 'SHOWINDEXES',
DESCRIBE: 'DESCRIBE', DESCRIBE: 'DESCRIBE',
RAW: 'RAW', RAW: 'RAW',
FOREIGNKEYS: 'FOREIGNKEYS',
}; };
...@@ -634,11 +634,11 @@ module.exports = (function() { ...@@ -634,11 +634,11 @@ module.exports = (function() {
* *
* ```js * ```js
* sequlize.query('SELECT...').spread(function (results, metadata) { * sequlize.query('SELECT...').spread(function (results, metadata) {
* * // Raw query - use spread
* }); * });
* *
* sequlize.query('SELECT...', { type: sequelize.QueryTypes.SELECT }).then(function (results) { * sequlize.query('SELECT...', { type: sequelize.QueryTypes.SELECT }).then(function (results) {
* * // SELECT query - use then
* }) * })
* ``` * ```
* *
......
...@@ -34,24 +34,21 @@ if (Support.dialectIsMySQL()) { ...@@ -34,24 +34,21 @@ if (Support.dialectIsMySQL()) {
}); });
}); });
it('accepts new queries after shutting down a connection', function(done) { it('accepts new queries after shutting down a connection', function() {
// Create a sequelize instance with pooling disabled // Create a sequelize instance with pooling disabled
var sequelize = Support.createSequelizeInstance({ pool: false }); var sequelize = Support.createSequelizeInstance({ pool: false });
var User = sequelize.define('User', { username: DataTypes.STRING }); var User = sequelize.define('User', { username: DataTypes.STRING });
User.sync({force: true}).on('success', function() { return User.sync({force: true}).then(function() {
User.create({username: 'user1'}).on('success', function() { return User.create({username: 'user1'});
}).then(function() {
// After 100 ms the DB connection will be disconnected for inactivity // After 100 ms the DB connection will be disconnected for inactivity
setTimeout(function() { return sequelize.Promise.delay(100);
}).then(function () {
// This query will be queued just after the `client.end` is executed and before its callback is called // This query will be queued just after the `client.end` is executed and before its callback is called
sequelize.query('SELECT COUNT(*) AS count FROM Users', { type: sequelize.QueryTypes.SELECT }).on('success', function(count) { return sequelize.query('SELECT COUNT(*) AS count FROM Users', { type: sequelize.QueryTypes.SELECT });
}).then(function(count) {
expect(count[0].count).to.equal(1); expect(count[0].count).to.equal(1);
done();
}).error(function(error) {
expect(error).to.not.exist;
});
}, 100);
});
}); });
}); });
......
...@@ -386,4 +386,65 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -386,4 +386,65 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
}); });
}); });
}); });
describe('describeForeignKeys', function() {
beforeEach(function() {
return this.queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
}
}).bind(this).then(function() {
return this.queryInterface.createTable('hosts', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
admin: {
type: DataTypes.INTEGER,
references: 'users',
referenceKey: 'id'
},
operator: {
type: DataTypes.INTEGER,
references: 'users',
referenceKey: 'id',
onUpdate: 'cascade'
},
owner: {
type: DataTypes.INTEGER,
references: 'users',
referenceKey: 'id',
onUpdate: 'cascade',
onDelete: 'set null'
}
});
});
});
it('should get a list of foreign keys for the table', function() {
var sql = this.queryInterface.QueryGenerator.getForeignKeysQuery('hosts', this.sequelize.config.database);
return this.sequelize.query(sql, {type: this.sequelize.QueryTypes.FOREIGNKEYS}).then(function(fks) {
expect(fks).to.have.length(3);
var keys = Object.keys(fks[0]),
keys2 = Object.keys(fks[1]),
keys3 = Object.keys(fks[2]);
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(keys).to.have.length(6);
expect(keys2).to.have.length(7);
expect(keys3).to.have.length(7);
} else if (dialect === 'sqlite') {
expect(keys).to.have.length(8);
} else if (dialect === 'mysql' || dialect === 'mssql') {
expect(keys).to.have.length(1);
} else {
console.log("This test doesn't support " + dialect);
}
});
});
});
}); });
...@@ -29,13 +29,17 @@ describe(Support.getTestDialectTeaser('Sequelize#transaction'), function() { ...@@ -29,13 +29,17 @@ describe(Support.getTestDialectTeaser('Sequelize#transaction'), function() {
if (Support.getTestDialect() !== 'sqlite') { if (Support.getTestDialect() !== 'sqlite') {
it('works for long running transactions', function() { it('works for long running transactions', function() {
return Support.prepareTransactionTest(this.sequelize, function(sequelize) { this.timeout(10000);
var User = sequelize.define('User', { return Support.prepareTransactionTest(this.sequelize).bind(this).then(function(sequelize) {
this.sequelize = sequelize;
this.User = sequelize.define('User', {
name: Support.Sequelize.STRING name: Support.Sequelize.STRING
}, { timestamps: false }); }, { timestamps: false });
return sequelize.sync({ force: true }).then(function() { return sequelize.sync({ force: true });
return sequelize.transaction(); }).then(function() {
return this.sequelize.transaction();
}).then(function(t) { }).then(function(t) {
var query = 'select sleep(2);'; var query = 'select sleep(2);';
...@@ -50,25 +54,20 @@ describe(Support.getTestDialectTeaser('Sequelize#transaction'), function() { ...@@ -50,25 +54,20 @@ describe(Support.getTestDialectTeaser('Sequelize#transaction'), function() {
break; break;
} }
return sequelize.query(query, { transaction: t }).then(function() { return this.sequelize.query(query, { transaction: t }).bind(this).then(function() {
var dao = User.build({ name: 'foo' }); return this.User.create({ name: 'foo' });
return sequelize.getQueryInterface().QueryGenerator.insertQuery(User.tableName, dao.values, User.rawAttributes);
}).then(function() { }).then(function() {
return Promise.delay(1000); return this.sequelize.query(query, { transaction: t });
}).then(function() {
return sequelize.query(query, { transaction: t });
}).then(function() { }).then(function() {
return t.commit(); return t.commit();
}); });
}).then(function() { }).then(function() {
return User.all(); return this.User.all();
}).then(function(users) { }).then(function(users) {
expect(users.length).to.equal(1); expect(users.length).to.equal(1);
expect(users[0].name).to.equal('foo'); expect(users[0].name).to.equal('foo');
}); });
}); });
});
} }
}); });
......
...@@ -11,7 +11,7 @@ var chai = require('chai') ...@@ -11,7 +11,7 @@ var chai = require('chai')
if (current.dialect.supports.transactions) { if (current.dialect.supports.transactions) {
describe.skip(Support.getTestDialectTeaser('Transaction'), function() { describe(Support.getTestDialectTeaser('Transaction'), function() {
this.timeout(4000); this.timeout(4000);
describe('constructor', function() { describe('constructor', function() {
it('stores options', function() { it('stores options', function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!