From ab65f41542db7533eeb3d170131593294faa6d41 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Sun, 11 Oct 2026 09:37:13 +0200 Subject: [PATCH] Add getvalues to read all the values of a result in one call --- README.md | 4 ++++ index.js | 3 +++ src/addon.cc | 1 + src/connection.cc | 29 +++++++++++++++++++++++++++++ src/connection.h | 1 + test/sync-integration.js | 4 ++++ 6 files changed, 42 insertions(+) diff --git a/README.md b/README.md index 7f0882c..dc982c8 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,10 @@ Retrieve the text value at a given tuple (row) and field (column) offset. Both o Returns `true` if the value at the given offsets is actually `null`. Otherwise returns `false`. This is because `pq.getvalue()` returns an empty string for both an actual empty string and for a `null` value. Weird, huh? +##### `pq.getvalues():Array` + +Retrieve all the text values of the result in one flat array, row by row: the value at tuple `t` and field `f` is at index `t * pq.nfields() + f`. A null value is returned as `null`. Faster than calling `pq.getvalue()` for each value of a large result. + ##### `pq.nparams():int` Returns the number of parameters a prepared statement expects. diff --git a/index.js b/index.js index 31dd42c..6c93aab 100644 --- a/index.js +++ b/index.js @@ -238,6 +238,9 @@ PQ.prototype.getvalue = PQ.prototype.$getvalue; //returns true/false if the value is null PQ.prototype.getisnull = PQ.prototype.$getisnull; +//returns all the values of the result in one flat array, row by row, null for a null value +PQ.prototype.getvalues = PQ.prototype.$getvalues; + //returns the number of parameters of a prepared statement PQ.prototype.nparams = PQ.prototype.$nparams; diff --git a/src/addon.cc b/src/addon.cc index 94aa528..6c9f5f3 100644 --- a/src/addon.cc +++ b/src/addon.cc @@ -51,6 +51,7 @@ NAN_MODULE_INIT(InitAddon) { Nan::SetPrototypeMethod(tpl, "$ftype", Connection::Ftype); Nan::SetPrototypeMethod(tpl, "$getvalue", Connection::Getvalue); Nan::SetPrototypeMethod(tpl, "$getisnull", Connection::Getisnull); + Nan::SetPrototypeMethod(tpl, "$getvalues", Connection::Getvalues); Nan::SetPrototypeMethod(tpl, "$nparams", Connection::Nparams); Nan::SetPrototypeMethod(tpl, "$paramtype", Connection::Paramtype); Nan::SetPrototypeMethod(tpl, "$cmdStatus", Connection::CmdStatus); diff --git a/src/connection.cc b/src/connection.cc index 0285b3a..7f05674 100644 --- a/src/connection.cc +++ b/src/connection.cc @@ -1,4 +1,5 @@ #include "addon.h" +#include Connection::Connection() : Nan::ObjectWrap() { TRACE("Connection::Constructor"); @@ -309,6 +310,34 @@ NAN_METHOD(Connection::Getisnull) { info.GetReturnValue().Set(rowValue == 1); } +// every value of the result in one call: one native call per cell is the main cost of a large result +NAN_METHOD(Connection::Getvalues) { + TRACE("Connection::Getvalues"); + Connection *self = NODE_THIS(); + + PGresult* res = self->lastResult; + int rows = PQntuples(res); + int cols = PQnfields(res); + v8::Isolate* isolate = info.GetIsolate(); + std::vector> values((size_t)rows * cols); + v8::Local null = Nan::Null(); + + size_t i = 0; + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++, i++) { + if (PQgetisnull(res, r, c)) { + values[i] = null; + } else { + values[i] = v8::String::NewFromUtf8( + isolate, PQgetvalue(res, r, c), v8::NewStringType::kNormal, PQgetlength(res, r, c) + ).ToLocalChecked(); + } + } + } + + info.GetReturnValue().Set(v8::Array::New(isolate, values.data(), values.size())); +} + NAN_METHOD(Connection::Nparams) { TRACE("Connection::Nparams"); Connection *self = NODE_THIS(); diff --git a/src/connection.h b/src/connection.h index 03284b7..acf81bb 100644 --- a/src/connection.h +++ b/src/connection.h @@ -27,6 +27,7 @@ class Connection : public Nan::ObjectWrap { static NAN_METHOD(Ftype); static NAN_METHOD(Getvalue); static NAN_METHOD(Getisnull); + static NAN_METHOD(Getvalues); static NAN_METHOD(Nparams); static NAN_METHOD(Paramtype); static NAN_METHOD(CmdStatus); diff --git a/test/sync-integration.js b/test/sync-integration.js index 41c67d2..26cf234 100644 --- a/test/sync-integration.js +++ b/test/sync-integration.js @@ -27,6 +27,10 @@ describe('low-level query integration tests', function () { assert.strictEqual(this.pq.getisnull(2, 1), true); }); + it('has correct values in one call', function () { + assert.deepStrictEqual(this.pq.getvalues(), ['brian', '32', 'aaron', '30', '', null]); + }); + it('has correct identifiers', function() { assert.notEqual(this.pq.ftable(0), 0); assert.notEqual(this.pq.ftable(1), 0);