2012-02-24 06:13:59 +08:00
|
|
|
var arrayParser = require(__dirname + "/arrayParser.js");
|
|
|
|
|
2011-06-22 03:37:48 +08:00
|
|
|
//parses PostgreSQL server formatted date strings into javascript date objects
|
|
|
|
var parseDate = function(isoDate) {
|
|
|
|
//TODO this could do w/ a refactor
|
2013-12-10 12:35:18 +08:00
|
|
|
var dateMatcher = /(\d{1,})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?/;
|
2011-06-22 03:37:48 +08:00
|
|
|
|
|
|
|
var match = dateMatcher.exec(isoDate);
|
|
|
|
//could not parse date
|
|
|
|
if(!match) {
|
2013-12-10 12:35:18 +08:00
|
|
|
dateMatcher = /^(\d{1,})-(\d{2})-(\d{2})$/;
|
2012-07-24 20:03:30 +08:00
|
|
|
match = dateMatcher.test(isoDate);
|
|
|
|
if(!match) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
//it is a date in YYYY-MM-DD format
|
|
|
|
return new Date(isoDate);
|
|
|
|
}
|
2011-06-22 03:37:48 +08:00
|
|
|
}
|
2013-08-27 01:10:32 +08:00
|
|
|
var isBC = /BC$/.test(isoDate);
|
2013-08-27 00:56:50 +08:00
|
|
|
var _year = parseInt(match[1], 10);
|
|
|
|
var isFirstCentury = (_year > 0) && (_year < 100);
|
|
|
|
var year = (isBC ? "-" : "") + match[1];
|
|
|
|
|
2011-06-22 03:37:48 +08:00
|
|
|
var month = parseInt(match[2],10)-1;
|
|
|
|
var day = match[3];
|
|
|
|
var hour = parseInt(match[4],10);
|
|
|
|
var min = parseInt(match[5],10);
|
|
|
|
var seconds = parseInt(match[6], 10);
|
|
|
|
|
|
|
|
var miliString = match[7];
|
|
|
|
var mili = 0;
|
|
|
|
if(miliString) {
|
|
|
|
mili = 1000 * parseFloat(miliString);
|
|
|
|
}
|
|
|
|
|
2013-04-22 17:57:46 +08:00
|
|
|
//match timezones like the following:
|
|
|
|
//Z (UTC)
|
|
|
|
//-05
|
|
|
|
//+06:30
|
|
|
|
var tZone = /([Z|+\-])(\d{2})?:?(\d{2})?/.exec(isoDate.split(' ')[1]);
|
2011-06-22 03:37:48 +08:00
|
|
|
//minutes to adjust for timezone
|
|
|
|
var tzAdjust = 0;
|
2013-08-27 00:56:50 +08:00
|
|
|
var date;
|
2011-06-22 03:37:48 +08:00
|
|
|
if(tZone) {
|
|
|
|
var type = tZone[1];
|
|
|
|
switch(type) {
|
2013-01-24 08:01:38 +08:00
|
|
|
case 'Z':
|
|
|
|
break;
|
2011-06-22 03:37:48 +08:00
|
|
|
case '-':
|
|
|
|
tzAdjust = -(((parseInt(tZone[2],10)*60)+(parseInt(tZone[3]||0,10))));
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
tzAdjust = (((parseInt(tZone[2],10)*60)+(parseInt(tZone[3]||0,10))));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error("Unidentifed tZone part " + type);
|
|
|
|
}
|
|
|
|
|
2012-12-07 21:44:52 +08:00
|
|
|
var utcOffset = Date.UTC(year, month, day, hour, min, seconds, mili);
|
2013-08-27 00:56:50 +08:00
|
|
|
|
|
|
|
date = new Date(utcOffset - (tzAdjust * 60* 1000));
|
2012-12-07 21:44:52 +08:00
|
|
|
}
|
2013-04-22 17:57:46 +08:00
|
|
|
//no timezone information
|
2012-12-07 21:44:52 +08:00
|
|
|
else {
|
2013-08-27 00:56:50 +08:00
|
|
|
date = new Date(year, month, day, hour, min, seconds, mili);
|
2012-12-07 21:44:52 +08:00
|
|
|
}
|
2013-08-27 01:10:32 +08:00
|
|
|
|
2013-08-27 00:56:50 +08:00
|
|
|
if (isFirstCentury) {
|
|
|
|
date.setUTCFullYear(year);
|
|
|
|
}
|
|
|
|
return date;
|
2011-06-22 03:37:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
var parseBool = function(val) {
|
|
|
|
return val === 't';
|
2013-01-21 21:26:22 +08:00
|
|
|
};
|
2011-06-22 03:37:48 +08:00
|
|
|
|
|
|
|
var parseIntegerArray = function(val) {
|
2013-01-21 21:26:22 +08:00
|
|
|
if(!val) { return null; }
|
2012-02-24 06:13:59 +08:00
|
|
|
var p = arrayParser.create(val, function(entry){
|
2013-01-21 21:26:22 +08:00
|
|
|
if(entry !== null) {
|
2012-03-27 21:24:45 +08:00
|
|
|
entry = parseInt(entry, 10);
|
2013-01-21 21:26:22 +08:00
|
|
|
}
|
2012-05-31 11:51:59 +08:00
|
|
|
return entry;
|
|
|
|
});
|
2013-01-24 08:01:38 +08:00
|
|
|
|
2012-05-31 11:51:59 +08:00
|
|
|
return p.parse();
|
|
|
|
};
|
2012-02-24 06:13:59 +08:00
|
|
|
|
2012-05-31 11:51:59 +08:00
|
|
|
var parseFloatArray = function(val) {
|
2013-01-21 21:26:22 +08:00
|
|
|
if(!val) { return null; }
|
2013-03-08 06:19:11 +08:00
|
|
|
var p = arrayParser.create(val, function(entry) {
|
2012-02-24 06:13:59 +08:00
|
|
|
return entry;
|
|
|
|
});
|
2013-01-24 08:01:38 +08:00
|
|
|
|
2012-02-24 06:13:59 +08:00
|
|
|
return p.parse();
|
2011-06-22 03:37:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
var parseStringArray = function(val) {
|
2013-01-21 21:26:22 +08:00
|
|
|
if(!val) { return null; }
|
2013-01-24 08:01:38 +08:00
|
|
|
|
2012-02-24 06:13:59 +08:00
|
|
|
var p = arrayParser.create(val);
|
|
|
|
return p.parse();
|
2011-06-22 03:37:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var NUM = '([+-]?\\d+)';
|
|
|
|
var YEAR = NUM + '\\s+years?';
|
|
|
|
var MON = NUM + '\\s+mons?';
|
|
|
|
var DAY = NUM + '\\s+days?';
|
|
|
|
var TIME = '([+-])?(\\d\\d):(\\d\\d):(\\d\\d)';
|
2013-01-24 08:01:38 +08:00
|
|
|
var INTERVAL = [YEAR,MON,DAY,TIME].map(function(p){
|
|
|
|
return "("+p+")?";
|
|
|
|
}).join('\\s*');
|
2011-06-22 03:37:48 +08:00
|
|
|
|
|
|
|
var parseInterval = function(val) {
|
2013-01-21 21:26:22 +08:00
|
|
|
if (!val) { return {}; }
|
2011-06-22 03:37:48 +08:00
|
|
|
var m = new RegExp(INTERVAL).exec(val);
|
|
|
|
var i = {};
|
2013-01-21 21:26:22 +08:00
|
|
|
if (m[2]) { i.years = parseInt(m[2], 10); }
|
|
|
|
if (m[4]) { i.months = parseInt(m[4], 10); }
|
|
|
|
if (m[6]) { i.days = parseInt(m[6], 10); }
|
|
|
|
if (m[9]) { i.hours = parseInt(m[9], 10); }
|
|
|
|
if (m[10]) { i.minutes = parseInt(m[10], 10); }
|
|
|
|
if (m[11]) { i.seconds = parseInt(m[11], 10); }
|
2011-06-22 03:37:48 +08:00
|
|
|
if (m[8] == '-'){
|
2013-01-24 08:01:38 +08:00
|
|
|
if (i.hours) { i.hours *= -1; }
|
|
|
|
if (i.minutes) { i.minutes *= -1; }
|
|
|
|
if (i.seconds) { i.seconds *= -1; }
|
2011-06-22 03:37:48 +08:00
|
|
|
}
|
2013-01-21 21:26:22 +08:00
|
|
|
for (var field in i){
|
2013-01-24 08:01:38 +08:00
|
|
|
if (i[field] === 0) {
|
|
|
|
delete i[field];
|
|
|
|
}
|
2011-06-22 03:37:48 +08:00
|
|
|
}
|
|
|
|
return i;
|
|
|
|
};
|
|
|
|
|
2011-11-19 04:12:28 +08:00
|
|
|
var parseByteA = function(val) {
|
2012-08-18 19:17:10 +08:00
|
|
|
if(/^\\x/.test(val)){
|
2012-08-10 10:06:49 +08:00
|
|
|
// new 'hex' style response (pg >9.0)
|
2012-08-18 19:17:10 +08:00
|
|
|
return new Buffer(val.substr(2), 'hex');
|
2012-08-10 10:06:49 +08:00
|
|
|
}else{
|
2013-01-21 21:26:22 +08:00
|
|
|
var out = "";
|
|
|
|
var i = 0;
|
2012-08-10 10:06:49 +08:00
|
|
|
while(i < val.length){
|
|
|
|
if(val[i] != "\\"){
|
2013-01-21 21:26:22 +08:00
|
|
|
out += val[i];
|
|
|
|
++i;
|
2012-08-10 10:06:49 +08:00
|
|
|
}else{
|
2012-08-18 19:48:06 +08:00
|
|
|
if(val.substr(i+1,3).match(/[0-7]{3}/)){
|
2013-01-21 21:26:22 +08:00
|
|
|
out += String.fromCharCode(parseInt(val.substr(i+1,3),8));
|
|
|
|
i += 4;
|
2012-08-10 10:06:49 +08:00
|
|
|
}else{
|
2013-01-21 21:26:22 +08:00
|
|
|
backslashes = 1;
|
2012-08-10 10:06:49 +08:00
|
|
|
while(i+backslashes < val.length && val[i+backslashes] == "\\")
|
2013-01-21 21:26:22 +08:00
|
|
|
backslashes++;
|
2012-08-10 10:06:49 +08:00
|
|
|
for(k=0; k<Math.floor(backslashes/2); ++k)
|
2013-01-21 21:26:22 +08:00
|
|
|
out += "\\";
|
|
|
|
i += Math.floor(backslashes / 2) * 2;
|
2012-08-10 10:06:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new Buffer(out,"binary");
|
|
|
|
}
|
2013-01-21 21:26:22 +08:00
|
|
|
};
|
2011-11-19 04:12:28 +08:00
|
|
|
|
2013-01-21 21:26:22 +08:00
|
|
|
var maxLen = Number.MAX_VALUE.toString().length;
|
2012-03-22 11:36:18 +08:00
|
|
|
|
2012-03-27 21:24:45 +08:00
|
|
|
var parseInteger = function(val) {
|
|
|
|
return parseInt(val, 10);
|
2013-01-21 21:26:22 +08:00
|
|
|
};
|
2012-03-27 21:24:45 +08:00
|
|
|
|
2013-05-24 01:10:08 +08:00
|
|
|
var parseBigInteger = function(val) {
|
|
|
|
var valStr = String(val);
|
|
|
|
if (/^\d+$/.test(valStr)) { return valStr; }
|
|
|
|
return val;
|
|
|
|
};
|
|
|
|
|
2013-10-16 13:03:43 +08:00
|
|
|
var parseJsonArray = function(val) {
|
|
|
|
var arr = parseStringArray(val);
|
2013-10-17 09:06:31 +08:00
|
|
|
|
2013-10-16 13:03:43 +08:00
|
|
|
if (!arr) {
|
|
|
|
return arr;
|
|
|
|
}
|
2013-10-17 09:06:31 +08:00
|
|
|
|
2013-10-16 13:03:43 +08:00
|
|
|
return arr.map(function(el) { return JSON.parse(el); });
|
|
|
|
};
|
|
|
|
|
2011-06-22 03:37:48 +08:00
|
|
|
var init = function(register) {
|
2013-05-27 15:55:49 +08:00
|
|
|
register(20, parseBigInteger); // int8
|
|
|
|
register(21, parseInteger); // int2
|
|
|
|
register(23, parseInteger); // int4
|
|
|
|
register(26, parseInteger); // oid
|
|
|
|
register(700, parseFloat); // float4/real
|
|
|
|
register(701, parseFloat); // float8/double
|
2013-01-24 08:01:38 +08:00
|
|
|
register(16, parseBool);
|
|
|
|
register(1082, parseDate); // date
|
|
|
|
register(1114, parseDate); // timestamp without timezone
|
|
|
|
register(1184, parseDate); // timestamp
|
|
|
|
register(1005, parseIntegerArray); // _int2
|
|
|
|
register(1007, parseIntegerArray); // _int4
|
|
|
|
register(1016, parseIntegerArray); // _int8
|
|
|
|
register(1021, parseFloatArray); // _float4
|
|
|
|
register(1022, parseFloatArray); // _float8
|
2013-03-14 17:06:46 +08:00
|
|
|
register(1231, parseFloatArray); // _numeric
|
2013-01-24 08:01:38 +08:00
|
|
|
register(1014, parseStringArray); //char
|
|
|
|
register(1015, parseStringArray); //varchar
|
|
|
|
register(1008, parseStringArray);
|
|
|
|
register(1009, parseStringArray);
|
|
|
|
register(1186, parseInterval);
|
|
|
|
register(17, parseByteA);
|
2013-04-22 23:18:17 +08:00
|
|
|
register(114, JSON.parse.bind(JSON));
|
2013-10-16 13:03:43 +08:00
|
|
|
register(199, parseJsonArray); // json[]
|
|
|
|
register(2951, parseStringArray); // uuid[]
|
2011-06-22 03:37:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = {
|
2013-01-24 08:01:38 +08:00
|
|
|
init: init
|
2011-06-22 03:37:48 +08:00
|
|
|
};
|