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

Commit 5a266dcb by Sushant Committed by Jan Aagaard Meier

DATEONLY is now actually date only (#6709)

1 parent dd984e8e
# Future # Future
- [FIXED] `DATEONLY` now returns `YYYY-MM-DD` date string [#4858] (https://github.com/sequelize/sequelize/issues/4858)
- [FIXED] Issues with `createFunction` and `dropFunction` (PostgresSQL) - [FIXED] Issues with `createFunction` and `dropFunction` (PostgresSQL)
- [FIXED] Issue with belongsTo association and foreign keys [#6400](https://github.com/sequelize/sequelize/issues/6400) - [FIXED] Issue with belongsTo association and foreign keys [#6400](https://github.com/sequelize/sequelize/issues/6400)
- [FIXED] Issue with query generation in MSSQL, an identifier was not escaped [#6686] (https://github.com/sequelize/sequelize/pull/6686) - [FIXED] Issue with query generation in MSSQL, an identifier was not escaped [#6686] (https://github.com/sequelize/sequelize/pull/6686)
- [FIXED] GroupedLimit when foreignKey has a field alias - [FIXED] GroupedLimit when foreignKey has a field alias
- [FIXED] groupedLimit.through.where support - [FIXED] groupedLimit.through.where support
## BC breaks:
- `DATEONLY` now returns string in `YYYY-MM-DD` format rather than `Date` type
# 4.0.0-2 # 4.0.0-2
- [ADDED] include now supports string as an argument (on top of model/association), string will expand into an association matched literally from Model.associations - [ADDED] include now supports string as an argument (on top of model/association), string will expand into an association matched literally from Model.associations
- [FIXED] Accept dates as string while using `typeValidation` [#6453](https://github.com/sequelize/sequelize/issues/6453) - [FIXED] Accept dates as string while using `typeValidation` [#6453](https://github.com/sequelize/sequelize/issues/6453)
......
...@@ -476,6 +476,10 @@ DATEONLY.prototype.toSql = function() { ...@@ -476,6 +476,10 @@ DATEONLY.prototype.toSql = function() {
return 'DATE'; return 'DATE';
}; };
DATEONLY.prototype._stringify = function _stringify(date) {
return moment(date).format('YYYY-MM-DD');
};
/** /**
* A key / value column. Only available in postgres. * A key / value column. Only available in postgres.
* *
......
'use strict'; 'use strict';
const _ = require('lodash'); const _ = require('lodash');
const moment = require('moment');
const inherits = require('../../utils/inherits'); const inherits = require('../../utils/inherits');
module.exports = BaseTypes => { module.exports = BaseTypes => {
...@@ -135,6 +136,16 @@ module.exports = BaseTypes => { ...@@ -135,6 +136,16 @@ module.exports = BaseTypes => {
return date.format('YYYY-MM-DD HH:mm:ss.SSS'); return date.format('YYYY-MM-DD HH:mm:ss.SSS');
}; };
function DATEONLY() {
if (!(this instanceof DATEONLY)) return new DATEONLY();
BaseTypes.DATEONLY.apply(this, arguments);
}
inherits(DATEONLY, BaseTypes.DATEONLY);
DATEONLY.parse = function (value) {
return moment(value).format('YYYY-MM-DD');
};
function INTEGER(length) { function INTEGER(length) {
if (!(this instanceof INTEGER)) return new INTEGER(length); if (!(this instanceof INTEGER)) return new INTEGER(length);
BaseTypes.INTEGER.apply(this, arguments); BaseTypes.INTEGER.apply(this, arguments);
...@@ -225,6 +236,7 @@ module.exports = BaseTypes => { ...@@ -225,6 +236,7 @@ module.exports = BaseTypes => {
STRING, STRING,
UUID, UUID,
DATE, DATE,
DATEONLY,
NOW, NOW,
INTEGER, INTEGER,
BIGINT, BIGINT,
......
...@@ -24,6 +24,7 @@ module.exports = BaseTypes => { ...@@ -24,6 +24,7 @@ module.exports = BaseTypes => {
BaseTypes.ENUM.types.mysql = false; BaseTypes.ENUM.types.mysql = false;
BaseTypes.REAL.types.mysql = ['DOUBLE']; BaseTypes.REAL.types.mysql = ['DOUBLE'];
BaseTypes.DOUBLE.types.mysql = ['DOUBLE']; BaseTypes.DOUBLE.types.mysql = ['DOUBLE'];
BaseTypes.GEOMETRY.types.mysql = ['GEOMETRY'];
function BLOB(length) { function BLOB(length) {
if (!(this instanceof BLOB)) return new BLOB(length); if (!(this instanceof BLOB)) return new BLOB(length);
...@@ -62,7 +63,7 @@ module.exports = BaseTypes => { ...@@ -62,7 +63,7 @@ module.exports = BaseTypes => {
}; };
function DATE(length) { function DATE(length) {
if (!(this instanceof DATE)) return new Date(length); if (!(this instanceof DATE)) return new DATE(length);
BaseTypes.DATE.apply(this, arguments); BaseTypes.DATE.apply(this, arguments);
} }
inherits(DATE, BaseTypes.DATE); inherits(DATE, BaseTypes.DATE);
...@@ -97,6 +98,16 @@ module.exports = BaseTypes => { ...@@ -97,6 +98,16 @@ module.exports = BaseTypes => {
return value; return value;
}; };
function DATEONLY() {
if (!(this instanceof DATEONLY)) return new DATEONLY();
BaseTypes.DATEONLY.apply(this, arguments);
}
inherits(DATEONLY, BaseTypes.DATEONLY);
DATEONLY.parse = function parse(value) {
return value.string();
};
function UUID() { function UUID() {
if (!(this instanceof UUID)) return new UUID(); if (!(this instanceof UUID)) return new UUID();
BaseTypes.UUID.apply(this, arguments); BaseTypes.UUID.apply(this, arguments);
...@@ -157,11 +168,10 @@ module.exports = BaseTypes => { ...@@ -157,11 +168,10 @@ module.exports = BaseTypes => {
return 'ENUM(' + _.map(this.values, value => options.escape(value)).join(', ') + ')'; return 'ENUM(' + _.map(this.values, value => options.escape(value)).join(', ') + ')';
}; };
BaseTypes.GEOMETRY.types.mysql = ['GEOMETRY'];
const exports = { const exports = {
ENUM, ENUM,
DATE, DATE,
DATEONLY,
UUID, UUID,
GEOMETRY, GEOMETRY,
DECIMAL, DECIMAL,
......
...@@ -93,7 +93,7 @@ class Query extends AbstractQuery { ...@@ -93,7 +93,7 @@ class Query extends AbstractQuery {
this.handleInsertQuery(data); this.handleInsertQuery(data);
if (!this.instance) { if (!this.instance) {
// handle bulkCreate AI primiary key // handle bulkCreate AI primiary key
if ( if (
data.constructor.name === 'ResultSetHeader' data.constructor.name === 'ResultSetHeader'
&& this.model && this.model
......
...@@ -24,16 +24,26 @@ module.exports = BaseTypes => { ...@@ -24,16 +24,26 @@ module.exports = BaseTypes => {
array_oids: [3807] array_oids: [3807]
}; };
BaseTypes.DATEONLY.types.postgres = {
oids: [1082],
array_oids: [1182]
};
BaseTypes.TIME.types.postgres = { BaseTypes.TIME.types.postgres = {
oids: [1083], oids: [1083],
array_oids: [1183] array_oids: [1183]
}; };
function DATEONLY() {
if (!(this instanceof DATEONLY)) return new DATEONLY();
BaseTypes.DATEONLY.apply(this, arguments);
}
inherits(DATEONLY, BaseTypes.DATEONLY);
DATEONLY.parse = function parse(value) {
return value;
};
BaseTypes.DATEONLY.types.postgres = {
oids: [1082],
array_oids: [1182]
};
function DECIMAL(precision, scale) { function DECIMAL(precision, scale) {
if (!(this instanceof DECIMAL)) return new DECIMAL(precision, scale); if (!(this instanceof DECIMAL)) return new DECIMAL(precision, scale);
BaseTypes.DECIMAL.apply(this, arguments); BaseTypes.DECIMAL.apply(this, arguments);
...@@ -461,6 +471,7 @@ module.exports = BaseTypes => { ...@@ -461,6 +471,7 @@ module.exports = BaseTypes => {
INTEGER, INTEGER,
BOOLEAN, BOOLEAN,
DATE, DATE,
DATEONLY,
BIGINT, BIGINT,
REAL, REAL,
'DOUBLE PRECISION': DOUBLE, 'DOUBLE PRECISION': DOUBLE,
......
...@@ -39,6 +39,16 @@ module.exports = BaseTypes => { ...@@ -39,6 +39,16 @@ module.exports = BaseTypes => {
} }
}; };
function DATEONLY() {
if (!(this instanceof DATEONLY)) return new DATEONLY();
BaseTypes.DATEONLY.apply(this, arguments);
}
inherits(DATEONLY, BaseTypes.DATEONLY);
DATEONLY.parse = function parse(date) {
return date;
};
function STRING(length, binary) { function STRING(length, binary) {
if (!(this instanceof STRING)) return new STRING(length, binary); if (!(this instanceof STRING)) return new STRING(length, binary);
BaseTypes.STRING.apply(this, arguments); BaseTypes.STRING.apply(this, arguments);
...@@ -185,6 +195,7 @@ module.exports = BaseTypes => { ...@@ -185,6 +195,7 @@ module.exports = BaseTypes => {
const exports = { const exports = {
DATE, DATE,
DATEONLY,
STRING, STRING,
CHAR, CHAR,
NUMBER, NUMBER,
......
...@@ -126,9 +126,8 @@ class Query extends AbstractQuery { ...@@ -126,9 +126,8 @@ class Query extends AbstractQuery {
// add the inserted row id to the instance // add the inserted row id to the instance
if (query.isInsertQuery(results, metaData)) { if (query.isInsertQuery(results, metaData)) {
query.handleInsertQuery(results, metaData); query.handleInsertQuery(results, metaData);
if (!query.instance) { if (!query.instance) {
// handle bulkCreate AI primiary key // handle bulkCreate AI primary key
if ( if (
metaData.constructor.name === 'Statement' metaData.constructor.name === 'Statement'
&& query.model && query.model
...@@ -138,7 +137,7 @@ class Query extends AbstractQuery { ...@@ -138,7 +137,7 @@ class Query extends AbstractQuery {
) { ) {
const startId = metaData[query.getInsertIdField()] - metaData.changes + 1; const startId = metaData[query.getInsertIdField()] - metaData.changes + 1;
result = []; result = [];
for (let i = startId; i< startId + metaData.changes; i++) { for (let i = startId; i < startId + metaData.changes; i++) {
result.push({ [query.model.rawAttributes[query.model.primaryKeyAttribute].field]: i }); result.push({ [query.model.rawAttributes[query.model.primaryKeyAttribute].field]: i });
} }
} else { } else {
...@@ -180,21 +179,9 @@ class Query extends AbstractQuery { ...@@ -180,21 +179,9 @@ class Query extends AbstractQuery {
}); });
} }
let type = tableTypes[name]; return tableTypes[name]
if (type) { ? query.applyParsers(tableTypes[name], value)
if (type.indexOf('(') !== -1) { : value;
// Remove the lenght part
type = type.substr(0, type.indexOf('('));
}
type = type.replace('UNSIGNED', '').replace('ZEROFILL', '');
type = type.trim().toUpperCase();
const parse = parserStore.get(type);
if (value !== null && parse) {
return parse(value, { timezone: query.sequelize.options.timezone});
}
}
return value;
}); });
}); });
} }
...@@ -306,6 +293,21 @@ class Query extends AbstractQuery { ...@@ -306,6 +293,21 @@ class Query extends AbstractQuery {
}); });
} }
applyParsers(type, value) {
if (type.indexOf('(') !== -1) {
// Remove the length part
type = type.substr(0, type.indexOf('('));
}
type = type.replace('UNSIGNED', '').replace('ZEROFILL', '');
type = type.trim().toUpperCase();
const parse = parserStore.get(type);
if (value !== null && parse) {
return parse(value, { timezone: this.sequelize.options.timezone });
}
return value;
}
formatError(err) { formatError(err) {
switch (err.code) { switch (err.code) {
......
...@@ -9,6 +9,7 @@ const sequelizeErrors = require('./errors'); ...@@ -9,6 +9,7 @@ const sequelizeErrors = require('./errors');
const Dottie = require('dottie'); const Dottie = require('dottie');
const Promise = require('./promise'); const Promise = require('./promise');
const _ = require('lodash'); const _ = require('lodash');
const moment = require('moment');
const Association = require('./associations/base'); const Association = require('./associations/base');
const HasMany = require('./associations/has-many'); const HasMany = require('./associations/has-many');
const DataTypes = require('./data-types'); const DataTypes = require('./data-types');
...@@ -3085,14 +3086,23 @@ class Model { ...@@ -3085,14 +3086,23 @@ class Model {
// Convert date fields to real date objects // Convert date fields to real date objects
if (this.constructor._hasDateAttributes && this.constructor._isDateAttribute(key) && !!value && !value._isSequelizeMethod) { if (this.constructor._hasDateAttributes && this.constructor._isDateAttribute(key) && !!value && !value._isSequelizeMethod) {
if (!(value instanceof Date)) { // Dont parse DATEONLY to new Date, keep them as string
value = new Date(value); if (this.rawAttributes[key].type instanceof DataTypes.DATEONLY) {
} if (originalValue && originalValue === value) {
if (!(originalValue instanceof Date)) { return this;
originalValue = new Date(originalValue); } else {
} value = moment(value).format('YYYY-MM-DD');
if (originalValue && value.getTime() === originalValue.getTime()) { }
return this; } else { // go ahread and parse as Date if required
if (!(value instanceof Date)) {
value = new Date(value);
}
if (!(originalValue instanceof Date)) {
originalValue = new Date(originalValue);
}
if (originalValue && value.getTime() === originalValue.getTime()) {
return this;
}
} }
} }
} }
......
...@@ -156,7 +156,7 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -156,7 +156,7 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
it('calls parse and stringify for DATEONLY', function () { it('calls parse and stringify for DATEONLY', function () {
var Type = new Sequelize.DATEONLY(); var Type = new Sequelize.DATEONLY();
return testSuccess(Type, new Date()); return testSuccess(Type, moment(new Date()).format('YYYY-MM-DD'));
}); });
it('calls parse and stringify for TIME', function () { it('calls parse and stringify for TIME', function () {
...@@ -438,4 +438,22 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -438,4 +438,22 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
}); });
}); });
it('should return YYYY-MM-DD format string for DATEONLY', function () {
const Model = this.sequelize.define('user', {
stamp: Sequelize.DATEONLY
});
const testDate = moment().format('YYYY-MM-DD');
return Model.sync({ force: true})
.then(() => Model.create({ stamp: testDate }))
.then(record => {
expect(typeof record.stamp).to.be.eql('string');
expect(record.stamp).to.be.eql(testDate);
return Model.findById(record.id);
}).then(record => {
expect(typeof record.stamp).to.be.eql('string');
expect(record.stamp).to.be.eql(testDate);
});
});
}); });
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!