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

Commit 5f155f19 by Dr. Evil

Proper parsing of HSTORE and RANGE attributes in included models

1 parent eee2e04d
Showing with 96 additions and 46 deletions
...@@ -9,37 +9,64 @@ var Utils = require('../../utils') ...@@ -9,37 +9,64 @@ var Utils = require('../../utils')
, Promise = require('../../promise') , Promise = require('../../promise')
, sequelizeErrors = require('../../errors.js'); , sequelizeErrors = require('../../errors.js');
// Parses hstore fields if the model has any hstore fields. var parseDialectSpecificFields = {
// This cannot be done in the 'pg' lib because hstore is a UDT. // Parses hstore fields if the model has any hstore fields.
var parseHstoreFields = function(model, row) { // This cannot be done in the 'pg' lib because hstore is a UDT.
Utils._.forEach(row, function(value, key) { hstore: function (value, options) {
if(value === null) return row[key] = null; if (value === null) return null;
if (model._isHstoreAttribute(key)) { return DataTypes.ARRAY.is(options.dataType, DataTypes.HSTORE) ?
row[key] = hstore.parse(value); Utils._.map(
}else if (model.attributes[key] && DataTypes.ARRAY.is(model.attributes[key].type, DataTypes.HSTORE)) { JSON.parse('[' + value.substring(1, value.length - 1) + ']'), function (v) {
var array = JSON.parse('[' + value.slice(1).slice(0,-1) + ']'); return hstore.parse(v);
row[key] = Utils._.map(array, function(v){return hstore.parse(v);}); }) : hstore.parse(value);
}else{ },
row[key] = value; range: function (value, options) {
if (value === null) return null;
return DataTypes.ARRAY.is(options.dataType, DataTypes.RANGE) ?
Utils._.map(
JSON.parse('[' + value.substring(1, value.length - 1) + ']'),
function (v) {
return range.parse(v, options.dataType.type);
}) :
range.parse(value, options.dataType);
} }
}); },
}; dialectSpecificTypes = Utils._.keys(parseDialectSpecificFields);
var parseRangeFields = function (model, row) { function dialectSpecificFieldDatatypeMap (options, prefix) {
Utils._.forEach(row, function (value, key) { if (!Utils._.isArray(options.types))
if (value === null) return row[key] = null; return [];
if (model._isRangeAttribute(key)) { prefix = prefix || '';
row[key] = range.parse(value, model.attributes[key].type);
} else if (model.attributes[key] && DataTypes.ARRAY.is(model.attributes[key].type, DataTypes.RANGE)) { var fields = {};
var array = JSON.parse('[' + value.slice(1).slice(0, -1) + ']'); if (options.callee) {
row[key] = Utils._.map(array, function (v) { return range.parse(v, model.attributes[key].type.type); }); if (options.as)
} else { prefix += options.as + '.';
row[key] = value;
Utils._.each(options.types, function (type) {
Utils._.each(options.callee['_' + type + 'Attributes'], function (attrName) {
fields[prefix + attrName] = {
dataType: options.callee.attributes[attrName].type || null,
type: type
};
});
});
} }
Utils._.each(options.include, function (include) {
fields = Utils._.merge(fields, dialectSpecificFieldDatatypeMap({
callee: include.model,
as: include.as,
include: include.include,
types: options.types
}, prefix));
}); });
};
return fields;
}
module.exports = (function() { module.exports = (function() {
var Query = function(client, sequelize, callee, options) { var Query = function(client, sequelize, callee, options) {
...@@ -90,7 +117,9 @@ module.exports = (function() { ...@@ -90,7 +117,9 @@ module.exports = (function() {
}).spread(function(rows, sql, result) { }).spread(function(rows, sql, result) {
var results = rows var results = rows
, isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0) , isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0)
, isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0); , isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0)
, dialectSpecificFields
, isDialectSpecificField = Utils._.memoize(function (key) { return dialectSpecificFields.hasOwnProperty(key); });
if (isTableNameQuery || isRelNameQuery) { if (isTableNameQuery || isRelNameQuery) {
if (isRelNameQuery) { if (isRelNameQuery) {
...@@ -177,16 +206,23 @@ module.exports = (function() { ...@@ -177,16 +206,23 @@ module.exports = (function() {
}); });
} }
if (!!self.callee && !!self.callee._hasHstoreAttributes) { if (!!self.callee && rows.length > 0) {
rows.forEach(function(row) { dialectSpecificFields = dialectSpecificFieldDatatypeMap({
parseHstoreFields(self.callee, row); callee: self.callee,
include: self.options.include,
types: dialectSpecificTypes
}); });
}
if (!!self.callee && !!self.callee._hasRangeAttributes) { // check whether custom fields exist in responses model
rows.forEach(function (row) { if (!Utils._.isEmpty(dialectSpecificFields)) {
parseRangeFields(self.callee, row); rows.forEach(function (row, rowId, rows) {
Utils._.each(row, function (value, key) {
if (isDialectSpecificField(key))
rows[rowId][key] =
parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
}); });
});
}
} }
return self.handleSelectQuery(rows); return self.handleSelectQuery(rows);
...@@ -229,17 +265,23 @@ module.exports = (function() { ...@@ -229,17 +265,23 @@ module.exports = (function() {
return parseInt(result.rowCount, 10); return parseInt(result.rowCount, 10);
} }
if (!!self.callee && !!self.callee._hasHstoreAttributes) { if (!!self.callee && rows.length > 0) {
rows.forEach(function(row) { dialectSpecificFields = dialectSpecificFieldDatatypeMap({
parseHstoreFields(self.callee, row); callee: self.callee,
types: dialectSpecificTypes
}); });
}
if (!!self.callee && !!self.callee._hasRangeAttributes) { // check whether custom fields exist in responses model
rows.forEach(function (row) { if (!Utils._.isEmpty(dialectSpecificFields)) {
parseRangeFields(self.callee, row); rows.forEach(function (row, rowId, rows) {
Utils._.each(row, function (value, key) {
if (isDialectSpecificField(key))
rows[rowId][key] =
parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
});
}); });
} }
}
return self.handleSelectQuery(rows); return self.handleSelectQuery(rows);
} else if (QueryTypes.BULKDELETE === self.options.type) { } else if (QueryTypes.BULKDELETE === self.options.type) {
...@@ -248,12 +290,20 @@ module.exports = (function() { ...@@ -248,12 +290,20 @@ module.exports = (function() {
return rows[0].sequelize_upsert; return rows[0].sequelize_upsert;
} else if (self.isInsertQuery() || self.isUpdateQuery()) { } else if (self.isInsertQuery() || self.isUpdateQuery()) {
if (!!self.callee && self.callee.dataValues) { if (!!self.callee && self.callee.dataValues) {
if (!!self.callee.Model && !!self.callee.Model._hasHstoreAttributes) { if (!!self.callee.Model) {
parseHstoreFields(self.callee.Model, rows[0]); dialectSpecificFields = dialectSpecificFieldDatatypeMap({
} callee: self.callee.Model,
types: dialectSpecificTypes
});
if (!!self.callee.Model && !!self.callee.Model._hasRangeAttributes) { // check whether custom fields exist in responses model
parseRangeFields(self.callee.Model, rows[0]); if (!Utils._.isEmpty(dialectSpecificFields)) {
Utils._.each(rows[0], function (value, key) {
if (isDialectSpecificField(key))
rows[0][key] =
parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
});
}
} }
for (var key in rows[0]) { for (var key in rows[0]) {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!