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

Commit d7aa81d1 by Jan Aagaard Meier

almost there

1 parent 8404668d
......@@ -131,7 +131,7 @@ module.exports = (function() {
var definition = self.daoFactory.rawAttributes[attrName]
, isHstore = !!definition.type && !!definition.type.type && definition.type.type === DataTypes.HSTORE.type
, isEnum = definition.type && (definition.type.toString() === DataTypes.ENUM.toString())
, isMySQL = self.daoFactory.daoFactoryManager.sequelize.options.dialect === "mysql"
, isMySQL = ['mysql', 'mariadb'].indexOf(self.daoFactory.daoFactoryManager.sequelize.options.dialect) !== -1
, ciCollation = !!self.daoFactory.options.collate && self.daoFactory.options.collate.match(/_ci$/i)
// Unfortunately for MySQL CI collation we need to map/lowercase values again
......
......@@ -79,7 +79,7 @@ module.exports = (function() {
connect.call(self, function (err, connection) {
connection.queryType = 'read'
done(null, connection)
done(err, connection)
}, config);
},
destroy: function(client) {
......@@ -94,7 +94,7 @@ module.exports = (function() {
create: function (done) {
connect.call(self, function (err, connection) {
connection.queryType = 'write'
done(null, connection)
done(err, connection)
}, self.config.replication.write);
},
destroy: function(client) {
......@@ -231,7 +231,8 @@ module.exports = (function() {
user: config.username,
password: config.password,
db: config.database,
ssl: config.ssl || undefined
ssl: config.ssl || undefined,
metadata: true
// timezone: 'Z' // unsupported by mariasql
})
......@@ -241,12 +242,14 @@ module.exports = (function() {
this.isConnecting = false
done(null, connection)
}).on('error', function() {
disconnect.call(self, connection)
}).on('error', function(err) {
this.isConnecting = false
done(err)
// disconnect.call(self, connection)
}).on('close', function() {
disconnect.call(self, connection)
})
}
var enqueue = function(queueItem, options) {
......
......@@ -25,25 +25,60 @@ module.exports = (function() {
var resultSet = [],
errorDetected = false,
alreadyEnded = false, // This is needed because CALL queries emit 'end' twice...
self = this
this.client.query(this.sql)
.on('result', function(results) {
results
.on('row', function(row, metadata) {
for (var prop in row) {
if (row.hasOwnProperty(prop)) {
if (row[prop] === null) {
continue
}
results.on('row', function(row) {
// iterate through each property to convert
// strings into JS objects when possible
for(var prop in row) {
// take care of properties that shouldn't be strings
if( row[prop] == null) {
continue; // don't mess with null
} else if( parseIso8601.call(this, row[prop]) ) {
// if string can be converted into a JS date, it probably
// is a JS date -- replace the string with the date
row[prop] = parseIso8601.call(this, row[prop] + 'Z')
} else if( !isNaN(row[prop]) ) {
// take care of strings that are really numbers
row[prop] = +(row[prop]);
type = metadata.types[prop]
switch (type) {
case "TINYINT":
case "SMALLINT":
case "INTEGER":
case "MEDIUMINT":
case "BIGINT":
case "YEAR":
row[prop] = parseInt(row[prop], 10)
break
case "DECIMAL":
case "FLOAT":
case "DOUBLE":
row[prop] = parseFloat(row[prop])
break
case "DATE":
case "TIMESTAMP":
case "DATETIME":
row[prop] = new Date(row[prop] + 'Z')
break;
case "BIT":
case "BLOB":
case "TINYBLOB":
case "MEDIUMBLOB":
case "LONGBLOB":
if (metadata.charsetNrs[prop] === 63) { // binary
row[prop] = new Buffer(row[prop])
}
break;
case "TIME":
case "CHAR":
case "VARCHAR":
case "SET":
case "ENUM":
case "GEOMETRY":
case "NULL":
break;
default:
// blank
}
}
}
resultSet.push(row)
......@@ -54,16 +89,19 @@ module.exports = (function() {
self.emit('error', err, this.callee)
}.bind(this))
.on('end', function(info) {
if(errorDetected) {
if (alreadyEnded || errorDetected) {
return
}
alreadyEnded = true
self.emit('sql', this.sql)
// we need to figure out whether to send the result set
// or info depending upon the type of query
if( /^show/.test(this.sql.toLowerCase()) ||
if (/^call/.test(this.sql.toLowerCase())) {
self.emit('success', resultSet)
} else if( /^show/.test(this.sql.toLowerCase()) ||
/^select/.test(this.sql.toLowerCase()) ||
/^describe/.test(this.sql.toLowerCase()) ||
( resultSet.length && /^call/.test(this.sql.toLowerCase()) ) ) {
/^describe/.test(this.sql.toLowerCase())) {
self.emit('success', this.formatResults(resultSet))
} else {
self.emit('success', this.formatResults(info))
......@@ -72,7 +110,7 @@ module.exports = (function() {
}.bind(this));
}.bind(this))
.on('error', function(err) {
if(errorDetected) {
if (errorDetected) {
return
}
errorDetected = true
......@@ -81,73 +119,11 @@ module.exports = (function() {
}.bind(this))
.on('end', function(info) {
// nothing here (query info is returned during the 'result' event)
}.bind(this)).setMaxListeners(100)
return this
}
var parseIso8601 = function(CurDate) {
// note -- this function is borrowed from the following author
// Author: Jim Davis, The Depressed Press of Boston
// Library: DP_DateExtensions
// Website: www.depressedpress.com
// Check the input parameters
if ( typeof CurDate != "string" || CurDate == "" ) {
return null;
};
// Set the fragment expressions
var S = "[\\-/:.]";
var Yr = "((?:1[6-9]|[2-9][0-9])[0-9]{2})";
var Mo = S + "((?:1[012])|(?:0[1-9])|[1-9])";
var Dy = S + "((?:3[01])|(?:[12][0-9])|(?:0[1-9])|[1-9])";
var Hr = "(2[0-4]|[01]?[0-9])";
var Mn = S + "([0-5]?[0-9])";
var Sd = "(?:" + S + "([0-5]?[0-9])(?:[.,]([0-9]+))?)?";
var TZ = "(?:(Z)|(?:([\+\-])(1[012]|[0]?[0-9])(?::?([0-5]?[0-9]))?))?";
// RegEx the input
// First check: Just date parts (month and day are optional)
// Second check: Full date plus time (seconds, milliseconds and TimeZone info are optional)
var TF;
if ( TF = new RegExp("^" + Yr + "(?:" + Mo + "(?:" + Dy + ")?)?" + "$").exec(CurDate) ) {} else if ( TF = new RegExp("^" + Yr + Mo + Dy + "[Tt ]" + Hr + Mn + Sd + TZ + "$").exec(CurDate) ) {};
// If the date couldn't be parsed, return null
if ( !TF ) { return null };
// Default the Time Fragments if they're not present
if ( !TF[2] ) { TF[2] = 1 } else { TF[2] = TF[2] - 1 };
if ( !TF[3] ) { TF[3] = 1 };
if ( !TF[4] ) { TF[4] = 0 };
if ( !TF[5] ) { TF[5] = 0 };
if ( !TF[6] ) { TF[6] = 0 };
if ( !TF[7] ) { TF[7] = 0 };
if ( !TF[8] ) { TF[8] = null };
if ( TF[9] != "-" && TF[9] != "+" ) { TF[9] = null };
if ( !TF[10] ) { TF[10] = 0 } else { TF[10] = TF[9] + TF[10] };
if ( !TF[11] ) { TF[11] = 0 } else { TF[11] = TF[9] + TF[11] };
// If there's no timezone info the data is local time
if ( !TF[8] && !TF[9] ) {
return new Date(TF[1], TF[2], TF[3], TF[4], TF[5], TF[6], TF[7]);
};
// If the UTC indicator is set the date is UTC
if ( TF[8] == "Z" ) {
return new Date(Date.UTC(TF[1], TF[2], TF[3], TF[4], TF[5], TF[6], TF[7]));
};
// If the date has a timezone offset
if ( TF[9] == "-" || TF[9] == "+" ) {
// Get current Timezone information
var CurTZ = new Date().getTimezoneOffset();
var CurTZh = TF[10] - ((CurTZ >= 0 ? "-" : "+") + Math.floor(Math.abs(CurTZ) / 60))
var CurTZm = TF[11] - ((CurTZ >= 0 ? "-" : "+") + (Math.abs(CurTZ) % 60))
// Return the date
return new Date(TF[1], TF[2], TF[3], TF[4] - CurTZh, TF[5] - CurTZm, TF[6], TF[7]);
};
// If we've reached here we couldn't deal with the input, return null
return null;
};
return Query
})()
......
......@@ -193,7 +193,7 @@ module.exports = (function() {
attributes[name].validate = attributes[name].validate || {
_checkEnum: function(value) {
var hasValue = value !== undefined
, isMySQL = self.options.dialect === "mysql"
, isMySQL = ['mysql', 'mariadb'].indexOf(self.options.dialect) !== -1
, ciCollation = !!options.collate && options.collate.match(/_ci$/i) !== null
, valueOutOfScope
......
......@@ -58,7 +58,7 @@
"mocha": "~1.13.0",
"chai-datetime": "~1.1.1",
"sinon": "~1.7.3",
"mariasql": "~0.1.19"
"mariasql": "git://github.com/sequelize/node-mariasql.git"
},
"keywords": [
"mysql",
......
......@@ -3462,7 +3462,7 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
UserPublic.schema('special').sync({ force: true }).success(function() {
self.sequelize.queryInterface.describeTable('Publics')
.on('sql', function(sql) {
if (dialect === "sqlite" || dialect === "mysql") {
if (dialect === "sqlite" || dialect === "mysql" || dialect === 'mariadb') {
expect(sql).to.not.contain('special')
_done()
}
......@@ -3475,7 +3475,7 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
self.sequelize.queryInterface.describeTable('Publics', 'special')
.on('sql', function(sql) {
if (dialect === "sqlite" || dialect === "mysql") {
if (dialect === "sqlite" || dialect === "mysql" || dialect === 'mariadb') {
expect(sql).to.contain('special')
_done()
}
......@@ -3673,7 +3673,9 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
describe("dataset", function() {
it("returns a node-sql instance with the correct dialect", function() {
expect(this.User.dataset().sql.dialectName).to.equal(dialect)
var _dialect = dialect === 'mariadb' ? 'mysql' : dialect
expect(this.User.dataset().sql.dialectName).to.equal(_dialect)
})
it("allows me to generate sql queries", function() {
......
......@@ -7,7 +7,7 @@ var chai = require('chai')
chai.Assertion.includeStack = true
if (dialect.match(/^mysql/)) {
if (dialect.match(/^mysql|mariadb/)) {
describe('[MYSQL Specific] Associations', function() {
describe('many-to-many', function() {
describe('where tables have the same prefix', function() {
......
......@@ -7,7 +7,7 @@ var chai = require('chai')
chai.Assertion.includeStack = true
if (dialect.match(/^mysql/)) {
if (dialect.match(/^mysql|mariadb/)) {
describe('[MYSQL Specific] Connector Manager', function() {
this.timeout(10000)
......
......@@ -8,7 +8,7 @@ var chai = require('chai')
chai.Assertion.includeStack = true
if (dialect.match(/^mysql/)) {
if (dialect.match(/^mysql|mariadb/)) {
describe("[MYSQL Specific] DAOFactory", function () {
describe('constructor', function() {
it("handles extended attributes (unique)", function(done) {
......
......@@ -9,7 +9,7 @@ var chai = require('chai')
chai.Assertion.includeStack = true
if (dialect.match(/^mysql/)) {
if (dialect.match(/^mysql|mariadb/)) {
describe("[MYSQL Specific] QueryGenerator", function () {
var suites = {
attributesToSQL: [
......
......@@ -18,7 +18,7 @@ describe(Support.getTestDialectTeaser("QueryGenerators"), function () {
User.sync({ force: true }).success(function() {
var sql = ''
if (dialect === "mysql") {
if (dialect === "mysql" || dialect === 'mariadb') {
sql = 'SELECT COLUMN_COMMENT as cmt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = \'' + self.sequelize.config.database + '\' AND TABLE_NAME = \'Users\' AND COLUMN_NAME = \'username\'';
}
else if (dialect === "postgres" || dialect === "postgres-native") {
......
......@@ -13,7 +13,7 @@ chai.Assertion.includeStack = true
var qq = function(str) {
if (dialect == 'postgres' || dialect == 'sqlite') {
return '"' + str + '"'
} else if (dialect == 'mysql') {
} else if (dialect == 'mysql' || dialect === 'mariadb') {
return '`' + str + '`'
} else {
return str
......@@ -147,7 +147,7 @@ describe(Support.getTestDialectTeaser("Sequelize"), function () {
})
})
if (dialect == 'mysql') {
if (dialect == 'mysql' || dialect === 'mariadb') {
it('executes stored procedures', function(done) {
var self = this
self.sequelize.query(this.insertQuery).success(function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!