diff --git a/lib/connection.js b/lib/connection.js index f11ecf05c..ac038bf30 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -19,6 +19,8 @@ var Connection = function(config) { this.parsedStatements = {}; this.writer = new Writer(); this.ssl = config.ssl || false; + this.longNameI = 0; + this.longNameMap = {}; this._ending = false; this._mode = TEXT_MODE; this._emitMessage = false; @@ -189,6 +191,15 @@ Connection.prototype.query = function(text) { this.stream.write(this.writer.addCString(text).flush(0x51)); }; +Connection.prototype.getShortName = function(longName) { + var shortName = this.longNameMap[longName]; + if (!shortName) { + shortName = '__node_pg_short_name_' + (++this.longNameI) + '__'; + this.longNameMap[longName] = shortName; + } + return shortName; +}; + //send parse message //"more" === true to buffer the message until flush() is called Connection.prototype.parse = function(query, more) { @@ -198,12 +209,16 @@ Connection.prototype.parse = function(query, more) { // types: ['int8', 'bool'] } //normalize missing query names to allow for null - query.name = query.name || ''; + var query_name = query.name || ''; + //shorten long (>63 character) names + if (query_name.length > 63) { + query_name = this.getShortName(query_name); + } //normalize null type array query.types = query.types || []; var len = query.types.length; var buffer = this.writer - .addCString(query.name) //name of query + .addCString(query_name) //name of query .addCString(query.text) //actual query text .addInt16(len); for(var i = 0; i < len; i++) { @@ -220,7 +235,11 @@ Connection.prototype.bind = function(config, more) { //normalize config config = config || {}; config.portal = config.portal || ''; - config.statement = config.statement || ''; + var config_statement = config.statement || ''; + //shorten long (>63 character) names + if (config_statement.length > 63) { + config_statement = this.getShortName(config_statement); + } config.binary = config.binary || false; var values = config.values || []; var len = values.length; @@ -229,7 +248,7 @@ Connection.prototype.bind = function(config, more) { useBinary |= values[j] instanceof Buffer; var buffer = this.writer .addCString(config.portal) - .addCString(config.statement); + .addCString(config_statement); if (!useBinary) buffer.addInt16(0); else { diff --git a/lib/native/index.js b/lib/native/index.js index 7569c4d47..8a8e28d4e 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -36,6 +36,8 @@ var Client = module.exports = function(config) { //a hash to hold named queries this.namedQueries = {}; + this.longNameI = 0; + this.longNameMap = {}; }; util.inherits(Client, EventEmitter); @@ -191,3 +193,12 @@ Client.prototype.setTypeParser = function(oid, format, parseFn) { Client.prototype.getTypeParser = function(oid, format) { return this._types.getTypeParser(oid, format); }; + +Client.prototype.getShortName = function(longName) { + var shortName = this.longNameMap[longName]; + if (!shortName) { + shortName = '__node_pg_native_short_name_' + (++this.longNameI) + '__'; + this.longNameMap[longName] = shortName; + } + return shortName; +}; diff --git a/lib/native/query.js b/lib/native/query.js index 29b77ba96..051965f6c 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -86,17 +86,21 @@ NativeQuery.prototype.submit = function(client) { //named query if(this.name) { var values = (this.values||[]).map(utils.prepareValue); + var this_name = this.name; + if(this_name.length > 63) { + this_name = client.getShortName(this_name); + } //check if the client has already executed this named query //if so...just execute it again - skip the planning phase - if(client.namedQueries[this.name]) { - return this.native.execute(this.name, values, after); + if(client.namedQueries[this_name]) { + return this.native.execute(this_name, values, after); } //plan the named query the first time, then execute it - return this.native.prepare(this.name, this.text, values.length, function(err) { + return this.native.prepare(this_name, this.text, values.length, function(err) { if(err) return after(err); - client.namedQueries[self.name] = true; - return self.native.execute(self.name, values, after); + client.namedQueries[this_name] = true; + return self.native.execute(this_name, values, after); }); } else if(this.values) { diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 478cd007c..21c093502 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -211,4 +211,20 @@ test('prepared statement', function() { checkForResults(query); }) + test('with long name', function() { + var queryA = client.query({ + name: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + text: 'SELECT name FROM zoom ORDER BY name', + rows: 1000 + }) + checkForResults(queryA); + + var queryB = client.query({ + name: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab', + text: 'SELECT name FROM zoom ORDER BY name', + rows: 1000 + }) + checkForResults(queryB); + }) + })