Socket
Socket
Sign inDemoInstall

pg-types

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pg-types - npm Package Compare versions

Comparing version 1.7.0 to 1.8.0

test/types.js

16

index.js

@@ -5,2 +5,6 @@ var textParsers = require('./lib/textParsers');

exports.getTypeParser = getTypeParser;
exports.setTypeParser = setTypeParser;
exports.arrayParser = arrayParser;
var typeParsers = {

@@ -12,3 +16,3 @@ text: {},

//the empty parse function
var noParse = function(val) {
function noParse (val) {
return String(val);

@@ -21,3 +25,3 @@ };

//SELECT oid FROM pg_type WHERE typname = 'TYPE_NAME_HERE';
var getTypeParser = function(oid, format) {
function getTypeParser (oid, format) {
format = format || 'text';

@@ -30,3 +34,3 @@ if (!typeParsers[format]) {

var setTypeParser = function(oid, format, parseFn) {
function setTypeParser (oid, format, parseFn) {
if(typeof format == 'function') {

@@ -46,7 +50,1 @@ parseFn = format;

});
module.exports = {
getTypeParser: getTypeParser,
setTypeParser: setTypeParser,
arrayParser: arrayParser
};

@@ -1,97 +0,9 @@

function ArrayParser(source, converter) {
this.source = source;
this.converter = converter;
this.pos = 0;
this.entries = [];
this.recorded = [];
this.dimension = 0;
if (!this.converter) {
this.converter = function(entry) {
return entry;
};
}
}
var array = require('postgres-array');
ArrayParser.prototype.eof = function() {
return this.pos >= this.source.length;
};
ArrayParser.prototype.nextChar = function() {
var c;
if ((c = this.source[this.pos++]) === "\\") {
module.exports = {
create: function (source, transform) {
return {
char: this.source[this.pos++],
escaped: true
parse: array.parse
};
} else {
return {
char: c,
escaped: false
};
}
};
ArrayParser.prototype.record = function(c) {
return this.recorded.push(c);
};
ArrayParser.prototype.newEntry = function(includeEmpty) {
var entry;
if (this.recorded.length > 0 || includeEmpty) {
entry = this.recorded.join("");
if (entry === "NULL" && !includeEmpty) {
entry = null;
}
if (entry !== null) {
entry = this.converter(entry);
}
this.entries.push(entry);
this.recorded = [];
}
};
ArrayParser.prototype.parse = function(nested) {
var c, p, quote;
if (nested === null) {
nested = false;
}
quote = false;
while (!this.eof()) {
c = this.nextChar();
if (c.char === "{" && !quote) {
this.dimension++;
if (this.dimension > 1) {
p = new ArrayParser(this.source.substr(this.pos - 1), this.converter);
this.entries.push(p.parse(true));
this.pos += p.pos - 2;
}
} else if (c.char === "}" && !quote) {
this.dimension--;
if (this.dimension === 0) {
this.newEntry();
if (nested) {
return this.entries;
}
}
} else if (c.char === '"' && !c.escaped) {
if (quote) {
this.newEntry(true);
}
quote = !quote;
} else if (c.char === ',' && !quote) {
this.newEntry();
} else {
this.record(c.char);
}
}
if (this.dimension !== 0) {
throw "array dimension not balanced";
}
return this.entries;
};
module.exports = {
create: function(source, converter){
return new ArrayParser(source, converter);
}
};

@@ -0,122 +1,37 @@

var array = require('postgres-array')
var ap = require('ap')
var arrayParser = require(__dirname + "/arrayParser.js");
var parseDate = require('postgres-date');
var parseInterval = require('postgres-interval');
var parseByteA = require('postgres-bytea');
//parses PostgreSQL server formatted date strings into javascript date objects
var parseDate = function(isoDate) {
//TODO this could do w/ a refactor
var dateMatcher = /(\d{1,})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?/;
var match = dateMatcher.exec(isoDate);
//could not parse date
if(!match) {
dateMatcher = /^(\d{1,})-(\d{2})-(\d{2})$/;
match = dateMatcher.test(isoDate);
if(!match) {
return null;
} else {
//it is a date in YYYY-MM-DD format
//add time portion to force js to parse as local time
return new Date(isoDate + ' 00:00:00');
}
function allowNull (fn) {
return function nullAllowed (value) {
if (value === null) return value
return fn(value)
}
var isBC = /BC$/.test(isoDate);
var _year = parseInt(match[1], 10);
var isFirstCentury = (_year > 0) && (_year < 100);
var year = (isBC ? "-" : "") + match[1];
}
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);
function parseBool (value) {
if (value === null) return value
return value === 't';
}
var miliString = match[7];
var mili = 0;
if(miliString) {
mili = 1000 * parseFloat(miliString);
}
function parseBoolArray (value) {
if (!value) return null
return array.parse(value, parseBool)
}
//match timezones like the following:
//Z (UTC)
//-05
//+06:30
var tZone = /([Z|+\-])(\d{2})?:?(\d{2})?:?(\d{2})?/.exec(isoDate.split(' ')[1]);
//minutes to adjust for timezone
var tzAdjust = 0;
var tzSign = 1;
var date;
if(tZone) {
var type = tZone[1];
switch(type) {
case 'Z':
break;
case '-':
tzSign = -1;
case '+':
tzAdjust = tzSign * (
(parseInt(tZone[2], 10) * 3600) +
(parseInt(tZone[3] || 0, 10) * 60) +
(parseInt(tZone[4] || 0, 10))
);
break;
default:
throw new Error("Unidentifed tZone part " + type);
}
function parseIntegerArray (value) {
if (!value) return null
return array.parse(value, allowNull(ap.partialRight(parseInt, 10)))
}
var utcOffset = Date.UTC(year, month, day, hour, min, seconds, mili);
function parseBigIntegerArray (value) {
if (!value) return null
return array.parse(val, allowNull(function (item) {
return parseBigInteger(entry).trim()
}))
}
date = new Date(utcOffset - (tzAdjust * 1000));
}
//no timezone information
else {
date = new Date(year, month, day, hour, min, seconds, mili);
}
if (isFirstCentury) {
date.setUTCFullYear(year);
}
return date;
};
var parseBool = function(val) {
if(val === null) return val;
return val === 't';
};
var parseBoolArray = function(val) {
if(!val) { return null; }
var p = arrayParser.create(val, function(entry){
if(entry !== null) {
entry = parseBool(entry);
}
return entry;
});
return p.parse();
};
var parseIntegerArray = function(val) {
if(!val) { return null; }
var p = arrayParser.create(val, function(entry){
if(entry !== null) {
entry = parseInt(entry, 10);
}
return entry;
});
return p.parse();
};
var parseBigIntegerArray = function(val) {
if(!val) { return null; }
var p = arrayParser.create(val, function(entry){
if(entry !== null) {
entry = parseBigInteger(entry).trim();
}
return entry;
});
return p.parse();
};
var parseFloatArray = function(val) {

@@ -154,78 +69,11 @@ if(!val) { return null; }

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):?(\\d\\d\\d)?';
var INTERVAL = [YEAR,MON,DAY,TIME].map(function(p){
return "("+p+")?";
}).join('\\s*');
var parseByteAArray = function(val) {
var arr = parseStringArray(val);
if (!arr) return arr;
/* Wrapper object that makes sure Interval objects can be passed back
* into prepared statements */
function PostgresInterval() {}
PostgresInterval.prototype.toPostgres = function() {
var intervalElements = [];
if (this.seconds) intervalElements.push(this.seconds + ' seconds');
if (this.minutes) intervalElements.push(this.minutes + ' minutes');
if (this.hours) intervalElements.push(this.hours + ' hours');
if (this.days) intervalElements.push(this.days + ' days');
if (this.months) intervalElements.push(this.months + ' months');
if (this.years) intervalElements.push(this.years + ' years');
return intervalElements.join(' ');
return arr.map(function(element) {
return parseByteA(element);
});
};
var parseInterval = function(val) {
if (!val) { return {}; }
var m = new RegExp(INTERVAL).exec(val);
var i = new PostgresInterval();
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); }
if (m[12]) { i.milliseconds = parseInt(m[12], 10); }
if (m[8] == '-'){
if (i.hours) { i.hours *= -1; }
if (i.minutes) { i.minutes *= -1; }
if (i.seconds) { i.seconds *= -1; }
}
for (var field in i){
if (i[field] === 0) {
delete i[field];
}
}
return i;
};
var parseByteA = function(val) {
if(/^\\x/.test(val)){
// new 'hex' style response (pg >9.0)
return new Buffer(val.substr(2), 'hex');
}else{
var out = "";
var i = 0;
while(i < val.length){
if(val[i] != "\\"){
out += val[i];
++i;
}else{
if(val.substr(i+1,3).match(/[0-7]{3}/)){
out += String.fromCharCode(parseInt(val.substr(i+1,3),8));
i += 4;
}else{
backslashes = 1;
while(i+backslashes < val.length && val[i+backslashes] == "\\")
backslashes++;
for(k=0; k<Math.floor(backslashes/2); ++k)
out += "\\";
i += Math.floor(backslashes / 2) * 2;
}
}
}
return new Buffer(out,"binary");
}
};
var parseInteger = function(val) {

@@ -306,2 +154,3 @@ return parseInt(val, 10);

register(1000, parseBoolArray);
register(1001, parseByteAArray);
register(1005, parseIntegerArray); // _int2

@@ -322,6 +171,9 @@ register(1007, parseIntegerArray); // _int4

register(17, parseByteA);
register(114, JSON.parse.bind(JSON));
register(3802, JSON.parse.bind(JSON));
register(114, JSON.parse.bind(JSON)); // json
register(3802, JSON.parse.bind(JSON)); // jsonb
register(199, parseJsonArray); // json[]
register(3807, parseJsonArray); // jsonb[]
register(2951, parseStringArray); // uuid[]
register(791, parseStringArray); // money[]
register(1183, parseStringArray); // time[]
};

@@ -328,0 +180,0 @@

{
"name": "pg-types",
"version": "1.7.0",
"version": "1.8.0",
"description": "Query result type converters for node-postgres",
"main": "index.js",
"scripts": {
"test": "mocha"
"test": "tape test/*.js | tap-spec"
},

@@ -25,4 +25,13 @@ "repository": {

"devDependencies": {
"mocha": "^1.18.0"
"pff": "^1.0.0",
"tap-spec": "^4.0.0",
"tape": "^4.0.0"
},
"dependencies": {
"ap": "~0.2.0",
"postgres-array": "~1.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.0",
"postgres-interval": "~1.0.0"
}
}

@@ -42,6 +42,6 @@ # pg-types

If you're thinking "gee, this seems pretty handy, but how can I get a list of all the OIDs in the database and what the correspond to?!?!?!" worry not:
If you're thinking "gee, this seems pretty handy, but how can I get a list of all the OIDs in the database and what they correspond to?!?!?!" worry not:
```bash
$ psql -c "select oid, typname from pg_type where typtype = 'b' order by oid"
$ psql -c "select typname, oid, typarray from pg_type where typtype = 'b' order by oid"
```

@@ -48,0 +48,0 @@

//http://www.postgresql.org/docs/9.2/static/datatype.html
var test = require('tape')
var printf = require('pff')
var getTypeParser = require('../').getTypeParser
var types = require('./types')
var tests = [{
name: 'string/varchar',
format: 'text',
dataTypeID: 1043,
actual: 'bang',
expected: 'bang'
},{
name: 'integer/int4',
format: 'text',
dataTypeID: 23,
actual: '2147483647',
expected: 2147483647
},{
name: 'smallint/int2',
format: 'text',
dataTypeID: 21,
actual: '32767',
expected: 32767
},{
name: 'bigint/int8',
format: 'text',
dataTypeID: 20,
actual: '9223372036854775807',
expected: '9223372036854775807'
},{
name: 'oid',
format: 'text',
dataTypeID: 26,
actual: '103',
expected: 103
},{
name: 'numeric',
format: 'text',
dataTypeID: 1700,
actual: '31415926535897932384626433832795028841971693993751058.16180339887498948482045868343656381177203091798057628',
expected: '31415926535897932384626433832795028841971693993751058.16180339887498948482045868343656381177203091798057628'
},{
name: 'real/float4',
dataTypeID: 700,
format: 'text',
actual: '123.456',
expected: 123.456
},{
name: 'double precision / float8',
format: 'text',
dataTypeID: 701,
actual: '12345678.12345678',
expected: 12345678.12345678
},{
name: 'boolean true',
format: 'text',
dataTypeID: 16,
actual: 't',
expected: true
},{
name: 'boolean false',
format: 'text',
dataTypeID: 16,
actual: 'f',
expected: false
},{
name: 'boolean null',
format: 'text',
dataTypeID: 16,
actual: null,
expected: null
},{
name: 'timestamptz with minutes in timezone',
format: 'text',
dataTypeID: 1184,
actual: '2010-10-31 14:54:13.74-05:30',
expected: function(val) {
assert.UTCDate(val, 2010, 9, 31, 20, 24, 13, 740);
}
}, {
name: 'timestamptz with other milisecond digits dropped',
format: 'text',
dataTypeID: 1184,
actual: '2011-01-23 22:05:00.68-06',
expected: function(val) {
assert.UTCDate(val, 2011, 0, 24, 4, 5, 0, 680);
}
}, {
name: 'timestampz with huge miliseconds in UTC',
format: 'text',
dataTypeID: 1184,
actual: '2010-10-30 14:11:12.730838Z',
expected: function(val) {
assert.UTCDate(val, 2010, 9, 30, 14, 11, 12, 730);
}
},{
name: 'timestampz with no miliseconds',
format: 'text',
dataTypeID: 1184,
actual: '2010-10-30 13:10:01+05',
expected: function(val) {
assert.UTCDate(val, 2010, 9, 30, 8, 10, 01, 0);
}
},{
name: 'timestamp',
format: 'text',
dataTypeID: 1114,
actual: '2010-10-31 00:00:00',
expected: function(val) {
assert.equal(val.toUTCString(), new Date(2010, 9, 31, 0, 0, 0, 0, 0).toUTCString());
assert.equal(val.toString(), new Date(2010, 9, 31, 0, 0, 0, 0, 0, 0).toString());
}
},{
name: 'date',
format: 'text',
dataTypeID: 1082,
actual: '2010-10-31',
expected: function(val) {
var now = new Date(2010, 9, 31);
assert.UTCDate(val, 2010, now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), 0, 0, 0);
assert.equal(val.getHours(), now.getHours());
}
},{
name: 'interval time',
format: 'text',
dataTypeID: 1186,
actual: '01:02:03',
expected: function(val) {
assert.equal(val.toPostgres(), '3 seconds 2 minutes 1 hours');
assert.deepEqual(val, {'hours':1, 'minutes':2, 'seconds':3});
}
},{
name: 'interval time with milliseconds',
format: 'text',
dataTypeID: 1186,
actual: '01:02:03:456',
expected: function(val) {
assert.deepEqual(val, {'hours':1, 'minutes':2, 'seconds':3, 'milliseconds': 456});
}
},{
name: 'interval long',
format: 'text',
dataTypeID: 1186,
actual: '1 year -32 days',
expected: function(val) {
assert.equal(val.toPostgres(), '-32 days 1 years');
assert.deepEqual(val, {'years':1, 'days':-32});
}
},{
name: 'interval combined negative',
format: 'text',
dataTypeID: 1186,
actual: '1 day -00:00:03',
expected: function(val) {
assert.equal(val.toPostgres(), '-3 seconds 1 days');
assert.deepEqual(val, {'days':1, 'seconds':-3});
}
},{
name: 'bytea',
format: 'text',
dataTypeID: 17,
actual: 'foo\\000\\200\\\\\\377',
expected: function(val) {
assert.deepEqual(val, new Buffer([102, 111, 111, 0, 128, 92, 255]));
}
},{
name: 'empty bytea',
format: 'text',
dataTypeID: 17,
actual: '',
expected: function(val) {
assert.deepEqual(val, new Buffer(0));
}
},
{
name : 'array/char',
format : 'text',
dataTypeID: 1014,
actual: '{asdf,asdf}',
expected : function(val){
assert.deepEqual(val, ['asdf','asdf']);
}
},{
name : 'array/varchar',
format : 'text',
dataTypeID: 1015,
actual: '{asdf,asdf}',
expected :function(val){
assert.deepEqual(val, ['asdf','asdf']);
}
},{
name : 'array/text',
format : 'text',
dataTypeID: 1008,
actual: '{"hello world"}',
expected :function(val){
assert.deepEqual(val, ['hello world']);
}
},{
name : 'array/numeric',
format : 'text',
dataTypeID: 1231,
actual: '{1.2,3.4}',
expected :function(val){
assert.deepEqual(val, [1.2,3.4]);
}
},{
name : 'array/int2',
format : 'text',
dataTypeID: 1005,
actual: '{-32768, -32767, 32766, 32767}',
expected :function(val){
assert.deepEqual(val, [-32768, -32767, 32766, 32767]);
}
},{
name : 'array/int4',
format : 'text',
dataTypeID: 1007,
actual: '{-2147483648, -2147483647, 2147483646, 2147483647}',
expected :function(val){
assert.deepEqual(val, [-2147483648, -2147483647, 2147483646, 2147483647]);
}
},{
name : 'array/int8',
format : 'text',
dataTypeID: 1016,
actual: '{-9223372036854775808, -9223372036854775807, 9223372036854775806, 9223372036854775807}',
expected :function(val){
assert.deepEqual(val, [
'-9223372036854775808',
'-9223372036854775807',
'9223372036854775806',
'9223372036854775807']);
}
},{
name : 'array/float4',
format : 'text',
dataTypeID: 1021,
actual: '{1.2, 3.4}',
expected :function(val){
assert.deepEqual(val, [1.2, 3.4]);
}
},{
name : 'array/float8',
format : 'text',
dataTypeID: 1022,
actual: '{-12345678.1234567, 12345678.12345678}',
expected :function(val){
assert.deepEqual(val, [-12345678.1234567, 12345678.12345678]);
}
},{
name : 'array/date',
format : 'text',
dataTypeID: 1182,
actual: '{2014-01-01,2015-12-31}',
expected :function(val){
var now = new Date(2014, 0, 1);
var then = new Date(2015, 11, 31);
assert.equal(val.length, 2);
val.forEach(function(element, index) {
var match = index ? then : now;
assert.UTCDate(element, match.getUTCFullYear(), match.getUTCMonth(), match.getUTCDate(), match.getUTCHours(), 0, 0, 0);
});
}
},{
name: 'binary-string/varchar',
format: 'binary',
dataTypeID: 1043,
actual: 'bang',
expected: 'bang'
},{
name: 'binary-integer/int4',
format: 'binary',
dataTypeID: 23,
actual: [0, 0, 0, 100],
expected: 100
},{
name: 'binary-smallint/int2',
format: 'binary',
dataTypeID: 21,
actual: [0, 101],
expected: 101
},{
// name: 'binary-bigint/int8',
// format: 'binary',
// dataTypeID: 20,
// actual: [0, 0, 0, 0, 0, 0, 0, 102],
// expected: '102'
// },{
// name: 'binary-bigint/int8-full',
// format: 'binary',
// dataTypeID: 20,
// actual: [1, 0, 0, 0, 0, 0, 0, 102],
// expected: '72057594037928038'
// },{
name: 'binary-oid',
format: 'binary',
dataTypeID: 26,
actual: [0, 0, 0, 103],
expected: 103
},{
name: 'binary-numeric',
format: 'binary',
dataTypeID: 1700,
actual: [0,2,0,0,0,0,0,0x64,0,12,0xd,0x48,0,0,0,0],
expected: 12.34
},{
name: 'binary-real/float4',
dataTypeID: 700,
format: 'binary',
actual: [0x41, 0x48, 0x00, 0x00],
expected: 12.5
},{
name: 'binary-double precision / float8',
format: 'binary',
dataTypeID: 701,
actual: [0x3F,0xF3,0x33,0x33,0x33,0x33,0x33,0x33],
expected: 1.2
},{
name: 'binary-boolean true',
format: 'binary',
dataTypeID: 16,
actual: [1],
expected: true
},{
name: 'binary-boolean false',
format: 'binary',
dataTypeID: 16,
actual: [0],
expected: false
},{
name: 'binary-boolean null',
format: 'binary',
dataTypeID: 16,
actual: null,
expected: null
},{
name: 'binary-timestamp',
format: 'binary',
dataTypeID: 1184,
actual: [0x00, 0x01, 0x36, 0xee, 0x3e, 0x66, 0x9f, 0xe0],
expected: function(val) {
assert.UTCDate(val, 2010, 9, 31, 20, 24, 13, 740);
}
},{
name: 'binary-string',
format: 'binary',
dataTypeID: 25,
actual: new Buffer([0x73, 0x6c, 0x61, 0x64, 0x64, 0x61]),
expected: 'sladda'
},{
name: 'point',
format: 'text',
dataTypeID: 600,
actual: '(25.1,50.5)',
expected: function(val) {
assert.deepEqual(val, { x: 25.1, y: 50.5 });
}
},{
name: 'circle',
format: 'text',
dataTypeID: 718,
actual: '<(25,10),5>',
expected: function(val) {
assert.deepEqual(val, { x: 25, y: 10, radius: 5 });
}
}];
var pgTypes = require('../');
var assert = require('./assert');
describe('type parsing', function() {
tests.forEach(function(test) {
test.format = test.format || 'text';
it('correctly parses ' + test.name + ' (' + test.format + ')', function() {
var parser = pgTypes.getTypeParser(test.dataTypeID, test.format);
var result = parser(test.actual);
if(typeof test.expected == 'function') {
return test.expected(result);
}
assert.strictEqual(result, test.expected);
});
});
});
describe('interface', function() {
it('exports text parsers by default', function() {
assert.strictEqual(pgTypes.getTypeParser(23), pgTypes.getTypeParser(23, 'text'));
});
});
test('types', function (t) {
Object.keys(types).forEach(function (typeName) {
var type = types[typeName]
t.test(typeName, function (t) {
var parser = getTypeParser(type.id, type.format)
type.tests.forEach(function (tests) {
var input = tests[0]
var expected = tests[1]
var result = parser(input)
if (typeof expected === 'function') {
return expected(t, result)
}
t.equal(result, expected)
})
t.end()
})
})
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc