Merge pull request #39 from dgsan/master
Support for Enum type in MySQL adapter. Requires patch to mainline JDB.
This commit is contained in:
commit
f2412bc170
|
@ -0,0 +1,49 @@
|
|||
var EnumFactory = function() {
|
||||
if(arguments.length > 0){
|
||||
var Enum = function Enum(arg){
|
||||
if(typeof arg === 'number' && arg % 1 == 0) {
|
||||
return Enum._values[arg];
|
||||
} else if(Enum[arg]){
|
||||
return Enum[arg]
|
||||
} else if (Enum._values.indexOf(arg) !== -1 ) {
|
||||
return arg;
|
||||
} else if (arg === null) {
|
||||
return null;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
var dxList = [];
|
||||
dxList.push(''); // Want empty value to be at index 0 to match MySQL Enum values and MySQL non-strict behavior.
|
||||
for(var arg in arguments){
|
||||
arg = String(arguments[arg]);
|
||||
Object.defineProperty(Enum, arg.toUpperCase(), {configurable: false, enumerable: true, value: arg, writable: false});
|
||||
dxList.push(arg);
|
||||
}
|
||||
Object.defineProperty(Enum, '_values', {configurable: false, enumerable: false, value: dxList, writable: false});
|
||||
Object.defineProperty(Enum, '_string', {configurable: false, enumerable: false, value: stringified(Enum), writable: false});
|
||||
Object.freeze(Enum);
|
||||
return Enum;
|
||||
} else {
|
||||
throw "No arguments - could not create Enum.";
|
||||
}
|
||||
};
|
||||
|
||||
function stringified(anEnum) {
|
||||
var s = [];
|
||||
for(var i in anEnum._values){
|
||||
if(anEnum._values[i] != ''){
|
||||
s.push("'" + anEnum._values[i] + "'");
|
||||
}
|
||||
}
|
||||
return s.join(',');
|
||||
}
|
||||
|
||||
exports.EnumFactory = EnumFactory;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
11
lib/mysql.js
11
lib/mysql.js
|
@ -3,6 +3,8 @@
|
|||
*/
|
||||
var mysql = require('mysql');
|
||||
var jdb = require('jugglingdb');
|
||||
var EnumFactory = require('./enumFactory').EnumFactory;
|
||||
|
||||
|
||||
exports.initialize = function initializeSchema(schema, callback) {
|
||||
if (!mysql) return;
|
||||
|
@ -58,6 +60,10 @@ exports.initialize = function initializeSchema(schema, callback) {
|
|||
|
||||
// MySQL specific column types
|
||||
schema.constructor.registerType(function Point() {});
|
||||
|
||||
schema.EnumFactory = EnumFactory; // factory for Enums. Note that currently Enums can not be registered.
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -205,6 +211,7 @@ MySQL.prototype.toDatabase = function (prop, val) {
|
|||
return '"' + dateToMysql(val) + '"';
|
||||
}
|
||||
if (prop.type.name == "Boolean") return val ? 1 : 0;
|
||||
if (typeof prop.type === 'function') return this.client.escape(prop.type(val));
|
||||
return this.client.escape(val.toString());
|
||||
};
|
||||
|
||||
|
@ -644,6 +651,10 @@ function datatype(p) {
|
|||
case 'Point':
|
||||
dt = 'POINT';
|
||||
break;
|
||||
case 'Enum':
|
||||
dt = 'ENUM(' + p.type._string + ')';
|
||||
dt = stringOptions(p, dt); // Enum columns can have charset/collation.
|
||||
break;
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
var should = require('./init.js');
|
||||
var assert = require('assert');
|
||||
var Schema = require('jugglingdb').Schema;
|
||||
|
||||
var db, settings, adapter, EnumModel, ANIMAL_ENUM;
|
||||
|
||||
describe('MySQL specific datatypes', function() {
|
||||
|
||||
before(setup);
|
||||
|
||||
it('should run migration', function(done) {
|
||||
db.automigrate(function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('An enum should parse itself', function(done) {
|
||||
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('cat'));
|
||||
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM('CAT'));
|
||||
assert.equal(ANIMAL_ENUM.CAT, ANIMAL_ENUM(2));
|
||||
assert.equal(ANIMAL_ENUM.CAT, 'cat');
|
||||
assert.equal(ANIMAL_ENUM(null), null);
|
||||
assert.equal(ANIMAL_ENUM(''), '');
|
||||
assert.equal(ANIMAL_ENUM(0), '');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create a model instance with Enums', function(done) {
|
||||
var em = EnumModel.create({animal: ANIMAL_ENUM.CAT, condition: 'sleepy', mood: 'happy'}, function(err, obj) {
|
||||
assert.ok(!err);
|
||||
assert.equal(obj.condition, 'sleepy');
|
||||
EnumModel.findOne({where: {animal: ANIMAL_ENUM.CAT}}, function(err, found){
|
||||
assert.ok(!err);
|
||||
assert.equal(found.mood, 'happy');
|
||||
assert.equal(found.animal, ANIMAL_ENUM.CAT);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail spectacularly with invalid enum values', function(done) {
|
||||
var em = EnumModel.create({animal: 'horse', condition: 'sleepy', mood: 'happy'}, function(err, obj) {
|
||||
assert.ok(!err);
|
||||
EnumModel.find(obj.id, function(err, found){
|
||||
assert.ok(!err);
|
||||
assert.equal(found.animal, ''); // MySQL fun.
|
||||
assert.equal(found.animal, 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should disconnect when done', function(done) {
|
||||
db.disconnect();
|
||||
done()
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function setup(done) {
|
||||
|
||||
require('./init.js');
|
||||
|
||||
db = getSchema();
|
||||
|
||||
ANIMAL_ENUM = db.EnumFactory('dog', 'cat', 'mouse');
|
||||
|
||||
EnumModel = db.define('EnumModel', {
|
||||
animal: { type: ANIMAL_ENUM, null: false },
|
||||
condition: { type: db.EnumFactory('hungry', 'sleepy', 'thirsty') },
|
||||
mood: { type: db.EnumFactory('angry', 'happy', 'sad') }
|
||||
});
|
||||
|
||||
blankDatabase(db, done);
|
||||
|
||||
}
|
||||
|
||||
var query = function (sql, cb) {
|
||||
db.adapter.query(sql, cb);
|
||||
};
|
||||
|
||||
var blankDatabase = function (db, cb) {
|
||||
var dbn = db.settings.database;
|
||||
var cs = db.settings.charset;
|
||||
var co = db.settings.collation;
|
||||
query('DROP DATABASE IF EXISTS ' + dbn, function(err) {
|
||||
var q = 'CREATE DATABASE ' + dbn;
|
||||
if(cs){
|
||||
q += ' CHARACTER SET ' + cs;
|
||||
}
|
||||
if(co){
|
||||
q += ' COLLATE ' + co;
|
||||
}
|
||||
query(q, function(err) {
|
||||
query('USE '+ dbn, cb);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
getFields = function (model, cb) {
|
||||
query('SHOW FIELDS FROM ' + model, function(err, res) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
var fields = {};
|
||||
res.forEach(function(field){
|
||||
fields[field.Field] = field;
|
||||
});
|
||||
cb(err, fields);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getIndexes = function (model, cb) {
|
||||
query('SHOW INDEXES FROM ' + model, function(err, res) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
cb(err);
|
||||
} else {
|
||||
var indexes = {};
|
||||
// Note: this will only show the first key of compound keys
|
||||
res.forEach(function(index) {
|
||||
if (parseInt(index.Seq_in_index, 10) == 1) {
|
||||
indexes[index.Key_name] = index
|
||||
}
|
||||
});
|
||||
cb(err, indexes);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue