From 71be9c73feff96b88fcb1a7f5fe68c6f2f4d3039 Mon Sep 17 00:00:00 2001 From: Bas van Zanten Date: Wed, 5 Apr 2023 16:38:21 +0200 Subject: [PATCH 1/4] feat: use ; as a delimiter for _box --- cjs/src/connection.js | 4 ++-- cjs/src/types.js | 20 ++++++++++++-------- deno/src/connection.js | 4 ++-- deno/src/types.js | 20 ++++++++++++-------- src/connection.js | 4 ++-- src/types.js | 20 ++++++++++++-------- 6 files changed, 42 insertions(+), 30 deletions(-) diff --git a/cjs/src/connection.js b/cjs/src/connection.js index f73ee216..fb072882 100644 --- a/cjs/src/connection.js +++ b/cjs/src/connection.js @@ -738,9 +738,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray - options.parsers[typarray] = (xs) => arrayParser(xs, parser) + options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) options.parsers[typarray].array = true - options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options) + options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray) } function tryNext(x, xs) { diff --git a/cjs/src/types.js b/cjs/src/types.js index 8d2f4ed1..88120294 100644 --- a/cjs/src/types.js +++ b/cjs/src/types.js @@ -235,7 +235,7 @@ function arrayEscape(x) { .replace(escapeQuote, '\\"') } -const arraySerializer = module.exports.arraySerializer = function arraySerializer(xs, serializer, options) { +const arraySerializer = module.exports.arraySerializer = function arraySerializer(xs, serializer, options, typarray) { if (Array.isArray(xs) === false) return xs @@ -243,9 +243,11 @@ const arraySerializer = module.exports.arraySerializer = function arraySerialize return '{}' const first = xs[0] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' if (Array.isArray(first) && !first.type) - return '{' + xs.map(x => arraySerializer(x, serializer)).join(',') + '}' + return '{' + xs.map(x => arraySerializer(x, serializer, options, typarray)).join(delimiter) + '}' return '{' + xs.map(x => { if (x === undefined) { @@ -257,7 +259,7 @@ const arraySerializer = module.exports.arraySerializer = function arraySerialize return x === null ? 'null' : '"' + arrayEscape(serializer ? serializer(x.type ? x.value : x) : '' + x) + '"' - }).join(',') + '}' + }).join(delimiter) + '}' } const arrayParserState = { @@ -268,13 +270,15 @@ const arrayParserState = { last: 0 } -const arrayParser = module.exports.arrayParser = function arrayParser(x, parser) { +const arrayParser = module.exports.arrayParser = function arrayParser(x, parser, typarray) { arrayParserState.i = arrayParserState.last = 0 - return arrayParserLoop(arrayParserState, x, parser) + return arrayParserLoop(arrayParserState, x, parser, typarray) } -function arrayParserLoop(s, x, parser) { +function arrayParserLoop(s, x, parser, typarray) { const xs = [] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' for (; s.i < x.length; s.i++) { s.char = x[s.i] if (s.quoted) { @@ -292,13 +296,13 @@ function arrayParserLoop(s, x, parser) { s.quoted = true } else if (s.char === '{') { s.last = ++s.i - xs.push(arrayParserLoop(s, x, parser)) + xs.push(arrayParserLoop(s, x, parser, typarray)) } else if (s.char === '}') { s.quoted = false s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 break - } else if (s.char === ',' && s.p !== '}' && s.p !== '"') { + } else if (s.char === delimiter && s.p !== '}' && s.p !== '"') { xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 } diff --git a/deno/src/connection.js b/deno/src/connection.js index 7ce601e2..33c25fca 100644 --- a/deno/src/connection.js +++ b/deno/src/connection.js @@ -742,9 +742,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray - options.parsers[typarray] = (xs) => arrayParser(xs, parser) + options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) options.parsers[typarray].array = true - options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options) + options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray) } function tryNext(x, xs) { diff --git a/deno/src/types.js b/deno/src/types.js index 00ef70c2..e39df931 100644 --- a/deno/src/types.js +++ b/deno/src/types.js @@ -236,7 +236,7 @@ function arrayEscape(x) { .replace(escapeQuote, '\\"') } -export const arraySerializer = function arraySerializer(xs, serializer, options) { +export const arraySerializer = function arraySerializer(xs, serializer, options, typarray) { if (Array.isArray(xs) === false) return xs @@ -244,9 +244,11 @@ export const arraySerializer = function arraySerializer(xs, serializer, options) return '{}' const first = xs[0] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' if (Array.isArray(first) && !first.type) - return '{' + xs.map(x => arraySerializer(x, serializer)).join(',') + '}' + return '{' + xs.map(x => arraySerializer(x, serializer, options, typarray)).join(delimiter) + '}' return '{' + xs.map(x => { if (x === undefined) { @@ -258,7 +260,7 @@ export const arraySerializer = function arraySerializer(xs, serializer, options) return x === null ? 'null' : '"' + arrayEscape(serializer ? serializer(x.type ? x.value : x) : '' + x) + '"' - }).join(',') + '}' + }).join(delimiter) + '}' } const arrayParserState = { @@ -269,13 +271,15 @@ const arrayParserState = { last: 0 } -export const arrayParser = function arrayParser(x, parser) { +export const arrayParser = function arrayParser(x, parser, typarray) { arrayParserState.i = arrayParserState.last = 0 - return arrayParserLoop(arrayParserState, x, parser) + return arrayParserLoop(arrayParserState, x, parser, typarray) } -function arrayParserLoop(s, x, parser) { +function arrayParserLoop(s, x, parser, typarray) { const xs = [] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' for (; s.i < x.length; s.i++) { s.char = x[s.i] if (s.quoted) { @@ -293,13 +297,13 @@ function arrayParserLoop(s, x, parser) { s.quoted = true } else if (s.char === '{') { s.last = ++s.i - xs.push(arrayParserLoop(s, x, parser)) + xs.push(arrayParserLoop(s, x, parser, typarray)) } else if (s.char === '}') { s.quoted = false s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 break - } else if (s.char === ',' && s.p !== '}' && s.p !== '"') { + } else if (s.char === delimiter && s.p !== '}' && s.p !== '"') { xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 } diff --git a/src/connection.js b/src/connection.js index 327f88e1..9563b8bb 100644 --- a/src/connection.js +++ b/src/connection.js @@ -739,9 +739,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray - options.parsers[typarray] = (xs) => arrayParser(xs, parser) + options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) options.parsers[typarray].array = true - options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options) + options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray) } function tryNext(x, xs) { diff --git a/src/types.js b/src/types.js index e4c1b680..8a0905c9 100644 --- a/src/types.js +++ b/src/types.js @@ -235,7 +235,7 @@ function arrayEscape(x) { .replace(escapeQuote, '\\"') } -export const arraySerializer = function arraySerializer(xs, serializer, options) { +export const arraySerializer = function arraySerializer(xs, serializer, options, typarray) { if (Array.isArray(xs) === false) return xs @@ -243,9 +243,11 @@ export const arraySerializer = function arraySerializer(xs, serializer, options) return '{}' const first = xs[0] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' if (Array.isArray(first) && !first.type) - return '{' + xs.map(x => arraySerializer(x, serializer)).join(',') + '}' + return '{' + xs.map(x => arraySerializer(x, serializer, options, typarray)).join(delimiter) + '}' return '{' + xs.map(x => { if (x === undefined) { @@ -257,7 +259,7 @@ export const arraySerializer = function arraySerializer(xs, serializer, options) return x === null ? 'null' : '"' + arrayEscape(serializer ? serializer(x.type ? x.value : x) : '' + x) + '"' - }).join(',') + '}' + }).join(delimiter) + '}' } const arrayParserState = { @@ -268,13 +270,15 @@ const arrayParserState = { last: 0 } -export const arrayParser = function arrayParser(x, parser) { +export const arrayParser = function arrayParser(x, parser, typarray) { arrayParserState.i = arrayParserState.last = 0 - return arrayParserLoop(arrayParserState, x, parser) + return arrayParserLoop(arrayParserState, x, parser, typarray) } -function arrayParserLoop(s, x, parser) { +function arrayParserLoop(s, x, parser, typarray) { const xs = [] + // Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter + const delimiter = typarray === 1020 ? ';' : ',' for (; s.i < x.length; s.i++) { s.char = x[s.i] if (s.quoted) { @@ -292,13 +296,13 @@ function arrayParserLoop(s, x, parser) { s.quoted = true } else if (s.char === '{') { s.last = ++s.i - xs.push(arrayParserLoop(s, x, parser)) + xs.push(arrayParserLoop(s, x, parser, typarray)) } else if (s.char === '}') { s.quoted = false s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 break - } else if (s.char === ',' && s.p !== '}' && s.p !== '"') { + } else if (s.char === delimiter && s.p !== '}' && s.p !== '"') { xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i)) s.last = s.i + 1 } From c2bb7a2b4450d49568ae9f5a07c983455d14f697 Mon Sep 17 00:00:00 2001 From: Bas van Zanten Date: Wed, 5 Apr 2023 19:57:43 +0200 Subject: [PATCH 2/4] chore: add test --- cjs/tests/index.js | 5 +++++ deno/tests/index.js | 5 +++++ tests/index.js | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/cjs/tests/index.js b/cjs/tests/index.js index 639fdf5f..198a6d2e 100644 --- a/cjs/tests/index.js +++ b/cjs/tests/index.js @@ -137,6 +137,11 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) +t("Array of Box", async () => [ + '(3,4),(1,2);(6,7),(4,5)', + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") +]); + t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] ) diff --git a/deno/tests/index.js b/deno/tests/index.js index e04e532c..f6ea4a53 100644 --- a/deno/tests/index.js +++ b/deno/tests/index.js @@ -139,6 +139,11 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) +t("Array of Box", async () => [ + '(3,4),(1,2);(6,7),(4,5)', + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") +]); + t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] ) diff --git a/tests/index.js b/tests/index.js index f59c641b..259b7dd9 100644 --- a/tests/index.js +++ b/tests/index.js @@ -137,6 +137,11 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) +t("Array of Box", async () => [ + '(3,4),(1,2);(6,7),(4,5)', + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") +]); + t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] ) From 7a02288c405afbfc3e014795c752dccfc7eb52e9 Mon Sep 17 00:00:00 2001 From: Bas van Zanten Date: Wed, 5 Apr 2023 21:18:22 +0200 Subject: [PATCH 3/4] chore: run lint --- cjs/src/connection.js | 2 +- cjs/tests/index.js | 8 ++++---- deno/src/connection.js | 2 +- deno/tests/index.js | 8 ++++---- src/connection.js | 2 +- tests/index.js | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cjs/src/connection.js b/cjs/src/connection.js index fb072882..56488d82 100644 --- a/cjs/src/connection.js +++ b/cjs/src/connection.js @@ -735,7 +735,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose } function addArrayType(oid, typarray) { - if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; + if (!!options.parsers[typarray] && !!options.serializers[typarray]) return const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) diff --git a/cjs/tests/index.js b/cjs/tests/index.js index 198a6d2e..4a60ff5c 100644 --- a/cjs/tests/index.js +++ b/cjs/tests/index.js @@ -8,7 +8,7 @@ const crypto = require('crypto') const postgres = require('../src/index.js') const delay = ms => new Promise(r => setTimeout(r, ms)) -const rel = x => require("path").join(__dirname, x) +const rel = x => require('path').join(__dirname, x) const idle_timeout = 1 const login = { @@ -137,10 +137,10 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) -t("Array of Box", async () => [ +t('Array of Box', async() => [ '(3,4),(1,2);(6,7),(4,5)', - (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") -]); + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(';') +]) t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] diff --git a/deno/src/connection.js b/deno/src/connection.js index 33c25fca..7ff87bc5 100644 --- a/deno/src/connection.js +++ b/deno/src/connection.js @@ -739,7 +739,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose } function addArrayType(oid, typarray) { - if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; + if (!!options.parsers[typarray] && !!options.serializers[typarray]) return const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) diff --git a/deno/tests/index.js b/deno/tests/index.js index f6ea4a53..59294818 100644 --- a/deno/tests/index.js +++ b/deno/tests/index.js @@ -139,10 +139,10 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) -t("Array of Box", async () => [ +t('Array of Box', async() => [ '(3,4),(1,2);(6,7),(4,5)', - (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") -]); + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(';') +]) t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] @@ -2480,4 +2480,4 @@ t('Insert array with undefined transform', async() => { ] }) -;window.addEventListener("unload", () => Deno.exit(process.exitCode)) \ No newline at end of file +;window.addEventListener('unload', () => Deno.exit(process.exitCode)) \ No newline at end of file diff --git a/src/connection.js b/src/connection.js index 9563b8bb..2f32f5d9 100644 --- a/src/connection.js +++ b/src/connection.js @@ -736,7 +736,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose } function addArrayType(oid, typarray) { - if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; + if (!!options.parsers[typarray] && !!options.serializers[typarray]) return const parser = options.parsers[oid] options.shared.typeArrayMap[oid] = typarray options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray) diff --git a/tests/index.js b/tests/index.js index 259b7dd9..3bc7e0e8 100644 --- a/tests/index.js +++ b/tests/index.js @@ -137,10 +137,10 @@ t('Array of Date', async() => { return [now.getTime(), (await sql`select ${ sql.array([now, now, now]) } as x`)[0].x[2].getTime()] }) -t("Array of Box", async () => [ +t('Array of Box', async() => [ '(3,4),(1,2);(6,7),(4,5)', - (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(";") -]); + (await sql`select ${ '{(1,2),(3,4);(4,5),(6,7)}' }::box[] as x`)[0].x.join(';') +]) t('Nested array n2', async() => ['4', (await sql`select ${ sql.array([[1, 2], [3, 4]]) } as x`)[0].x[1][1]] From a10bb6a892efaeef4252172fd7ed95608f007ed5 Mon Sep 17 00:00:00 2001 From: Bas van Zanten Date: Tue, 2 May 2023 13:39:46 +0200 Subject: [PATCH 4/4] chore: remove prepublish --- package.json | 105 +++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index deb38b19..0902e57a 100644 --- a/package.json +++ b/package.json @@ -1,55 +1,54 @@ { - "name": "postgres", - "version": "3.3.4", - "description": "Fastest full featured PostgreSQL client for Node.js", - "type": "module", - "module": "src/index.js", - "main": "cjs/src/index.js", - "exports": { - "types": "./types/index.d.ts", - "import": "./src/index.js", - "default": "./cjs/src/index.js" - }, - "types": "types/index.d.ts", - "typings": "types/index.d.ts", - "scripts": { - "build": "npm run build:cjs && npm run build:deno", - "build:cjs": "node transpile.cjs", - "build:deno": "node transpile.deno.js", - "test": "npm run test:esm && npm run test:cjs && npm run test:deno", - "test:esm": "node tests/index.js", - "test:cjs": "npm run build:cjs && cd cjs/tests && node index.js && cd ../../", - "test:deno": "npm run build:deno && cd deno/tests && deno run --unstable --allow-all --unsafely-ignore-certificate-errors index.js && cd ../../", - "lint": "eslint src && eslint tests", - "prepare": "npm run build", - "prepublishOnly": "npm run lint" - }, - "files": [ - "/cjs/src", - "/cjs/package.json", - "/src", - "/types" - ], - "author": "Rasmus Porsager (https://www.porsager.com)", - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/porsager" - }, - "license": "Unlicense", - "repository": "porsager/postgres", - "homepage": "https://github.com/porsager/postgres", - "bugs": "https://github.com/porsager/postgres/issues", - "keywords": [ - "driver", - "postgresql", - "postgres.js", - "postgres", - "postrges", - "postgre", - "client", - "sql", - "db", - "pg", - "database" - ] + "name": "postgres", + "version": "3.3.4", + "description": "Fastest full featured PostgreSQL client for Node.js", + "type": "module", + "module": "src/index.js", + "main": "cjs/src/index.js", + "exports": { + "types": "./types/index.d.ts", + "import": "./src/index.js", + "default": "./cjs/src/index.js" + }, + "types": "types/index.d.ts", + "typings": "types/index.d.ts", + "scripts": { + "build": "npm run build:cjs && npm run build:deno", + "build:cjs": "node transpile.cjs", + "build:deno": "node transpile.deno.js", + "test": "npm run test:esm && npm run test:cjs && npm run test:deno", + "test:esm": "node tests/index.js", + "test:cjs": "npm run build:cjs && cd cjs/tests && node index.js && cd ../../", + "test:deno": "npm run build:deno && cd deno/tests && deno run --unstable --allow-all --unsafely-ignore-certificate-errors index.js && cd ../../", + "lint": "eslint src && eslint tests", + "prepare": "npm run build" + }, + "files": [ + "/cjs/src", + "/cjs/package.json", + "/src", + "/types" + ], + "author": "Rasmus Porsager (https://www.porsager.com)", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + }, + "license": "Unlicense", + "repository": "porsager/postgres", + "homepage": "https://github.com/porsager/postgres", + "bugs": "https://github.com/porsager/postgres/issues", + "keywords": [ + "driver", + "postgresql", + "postgres.js", + "postgres", + "postrges", + "postgre", + "client", + "sql", + "db", + "pg", + "database" + ] }