Use MySQL DEFAULT Clause/Constant (#319)

* Adding ability to use MySQL DEFAULT clause

Adding mysql.default option and documentation on special case for date.

Adding unit tests for Default Clause.

* Handle unsupported types, don't stringify numbers

* Adding note about unsupported column types.

* Update readme.
This commit is contained in:
Eric Dowell 2017-08-08 19:40:40 -05:00 committed by Sakib Hasan
parent ccac704cce
commit 99597460f0
3 changed files with 144 additions and 2 deletions

View File

@ -258,6 +258,37 @@ Use the `limit` option to alter the display width. Example:
}
```
### Default Clause/Constant
Use the `default` property to have MySQL handle setting column `DEFAULT` value.
```javascript
"status": {
"type": "string",
"mysql": {
"default": "pending"
}
},
"number": {
"type": "number",
"mysql": {
"default": 256
}
}
```
For the date or timestamp types use `CURRENT_TIMESTAMP` or `now`:
```javascript
"last_modified": {
"type": "date",
"mysql": {
"default":"CURRENT_TIMESTAMP"
}
}
```
**NOTE**: The following column types do **NOT** supported [MySQL Default Values](https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html):
- BLOB
- TEXT
- GEOMETRY
- JSON
### Floating-point types
For Float and Double data types, use the `precision` and `scale` options to specify custom precision. Default is (16,8). For example:

View File

@ -701,7 +701,7 @@ function mixinMigration(MySQL, mysql) {
var p = this.getModelDefinition(model).properties[prop];
var line = this.columnDataType(model, prop) + ' ' +
(this.isNullable(p) ? 'NULL' : 'NOT NULL');
return line;
return columnDefault(p, line);
};
// override this function from base connector to allow mysql connector to
@ -770,6 +770,28 @@ function mixinMigration(MySQL, mysql) {
return dt;
};
function columnDefault(p, line) {
if (typeof p.type === 'undefined' || typeof p.type.name !== 'string') {
return line;
}
// Unsupported column types
if (['blob', 'json', 'text'].indexOf(p.type.name.toLowerCase()) !== -1) {
return line;
}
if (typeof p.mysql !== 'undefined' && p.mysql.default) {
var columnDefault = p.mysql.default;
if (typeof columnDefault === 'number') {
return line + ' DEFAULT ' + columnDefault;
}
if (typeof columnDefault === 'string') {
return line + ' DEFAULT ' +
(columnDefault.toUpperCase() === 'CURRENT_TIMESTAMP' || columnDefault.toLowerCase() === 'now' ?
'CURRENT_TIMESTAMP' : '"' + columnDefault + '"');
}
}
return line;
}
function columnType(p, defaultType) {
var dt = defaultType;
if (p.mysql && p.mysql.dataType) {

View File

@ -10,7 +10,7 @@ var platform = require('./helpers/platform');
var should = require('./init');
var Schema = require('loopback-datasource-juggler').Schema;
var db, UserData, StringData, NumberData, DateData, SimpleEmployee;
var db, UserData, StringData, NumberData, DateData, DefaultData, SimpleEmployee;
var mysqlVersion;
describe('migrations', function() {
@ -373,6 +373,84 @@ describe('migrations', function() {
], done);
});
it('should take on database default CURRENT_TIMESTAMP, boolean 0 and pending string for columns', function(done) {
DefaultData.create({}, function(err, obj) {
assert.ok(!err);
assert.ok(obj);
var now = new Date();
DefaultData.findById(obj.id, function(err, found) {
now.setSeconds(0);
found.dateTime.setSeconds(0);
found.timestamp.setSeconds(0);
assert.equal(found.dateTime.toGMTString(), now.toGMTString());
assert.equal(found.timestamp.toGMTString(), now.toGMTString());
assert.equal(found.isAdmin, '0');
assert.equal(found.number, 256);
assert.equal(found.data, null);
assert.equal(found.text, null);
assert.equal(found.status, 'pending');
done();
});
});
});
it('DefaultData should have correct columns', function(done) {
getFields('DefaultData', function(err, fields) {
fields.should.be.eql({
id: {Field: 'id',
Type: 'int(11)',
Null: 'NO',
Key: 'PRI',
Default: null,
Extra: 'auto_increment'},
dateTime: {Field: 'dateTime',
Type: 'datetime',
Null: 'YES',
Key: '',
Default: 'CURRENT_TIMESTAMP',
Extra: ''},
timestamp: {Field: 'timestamp',
Type: 'timestamp',
Null: 'YES',
Key: '',
Default: 'CURRENT_TIMESTAMP',
Extra: ''},
isAdmin: {Field: 'isAdmin',
Type: 'tinyint(1)',
Null: 'YES',
Key: '',
Default: '0',
Extra: ''},
number: {Field: 'number',
Type: 'int(10) unsigned',
Null: 'NO',
Key: 'MUL',
Default: '256',
Extra: ''},
data: {Field: 'data',
Type: 'longtext',
Null: 'YES',
Key: '',
Default: null,
Extra: ''},
text: {Field: 'text',
Type: 'varchar(1024)',
Null: 'YES',
Key: '',
Default: null,
Extra: ''},
status: {Field: 'status',
Type: 'varchar(512)',
Null: 'YES',
Key: '',
Default: 'pending',
Extra: ''},
});
done();
});
});
it('should allow both kinds of date columns', function(done) {
DateData.create({
dateTime: new Date('Aug 9 1996 07:47:33 GMT'),
@ -503,6 +581,17 @@ function setup(done) {
floater: {type: Number, dataType: 'double', precision: 14, scale: 6},
});
DefaultData = db.define('DefaultData', {
dateTime: {type: Date, dataType: 'datetime', mysql: {default: 'now'}},
timestamp: {type: Date, dataType: 'timestamp', mysql: {default: 'CURRENT_TIMESTAMP'}},
isAdmin: {type: Boolean, mysql: {default: '0'}},
number: {type: Number, null: false, index: true, unsigned: true,
dataType: 'int', mysql: {default: 256}},
data: {type: Schema.JSON, dataType: 'longText', mysql: {default: 'Not Supported'}},
text: {type: Schema.Text, dataType: 'varchar', limit: 1024, mysql: {default: 'Not Supported'}},
status: {type: String, dataType: 'varchar', mysql: {default: 'pending'}},
});
DateData = db.define('DateData', {
dateTime: {type: Date, dataType: 'datetime'},
timestamp: {type: Date, dataType: 'timestamp'},