diff --git a/.travis.yml b/.travis.yml index 76cb6fea..ebd75021 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,5 @@ node_js: before_script: - npm install npm --global - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres +env: + - PGUSER=postgres PGDATABASE=postgres diff --git a/README.md b/README.md index f87d810d..64d50f97 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ __I love contributions.__ You are welcome contribute via pull requests. If you need help getting the tests running locally feel free to email me or gchat me. I will __happily__ accept your pull request if it: -- _)has tests__ +- __has tests__ - looks reasonable - does not break backwards compatibility - satisfies jshint @@ -135,6 +135,8 @@ node-postgres is by design _low level_ with the bare minimum of abstraction. Th - [brianc/node-sql](https://github.com/brianc/node-sql) - SQL generation for node.js - [hiddentao/suqel](https://hiddentao.github.io/squel/) - SQL query string builder for Javascript - [CSNW/sql-bricks](https://github.com/CSNW/sql-bricks) - Transparent, Schemaless SQL Generation +- [datalanche/node-pg-format](https://github.com/datalanche/node-pg-format) - Safely and easily create dynamic SQL queries with this Node implementation of [PostgreSQL format()](http://www.postgresql.org/docs/9.3/static/functions-string.html#FUNCTIONS-STRING-FORMAT). +- [iceddev/pg-transact](https://github.com/iceddev/pg-transact) - A nicer API on node-postgres transactions ### Windows diff --git a/lib/client.js b/lib/client.js index 5759706e..53b4481d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -115,6 +115,15 @@ Client.prototype.connect = function(callback) { self.activeQuery.handleCommandComplete(msg, con); }); + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function(msg) { + if(self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + con.on('copyInResponse', function(msg) { self.activeQuery.handleCopyInResponse(self.connection); }); diff --git a/lib/query.js b/lib/query.js index dc98580a..69be6e47 100644 --- a/lib/query.js +++ b/lib/query.js @@ -135,9 +135,6 @@ Query.prototype.prepare = function(connection) { name: self.name, types: self.types }, true); - if(this.name) { - connection.parsedStatements[this.name] = true; - } } //TODO is there some better way to prepare values for the database? diff --git a/test/integration/gh-issues/199-tests.js b/test/integration/gh-issues/199-tests.js new file mode 100644 index 00000000..b60477fd --- /dev/null +++ b/test/integration/gh-issues/199-tests.js @@ -0,0 +1,21 @@ +var helper = require('../test-helper'); +var client = helper.client(); + +client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)'); +client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');"); + +var qText = "SELECT \ +ARRAY[1, 2, 3] AS b,\ +ARRAY['xx', 'yy', 'zz'] AS c,\ +ARRAY(SELECT n FROM arrtest) AS d,\ +ARRAY(SELECT s FROM arrtest) AS e;"; + +client.query(qText, function(err, result) { + if(err) throw err; + var row = result.rows[0]; + for(var key in row) { + assert.equal(typeof row[key], 'object'); + assert.equal(row[key].length, 3); + } + client.end(); +}); diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js new file mode 100644 index 00000000..0476d42d --- /dev/null +++ b/test/integration/gh-issues/600-tests.js @@ -0,0 +1,77 @@ +var async = require('async'); +var helper = require('../test-helper'); + +var db = helper.client(); + +function createTableFoo(callback){ + db.query("create temp table foo(column1 int, column2 int)", callback); +} + +function createTableBar(callback){ + db.query("create temp table bar(column1 text, column2 text)", callback); +} + +function insertDataFoo(callback){ + db.query({ + name: 'insertFoo', + text: 'insert into foo values($1,$2)', + values:['one','two'] + }, callback ); +} + +function insertDataBar(callback){ + db.query({ + name: 'insertBar', + text: 'insert into bar values($1,$2)', + values:['one','two'] + }, callback ); +} + +function startTransaction(callback) { + db.query('BEGIN', callback); +} +function endTransaction(callback) { + db.query('COMMIT', callback); +} + +function doTransaction(callback) { + // The transaction runs startTransaction, then all queries, then endTransaction, + // no matter if there has been an error in a query in the middle. + startTransaction(function() { + insertDataFoo(function() { + insertDataBar(function() { + endTransaction( callback ); + }); + }); + }); +} + +var steps = [ + createTableFoo, + createTableBar, + doTransaction, + insertDataBar +] + +test('test if query fails', function() { + async.series(steps, assert.success(function() { + db.end() + })) +}) + +test('test if prepare works but bind fails', function() { + var client = helper.client(); + var q = { + text: 'SELECT $1::int as name', + values: ['brian'], + name: 'test' + }; + client.query(q, assert.calls(function(err, res) { + q.values = [1]; + client.query(q, assert.calls(function(err, res) { + assert.ifError(err); + client.end(); + })); + })); +}); + diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js new file mode 100644 index 00000000..128afc65 --- /dev/null +++ b/test/integration/gh-issues/675-tests.js @@ -0,0 +1,28 @@ +var helper = require('../test-helper'); +var assert = require('assert'); + +helper.pg.connect(function(err, client, done) { + if (err) throw err; + + var c = 'CREATE TEMP TABLE posts (body TEXT)'; + + client.query(c, function(err) { + if (err) throw err; + + c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *'; + + var body = new Buffer('foo'); + client.query(c, [body], function(err) { + if (err) throw err; + + body = new Buffer([]); + client.query(c, [body], function(err, res) { + done(); + + if (err) throw err; + assert.equal(res.rows[0].body, '') + helper.pg.end(); + }); + }); + }); +});