Skip to content

Commit 5ada694

Browse files
author
making3
committed
Previous commit had an old, modified copy from npm. Updated copy to the latest commit and made changes to include or/and functionality.
1 parent d33d8e3 commit 5ada694

File tree

1 file changed

+220
-29
lines changed

1 file changed

+220
-29
lines changed

lib/mysql.js

Lines changed: 220 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,34 @@
33
*/
44
var mysql = require('mysql');
55
var jdb = require('jugglingdb');
6+
var EnumFactory = require('./enumFactory').EnumFactory;
7+
68

79
exports.initialize = function initializeSchema(schema, callback) {
810
if (!mysql) return;
911

1012
var s = schema.settings;
13+
14+
if (s.collation) {
15+
s.charset = s.collation.substr(0,s.collation.indexOf('_')); // Charset should be first 'chunk' of collation.
16+
} else {
17+
s.collation = 'utf8mb4_general_ci';
18+
s.charset = 'utf8mb4';
19+
}
20+
21+
s.supportBigNumbers = (s.supportBigNumbers || false);
22+
s.timezone = (s.timezone || 'local');
23+
1124
schema.client = mysql.createConnection({
1225
host: s.host || 'localhost',
1326
port: s.port || 3306,
1427
user: s.username,
1528
password: s.password,
29+
timezone: s.timezone,
1630
debug: s.debug,
17-
socketPath: s.socketPath
31+
socketPath: s.socketPath,
32+
charset: s.collation.toUpperCase(), // Correct by docs despite seeming odd.
33+
supportBigNumbers: s.supportBigNumbers
1834
});
1935

2036
schema.client.on('error', function (err) {
@@ -24,22 +40,30 @@ exports.initialize = function initializeSchema(schema, callback) {
2440
schema.adapter = new MySQL(schema.client);
2541
schema.adapter.schema = schema;
2642

27-
// schema.client.query('SET TIME_ZONE = "+04:00"', callback);
2843
schema.client.query('USE `' + s.database + '`', function (err) {
29-
if (err && err.message.match(/(^|: )unknown database/i)) {
30-
var dbName = s.database;
31-
schema.client.query('CREATE DATABASE ' + dbName, function (error) {
32-
if (!error) {
33-
schema.client.query('USE ' + s.database, callback);
34-
} else {
35-
throw error;
36-
}
37-
});
44+
if (err) {
45+
if (err.message.match(/(^|: )unknown database/i)) {
46+
var dbName = s.database;
47+
var charset = s.charset;
48+
var collation = s.collation;
49+
var q = 'CREATE DATABASE ' + dbName + ' CHARACTER SET ' + charset + ' COLLATE ' + collation;
50+
schema.client.query(q, function (error) {
51+
if (!error) {
52+
schema.client.query('USE ' + s.database, callback);
53+
} else {
54+
throw error;
55+
}
56+
});
57+
} else throw err;
3858
} else callback();
3959
});
4060

4161
// MySQL specific column types
4262
schema.constructor.registerType(function Point() {});
63+
64+
schema.EnumFactory = EnumFactory; // factory for Enums. Note that currently Enums can not be registered.
65+
66+
4367
};
4468

4569
/**
@@ -175,8 +199,8 @@ MySQL.prototype.toDatabase = function (prop, val) {
175199
} else {
176200
return val;
177201
}
178-
}
179-
}
202+
}
203+
}
180204
if (!prop) return val;
181205
if (prop.type.name === 'Number') return Number(val);
182206
if (prop.type.name === 'Date') {
@@ -187,6 +211,7 @@ MySQL.prototype.toDatabase = function (prop, val) {
187211
return '"' + dateToMysql(val) + '"';
188212
}
189213
if (prop.type.name == "Boolean") return val ? 1 : 0;
214+
if (typeof prop.type === 'function') return this.client.escape(prop.type(val));
190215
return this.client.escape(val.toString());
191216
};
192217

@@ -204,7 +229,7 @@ MySQL.prototype.fromDatabase = function (model, data) {
204229
val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));
205230
break;
206231
case 'Boolean':
207-
val = new Boolean(val);
232+
val = Boolean(val);
208233
break;
209234
}
210235
}
@@ -238,7 +263,6 @@ MySQL.prototype.all = function all(model, filter, callback) {
238263
}
239264

240265
}
241-
debugger;
242266

243267
this.query(sql, function (err, data) {
244268
if (err) {
@@ -267,15 +291,15 @@ MySQL.prototype.all = function all(model, filter, callback) {
267291
} else if (conds[key] && conds[key].constructor.name === 'Object') {
268292
var condType = Object.keys(conds[key])[0];
269293
var sqlCond = keyEscaped;
270-
if ((condType == 'inq' || condType == 'nin') && val.length == 0) {
294+
if ((condType == 'inq' || condType == 'nin') && val.length == 0) {
271295
cs.push(condType == 'inq' ? 0 : 1);
272296
return true;
273297
}
274298
switch (condType) {
275299
case 'gt':
276300
sqlCond += ' > ';
277301
break;
278-
case 'gte':
302+
case 'gte':
279303
sqlCond += ' >= ';
280304
break;
281305
case 'lt':
@@ -297,7 +321,6 @@ MySQL.prototype.all = function all(model, filter, callback) {
297321
sqlCond += ' != ';
298322
break;
299323
}
300-
301324
sqlCond += (condType == 'inq' || condType == 'nin') ? '(' + val + ')' : val;
302325
cs.push(sqlCond);
303326
} else if (conds[key] && conds[key].constructor.name === 'Array') {
@@ -308,7 +331,7 @@ MySQL.prototype.all = function all(model, filter, callback) {
308331

309332
sqlCond += ')';
310333
cs.push(sqlCond);
311-
} else {
334+
} else {
312335
cs.push(keyEscaped + ' = ' + val);
313336
}
314337
});
@@ -528,9 +551,17 @@ MySQL.prototype.alterTable = function (model, actualFields, actualIndexes, done,
528551
}
529552

530553
function changed(newSettings, oldSettings) {
531-
if (oldSettings.Null === 'YES' && (newSettings.allowNull === false || newSettings.null === false)) return true;
532-
if (oldSettings.Null === 'NO' && !(newSettings.allowNull === false || newSettings.null === false)) return true;
533-
if (oldSettings.Type.toUpperCase() !== datatype(newSettings)) return true;
554+
if (oldSettings.Null === 'YES') { // Used to allow null and does not now.
555+
if(newSettings.allowNull === false) return true;
556+
if(newSettings.null === false) return true;
557+
}
558+
if (oldSettings.Null === 'NO') { // Did not allow null and now does.
559+
if(newSettings.allowNull === true) return true;
560+
if(newSettings.null === true) return true;
561+
if(newSettings.null === undefined && newSettings.allowNull === undefined) return true;
562+
}
563+
564+
if (oldSettings.Type.toUpperCase() !== datatype(newSettings).toUpperCase()) return true;
534565
return false;
535566
}
536567
};
@@ -597,8 +628,9 @@ MySQL.prototype.indexSettingsSQL = function (model, prop) {
597628

598629
MySQL.prototype.propertySettingsSQL = function (model, prop) {
599630
var p = this._models[model].properties[prop];
600-
return datatype(p) + ' ' +
631+
var line = datatype(p) + ' ' +
601632
(p.allowNull === false || p['null'] === false ? 'NOT NULL' : 'NULL');
633+
return line;
602634
};
603635

604636
function datatype(p) {
@@ -607,24 +639,183 @@ function datatype(p) {
607639
default:
608640
case 'String':
609641
case 'JSON':
610-
dt = 'VARCHAR(' + (p.limit || 255) + ')';
642+
dt = columnType(p, 'VARCHAR');
643+
dt = stringOptionsByType(p, dt);
611644
break;
612645
case 'Text':
613-
dt = 'TEXT';
646+
dt = columnType(p, 'TEXT');
647+
dt = stringOptionsByType(p, dt);
614648
break;
615649
case 'Number':
616-
dt = 'INT(' + (p.limit || 11) + ')';
650+
dt = columnType(p, 'INT');
651+
dt = numericOptionsByType(p, dt);
617652
break;
618653
case 'Date':
619-
dt = 'DATETIME';
654+
dt = columnType(p, 'DATETIME'); // Currently doesn't need options.
620655
break;
621656
case 'Boolean':
622-
dt = 'TINYINT(1)';
657+
dt = 'TINYINT(1)';
623658
break;
624659
case 'Point':
625-
dt = 'POINT';
660+
dt = 'POINT';
661+
break;
662+
case 'Enum':
663+
dt = 'ENUM(' + p.type._string + ')';
664+
dt = stringOptions(p, dt); // Enum columns can have charset/collation.
626665
break;
627666
}
628667
return dt;
629668
}
630669

670+
function columnType(p, defaultType) {
671+
var dt = defaultType;
672+
if(p.dataType){
673+
dt = String(p.dataType);
674+
}
675+
return dt;
676+
}
677+
678+
function stringOptionsByType(p, dt) {
679+
switch (dt.toLowerCase()) {
680+
default:
681+
case 'varchar':
682+
case 'char':
683+
dt += '(' + (p.limit || 255) + ')';
684+
break;
685+
686+
case 'text':
687+
case 'tinytext':
688+
case 'mediumtext':
689+
case 'longtext':
690+
691+
break;
692+
}
693+
dt = stringOptions(p, dt);
694+
return dt;
695+
}
696+
697+
function stringOptions(p, dt){
698+
if(p.charset){
699+
dt += " CHARACTER SET " + p.charset;
700+
}
701+
if(p.collation){
702+
dt += " COLLATE " + p.collation;
703+
}
704+
return dt;
705+
}
706+
707+
function numericOptionsByType(p, dt) {
708+
switch (dt.toLowerCase()) {
709+
default:
710+
case 'tinyint':
711+
case 'smallint':
712+
case 'mediumint':
713+
case 'int':
714+
case 'integer':
715+
case 'bigint':
716+
dt = integerOptions(p, dt);
717+
break;
718+
719+
case 'decimal':
720+
case 'numeric':
721+
dt = fixedPointOptions(p, dt);
722+
break;
723+
724+
case 'float':
725+
case 'double':
726+
dt = floatingPointOptions(p, dt);
727+
break;
728+
}
729+
dt = unsigned(p, dt);
730+
return dt;
731+
}
732+
733+
function floatingPointOptions(p, dt) {
734+
var precision = 16;
735+
var scale = 8;
736+
if(p.precision){
737+
precision = Number(p.precision);
738+
}
739+
if(p.scale){
740+
scale = Number(p.scale);
741+
}
742+
if (p.precision && p.scale) {
743+
dt += '(' + precision + ',' + scale + ')';
744+
} else if(p.precision){
745+
dt += '(' + precision + ')';
746+
}
747+
return dt;
748+
}
749+
750+
/* @TODO: Change fixed point to use an arbitrary precision arithmetic library. */
751+
/* Currently fixed point will lose precision because it's turned to non-fixed in */
752+
/* JS. Also, defaulting column to (9,2) and not allowing non-specified 'DECIMAL' */
753+
/* declaration which would default to DECIMAL(10,0). Instead defaulting to (9,2). */
754+
function fixedPointOptions(p, dt) {
755+
var precision = 9;
756+
var scale = 2;
757+
if(p.precision){
758+
precision = Number(p.precision);
759+
}
760+
if(p.scale){
761+
scale = Number(p.scale);
762+
}
763+
dt += '(' + precision + ',' + scale + ')';
764+
return dt;
765+
}
766+
767+
function integerOptions(p, dt) {
768+
var tmp = 0;
769+
if (p.display || p.limit) {
770+
tmp = Number(p.display || p.limit);
771+
}
772+
if(tmp > 0){
773+
dt += '(' + tmp + ')';
774+
} else if(p.unsigned){
775+
switch (dt.toLowerCase()) {
776+
default:
777+
case 'int':
778+
dt += '(10)';
779+
break;
780+
case 'mediumint':
781+
dt += '(8)';
782+
break;
783+
case 'smallint':
784+
dt += '(5)';
785+
break;
786+
case 'tinyint':
787+
dt += '(3)';
788+
break;
789+
case 'bigint':
790+
dt += '(20)';
791+
break;
792+
}
793+
} else {
794+
switch (dt.toLowerCase()) {
795+
default:
796+
case 'int':
797+
dt += '(11)';
798+
break;
799+
case 'mediumint':
800+
dt += '(9)';
801+
break;
802+
case 'smallint':
803+
dt += '(6)';
804+
break;
805+
case 'tinyint':
806+
dt += '(4)';
807+
break;
808+
case 'bigint':
809+
dt += '(20)';
810+
break;
811+
}
812+
}
813+
return dt;
814+
}
815+
816+
function unsigned(p, dt){
817+
if (p.unsigned) {
818+
dt += ' UNSIGNED';
819+
}
820+
return dt;
821+
}

0 commit comments

Comments
 (0)