213 lines
6.1 KiB
JavaScript
213 lines
6.1 KiB
JavaScript
'use strict';
|
|
|
|
var Utils = require('../../utils')
|
|
, AbstractQuery = require('../abstract/query')
|
|
, uuid = require('node-uuid')
|
|
, sequelizeErrors = require('../../errors.js')
|
|
;
|
|
|
|
module.exports = (function() {
|
|
var Query = function(connection, sequelize, options) {
|
|
this.connection = connection;
|
|
this.instance = options.instance;
|
|
this.model = options.model;
|
|
this.sequelize = sequelize;
|
|
this.uuid = uuid.v4();
|
|
this.options = Utils._.extend({
|
|
logging: console.log,
|
|
plain: false,
|
|
raw: false
|
|
}, options || {});
|
|
|
|
this.checkLoggingOption();
|
|
|
|
this.maxRows= options.maxRows || 100;
|
|
this.outFormat= options.outFormat || this.sequelize.connectionManager.lib.OBJECT;
|
|
this.autoCommit= (options.autoCommit===false? false : true);
|
|
|
|
};
|
|
|
|
Utils.inherit(Query, AbstractQuery);
|
|
Query.prototype.run = function(sql) {
|
|
var self = this;
|
|
// this.sql = sql;
|
|
if(sql.match(/^(SELECT|INSERT|DELETE)/)){
|
|
this.sql = sql.replace(/; *$/,'');
|
|
}else{
|
|
this.sql = sql;
|
|
}
|
|
|
|
this.sequelize.log('Executing (' + (this.connection.uuid || 'default') + '): ' + this.sql, this.options);
|
|
|
|
var promise = new Utils.Promise(function(resolve, reject) {
|
|
|
|
if( self.sql==='START TRANSACTION;'
|
|
|| self.sql==='SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;'
|
|
){
|
|
self.autoCommit=false;
|
|
resolve();
|
|
return;
|
|
}else if( self.sql==='SET autocommit = 1;'){
|
|
// self.connection.autoCommit=true;
|
|
resolve();
|
|
return;
|
|
}else if( self.sql==='COMMIT;'){
|
|
self.connection.commit(function(err, results, fields) {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
return;
|
|
}else if( self.sql==='ROLLBACK;'){
|
|
self.connection.rollback(function(err, results, fields) {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
return;
|
|
}else{
|
|
if(self.autoCommit !== false ){
|
|
self.autoCommit=true;
|
|
}
|
|
|
|
self.options.bind = self.options.bind || [];
|
|
|
|
self.connection.execute(self.sql, self.options.bind, { maxRows:self.maxRows, outFormat: self.outFormat, autoCommit : self.autoCommit }, function(err, results, fields) {
|
|
if (err) {
|
|
// console.log(self.sql);
|
|
// console.error(err.message);
|
|
err.sql = self.sql;
|
|
|
|
reject(self.formatError(err));
|
|
} else {
|
|
resolve(self.formatResults(results));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
return promise;
|
|
};
|
|
|
|
/**
|
|
* High level function that handles the results of a query execution.
|
|
*
|
|
*
|
|
* Example:
|
|
* query.formatResults([
|
|
* {
|
|
* id: 1, // this is from the main table
|
|
* attr2: 'snafu', // this is from the main table
|
|
* Tasks.id: 1, // this is from the associated table
|
|
* Tasks.title: 'task' // this is from the associated table
|
|
* }
|
|
* ])
|
|
*
|
|
* @param {Array} data - The result of the query execution.
|
|
*/
|
|
Query.prototype.formatResults = function(data) {
|
|
var result = this.instance;
|
|
|
|
// if (data && typeof data.rows === 'object' && typeof data.metaData === 'object' ) {
|
|
|
|
|
|
// var rows=[], drows=data.rows, dmeta=data.metaData
|
|
// var endRows=drows.length;
|
|
// var endMeta=dmeta.length;
|
|
// for (var i = 0; i < endRows; i++){
|
|
// var obj={}
|
|
// for(var j = 0 ; j < endMeta; j++){
|
|
// obj[dmeta[j].name]=drows[i][j];
|
|
|
|
// }
|
|
// rows.push(obj);
|
|
// }
|
|
|
|
// data={
|
|
// metaData: data.metaData,
|
|
// outBinds: data.outBinds,
|
|
// rows: rows,
|
|
// rowsAffected: data.rowsAffected
|
|
// };
|
|
// }
|
|
|
|
if (this.isInsertQuery(data)) {
|
|
this.handleInsertQuery(data);
|
|
|
|
if (!this.instance && data && data.outBinds && data.outBinds[this.getInsertIdField()] && data.outBinds[this.getInsertIdField()][0]) {
|
|
result = data.outBinds[this.getInsertIdField()][0];
|
|
}
|
|
}
|
|
|
|
if (this.isSelectQuery()) {
|
|
result = this.handleSelectQuery(data.rows);
|
|
|
|
} else if (this.isShowTablesQuery()) {
|
|
result = this.handleShowTablesQuery(data.rows);
|
|
// } else if (this.isDescribeQuery()) {
|
|
// result = {};
|
|
|
|
// data.forEach(function(_result) {
|
|
// result[_result.Field] = {
|
|
// type: _result.Type.toUpperCase(),
|
|
// allowNull: (_result.Null === 'YES'),
|
|
// defaultValue: _result.Default
|
|
// };
|
|
// });
|
|
// } else if (this.isShowIndexesQuery()) {
|
|
// result = this.handleShowIndexesQuery(data);
|
|
|
|
// } else if (this.isCallQuery()) {
|
|
// result = data[0];
|
|
// } else if (this.isBulkUpdateQuery() || this.isBulkDeleteQuery() || this.isUpsertQuery()) {
|
|
// result = data.affectedRows;
|
|
} else if (this.isVersionQuery()) {
|
|
var drows=data.rows;
|
|
var endRows=drows.length;
|
|
for (var i = 0; i < endRows; i++){
|
|
if(drows[i].PRODUCT.indexOf('Database')>=0){
|
|
result='PRODUCT=' + drows[i].PRODUCT + ', VERSION=' + drows[i].VERSION + ', STATUS='+drows[i].STATUS;
|
|
}
|
|
}
|
|
// } else if (this.isForeignKeysQuery()) {
|
|
// result = data;
|
|
} else if (this.isRawQuery()) {
|
|
// MySQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta
|
|
result = [data.rows, data];
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
|
|
Query.prototype.formatError = function (err) {
|
|
|
|
// 00942
|
|
return new sequelizeErrors.DatabaseError(err);
|
|
};
|
|
|
|
AbstractQuery.prototype.handleInsertQuery = function(results, metaData) {
|
|
if (this.instance) {
|
|
// add the inserted row id to the instance
|
|
var autoIncrementField = this.model.autoIncrementField
|
|
, id = null;
|
|
|
|
if (results && results.outBinds && results.outBinds[this.getInsertIdField()] && results.outBinds[this.getInsertIdField()][0]) {
|
|
id = results.outBinds[this.getInsertIdField()][0];
|
|
}
|
|
|
|
this.instance[autoIncrementField] = id;
|
|
}
|
|
};
|
|
|
|
Query.prototype.getInsertIdField = function() {
|
|
return 'rid';
|
|
};
|
|
|
|
return Query;
|
|
})();
|