Permalink
Browse files

Support for INOUT types in stored procedures. Split tests into two fi…

…les. Minor refactoring
  • Loading branch information...
1 parent 028743f commit f9145b53ce0b53d02124e9f0249d87eb6ec35bba Damian Beresford committed Apr 30, 2013
Showing with 352 additions and 193 deletions.
  1. +35 −0 README.md
  2. +1 −1 package.json
  3. +30 −10 src/connection.cpp
  4. +1 −1 src/executeBaton.h
  5. +41 −4 src/outParam.cpp
  6. +13 −0 src/outParam.h
  7. +1 −177 test/integration.js
  8. +230 −0 test/outparams.js
View
@@ -68,8 +68,43 @@ connection.execute("call myProc(:1,:2)", ["nodejs", new oracle.OutParam(oracle.O
```
+When using Strings as Out Params, the size can be optionally specified as follows:
+
+```
+
+connection.execute("call myProc(:1,:2)", ["nodejs", new oracle.OutParam(oracle.OCCISTRING, {size: 1000})], function(err, results){
+
+```
+
+If no size is specified, a default size of 200 chars is used.
+
See tests for more examples.
+## In/Out Params
+
+The following INOUT param types are supported:
+
+```
+
+OCCIINT
+OCCISTRING
+OCCIDOUBLE
+OCCIFLOAT
+OCCINUMBER
+
+```
+
+INOUT params are used like normal OUT prams, with the optional 'in' paramater value being passed in the options object:
+
+```
+
+connection.execute("call myProc(:1)", [new oracle.OutParam(oracle.OCCIINT, {in: 42})], function(err, results){
+ console.dir(results);
+};
+
+```
+
+
# Develop
## Install Oracle/Oracle Express
View
@@ -26,7 +26,7 @@
"nodeunit": "~>0.8.0"
},
"scripts": {
- "test": "nodeunit test"
+ "test": "nodeunit test/integration.js test/outparams.js"
},
"main": "./index.js"
}
View
@@ -149,7 +149,6 @@ void Connection::closeConnection() {
}
}
-
void RandomBytesFree(char* data, void* hint) {
delete[] data;
}
@@ -174,20 +173,36 @@ int Connection::SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<
case VALUE_TYPE_DATE:
stmt->setDate(index, *((oracle::occi::Date*)val->value));
break;
- case VALUE_TYPE_OUTPUT:
+ case VALUE_TYPE_OUTPUT:
outParamType = ((OutParam*)val->value)->type();
switch(outParamType) {
case OutParam::OCCIINT:
- stmt->registerOutParam(index, oracle::occi::OCCIINT);
+ if (((OutParam*)val->value)->_inOut.hasInParam) {
+ stmt->setInt(index, ((OutParam*)val->value)->_inOut.intVal);
+ }else {
+ stmt->registerOutParam(index, oracle::occi::OCCIINT);
+ }
break;
case OutParam::OCCISTRING:
- stmt->registerOutParam(index, oracle::occi::OCCISTRING, ((OutParam*)val->value)->size());
+ if (((OutParam*)val->value)->_inOut.hasInParam) {
+ stmt->setString(index, ((OutParam*)val->value)->_inOut.stringVal);
+ }else {
+ stmt->registerOutParam(index, oracle::occi::OCCISTRING, ((OutParam*)val->value)->size());
+ }
break;
case OutParam::OCCIDOUBLE:
- stmt->registerOutParam(index, oracle::occi::OCCIDOUBLE);
+ if (((OutParam*)val->value)->_inOut.hasInParam) {
+ stmt->setDouble(index, ((OutParam*)val->value)->_inOut.doubleVal);
+ }else {
+ stmt->registerOutParam(index, oracle::occi::OCCIDOUBLE);
+ }
break;
case OutParam::OCCIFLOAT:
- stmt->registerOutParam(index, oracle::occi::OCCIFLOAT);
+ if (((OutParam*)val->value)->_inOut.hasInParam) {
+ stmt->setFloat(index, ((OutParam*)val->value)->_inOut.floatVal);
+ }else {
+ stmt->registerOutParam(index, oracle::occi::OCCIFLOAT);
+ }
break;
case OutParam::OCCICURSOR:
stmt->registerOutParam(index, oracle::occi::OCCICURSOR);
@@ -202,8 +217,14 @@ int Connection::SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<
stmt->registerOutParam(index, oracle::occi::OCCITIMESTAMP);
break;
case OutParam::OCCINUMBER:
- stmt->registerOutParam(index, oracle::occi::OCCINUMBER);
+ {
+ if (((OutParam*)val->value)->_inOut.hasInParam) {
+ stmt->setNumber(index, ((OutParam*)val->value)->_inOut.numberVal);
+ } else {
+ stmt->registerOutParam(index, oracle::occi::OCCINUMBER);
+ }
break;
+ }
case OutParam::OCCIBLOB:
stmt->registerOutParam(index, oracle::occi::OCCIBLOB);
break;
@@ -363,8 +384,7 @@ void Connection::EIO_Execute(uv_work_t* req) {
output->intVal = stmt->getInt(output->index);
break;
case OutParam::OCCISTRING:
- output->strVal = (const char*) new string;
- output->strVal = stmt->getString(output->index).c_str();
+ output->strVal = stmt->getString(output->index);
break;
case OutParam::OCCIDOUBLE:
output->doubleVal = stmt->getDouble(output->index);
@@ -608,7 +628,7 @@ void Connection::EIO_AfterExecute(uv_work_t* req, int status) {
obj->Set(String::New(returnParam.c_str()), Integer::New(output->intVal));
break;
case OutParam::OCCISTRING:
- obj->Set(String::New(returnParam.c_str()), String::New(output->strVal));
+ obj->Set(String::New(returnParam.c_str()), String::New(output->strVal.c_str()));
break;
case OutParam::OCCIDOUBLE:
obj->Set(String::New(returnParam.c_str()), Number::New(output->doubleVal));
View
@@ -44,7 +44,7 @@ struct value_t {
struct output_t {
int type;
int index;
- const char* strVal;
+ std::string strVal;
int intVal;
double doubleVal;
float floatVal;
View
@@ -1,5 +1,8 @@
#include "outParam.h"
+#include "nodeOracleException.h"
+#include <iostream>
+using namespace std;
Persistent<FunctionTemplate> OutParam::constructorTemplate;
@@ -17,15 +20,49 @@ void OutParam::Init(Handle<Object> target) {
Handle<Value> OutParam::New(const Arguments& args) {
HandleScope scope;
+ OutParam *outParam = new OutParam();
- OutParam *client = new OutParam();
- client->_type = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
- client->_size = args[1]->IsUndefined() ? 200 : args[1]->NumberValue();
- client->Wrap(args.This());
+ outParam->_type = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
+
+ if (!args[1]->IsUndefined()) {
+ REQ_OBJECT_ARG(1, opts);
+ OBJ_GET_NUMBER(opts, "size", outParam->_size, 200);
+
+ // check if there's an 'in' param
+ if (opts->Has(String::New("in"))) {
+ outParam->_inOut.hasInParam = true;
+ switch(outParam->_type) {
+ case OutParam::OCCIINT: {
+ OBJ_GET_NUMBER(opts, "in", outParam->_inOut.intVal, 0);
+ break;
+ }
+ case OutParam::OCCIDOUBLE: {
+ OBJ_GET_NUMBER(opts, "in", outParam->_inOut.doubleVal, 0);
+ break;
+ }
+ case OutParam::OCCIFLOAT: {
+ OBJ_GET_NUMBER(opts, "in", outParam->_inOut.floatVal, 0);
+ break;
+ }
+ case OutParam::OCCINUMBER: {
+ OBJ_GET_NUMBER(opts, "in", outParam->_inOut.numberVal, 0);
+ break;
+ }
+ case OutParam::OCCISTRING: {
+ OBJ_GET_STRING(opts, "in", outParam->_inOut.stringVal);
+ break;
+ }
+ default:
+ throw NodeOracleException("Unhandled OutPram type!");
+ }
+ }
+ }
+ outParam->Wrap(args.This());
return args.This();
}
OutParam::OutParam() {
+ _inOut.hasInParam = false;
}
OutParam::~OutParam() {
View
@@ -8,10 +8,22 @@
#include <unistd.h>
#endif
#include "utils.h"
+#include <occi.h>
using namespace node;
using namespace v8;
+struct inout_t {
+ bool hasInParam;
+ const char* stringVal;
+ int intVal;
+ double doubleVal;
+ float floatVal;
+ oracle::occi::Date dateVal;
+ oracle::occi::Timestamp timestampVal;
+ oracle::occi::Number numberVal;
+};
+
class OutParam : ObjectWrap {
public:
static void Init(Handle<Object> target);
@@ -20,6 +32,7 @@ class OutParam : ObjectWrap {
static v8::Handle<v8::Value> GetType(const v8::Arguments& args);
int _type;
int _size;
+ inout_t _inOut;
OutParam();
~OutParam();
Oops, something went wrong.

0 comments on commit f9145b5

Please sign in to comment.