Implement replaceAttributes
This commit is contained in:
parent
26712a7014
commit
3a92328fc3
173
lib/sql.js
173
lib/sql.js
|
@ -554,13 +554,10 @@ SQLConnector.prototype.buildDelete = function(model, where, options) {
|
||||||
* @param {Function} cb The callback function
|
* @param {Function} cb The callback function
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.destroyAll = function(model, where, options, cb) {
|
SQLConnector.prototype.destroyAll = function(model, where, options, cb) {
|
||||||
var self = this;
|
|
||||||
var stmt = this.buildDelete(model, where, options);
|
var stmt = this.buildDelete(model, where, options);
|
||||||
this.execute(stmt.sql, stmt.params, options, function(err, info) {
|
this._executeAlteringQuery(model, stmt.sql, stmt.params, options, function(err, data) {
|
||||||
var affectedRows = self.getCountForAffectedRows(model, info);
|
if (cb)
|
||||||
if (cb) {
|
cb(err, data);
|
||||||
cb(err, {count: affectedRows});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -582,14 +579,40 @@ Connector.defineAliases(SQLConnector.prototype, 'destroyAll', ['deleteAll']);
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.updateAttributes = function(model, id, data, options, cb) {
|
SQLConnector.prototype.updateAttributes = function(model, id, data, options, cb) {
|
||||||
if (!isIdValuePresent(id, cb)) {
|
if (!isIdValuePresent(id, cb)) return;
|
||||||
return;
|
var where = this._buildWhereObjById(model, id, data);
|
||||||
}
|
this.updateAll(model, where, data, options, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace attributes for a given model instance
|
||||||
|
* @param {String} model The model name
|
||||||
|
* @param {*} id The id value
|
||||||
|
* @param {Object} data The model data instance containing all properties to
|
||||||
|
* be replaced
|
||||||
|
* @param {Object} options Options object
|
||||||
|
* @param {Function} cb The callback function
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype.replace = function(model, id, data, options, cb) {
|
||||||
|
if (!isIdValuePresent(id, cb)) return;
|
||||||
|
var where = this._buildWhereObjById(model, id, data);
|
||||||
|
this._replace(model, where, data, options, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param model The model name.
|
||||||
|
* @param id The instance ID.
|
||||||
|
* @param {Object} data The data Object.
|
||||||
|
* @returns {Object} where The where object for a spcific instance.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._buildWhereObjById = function(model, id, data) {
|
||||||
var idName = this.idName(model);
|
var idName = this.idName(model);
|
||||||
delete data[idName];
|
delete data[idName];
|
||||||
var where = {};
|
var where = {};
|
||||||
where[idName] = id;
|
where[idName] = id;
|
||||||
this.updateAll(model, where, data, options, cb);
|
return where;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -601,8 +624,33 @@ SQLConnector.prototype.updateAttributes = function(model, id, data, options, cb)
|
||||||
* @param {Function} cb The callback function
|
* @param {Function} cb The callback function
|
||||||
* @returns {ParameterizedSQL} The UPDATE SQL statement
|
* @returns {ParameterizedSQL} The UPDATE SQL statement
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.buildUpdate = function(model, where, data, options) {
|
SQLConnector.prototype._buildUpdate = function(model, where, data, options) {
|
||||||
var fields = this.buildFieldsForUpdate(model, data);
|
var fields = this.buildFieldsForUpdate(model, data);
|
||||||
|
return this._constructUpdateQuery(model, where, fields);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the UPDATE statement for replacing
|
||||||
|
* @param {String} model The model name
|
||||||
|
* @param {Object} where The where object
|
||||||
|
* @param {Object} data The data to be changed
|
||||||
|
* @param {Object} options The options object
|
||||||
|
* @param {Function} cb The callback function
|
||||||
|
* @returns {ParameterizedSQL} The UPDATE SQL statement for replacing fields
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._buildReplace = function(model, where, data, options) {
|
||||||
|
var fields = this.buildFieldsForReplace(model, data);
|
||||||
|
return this._constructUpdateQuery(model, where, fields);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param model The model name.
|
||||||
|
* @param {} where The where object.
|
||||||
|
* @param {Object} field The parameterizedSQL fileds.
|
||||||
|
* @returns {Object} update query Constructed update query.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._constructUpdateQuery = function(model, where, fields) {
|
||||||
var updateClause = new ParameterizedSQL('UPDATE ' + this.tableEscaped(model));
|
var updateClause = new ParameterizedSQL('UPDATE ' + this.tableEscaped(model));
|
||||||
var whereClause = this.buildWhere(model, where);
|
var whereClause = this.buildWhere(model, where);
|
||||||
updateClause.merge([fields, whereClause]);
|
updateClause.merge([fields, whereClause]);
|
||||||
|
@ -619,18 +667,38 @@ SQLConnector.prototype.buildUpdate = function(model, where, data, options) {
|
||||||
* @param {Function} cb The callback function
|
* @param {Function} cb The callback function
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.update = function(model, where, data, options, cb) {
|
SQLConnector.prototype.update = function(model, where, data, options, cb) {
|
||||||
var self = this;
|
var stmt = this._buildUpdate(model, where, data, options);
|
||||||
var stmt = this.buildUpdate(model, where, data, options);
|
this._executeAlteringQuery(model, stmt.sql, stmt.params, options, function(err, data) {
|
||||||
this.execute(stmt.sql, stmt.params, options, function(err, info) {
|
if (cb)
|
||||||
var affectedRows = self.getCountForAffectedRows(model, info);
|
cb(err, data);
|
||||||
if (cb) {
|
|
||||||
cb(err, {count: affectedRows});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Alias to `update`. Juggler checks `update` only.
|
/**
|
||||||
|
* Replace all instances that match the where clause with the given data
|
||||||
|
* @param {String} model The model name
|
||||||
|
* @param {Object} where The where object
|
||||||
|
* @param {Object} data The property/value object representing changes
|
||||||
|
* to be made
|
||||||
|
* @param {Object} options The options object
|
||||||
|
* @param {Function} cb The callback function
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._replace = function(model, where, data, options, cb) {
|
||||||
|
var stmt = this._buildReplace(model, where, data, options);
|
||||||
|
this._executeAlteringQuery(model, stmt.sql, stmt.params, options, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
SQLConnector.prototype._executeAlteringQuery = function(model, sql, params, options, cb) {
|
||||||
|
var self = this;
|
||||||
|
this.execute(sql, params, options, function(err, info) {
|
||||||
|
var affectedRows = self.getCountForAffectedRows(model, info);
|
||||||
|
cb(err, {count: affectedRows});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alias to `update` and `replace`. Juggler checks `update` and `replace` only.
|
||||||
Connector.defineAliases(SQLConnector.prototype, 'update', ['updateAll']);
|
Connector.defineAliases(SQLConnector.prototype, 'update', ['updateAll']);
|
||||||
|
Connector.defineAliases(SQLConnector.prototype, 'replace', ['replaceAll']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the SQL WHERE clause for the where object
|
* Build the SQL WHERE clause for the where object
|
||||||
|
@ -877,13 +945,38 @@ SQLConnector.prototype.buildOrderBy = function(model, order) {
|
||||||
* @returns {{names: Array, values: Array, properties: Array}}
|
* @returns {{names: Array, values: Array, properties: Array}}
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.buildFields = function(model, data, excludeIds) {
|
SQLConnector.prototype.buildFields = function(model, data, excludeIds) {
|
||||||
|
// var props = this.getModelDefinition(model).properties;
|
||||||
|
var keys = Object.keys(data);
|
||||||
|
return this._createFields(model, data, keys, excludeIds);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array of fields for the replace database operation
|
||||||
|
* @param {String} model Model name
|
||||||
|
* @param {Object} data Model data object
|
||||||
|
* @param {Boolean} excludeIds Exclude id properties or not, default to false
|
||||||
|
* @returns {{names: Array, values: Array, properties: Array}}
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._buildReplaceFields = function(model, data, excludeIds) {
|
||||||
|
var props = this.getModelDefinition(model).properties;
|
||||||
|
var keys = Object.keys(props);
|
||||||
|
return this._createFields(model, data, keys, excludeIds);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param {String} model The model name.
|
||||||
|
* @returns {Object} data The model data object.
|
||||||
|
* @returns {Array} keys The key fields for which need to be built.
|
||||||
|
* @param {Boolean} excludeIds Exclude id properties or not, default to false
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._createFields = function(model, data, keys, excludeIds) {
|
||||||
|
var props = this.getModelDefinition(model).properties;
|
||||||
var fields = {
|
var fields = {
|
||||||
names: [], // field names
|
names: [], // field names
|
||||||
columnValues: [], // an array of ParameterizedSQL
|
columnValues: [], // an array of ParameterizedSQL
|
||||||
properties: [] // model properties
|
properties: [] // model properties
|
||||||
};
|
};
|
||||||
var props = this.getModelDefinition(model).properties;
|
|
||||||
var keys = Object.keys(data);
|
|
||||||
for (var i = 0, n = keys.length; i < n; i++) {
|
for (var i = 0, n = keys.length; i < n; i++) {
|
||||||
var key = keys[i];
|
var key = keys[i];
|
||||||
var p = props[key];
|
var p = props[key];
|
||||||
|
@ -892,10 +985,10 @@ SQLConnector.prototype.buildFields = function(model, data, excludeIds) {
|
||||||
debug('Unknown property %s is skipped for model %s', key, model);
|
debug('Unknown property %s is skipped for model %s', key, model);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (excludeIds && p.id) {
|
if (excludeIds && p.id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var k = this.columnEscaped(model, key);
|
var k = this.columnEscaped(model, key);
|
||||||
var v = this.toColumnValue(p, data[key]);
|
var v = this.toColumnValue(p, data[key]);
|
||||||
if (v !== undefined) {
|
if (v !== undefined) {
|
||||||
|
@ -912,17 +1005,41 @@ SQLConnector.prototype.buildFields = function(model, data, excludeIds) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the SET clause for database update
|
* Build the SET clause for database update.
|
||||||
* @param {String} model Model na
|
* @param {String} model Model name.
|
||||||
* @param {Object} data The model data object
|
* @param {Object} data The model data object.
|
||||||
* @param {Boolean} excludeIds Exclude id properties or not, default to true
|
* @param {Boolean} excludeIds Exclude id properties or not, default to true.
|
||||||
* @returns {string} The list of fields for update
|
* @returns {string} The list of fields for update query.
|
||||||
*/
|
*/
|
||||||
SQLConnector.prototype.buildFieldsForUpdate = function(model, data, excludeIds) {
|
SQLConnector.prototype.buildFieldsForUpdate = function(model, data, excludeIds) {
|
||||||
if (excludeIds === undefined) {
|
if (excludeIds === undefined) {
|
||||||
excludeIds = true;
|
excludeIds = true;
|
||||||
}
|
}
|
||||||
var fields = this.buildFields(model, data, excludeIds);
|
var fields = this.buildFields(model, data, excludeIds);
|
||||||
|
return this._constructUpdateParameterizedSQL(fields);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the SET clause for database replace through update query.
|
||||||
|
* @param {String} model Model name.
|
||||||
|
* @param {Object} data The model data object.
|
||||||
|
* @param {Boolean} excludeIds Exclude id properties or not, default to true.
|
||||||
|
* @returns {string} The list of fields for update query.
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype.buildFieldsForReplace = function(model, data, excludeIds) {
|
||||||
|
if (excludeIds === undefined) {
|
||||||
|
excludeIds = true;
|
||||||
|
}
|
||||||
|
var fields = this._buildReplaceFields(model, data, excludeIds);
|
||||||
|
return this._constructUpdateParameterizedSQL(fields);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param {Object} field The fileds.
|
||||||
|
* @returns {Object} parameterizedSQL.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype._constructUpdateParameterizedSQL = function(fields) {
|
||||||
var columns = new ParameterizedSQL('');
|
var columns = new ParameterizedSQL('');
|
||||||
for (var i = 0, n = fields.names.length; i < n; i++) {
|
for (var i = 0, n = fields.names.length; i < n; i++) {
|
||||||
var clause = ParameterizedSQL.append(fields.names[i],
|
var clause = ParameterizedSQL.append(fields.names[i],
|
||||||
|
|
|
@ -281,7 +281,7 @@ describe('sql connector', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('builds UPDATE', function() {
|
it('builds UPDATE', function() {
|
||||||
var sql = connector.buildUpdate('customer', {name: 'John'}, {vip: false});
|
var sql = connector._buildUpdate('customer', {name: 'John'}, {vip: false});
|
||||||
expect(sql.toJSON()).to.eql({
|
expect(sql.toJSON()).to.eql({
|
||||||
sql: 'UPDATE `CUSTOMER` SET `VIP`=$1 WHERE `NAME`=$2',
|
sql: 'UPDATE `CUSTOMER` SET `VIP`=$1 WHERE `NAME`=$2',
|
||||||
params: [false, 'John']
|
params: [false, 'John']
|
||||||
|
|
Loading…
Reference in New Issue