diff --git a/Makefile b/Makefile index 8d077d4..b4885d1 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ params := -u $(user) --password $(password) -p $(port) -d $(database) -h $(host) node-command := xargs -n 1 -I file node file $(params) -.PHONY : test test-connection test-integration bench test-native +.PHONY : test test-connection test-integration bench test-native build/default/binding.node test: test-unit test-all: test-unit test-integration test-native @@ -19,7 +19,7 @@ test-all: test-unit test-integration test-native bench: @find benchmark -name "*-bench.js" | $(node-command) -build/default/binding.node: src/binding.cc +build/default/binding.node: @node-waf configure build test-unit: diff --git a/lib/native.js b/lib/native.js index 3e06250..c7d78de 100644 --- a/lib/native.js +++ b/lib/native.js @@ -66,8 +66,13 @@ p._pulseQueryQueue = function() { } this._activeQuery = query; if(query.name) { - this._namedQuery = true; - this._sendPrepare(query.name, query.text, (query.values||[]).length); + if(this._namedQueries[query.name]) { + this._sendQueryPrepared(query.name, query.values||[]); + } else { + this._namedQuery = true; + this._namedQueries[query.name] = true; + this._sendPrepare(query.name, query.text, (query.values||[]).length); + } } else if(query.values) { //call native function @@ -82,6 +87,7 @@ var ctor = function(config) { config = config || {}; var connection = new Connection(); connection._queryQueue = []; + connection._namedQueries = {}; connection._activeQuery = null; connection._config = utils.normalizeConnectionInfo(config); connection.on('connect', function() { @@ -103,10 +109,11 @@ var ctor = function(config) { } }) connection.on('_readyForQuery', function() { + var q = this._activeQuery; //a named query finished being prepared if(this._namedQuery) { this._namedQuery = false; - connection. + this._sendQueryPrepared(q.name, q.values||[]); } else { connection._activeQuery.handleReadyForQuery(); connection._activeQuery = null; diff --git a/src/binding.cc b/src/binding.cc index 427a684..8c227dc 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -145,10 +145,6 @@ public: Handle params = args[1]; - if(!params->IsArray()) { - return ThrowException(Exception::Error(String::New("Values must be array"))); - } - char* queryText = MallocCString(args[0]); Local jsParams = Local::Cast(args[1]); char** paramValues = ArgToCStringArray(jsParams); @@ -214,21 +210,22 @@ public: return cString; } - //v8 entry point into Connection#_sendPrepare + //v8 entry point into Connection#_sendPrepare(string queryName, string queryText, int nParams) static Handle SendPrepare(const Arguments& args) { HandleScope scope; - return ThrowException(Exception::Error(String::New("Prepared named queries not implemented"))); + Connection *self = ObjectWrap::Unwrap(args.This()); String::Utf8Value queryName(args[0]); String::Utf8Value queryText(args[1]); - - self->SendPrepare(*queryName, *queryText, 0); + int length = args[2]->Int32Value(); + self->SendPrepare(*queryName, *queryText, length); return Undefined(); } + //v8 entry point into Connection#_sendQueryPrepared(string queryName, string[] paramValues) static Handle SendQueryPrepared(const Arguments& args) { @@ -236,6 +233,33 @@ public: Connection *self = ObjectWrap::Unwrap(args.This()); String::Utf8Value queryName(args[0]); + //TODO this is much copy/pasta code + if(!args[0]->IsString()) { + return ThrowException(Exception::Error(String::New("First parameter must be a string query"))); + } + + if(!args[1]->IsArray()) { + return ThrowException(Exception::Error(String::New("Values must be array"))); + } + + Handle params = args[1]; + + char* queryText = MallocCString(args[0]); + Local jsParams = Local::Cast(args[1]); + char** paramValues = ArgToCStringArray(jsParams); + if(!paramValues) { + return ThrowException(Exception::Error(String::New("Something bad happened when allocating parameter array"))); + } + + int len = jsParams->Length(); + int result = self->SendPreparedQuery(queryText, len, paramValues); + + free(queryText); + Free(paramValues, len); + if(result == 1) { + return Undefined(); + } + return ThrowException(Exception::Error(String::New("Could not dispatch parameterized query"))); return Undefined(); } @@ -300,6 +324,11 @@ protected: return PQsendPrepare(connection_, name, command, nParams, NULL); } + int SendPreparedQuery(const char *name, int nParams, const char * const *paramValues) + { + return PQsendQueryPrepared(connection_, name, nParams, paramValues, NULL, NULL, 0); + } + //flushes socket void Flush() {