Skip to content

Commit 0d5d339

Browse files
authored
Add bindings for PQdescribePrepared, PQnparams and PQparamtype (#72)
1 parent 14d7c03 commit 0d5d339

File tree

6 files changed

+85
-0
lines changed

6 files changed

+85
-0
lines changed

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ __sync__ sends a command to the server to execute a previously prepared statemen
9494
- `statementName` is a required string of the name of the prepared statement.
9595
- `parameters` are the parameters to pass to the prepared statement.
9696

97+
##### `pq.describePrepared(statementName:string)`
98+
__sync__ sends a command to the server to describe a previously prepared statement. blocks until the results are returned. Use `pq.nparams` and `pq.paramtype` to obtain information about the parameters and `pq.nfields`, `pq.fname` and `pq.ftype` about the result columns of the prepared statement.
99+
97100
### Async Command Execution Functions
98101

99102
In libpq the async command execution functions _only_ dispatch a request to the backend to run a query. They do not start result fetching on their own. Because libpq is a C api there is a somewhat complicated "dance" to retrieve the result information in a non-blocking way. node-libpq attempts to do as little as possible to abstract over this; therefore, the following functions are only part of the story. For a complete tutorial on how to dispatch & retrieve results from libpq in an async way you can [view the complete approach here](https://github.com/brianc/node-pg-native/blob/master/index.js#L105)
@@ -190,6 +193,14 @@ Retrieve the text value at a given tuple (row) and field (column) offset. Both o
190193

191194
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?
192195

196+
##### `pq.nparams():int`
197+
198+
Returns the number of parameters a prepared statement expects.
199+
200+
##### `pq.paramtype(paramNumber:int):int`
201+
202+
Returns the `Oid` of the prepared statement's parameter at the given offset.
203+
193204
##### `pq.cmdStatus():string`
194205

195206
Returns the status string associated with a result. Something akin to `INSERT 3 0` if you inserted 3 rows.

index.js

+20
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ PQ.prototype.execPrepared = function (statementName, parameters) {
131131
this.$execPrepared(statementName, parameters);
132132
};
133133

134+
//SYNC describes a named, prepared query and stores the result
135+
//immediately stores the results within the PQ object for consumption with
136+
//nparams, paramtype, nfields, etc...
137+
PQ.prototype.describePrepared = function(statementName) {
138+
if(!statementName) {
139+
statementName = '';
140+
}
141+
this.$describePrepared(statementName);
142+
};
143+
134144
//send a command to begin executing a query in async mode
135145
//returns true if sent, or false if there was a send failure
136146
PQ.prototype.sendQuery = function (commandText) {
@@ -257,6 +267,16 @@ PQ.prototype.getisnull = function (row, col) {
257267
return this.$getisnull(row, col);
258268
};
259269

270+
//returns the number of parameters of a prepared statement
271+
PQ.prototype.nparams = function() {
272+
return this.$nparams();
273+
};
274+
275+
//returns the data type of the indicated statement parameter (starting from 0)
276+
PQ.prototype.paramtype = function(n) {
277+
return this.$paramtype(n);
278+
};
279+
260280
//returns the status of the command
261281
PQ.prototype.cmdStatus = function () {
262282
return this.$cmdStatus();

src/addon.cc

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ NAN_MODULE_INIT(InitAddon) {
2121
Nan::SetPrototypeMethod(tpl, "$execParams", Connection::ExecParams);
2222
Nan::SetPrototypeMethod(tpl, "$prepare", Connection::Prepare);
2323
Nan::SetPrototypeMethod(tpl, "$execPrepared", Connection::ExecPrepared);
24+
Nan::SetPrototypeMethod(tpl, "$describePrepared", Connection::DescribePrepared);
2425

2526
//async query functions
2627
Nan::SetPrototypeMethod(tpl, "$sendQuery", Connection::SendQuery);
@@ -49,6 +50,8 @@ NAN_MODULE_INIT(InitAddon) {
4950
Nan::SetPrototypeMethod(tpl, "$ftype", Connection::Ftype);
5051
Nan::SetPrototypeMethod(tpl, "$getvalue", Connection::Getvalue);
5152
Nan::SetPrototypeMethod(tpl, "$getisnull", Connection::Getisnull);
53+
Nan::SetPrototypeMethod(tpl, "$nparams", Connection::Nparams);
54+
Nan::SetPrototypeMethod(tpl, "$paramtype", Connection::Paramtype);
5255
Nan::SetPrototypeMethod(tpl, "$cmdStatus", Connection::CmdStatus);
5356
Nan::SetPrototypeMethod(tpl, "$cmdTuples", Connection::CmdTuples);
5457
Nan::SetPrototypeMethod(tpl, "$resultStatus", Connection::ResultStatus);

src/connection.cc

+37
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,21 @@ NAN_METHOD(Connection::ExecPrepared) {
176176
self->SetLastResult(result);
177177
}
178178

179+
NAN_METHOD(Connection::DescribePrepared) {
180+
Connection *self = NODE_THIS();
181+
182+
Nan::Utf8String statementName(info[0]);
183+
184+
TRACEF("Connection::DescribePrepared: %s\n", *statementName);
185+
186+
PGresult* result = PQdescribePrepared(
187+
self->pq,
188+
*statementName
189+
);
190+
191+
self->SetLastResult(result);
192+
}
193+
179194

180195
NAN_METHOD(Connection::Clear) {
181196
TRACE("Connection::Clear");
@@ -282,6 +297,28 @@ NAN_METHOD(Connection::Getisnull) {
282297
info.GetReturnValue().Set(rowValue == 1);
283298
}
284299

300+
NAN_METHOD(Connection::Nparams) {
301+
TRACE("Connection::Nparams");
302+
Connection *self = NODE_THIS();
303+
304+
PGresult* res = self->lastResult;
305+
306+
int nparams = PQnparams(res);
307+
308+
info.GetReturnValue().Set(nparams);
309+
}
310+
311+
NAN_METHOD(Connection::Paramtype) {
312+
TRACE("Connection::Paramtype");
313+
Connection *self = NODE_THIS();
314+
315+
PGresult* res = self->lastResult;
316+
317+
int paramType = PQparamtype(res, Nan::To<int32_t>(info[0]).FromJust());
318+
319+
info.GetReturnValue().Set(paramType);
320+
}
321+
285322
NAN_METHOD(Connection::CmdStatus) {
286323
TRACE("Connection::CmdStatus");
287324
Connection *self = NODE_THIS();

src/connection.h

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Connection : public Nan::ObjectWrap {
1717
static NAN_METHOD(ExecParams);
1818
static NAN_METHOD(Prepare);
1919
static NAN_METHOD(ExecPrepared);
20+
static NAN_METHOD(DescribePrepared);
2021
static NAN_METHOD(Clear);
2122
static NAN_METHOD(Ntuples);
2223
static NAN_METHOD(Nfields);
@@ -26,6 +27,8 @@ class Connection : public Nan::ObjectWrap {
2627
static NAN_METHOD(Ftype);
2728
static NAN_METHOD(Getvalue);
2829
static NAN_METHOD(Getisnull);
30+
static NAN_METHOD(Nparams);
31+
static NAN_METHOD(Paramtype);
2932
static NAN_METHOD(CmdStatus);
3033
static NAN_METHOD(CmdTuples);
3134
static NAN_METHOD(ResultStatus);

test/sync-prepare.js

+11
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,15 @@ describe('prepare and execPrepared', function () {
3131
);
3232
});
3333
});
34+
35+
describe('describing a prepared statement', function() {
36+
it('works properly', function() {
37+
this.pq.describePrepared(statementName);
38+
assert.strictEqual(this.pq.nparams(), 1)
39+
assert.strictEqual(this.pq.paramtype(0), 25)
40+
assert.strictEqual(this.pq.nfields(), 1);
41+
assert.strictEqual(this.pq.fname(0), 'name');
42+
assert.strictEqual(this.pq.ftype(0), 25);
43+
});
44+
});
3445
});

0 commit comments

Comments
 (0)