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

Commit c04c5bac by Jan Aagaard Meier

datatypes(floating point) Add support for IEEE floating point literals (NaN and …

…Inf) in pg and sqlite. Closes #5194
1 parent 6c880204
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
- [ADDED] `beforeCount` hook [#5209](https://github.com/sequelize/sequelize/pull/5209) - [ADDED] `beforeCount` hook [#5209](https://github.com/sequelize/sequelize/pull/5209)
- [ADDED] `validationFailed` hook [#1626](https://github.com/sequelize/sequelize/issues/1626) - [ADDED] `validationFailed` hook [#1626](https://github.com/sequelize/sequelize/issues/1626)
- [FIXED] Mark index as `unique: true` when `type: 'UNIQUE'`. Fixes [#5351](https://github.com/sequelize/sequelize/issues/5351) - [FIXED] Mark index as `unique: true` when `type: 'UNIQUE'`. Fixes [#5351](https://github.com/sequelize/sequelize/issues/5351)
- [ADDED[ Support for IEEE floating point literals in postgres and sqlite [#5194](https://github.com/sequelize/sequelize/issues/5194)
# 3.19.3 # 3.19.3
- [FIXED] `updatedAt` and `createdAt` values are now set before validation [#5367](https://github.com/sequelize/sequelize/pull/5367) - [FIXED] `updatedAt` and `createdAt` values are now set before validation [#5367](https://github.com/sequelize/sequelize/pull/5367)
......
...@@ -225,6 +225,7 @@ NUMBER.prototype.toSql = function() { ...@@ -225,6 +225,7 @@ NUMBER.prototype.toSql = function() {
} }
return result; return result;
}; };
NUMBER.prototype.validate = function(value) { NUMBER.prototype.validate = function(value) {
if (!_.isNumber(value)) { if (!_.isNumber(value)) {
throw new sequelizeErrors.ValidationError(util.format('%j is not a valid number', value)); throw new sequelizeErrors.ValidationError(util.format('%j is not a valid number', value));
...@@ -390,6 +391,20 @@ DECIMAL.prototype.validate = function(value) { ...@@ -390,6 +391,20 @@ DECIMAL.prototype.validate = function(value) {
return true; return true;
}; };
[FLOAT, DOUBLE, REAL].forEach(function (floating) {
floating.prototype.escape = false;
floating.prototype.$stringify = function (value) {
if (isNaN(value)) {
return "'NaN'";
} else if (!isFinite(value)) {
var sign = value < 0 ? '-' : '';
return "'" + sign + "Infinity'";
}
return value;
};
});
/** /**
* A boolean / tinyint column, depending on dialect * A boolean / tinyint column, depending on dialect
* @property BOOLEAN * @property BOOLEAN
...@@ -816,48 +831,48 @@ var helpers = { ...@@ -816,48 +831,48 @@ var helpers = {
}; };
/** /**
* A column storing Geometry information. * A column storing Geometry information.
* *
* Only available in PostgreSQL (with PostGIS) or MySQL. * Only available in PostgreSQL (with PostGIS) or MySQL.
* In MySQL, allowable Geometry types are 'POINT', 'LINESTRING', 'POLYGON'. * In MySQL, allowable Geometry types are 'POINT', 'LINESTRING', 'POLYGON'.
* *
* When using, GeoJSON is accepted as input and returned as output. * When using, GeoJSON is accepted as input and returned as output.
* In PostGIS, the GeoJSON is parsed using the PostGIS function `ST_GeomFromGeoJSON`. * In PostGIS, the GeoJSON is parsed using the PostGIS function `ST_GeomFromGeoJSON`.
* In MySQL it is parsed using the function `GeomFromText`. * In MySQL it is parsed using the function `GeomFromText`.
* Therefore, one can just follow the [GeoJSON spec](http://geojson.org/geojson-spec.html) for handling geometry objects. See the following examples: * Therefore, one can just follow the [GeoJSON spec](http://geojson.org/geojson-spec.html) for handling geometry objects. See the following examples:
* *
* ```js * ```js
* // Create a new point: * // Create a new point:
* var point = { type: 'Point', coordinates: [39.807222,-76.984722]}; * var point = { type: 'Point', coordinates: [39.807222,-76.984722]};
* *
* User.create({username: 'username', geometry: point }).then(function(newUser) { * User.create({username: 'username', geometry: point }).then(function(newUser) {
* ... * ...
* }); * });
* *
* // Create a new linestring: * // Create a new linestring:
* var line = { type: 'LineString', 'coordinates': [ [100.0, 0.0], [101.0, 1.0] ] }; * var line = { type: 'LineString', 'coordinates': [ [100.0, 0.0], [101.0, 1.0] ] };
* *
* User.create({username: 'username', geometry: line }).then(function(newUser) { * User.create({username: 'username', geometry: line }).then(function(newUser) {
* ... * ...
* }); * });
* *
* // Create a new polygon: * // Create a new polygon:
* var polygon = { type: 'Polygon', coordinates: [ * var polygon = { type: 'Polygon', coordinates: [
* [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], * [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
* [100.0, 1.0], [100.0, 0.0] ] * [100.0, 1.0], [100.0, 0.0] ]
* ]}; * ]};
* *
* User.create({username: 'username', geometry: polygon }).then(function(newUser) { * User.create({username: 'username', geometry: polygon }).then(function(newUser) {
* ... * ...
* }); * });
* // Create a new point with a custom SRID: * // Create a new point with a custom SRID:
* var point = { * var point = {
* type: 'Point', * type: 'Point',
* coordinates: [39.807222,-76.984722], * coordinates: [39.807222,-76.984722],
* crs: { type: 'name', properties: { name: 'EPSG:4326'} } * crs: { type: 'name', properties: { name: 'EPSG:4326'} }
* }; * };
* *
* User.create({username: 'username', geometry: point }).then(function(newUser) { * User.create({username: 'username', geometry: point }).then(function(newUser) {
* ... * ...
* }); * });
......
...@@ -216,6 +216,7 @@ module.exports = function (BaseTypes) { ...@@ -216,6 +216,7 @@ module.exports = function (BaseTypes) {
this._zerofill = undefined; this._zerofill = undefined;
} }
}); });
delete FLOAT.parse; // Float has no separate type in PG
var BLOB = BaseTypes.BLOB.inherits(); var BLOB = BaseTypes.BLOB.inherits();
......
...@@ -144,6 +144,21 @@ module.exports = function (BaseTypes) { ...@@ -144,6 +144,21 @@ module.exports = function (BaseTypes) {
return NUMBER.prototype.toSql.call(this); return NUMBER.prototype.toSql.call(this);
}; };
[FLOAT, DOUBLE, REAL].forEach(function (floating) {
floating.parse = function (value) {
if (_.isString(value)) {
if (value === 'NaN') {
return NaN;
} else if (value === 'Infinity') {
return Infinity;
} else if (value === '-Infinity') {
return -Infinity;
}
}
return value;
};
});
var ENUM = BaseTypes.ENUM.inherits(); var ENUM = BaseTypes.ENUM.inherits();
ENUM.prototype.toSql = function () { ENUM.prototype.toSql = function () {
......
...@@ -304,4 +304,30 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -304,4 +304,30 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
}); });
} }
}); });
if (dialect === 'postgres' || dialect === 'sqlite') {
// postgres actively supports IEEE floating point literals, and sqlite doesn't care what we throw at it
it('should store and parse IEEE floating point literals (NaN and Infinity', function () {
var Model = this.sequelize.define('model', {
float: Sequelize.FLOAT,
double: Sequelize.DOUBLE,
real: Sequelize.REAL
});
return Model.sync({ force: true }).then(function () {
return Model.create({
id: 1,
float: NaN,
double: Infinity,
real: -Infinity
});
}).then(function () {
return Model.find({id: 1});
}).then(function (user) {
expect(user.get('float')).to.be.NaN;
expect(user.get('double')).to.eq(Infinity);
expect(user.get('real')).to.eq(-Infinity);
});
});
}
}); });
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!