Skip to content

Commit 2010a27

Browse files
author
Aurynn Shaw
committed
Fixed a bug with prepared queries not obtaining a localized scope.
Added some initial test cases under t/ Initial test work on the transaction object
1 parent 99f9bf6 commit 2010a27

File tree

5 files changed

+119
-111
lines changed

5 files changed

+119
-111
lines changed

demo.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,31 @@ db.query("SELECT 1::int as foobar;", function (rs, tx) {
1212
});
1313

1414
db.prepare("SELECT ?::int AS foobar", function (sth, tx) {
15-
sth.execute(1, function (rs, tx) {
15+
sth.execute(1, function (rs) {
1616
sys.puts(sys.inspect(rs));
1717
});
1818
sth.execute(2, function (rs) {
1919
sys.puts(sys.inspect(rs));
2020

2121
});
22+
tx.prepare("SELECT ?::int AS cheese", function (sth) {
23+
sth.execute(3, function (rs) {
24+
sys.puts(sys.inspect(rs));
25+
}) ;
26+
});
2227
// db.close();
2328
});
24-
db.close();
2529

26-
//
27-
// db.transaction(function (tx) {
28-
// tx.query("SELECT ?::int AS foobar", 1, function (rs) {
29-
// sys.puts(sys.inspect(rs));
30-
// });
31-
// tx.prepare("SELECT ?::int AS foobar", function (sth) {
32-
// sth.execute(2, function (rs) {
33-
// sys.puts(sys.inspect(rs));
34-
// });
35-
// });
36-
// tx.commit();
37-
// });
30+
db.transaction(function (tx) {
31+
tx.query("SELECT ?::int AS txtest1", 1, function (rs) {
32+
sys.puts(sys.inspect(rs));
33+
});
34+
tx.prepare("SELECT ?::int AS txtest2", function (sth) {
35+
sth.execute(2, function (rs) {
36+
sys.puts(sys.inspect(rs));
37+
});
38+
});
39+
tx.commit();
40+
});
41+
42+
db.close();

lib/postgres-pure.js

Lines changed: 40 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ function parse_response(code, buffer) {
289289

290290
function message () {
291291
var self = this;
292-
this.messages = [];
293-
var pos = 0; // instance variable
292+
this.messages = []; // public instance array.
293+
var pos = 0;
294+
this._position = 0; // instance variable
294295
this.setMessages = function (msg) {
295296
if (msg instanceof Array) {
296297
self.messages = msg;
@@ -305,35 +306,35 @@ function message () {
305306
}
306307
this.next = function() {
307308
if (exports.DEBUG > 3) {
308-
sys.debug("message pos: " + pos);
309-
sys.debug("messages:" + sys.inspect(self.messages));
309+
sys.debug("message pos: " + this._position);
310+
sys.debug("messages:" + sys.inspect(this.messages));
310311
}
311-
if (self.messages[pos] !== null && self.messages[pos] !== undefined) {
312-
pos = pos + 1;
312+
if (this.messages[this._position] !== null && this.messages[this._position] !== undefined) {
313+
this._position = this._position + 1;
313314
if (exports.DEBUG > 3){
314-
sys.debug("Returning: " + self.messages[pos-1]);
315+
sys.debug("Returning: " + this.messages[this._position-1]);
315316
}
316-
return self.messages[pos-1];
317+
return this.messages[this._position-1];
317318
}
318319
if (exports.DEBUG > 3) {
319-
sys.debug("pos " + pos + " exceeds internal message buffer.");
320+
sys.debug("pos " + this._position + " exceeds internal message buffer.");
320321
sys.debug("Returning null");
321322
}
322323
return null;
323324
}
324325
this.empty = function () {
325326
if (exports.DEBUG > 3){
326-
sys.debug("message pos " + pos + " exceeds length "+ self.messages.length +": " + (pos >= self.messages.length));
327+
sys.debug("message pos " + this._position + " exceeds length "+ this.messages.length +": " + (this._position >= this.messages.length));
327328
}
328-
if (pos >= self.messages.length) {
329+
if (this._position >= this.messages.length) {
329330
return true;
330331
}
331332
return false;
332333
}
333334
}
334335

335336
message.prototype = new process.EventEmitter;
336-
337+
// message.prototype.constructor = message;
337338

338339
function Query(sql, callback) {
339340
message.call(this);
@@ -376,7 +377,7 @@ function Query(sql, callback) {
376377
});
377378
}
378379

379-
Query.prototype = new message();
380+
Query.prototype = new message;
380381
Query.prototype.constructor = Query;
381382

382383
function Prepared(sql, conn /*, use_named */) {
@@ -386,10 +387,11 @@ function Prepared(sql, conn /*, use_named */) {
386387
// var prepared_name = md5(sql); // Use the md5 hash. This is easily selectable later.
387388

388389
var self = this;
389-
// message.call(this);
390+
message.call(this);
390391
self.row_description = null;
391392
self.parameters = null;
392393
self.noData = false;
394+
self.sql = sql;
393395

394396
var parseComplete = null;
395397
var readyToExec = false;
@@ -402,7 +404,7 @@ function Prepared(sql, conn /*, use_named */) {
402404
type: "Parse",
403405
// Prepared name, the query,
404406
// and a zero-length array to declare no types.
405-
args: ['', sql, []],
407+
args: ['', self.sql, []],
406408
},
407409
{
408410
type: "Describe",
@@ -483,11 +485,7 @@ function Prepared(sql, conn /*, use_named */) {
483485

484486
self.next = function () {
485487
// Override.
486-
var msg = this.__proto__.next();
487-
// if ( exports.DEBUG > 0) {
488-
// sys.debug("Message is: " + msg);
489-
// sys.debug("proto is: " + self.__proto__);
490-
// }
488+
var msg = this.__proto__.next.call(this);
491489
if (exports.DEBUG > 3) {
492490
sys.debug("currexec " + currExec);
493491
sys.debug("msg" + msg);
@@ -508,24 +506,14 @@ function Prepared(sql, conn /*, use_named */) {
508506
}
509507
currExec.args.forEach(function (i) {
510508
if (exports.DEBUG > 2) {
511-
sys.debug("Arg is: " + i.type);
509+
sys.debug("Adding Arg: " + i.type);
512510
}
513-
self.addMessage(i);
511+
self.addMessage.call(self, i);
514512
});
515-
// for (arg in currExec.args.slice(1)) {
516-
//
517-
// if (currExec.args.hasOwnProperty(arg)) {
518-
//
519-
// }
520-
// }
521-
// self.addMessage({
522-
// type: "Flush",
523-
// args: [],
524-
// }); // Flush the current query out.
525513
if (exports.DEBUG > 2) {
526514
sys.debug("Calling next from prototype.");
527515
}
528-
return self.__proto__.next();
516+
return self.__proto__.next.call(this);
529517
}
530518
}
531519
if (exports.DEBUG > 0) {
@@ -1042,8 +1030,9 @@ function Connection(args) {
10421030
// do the implicit sync/commit here?
10431031
callback.apply(callback, arguments);
10441032
}
1045-
if (exports.DEBUG > 0) {
1033+
if (exports.DEBUG > 3) {
10461034
sys.debug("Transaction is: " + tx);
1035+
sys.debug("Query is: " + query);
10471036
}
10481037
tx.prepare.call(tx, query, cb);
10491038
events.emit("queryAdded");
@@ -1118,16 +1107,19 @@ function Connection(args) {
11181107
Ergo, we set up a DB listener with the same name, and fire our emitter
11191108
when it's triggered.
11201109
1121-
Easy.
1110+
Easy, and very nifty.
11221111
*/
11231112
conn.addListener('newListener', function (e, listener) {
11241113
if (e === 'String') {
11251114
// It's a string.
1126-
if (!(e in ['newListener']))
1127-
conn.notify(e, listener);
1115+
if (!(e in ['newListener'])) {
1116+
conn.notify(e, listener);
1117+
}
11281118
}
1129-
11301119
});
1120+
conn.notify = function (name) {
1121+
1122+
}
11311123
}
11321124
Connection.prototype = new process.EventEmitter();
11331125

@@ -1220,12 +1212,15 @@ function Transaction (connection /*, params */) {
12201212
// Sets up a prepared query, and drops it onto the queue.
12211213
if (sql.match(/\?/)) {
12221214
var i = 1;
1223-
sql = sql.replace(/\?/g, function () { return "$" + i++; });
1215+
var fsql = sql.replace(/\?/g, function () { return "$" + i++; });
12241216
}
1225-
var p = new Prepared(sql, thisp);
1217+
var p = new Prepared(fsql, thisp);
12261218
thisp.push(p);
12271219
events.emit("queryAdded");
12281220
wrap(callback)(p, thisp);
1221+
if (exports.DEBUG == 4) {
1222+
sys.debug("Prepared messages: " + sys.inspect(messages));
1223+
}
12291224
// conn.emit.call(conn, "queryAdded");
12301225
}
12311226

@@ -1244,7 +1239,7 @@ function Transaction (connection /*, params */) {
12441239

12451240
this.begin = function () {
12461241
// Begins the transaction. We now lock the transaction to the wire.
1247-
thisp.append(thisp.query("BEGIN;")); // Don't need to watch for callbacks.
1242+
thisp.push(thisp.query("BEGIN;")); // Don't need to watch for callbacks.
12481243
}
12491244
this.rollback = function () {
12501245
// Rolls back the request, and does the connection release.
@@ -1278,6 +1273,9 @@ function Transaction (connection /*, params */) {
12781273
this.next = function () {
12791274
if (messages.length > 0) {
12801275
if (messages[0] !== null && messages[0] !== undefined) {
1276+
if (exports.DEBUG == 4) {
1277+
sys.debug("TX Returning: " + sys.inspect(messages[0]));
1278+
}
12811279
return messages.shift(); // Front of the array, there.
12821280
}
12831281
}
@@ -1295,59 +1293,4 @@ function connectionManager (dsn /*, connections=1 */) {
12951293
// var conn = new Connection(dsn);
12961294
}
12971295

1298-
exports.connect = Connection;
1299-
1300-
1301-
1302-
/* Allows a currently-executing query to selectively modify the current
1303-
query queue, IF it is currently executing.
1304-
1305-
Otherwise, it splices the query object in after its position in the queue.
1306-
*/
1307-
// conn.yield_to = function (first, query) {
1308-
// if (exports.DEBUG > 0) {
1309-
// sys.debug("got yield_to");
1310-
// }
1311-
// if (first === current_query) {
1312-
// query_queue.unshift(query);
1313-
// events.emit("queryAdded"); // Don't immediately switch to the next message.
1314-
// }
1315-
// else if (first in query_queue) {
1316-
// // Splice it in after the query
1317-
// query_queue.splice( query_queue.indexOf(first), 0, query );
1318-
// events.emit("queryAdded");
1319-
// }
1320-
// }
1321-
// // Transactions shouldn't release themselves, I don't think.
1322-
// //
1323-
// conn.release = function (query) {
1324-
// if (exports.DEBUG > 0) {
1325-
// sys.debug("got release");
1326-
// }
1327-
// if (query === current_query) {
1328-
// readyState = true;
1329-
// events.emit("ReadyForQuery"); // Cycle along.
1330-
// }
1331-
// }
1332-
1333-
1334-
// var parameters, callback;
1335-
//
1336-
// // Grab the variable length parameters and the row_callback is there is one.
1337-
// parameters = Array.prototype.slice.call(arguments, 1);
1338-
//
1339-
// if (typeof parameters[parameters.length - 1] === 'function') {
1340-
// callback = parameters.pop();
1341-
// }
1342-
// var q;
1343-
// if (parameters.length == 1 && parameters[0] instanceof Array) {
1344-
// // We have a parameterized query
1345-
// q = new Prepared(query, function (sth) {
1346-
// sth.execute(parameters[0], callback);
1347-
// });
1348-
// }
1349-
// else {
1350-
// q = new Query(query, callback);
1351-
//
1352-
// }
1353-
// query_queue.push(q);
1296+
exports.connect = Connection;

t/complex_prepared.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var sys = require("sys");
2+
var pg = require("../lib/postgres-pure");
3+
pg.DEBUG=0;
4+
5+
var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
6+
7+
db.prepare("SELECT ?::int AS foobar", function (sth, tx) {
8+
sth.execute(1, function (rs) {
9+
console.log(eq(rs[0]['foobar'], 1));
10+
//sys.puts(sys.inspect(rs));
11+
});
12+
sth.execute(2, function (rs) {
13+
console.log(eq(rs[0]['foobar'], 2));
14+
// sys.puts(sys.inspect(rs));
15+
16+
});
17+
tx.prepare("SELECT ?::int AS cheese", function (sth) {
18+
sth.execute(3, function (rs) {
19+
console.log(eq(rs[0]['cheese'], 3));
20+
// sys.puts(sys.inspect(rs));
21+
});
22+
});
23+
// db.close();
24+
});
25+
db.close();
26+
27+
28+
function eq (l, r) {
29+
if (l === r) {
30+
return "ok"
31+
}
32+
return "not ok\n " + l + " != " + r;
33+
}

t/query.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var sys = require("sys");
2+
var pg = require("../lib/postgres-pure");
3+
pg.DEBUG=0;
4+
5+
var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
6+
db.query("SELECT 1::int as foobar;", function (rs, tx) {
7+
sys.puts(sys.inspect(rs));
8+
tx.query("SELECT 2::int as foobartwo", function (rs) {
9+
sys.puts(sys.inspect(rs));
10+
});
11+
});
12+
db.close();

t/simple_prepared.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var sys = require("sys");
2+
var pg = require("../lib/postgres-pure");
3+
pg.DEBUG=0;
4+
5+
var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
6+
db.prepare("SELECT ?::int AS foobar", function (sth, tx) {
7+
sth.execute(1, function (rs) {
8+
sys.puts(sys.inspect(rs));
9+
});
10+
sth.execute(2, function (rs) {
11+
sys.puts(sys.inspect(rs));
12+
13+
});
14+
});
15+
db.close();

0 commit comments

Comments
 (0)