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

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