Skip to content

Commit

Permalink
add support for dateStrings connection option. Fixes sidorares#99
Browse files Browse the repository at this point in the history
  • Loading branch information
sidorares committed Apr 30, 2014
1 parent 22454ec commit 4cc63f8
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 16 deletions.
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ Backlog:
- custom typeCast handlers in generated parser #39

HEAD

0.12.1 0 30/04/2014

- 'dateStrings' connection option support #99
- use anonymous function for packet routing instead
of .bind() 3-5% speed improvement
- GEOMETRY type support in bimary protocol #97

0.12.0 - 29/04/2014

Expand Down
8 changes: 5 additions & 3 deletions lib/compile_binary_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ function compile(fields, options, config) {
lvalue = ' this[' + srcEscape(fields[i].name) + ']';

if (fields[i].flags & FieldFlags.NOT_NULL) { // don't need to check null bitmap if field can't be null.
result.push(lvalue + ' = ' + readCodeFor(fields[i]));
result.push(lvalue + ' = ' + readCodeFor(fields[i], config));
} else if (fields[i].columnType == Types.NULL) {
result.push(lvalue + ' = null;');
} else {
result.push(' if (nullBitmaskByte' + nullByteIndex + ' & ' + currentFieldNullBit + ')');
result.push(' ' + lvalue + ' = null;');
result.push(' else');
result.push(' ' + lvalue + ' = ' + readCodeFor(fields[i]));
result.push(' ' + lvalue + ' = ' + readCodeFor(fields[i], config));
}
currentFieldNullBit *= 2;
if (currentFieldNullBit == 0x100)
Expand All @@ -84,7 +84,7 @@ function compile(fields, options, config) {
return vm.runInThisContext(src);
}

function readCodeFor(field) {
function readCodeFor(field, config) {
var unsigned = field.flags & FieldFlags.UNSIGNED;
switch(field.columnType) {
case Types.TINY:
Expand All @@ -106,6 +106,8 @@ function readCodeFor(field) {
case Types.DATETIME:
case Types.TIMESTAMP:
case Types.NEWDATE:
if (config.dateStrings)
return "packet.readDateTimeString();";
return "packet.readDateTime();";
case Types.TIME:
return "packet.readTimeString()";
Expand Down
8 changes: 6 additions & 2 deletions lib/compile_text_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function compile(fields, options, config) {
lvalue = ' result[' + i.toString(10) + ']';
} else
lvalue = ' this[' + srcEscape(fields[i].name) + ']';
result.push(lvalue + ' = ' + readCodeFor(fields[i].columnType, fields[i].characterSet));
result.push(lvalue + ' = ' + readCodeFor(fields[i].columnType, fields[i].characterSet, config));
}

if (options.rowsAsArray)
Expand All @@ -59,7 +59,7 @@ function compile(fields, options, config) {
return vm.runInThisContext(src);
}

function readCodeFor(type, charset) {
function readCodeFor(type, charset, config) {
switch(type) {
case Types.TINY:
case Types.SHORT:
Expand All @@ -78,9 +78,13 @@ function readCodeFor(type, charset) {
case Types.NEWDECIMAL:
return "packet.readLengthCodedString(); //" + type + ' ' + charset;
case Types.DATE:
if (config.dateStrings)
return "packet.readLengthCodedString()";
return "packet.parseDate();";
case Types.DATETIME:
case Types.TIMESTAMP:
if (config.dateStrings)
return "packet.readLengthCodedString()";
return "packet.parseDateTime();";
case Types.TIME:
return "packet.readLengthCodedString()";
Expand Down
4 changes: 3 additions & 1 deletion lib/connection_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ function ConnectionConfig(options) {
this.multipleStatements = options.multipleStatements || false;
this.typeCast = (options.typeCast === undefined) ? true : options.typeCast;
this.ssl = options.ssl;
this.compress = options.compress;
this.compress = options.compress || false;
this.dateStrings = options.dateStrings || false;


if (this.timezone[0] == " ") {
// "+" is a url encoded char for space so it
Expand Down
51 changes: 49 additions & 2 deletions lib/packets/packet.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Packet.prototype.readBuffer = function(len) {

var INVALID_DATE = new Date(NaN);
// DATE, DATETIME and TIMESTAMP
Packet.prototype.readDateTime = function(convertTtoMs) {
Packet.prototype.readDateTime = function() {
var length = this.readInt8();
var y = 0;
var m = 0;
Expand All @@ -157,6 +157,7 @@ Packet.prototype.readDateTime = function(convertTtoMs) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();

}
if (length > 6) {
H = this.readInt8();
Expand All @@ -171,6 +172,50 @@ Packet.prototype.readDateTime = function(convertTtoMs) {
return new Date(y, m-1, d, H, M, S, ms);
};

// this is nearly duplicate of previous function so generated code is not slower
// due to "if (dateStrings)" branching
var pad = "000000000000";
function leftPad(num, value) {
var s = value.toString();
// if we don't need to pad
if (s.length >= num)
return s;
return (pad + s).slice(-num);
}

Packet.prototype.readDateTimeString = function() {
var length = this.readInt8();
var y = 0;
var m = 0;
var d = 0;
var H = 0;
var M = 0;
var S = 0;
var ms = 0;
var str;
if (length > 3) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();
str = [leftPad(4, y), leftPad(2, m), leftPad(2, d)].join('-')
}
if (length > 6) {
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
str += ' ' + [leftPad(2, H), leftPad(2, M), leftPad(2, S)].join(':');
}
/* in text protocol you don't see microseconds as DATETIME/TIMESTAMP result.
instead you need to use MICROSECOND() function
if (length > 11) {
ms = this.readInt32();
}
*/
return str;
};


/*
// TIME - value in microseconds. Can be negative
Packet.prototype.readTime = function(convertTtoMs) {
var length = this.readInt8();
Expand All @@ -194,6 +239,7 @@ Packet.prototype.readTime = function(convertTtoMs) {
ms = this.readInt32();
return d*86400000 + H*3600000 + M*60000 + S*1000 + ms;
};
*/

// TIME - value as a string, Can be negative
Packet.prototype.readTimeString = function(convertTtoMs) {
Expand Down Expand Up @@ -225,7 +271,8 @@ Packet.prototype.readTimeString = function(convertTtoMs) {
ms *= sign;
return ms;
}
return ( sign === -1 ? '-' : '' ) + [( d ? (d*24) + H : H ), M, S].join(':') + ( ms ? '.'+ ms : '' );
// TODO: add padding
return ( sign === -1 ? '-' : '' ) + [( d ? (d*24) + H : H ), leftPad(2, M), leftPad(2, S)].join(':') + ( ms ? '.'+ ms : '' );
// return ( sign === -1 ? '-' : '' ) + ( d ? d+'d ' : '' ) + [H, M, S].join(':') + ( ms ? '.'+ ms : '' );
};

Expand Down
3 changes: 2 additions & 1 deletion test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ module.exports.createConnection = function(args, callback) {
password: config.password,
database: config.database,
multipleStatements: args ? args.multipleStatements : false,
port: (args && args.port) || config.port
port: (args && args.port) || config.port,
dateStrings: args && args.dateStrings
});
};

Expand Down
39 changes: 32 additions & 7 deletions test/integration/connection/test-datetime.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');
var common = require('../../common');
var connection = common.createConnection();
var connection1 = common.createConnection({ dateStrings: true });
var assert = require('assert');

var rows = undefined;
var rows1 = undefined;
var rows2 = undefined;
var rows3 = undefined;
var rows, rows1, rows2, rows3, rows4, rows5;

var date = new Date('1990-01-01 08:15:11 UTC');
var date1 = new Date('2000-03-03 08:15:11 UTC');
var date2 = '2010-12-10 14:12:09.019473';
connection.query('CREATE TEMPORARY TABLE t (d1 DATE)');
connection.query('INSERT INTO t set d1=?', [date]);

connection1.query('CREATE TEMPORARY TABLE t (d1 DATE, d2 TIMESTAMP, d3 DATETIME)');
connection1.query('INSERT INTO t set d1=?, d2=?, d3=?', [date, date1, date2]);

var dateAsStringExpected = [
{ d1: '1990-01-01',
d2: '2000-03-03 19:15:11',
d3: '2010-12-10 14:12:09' } ];


connection.execute('select from_unixtime(?) t', [(+date).valueOf()/1000], function(err, _rows, _fields) {
if (err) throw err;
rows = _rows;
Expand All @@ -31,7 +40,20 @@ connection.execute('select * from t', function(err, _rows, _fields) {
rows3 = _rows;
});

connection1.query('select * from t', function(err, _rows, _fields) {
console.log(_rows);
if (err) throw err;
rows4 = _rows;
});

connection1.execute('select * from t', function(err, _rows, _fields) {
console.log(_rows);
if (err) throw err;
rows5 = _rows;
});

connection.end();
connection1.end();

process.on('exit', function() {
assert.equal(rows[0].t.constructor, Date);
Expand All @@ -45,4 +67,7 @@ process.on('exit', function() {

assert.equal(rows2[0].d1.getDate(), date.getDate());
assert.equal(rows3[0].d1.getDate(), date.getDate());

assert.deepEqual(rows4, dateAsStringExpected);
assert.deepEqual(rows5, dateAsStringExpected);
});

0 comments on commit 4cc63f8

Please sign in to comment.