package/package.json000644 0000001462 13203045454011570 0ustar00000000 000000 { "name": "pg-types", "version": "1.13.0", "description": "Query result type converters for node-postgres", "main": "index.js", "scripts": { "test": "tape test/*.js | tap-spec" }, "repository": { "type": "git", "url": "git://github.com/brianc/node-pg-types.git" }, "keywords": [ "postgres", "PostgreSQL", "pg" ], "author": "Brian M. Carlson", "license": "MIT", "bugs": { "url": "https://github.com/brianc/node-pg-types/issues" }, "homepage": "https://github.com/brianc/node-pg-types", "devDependencies": { "pff": "^1.0.0", "tap-spec": "^4.0.0", "tape": "^4.0.0" }, "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~1.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.0", "postgres-interval": "^1.1.0" } } package/.travis.yml000644 0000000122 13203045415011400 0ustar00000000 000000 language: node_js node_js: - '0.12' - '4' - 'node' env: - PGUSER=postgres package/index.js000644 0000002157 13203045415010746 0ustar00000000 000000 var textParsers = require('./lib/textParsers'); var binaryParsers = require('./lib/binaryParsers'); var arrayParser = require('./lib/arrayParser'); exports.getTypeParser = getTypeParser; exports.setTypeParser = setTypeParser; exports.arrayParser = arrayParser; var typeParsers = { text: {}, binary: {} }; //the empty parse function function noParse (val) { return String(val); }; //returns a function used to convert a specific type (specified by //oid) into a result javascript type //note: the oid can be obtained via the following sql query: //SELECT oid FROM pg_type WHERE typname = 'TYPE_NAME_HERE'; function getTypeParser (oid, format) { format = format || 'text'; if (!typeParsers[format]) { return noParse; } return typeParsers[format][oid] || noParse; }; function setTypeParser (oid, format, parseFn) { if(typeof format == 'function') { parseFn = format; format = 'text'; } typeParsers[format][oid] = parseFn; }; textParsers.init(function(oid, converter) { typeParsers.text[oid] = converter; }); binaryParsers.init(function(oid, converter) { typeParsers.binary[oid] = converter; }); package/Makefile000644 0000000350 13203045415010732 0ustar00000000 000000 .PHONY: publish-patch test test: npm test patch: test npm version patch -m "Bump version" git push origin master --tags npm publish minor: test npm version minor -m "Bump version" git push origin master --tags npm publish package/README.md000644 0000007425 13203045415010563 0ustar00000000 000000 # pg-types This is the code that turns all the raw text from postgres into JavaScript types for [node-postgres](https://github.com/brianc/node-postgres.git) ## use This module is consumed and exported from the root `pg` object of node-postgres. To access it, do the following: ```js var types = require('pg').types ``` Generally what you'll want to do is override how a specific data-type is parsed and turned into a JavaScript type. By default the PostgreSQL backend server returns everything as strings. Every data type corresponds to a unique `OID` within the server, and these `OIDs` are sent back with the query response. So, you need to match a particluar `OID` to a function you'd like to use to take the raw text input and produce a valid JavaScript object as a result. `null` values are never parsed. Let's do something I commonly like to do on projects: return 64-bit integers `(int8)` as JavaScript integers. Because JavaScript doesn't have support for 64-bit integers node-postgres cannot confidently parse `int8` data type results as numbers because if you have a _huge_ number it will overflow and the result you'd get back from node-postgres would not be the result in the datbase. That would be a __very bad thing__ so node-postgres just returns `int8` results as strings and leaves the parsing up to you. Let's say that you know you don't and wont ever have numbers greater than `int4` in your database, but you're tired of recieving results from the `COUNT(*)` function as strings (because that function returns `int8`). You would do this: ```js var types = require('pg').types types.setTypeParser(20, function(val) { return parseInt(val) }) ``` __boom__: now you get numbers instead of strings. Just as another example -- not saying this is a good idea -- let's say you want to return all dates from your database as [moment](http://momentjs.com/docs/) objects. Okay, do this: ```js var types = require('pg').types var moment = require('moment') var TIMESTAMPTZ_OID = 1184 var TIMESTAMP_OID = 1114 var parseFn = function(val) { return val === null ? null : moment(val) } types.setTypeParser(TIMESTAMPTZ_OID, parseFn) types.setTypeParser(TIMESTAMP_OID, parseFn) ``` _note: I've never done that with my dates, and I'm not 100% sure moment can parse all the date strings returned from postgres. It's just an example!_ 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 typname, oid, typarray from pg_type order by oid" ``` If you want to find out the OID of a specific type: ```bash $ psql -c "select typname, oid, typarray from pg_type where typname = 'daterange' order by oid" ``` :smile: ## license The MIT License (MIT) Copyright (c) 2014 Brian M. Carlson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/lib/arrayParser.js000644 0000000320 13203045415012666 0ustar00000000 000000 var array = require('postgres-array'); module.exports = { create: function (source, transform) { return { parse: function() { return array.parse(source, transform); } }; } }; package/lib/binaryParsers.js000644 0000013657 13203045415013240 0ustar00000000 000000 var parseInt64 = require('pg-int8'); var parseBits = function(data, bits, offset, invert, callback) { offset = offset || 0; invert = invert || false; callback = callback || function(lastValue, newValue, bits) { return (lastValue * Math.pow(2, bits)) + newValue; }; var offsetBytes = offset >> 3; var inv = function(value) { if (invert) { return ~value & 0xff; } return value; }; // read first (maybe partial) byte var mask = 0xff; var firstBits = 8 - (offset % 8); if (bits < firstBits) { mask = (0xff << (8 - bits)) & 0xff; firstBits = bits; } if (offset) { mask = mask >> (offset % 8); } var result = 0; if ((offset % 8) + bits >= 8) { result = callback(0, inv(data[offsetBytes]) & mask, firstBits); } // read bytes var bytes = (bits + offset) >> 3; for (var i = offsetBytes + 1; i < bytes; i++) { result = callback(result, inv(data[i]), 8); } // bits to read, that are not a complete byte var lastBits = (bits + offset) % 8; if (lastBits > 0) { result = callback(result, inv(data[bytes]) >> (8 - lastBits), lastBits); } return result; }; var parseFloatFromBits = function(data, precisionBits, exponentBits) { var bias = Math.pow(2, exponentBits - 1) - 1; var sign = parseBits(data, 1); var exponent = parseBits(data, exponentBits, 1); if (exponent === 0) { return 0; } // parse mantissa var precisionBitsCounter = 1; var parsePrecisionBits = function(lastValue, newValue, bits) { if (lastValue === 0) { lastValue = 1; } for (var i = 1; i <= bits; i++) { precisionBitsCounter /= 2; if ((newValue & (0x1 << (bits - i))) > 0) { lastValue += precisionBitsCounter; } } return lastValue; }; var mantissa = parseBits(data, precisionBits, exponentBits + 1, false, parsePrecisionBits); // special cases if (exponent == (Math.pow(2, exponentBits + 1) - 1)) { if (mantissa === 0) { return (sign === 0) ? Infinity : -Infinity; } return NaN; } // normale number return ((sign === 0) ? 1 : -1) * Math.pow(2, exponent - bias) * mantissa; }; var parseInt16 = function(value) { if (parseBits(value, 1) == 1) { return -1 * (parseBits(value, 15, 1, true) + 1); } return parseBits(value, 15, 1); }; var parseInt32 = function(value) { if (parseBits(value, 1) == 1) { return -1 * (parseBits(value, 31, 1, true) + 1); } return parseBits(value, 31, 1); }; var parseFloat32 = function(value) { return parseFloatFromBits(value, 23, 8); }; var parseFloat64 = function(value) { return parseFloatFromBits(value, 52, 11); }; var parseNumeric = function(value) { var sign = parseBits(value, 16, 32); if (sign == 0xc000) { return NaN; } var weight = Math.pow(10000, parseBits(value, 16, 16)); var result = 0; var digits = []; var ndigits = parseBits(value, 16); for (var i = 0; i < ndigits; i++) { result += parseBits(value, 16, 64 + (16 * i)) * weight; weight /= 10000; } var scale = Math.pow(10, parseBits(value, 16, 48)); return ((sign === 0) ? 1 : -1) * Math.round(result * scale) / scale; }; var parseDate = function(isUTC, value) { var sign = parseBits(value, 1); var rawValue = parseBits(value, 63, 1); // discard usecs and shift from 2000 to 1970 var result = new Date((((sign === 0) ? 1 : -1) * rawValue / 1000) + 946684800000); if (!isUTC) { result.setTime(result.getTime() + result.getTimezoneOffset() * 60000); } // add microseconds to the date result.usec = rawValue % 1000; result.getMicroSeconds = function() { return this.usec; }; result.setMicroSeconds = function(value) { this.usec = value; }; result.getUTCMicroSeconds = function() { return this.usec; }; return result; }; var parseArray = function(value) { var dim = parseBits(value, 32); var flags = parseBits(value, 32, 32); var elementType = parseBits(value, 32, 64); var offset = 96; var dims = []; for (var i = 0; i < dim; i++) { // parse dimension dims[i] = parseBits(value, 32, offset); offset += 32; // ignore lower bounds offset += 32; } var parseElement = function(elementType) { // parse content length var length = parseBits(value, 32, offset); offset += 32; // parse null values if (length == 0xffffffff) { return null; } var result; if ((elementType == 0x17) || (elementType == 0x14)) { // int/bigint result = parseBits(value, length * 8, offset); offset += length * 8; return result; } else if (elementType == 0x19) { // string result = value.toString(this.encoding, offset >> 3, (offset += (length << 3)) >> 3); return result; } else { console.log("ERROR: ElementType not implemented: " + elementType); } }; var parse = function(dimension, elementType) { var array = []; var i; if (dimension.length > 1) { var count = dimension.shift(); for (i = 0; i < count; i++) { array[i] = parse(dimension, elementType); } dimension.unshift(count); } else { for (i = 0; i < dimension[0]; i++) { array[i] = parseElement(elementType); } } return array; }; return parse(dims, elementType); }; var parseText = function(value) { return value.toString('utf8'); }; var parseBool = function(value) { if(value === null) return null; return (parseBits(value, 8) > 0); }; var init = function(register) { register(20, parseInt64); register(21, parseInt16); register(23, parseInt32); register(26, parseInt32); register(1700, parseNumeric); register(700, parseFloat32); register(701, parseFloat64); register(16, parseBool); register(1114, parseDate.bind(null, false)); register(1184, parseDate.bind(null, true)); register(1000, parseArray); register(1007, parseArray); register(1016, parseArray); register(1008, parseArray); register(1009, parseArray); register(25, parseText); }; module.exports = { init: init }; package/lib/textParsers.js000644 0000012013 13203045415012721 0ustar00000000 000000 var array = require('postgres-array') var arrayParser = require('./arrayParser'); var parseDate = require('postgres-date'); var parseInterval = require('postgres-interval'); var parseByteA = require('postgres-bytea'); function allowNull (fn) { return function nullAllowed (value) { if (value === null) return value return fn(value) } } function parseBool (value) { if (value === null) return value return value === 'TRUE' || value === 't' || value === 'true' || value === 'y' || value === 'yes' || value === 'on' || value === '1'; } function parseBoolArray (value) { if (!value) return null return array.parse(value, parseBool) } function parseBaseTenInt (string) { return parseInt(string, 10) } function parseIntegerArray (value) { if (!value) return null return array.parse(value, allowNull(parseBaseTenInt)) } function parseBigIntegerArray (value) { if (!value) return null return array.parse(value, allowNull(function (entry) { return parseBigInteger(entry).trim() })) } var parsePointArray = function(value) { if(!value) { return null; } var p = arrayParser.create(value, function(entry) { if(entry !== null) { entry = parsePoint(entry); } return entry; }); return p.parse(); }; var parseFloatArray = function(value) { if(!value) { return null; } var p = arrayParser.create(value, function(entry) { if(entry !== null) { entry = parseFloat(entry); } return entry; }); return p.parse(); }; var parseStringArray = function(value) { if(!value) { return null; } var p = arrayParser.create(value); return p.parse(); }; var parseDateArray = function(value) { if (!value) { return null; } var p = arrayParser.create(value, function(entry) { if (entry !== null) { entry = parseDate(entry); } return entry; }); return p.parse(); }; var parseByteAArray = function(value) { if (!value) { return null; } return array.parse(value, allowNull(parseByteA)); }; var parseInteger = function(value) { return parseInt(value, 10); }; var parseBigInteger = function(value) { var valStr = String(value); if (/^\d+$/.test(valStr)) { return valStr; } return value; }; var parseJsonArray = function(value) { var arr = parseStringArray(value); if (!arr) { return arr; } return arr.map(function(el) { return JSON.parse(el); }); }; var parsePoint = function(value) { if (value[0] !== '(') { return null; } value = value.substring( 1, value.length - 1 ).split(','); return { x: parseFloat(value[0]) , y: parseFloat(value[1]) }; }; var parseCircle = function(value) { if (value[0] !== '<' && value[1] !== '(') { return null; } var point = '('; var radius = ''; var pointParsed = false; for (var i = 2; i < value.length - 1; i++){ if (!pointParsed) { point += value[i]; } if (value[i] === ')') { pointParsed = true; continue; } else if (!pointParsed) { continue; } if (value[i] === ','){ continue; } radius += value[i]; } var result = parsePoint(point); result.radius = parseFloat(radius); return result; }; var init = function(register) { 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 register(16, parseBool); register(1082, parseDate); // date register(1114, parseDate); // timestamp without timezone register(1184, parseDate); // timestamp register(600, parsePoint); // point register(651, parseStringArray); // cidr[] register(718, parseCircle); // circle register(1000, parseBoolArray); register(1001, parseByteAArray); register(1005, parseIntegerArray); // _int2 register(1007, parseIntegerArray); // _int4 register(1028, parseIntegerArray); // oid[] register(1016, parseBigIntegerArray); // _int8 register(1017, parsePointArray); // point[] register(1021, parseFloatArray); // _float4 register(1022, parseFloatArray); // _float8 register(1231, parseFloatArray); // _numeric register(1014, parseStringArray); //char register(1015, parseStringArray); //varchar register(1008, parseStringArray); register(1009, parseStringArray); register(1040, parseStringArray); // macaddr[] register(1041, parseStringArray); // inet[] register(1115, parseDateArray); // timestamp without time zone[] register(1182, parseDateArray); // _date register(1185, parseDateArray); // timestamp with time zone[] register(1186, parseInterval); register(17, parseByteA); register(114, JSON.parse.bind(JSON)); // json register(3802, JSON.parse.bind(JSON)); // jsonb register(199, parseJsonArray); // json[] register(3807, parseJsonArray); // jsonb[] register(3907, parseStringArray); // numrange[] register(2951, parseStringArray); // uuid[] register(791, parseStringArray); // money[] register(1183, parseStringArray); // time[] register(1270, parseStringArray); // timetz[] }; module.exports = { init: init }; package/test/index.js000644 0000001204 13203045415011715 0ustar00000000 000000 var test = require('tape') var printf = require('pff') var getTypeParser = require('../').getTypeParser var types = require('./types') 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() }) }) }) package/test/types.js000644 0000025450 13203045415011763 0ustar00000000 000000 'use strict' exports['string/varchar'] = { format: 'text', id: 1043, tests: [ ['bang', 'bang'] ] } exports['integer/int4'] = { format: 'text', id: 23, tests: [ ['2147483647', 2147483647] ] } exports['smallint/int2'] = { format: 'text', id: 21, tests: [ ['32767', 32767] ] } exports['bigint/int8'] = { format: 'text', id: 20, tests: [ ['9223372036854775807', '9223372036854775807'] ] } exports.oid = { format: 'text', id: 26, tests: [ ['103', 103] ] } var bignum = '31415926535897932384626433832795028841971693993751058.16180339887498948482045868343656381177203091798057628' exports.numeric = { format: 'text', id: 1700, tests: [ [bignum, bignum] ] } exports['real/float4'] = { format: 'text', id: 700, tests: [ ['123.456', 123.456] ] } exports['double precision / float 8'] = { format: 'text', id: 701, tests: [ ['12345678.12345678', 12345678.12345678] ] } exports.boolean = { format: 'text', id: 16, tests: [ ['TRUE', true], ['t', true], ['true', true], ['y', true], ['yes', true], ['on', true], ['1', true], ['f', false], [null, null] ] } exports.timestamptz = { format: 'text', id: 1184, tests: [ [ '2010-10-31 14:54:13.74-05:30', dateEquals(2010, 9, 31, 20, 24, 13, 740) ], [ '2011-01-23 22:05:00.68-06', dateEquals(2011, 0, 24, 4, 5, 0, 680) ], [ '2010-10-30 14:11:12.730838Z', dateEquals(2010, 9, 30, 14, 11, 12, 730) ], [ '2010-10-30 13:10:01+05', dateEquals(2010, 9, 30, 8, 10, 1, 0) ] ] } exports.timestamp = { format: 'text', id: 1114, tests: [ [ '2010-10-31 00:00:00', function (t, value) { t.equal( value.toUTCString(), new Date(2010, 9, 31, 0, 0, 0, 0, 0).toUTCString() ) t.equal( value.toString(), new Date(2010, 9, 31, 0, 0, 0, 0, 0, 0).toString() ) } ] ] } exports.date = { format: 'text', id: 1082, tests: [ ['2010-10-31', function (t, value) { var now = new Date(2010, 9, 31) dateEquals( 2010, now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), 0, 0, 0)(t, value) t.equal(value.getHours(), now.getHours()) }] ] } exports.inet = { format: 'text', id: 869, tests: [ ['8.8.8.8', '8.8.8.8'], ['2001:4860:4860::8888', '2001:4860:4860::8888'], ['127.0.0.1', '127.0.0.1'], ['fd00:1::40e', 'fd00:1::40e'], ['1.2.3.4', '1.2.3.4'] ] } exports.cidr = { format: 'text', id: 650, tests: [ ['172.16.0.0/12', '172.16.0.0/12'], ['fe80::/10', 'fe80::/10'], ['fc00::/7', 'fc00::/7'], ['192.168.0.0/24', '192.168.0.0/24'], ['10.0.0.0/8', '10.0.0.0/8'] ] } exports.macaddr = { format: 'text', id: 829, tests: [ ['08:00:2b:01:02:03', '08:00:2b:01:02:03'], ['16:10:9f:0d:66:00', '16:10:9f:0d:66:00'] ] } exports.numrange = { format: 'text', id: 3906, tests: [ ['[,]', '[,]'], ['(,)', '(,)'], ['(,]', '(,]'], ['[1,)', '[1,)'], ['[,1]', '[,1]'], ['(1,2)', '(1,2)'], ['(1,20.5]', '(1,20.5]'] ] } exports.interval = { format: 'text', id: 1186, tests: [ ['01:02:03', function (t, value) { t.equal(value.toPostgres(), '3 seconds 2 minutes 1 hours') t.deepEqual(value, {hours: 1, minutes: 2, seconds: 3}) }], ['01:02:03:456', function (t, value) { t.deepEqual(value, {hours: 1, minutes:2, seconds: 3, milliseconds: 456}) }], ['1 year -32 days', function (t, value) { t.equal(value.toPostgres(), '-32 days 1 years') t.deepEqual(value, {years: 1, days: -32}) }], ['1 day -00:00:03', function (t, value) { t.equal(value.toPostgres(), '-3 seconds 1 days') t.deepEqual(value, {days: 1, seconds: -3}) }] ] } exports.bytea = { format: 'text', id: 17, tests: [ ['foo\\000\\200\\\\\\377', function (t, value) { var buffer = new Buffer([102, 111, 111, 0, 128, 92, 255]) t.ok(buffer.equals(value)) }], ['', function (t, value) { var buffer = new Buffer(0) t.ok(buffer.equals(value)) }] ] } exports['array/boolean'] = { format: 'text', id: 1000, tests: [ ['{true,false}', function (t, value) { t.deepEqual(value, [true, false]) }] ] } exports['array/char'] = { format: 'text', id: 1014, tests: [ ['{foo,bar}', function (t, value) { t.deepEqual(value, ['foo', 'bar']) }] ] } exports['array/varchar'] = { format: 'text', id: 1015, tests: [ ['{foo,bar}', function (t, value) { t.deepEqual(value, ['foo', 'bar']) }] ] } exports['array/text'] = { format: 'text', id: 1008, tests: [ ['{foo}', function (t, value) { t.deepEqual(value, ['foo']) }] ] } exports['array/bytea'] = { format: 'text', id: 1001, tests: [ ['{"\\\\x00000000"}', function (t, value) { var buffer = new Buffer('00000000', 'hex') t.ok(Array.isArray(value)) t.equal(value.length, 1) t.ok(buffer.equals(value[0])) }], ['{NULL,"\\\\x4e554c4c"}', function (t, value) { var buffer = new Buffer('4e554c4c', 'hex') t.ok(Array.isArray(value)) t.equal(value.length, 2) t.equal(value[0], null) t.ok(buffer.equals(value[1])) }], ] } exports['array/numeric'] = { format: 'text', id: 1231, tests: [ ['{1.2,3.4}', function (t, value) { t.deepEqual(value, [1.2, 3.4]) }] ] } exports['array/int2'] = { format: 'text', id: 1005, tests: [ ['{-32768, -32767, 32766, 32767}', function (t, value) { t.deepEqual(value, [-32768, -32767, 32766, 32767]) }] ] } exports['array/int4'] = { format: 'text', id: 1005, tests: [ ['{-2147483648, -2147483647, 2147483646, 2147483647}', function (t, value) { t.deepEqual(value, [-2147483648, -2147483647, 2147483646, 2147483647]) }] ] } exports['array/int8'] = { format: 'text', id: 1016, tests: [ [ '{-9223372036854775808, -9223372036854775807, 9223372036854775806, 9223372036854775807}', function (t, value) { t.deepEqual(value, [ '-9223372036854775808', '-9223372036854775807', '9223372036854775806', '9223372036854775807' ]) } ] ] } exports['array/point'] = { format: 'text', id: 1017, tests: [ ['{"(25.1,50.5)","(10.1,40)"}', function (t, value) { t.deepEqual(value, [{x: 25.1, y: 50.5}, {x: 10.1, y: 40}]) }] ] } exports['array/oid'] = { format: 'text', id: 1028, tests: [ ['{25864,25860}', function (t, value) { t.deepEqual(value, [25864, 25860]) }] ] } exports['array/float4'] = { format: 'text', id: 1021, tests: [ ['{1.2, 3.4}', function (t, value) { t.deepEqual(value, [1.2, 3.4]) }] ] } exports['array/float8'] = { format: 'text', id: 1022, tests: [ ['{-12345678.1234567, 12345678.12345678}', function (t, value) { t.deepEqual(value, [-12345678.1234567, 12345678.12345678]) }] ] } exports['array/date'] = { format: 'text', id: 1182, tests: [ ['{2014-01-01,2015-12-31}', function (t, value) { var expecteds = [new Date(2014, 0, 1), new Date(2015, 11, 31)] t.equal(value.length, 2) value.forEach(function (date, index) { var expected = expecteds[index] dateEquals( expected.getUTCFullYear(), expected.getUTCMonth(), expected.getUTCDate(), expected.getUTCHours(), 0, 0, 0)(t, date) }) }] ] } exports['array/inet'] = { format: 'text', id: 1041, tests: [ ['{8.8.8.8}', function (t, value) { t.deepEqual(value, ['8.8.8.8']); }], ['{2001:4860:4860::8888}', function (t, value) { t.deepEqual(value, ['2001:4860:4860::8888']); }], ['{127.0.0.1,fd00:1::40e,1.2.3.4}', function (t, value) { t.deepEqual(value, ['127.0.0.1', 'fd00:1::40e', '1.2.3.4']); }] ] } exports['array/cidr'] = { format: 'text', id: 651, tests: [ ['{172.16.0.0/12}', function (t, value) { t.deepEqual(value, ['172.16.0.0/12']); }], ['{fe80::/10}', function (t, value) { t.deepEqual(value, ['fe80::/10']); }], ['{10.0.0.0/8,fc00::/7,192.168.0.0/24}', function (t, value) { t.deepEqual(value, ['10.0.0.0/8', 'fc00::/7', '192.168.0.0/24']); }] ] } exports['array/macaddr'] = { format: 'text', id: 1040, tests: [ ['{08:00:2b:01:02:03,16:10:9f:0d:66:00}', function (t, value) { t.deepEqual(value, ['08:00:2b:01:02:03', '16:10:9f:0d:66:00']); }] ] } exports['array/numrange'] = { format: 'text', id: 3907, tests: [ ['{"[1,2]","(4.5,8)","[10,40)","(-21.2,60.3]"}', function (t, value) { t.deepEqual(value, ['[1,2]', '(4.5,8)', '[10,40)', '(-21.2,60.3]']); }], ['{"[,20]","[3,]","[,]","(,35)","(1,)","(,)"}', function (t, value) { t.deepEqual(value, ['[,20]', '[3,]', '[,]', '(,35)', '(1,)', '(,)']); }], ['{"[,20)","[3,)","[,)","[,35)","[1,)","[,)"}', function (t, value) { t.deepEqual(value, ['[,20)', '[3,)', '[,)', '[,35)', '[1,)', '[,)']); }] ] } exports['binary-string/varchar'] = { format: 'binary', id: 1043, tests: [ ['bang', 'bang'] ] } exports['binary-integer/int4'] = { format: 'binary', id: 23, tests: [ [[0, 0, 0, 100], 100] ] } exports['binary-smallint/int2'] = { format: 'binary', id: 21, tests: [ [[0, 101], 101] ] } exports['binary-bigint/int8'] = { format: 'binary', id: 20, tests: [ [new Buffer([0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), '9223372036854775807'] ] } exports['binary-oid'] = { format: 'binary', id: 26, tests: [ [[0, 0, 0, 103], 103] ] } exports['binary-numeric'] = { format: 'binary', id: 1700, tests: [ [ [0, 2, 0, 0, 0, 0, 0, hex('0x64'), 0, 12, hex('0xd'), hex('0x48'), 0, 0, 0, 0], 12.34 ] ] } exports['binary-real/float4'] = { format: 'binary', id: 700, tests: [ [['0x41', '0x48', '0x00', '0x00'].map(hex), 12.5] ] } exports['binary-boolean'] = { format: 'binary', id: 16, tests: [ [[1], true], [[0], false], [null, null] ] } exports['binary-string'] = { format: 'binary', id: 25, tests: [ [ new Buffer(['0x73', '0x6c', '0x61', '0x64', '0x64', '0x61'].map(hex)), 'sladda' ] ] } exports.point = { format: 'text', id: 600, tests: [ ['(25.1,50.5)', function (t, value) { t.deepEqual(value, {x: 25.1, y: 50.5}) }] ] } exports.circle = { format: 'text', id: 718, tests: [ ['<(25,10),5>', function (t, value) { t.deepEqual(value, {x: 25, y: 10, radius: 5}) }] ] } function hex (string) { return parseInt(string, 16) } function dateEquals () { var timestamp = Date.UTC.apply(Date, arguments) return function (t, value) { t.equal(value.toUTCString(), new Date(timestamp).toUTCString()) } }