Skip to content

Commit

Permalink
refactored baton to new file
Browse files Browse the repository at this point in the history
  • Loading branch information
joeferner committed Dec 21, 2011
1 parent 8bc49d3 commit 84cd071
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 120 deletions.
202 changes: 83 additions & 119 deletions src/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,6 @@

Persistent<FunctionTemplate> Connection::constructorTemplate;

#define VALUE_TYPE_OUTPUT 1
#define VALUE_TYPE_STRING 2

struct column_t {
int type;
std::string name;
};

struct row_t {
std::vector<void*> values;
};

struct value_t {
int type;
void* value;
};

struct execute_baton_t {
Connection *connection;
Persistent<Function> callback;
std::vector<value_t*> values;
std::string sql;
std::vector<column_t*> columns;
std::vector<row_t*>* rows;
std::string* error;
int updateCount;
int* returnParam;
};

void Connection::Init(Handle<Object> target) {
HandleScope scope;

Expand Down Expand Up @@ -72,32 +43,15 @@ Handle<Value> Connection::Execute(const Arguments& args) {

String::AsciiValue sqlVal(sql);

execute_baton_t* baton = new execute_baton_t();
baton->connection = connection;
baton->sql = *sqlVal;
baton->callback = Persistent<Function>::New(callback);
baton->returnParam = NULL;

for(uint32_t i=0; i<values->Length(); i++) {
Local<Value> val = values->Get(i);

value_t *value = new value_t();
if(val->IsString()) {
String::AsciiValue asciiVal(val);
value->type = VALUE_TYPE_STRING;
value->value = new std::string(*asciiVal);
baton->values.push_back(value);
} else if(val->IsObject() && val->ToObject()->FindInstanceInPrototypeChain(OutParam::constructorTemplate) != Null()) {
value->type = VALUE_TYPE_OUTPUT;
value->value = NULL;
baton->values.push_back(value);
} else {
Handle<Value> argv[2];
argv[0] = Exception::Error(String::New("unhandled value type"));
argv[1] = Undefined();
baton->callback->Call(Context::GetCurrent()->Global(), 2, argv);
return Undefined();
}
ExecuteBaton* baton;
try {
baton = new ExecuteBaton(connection, *sqlVal, &values, &callback);
} catch(NodeOracleException &ex) {
Handle<Value> argv[2];
argv[0] = Exception::Error(String::New(ex.getMessage().c_str()));
argv[1] = Undefined();
callback->Call(Context::GetCurrent()->Global(), 2, argv);
return Undefined();
}

eio_custom(EIO_Execute, EIO_PRI_DEFAULT, EIO_AfterExecute, baton);
Expand All @@ -122,8 +76,75 @@ void Connection::closeConnection() {
}
}

int Connection::SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<value_t*> &values) {
uint32_t index = 1;
int outputParam = -1;
for (std::vector<value_t*>::iterator iterator = values.begin(), end = values.end(); iterator != end; ++iterator, index++) {
value_t* val = *iterator;
switch(val->type) {
case VALUE_TYPE_STRING:
stmt->setString(index, *((std::string*)val->value));
break;
case VALUE_TYPE_OUTPUT:
stmt->registerOutParam(index, oracle::occi::OCCIINT);
outputParam = index;
break;
default:
throw NodeOracleException("Unhandled value type");
}
}
return outputParam;
}

void Connection::CreateColumnsFromResultSet(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns) {
std::vector<oracle::occi::MetaData> metadata = rs->getColumnListMetaData();
for (std::vector<oracle::occi::MetaData>::iterator iterator = metadata.begin(), end = metadata.end(); iterator != end; ++iterator) {
oracle::occi::MetaData metadata = *iterator;
column_t* col = new column_t();
col->name = metadata.getString(oracle::occi::MetaData::ATTR_NAME);
int type = metadata.getInt(oracle::occi::MetaData::ATTR_DATA_TYPE);
switch(type) {
case oracle::occi::OCCI_TYPECODE_NUMBER:
col->type = VALUE_TYPE_NUMBER;
break;
case oracle::occi::OCCI_TYPECODE_VARCHAR2:
case oracle::occi::OCCI_TYPECODE_VARCHAR:
col->type = VALUE_TYPE_STRING;
break;
default:
std::ostringstream message;
message << "Unhandled oracle data type: " << type;
throw NodeOracleException(message.str());
break;
}
columns.push_back(col);
}
}

row_t* Connection::CreateRowFromCurrentResultSetRow(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns) {
row_t* row = new row_t();
int colIndex = 1;
for (std::vector<column_t*>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator, colIndex++) {
column_t* col = *iterator;
switch(col->type) {
case VALUE_TYPE_STRING:
row->values.push_back(new std::string(rs->getString(colIndex)));
break;
case VALUE_TYPE_NUMBER:
row->values.push_back(new oracle::occi::Number(rs->getNumber(colIndex)));
break;
default:
std::ostringstream message;
message << "Unhandled type: " << col->type;
throw NodeOracleException(message.str());
break;
}
}
return row;
}

void Connection::EIO_Execute(eio_req* req) {
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
ExecuteBaton* baton = static_cast<ExecuteBaton*>(req->data);

baton->rows = NULL;
baton->error = NULL;
Expand All @@ -133,23 +154,7 @@ void Connection::EIO_Execute(eio_req* req) {
try {
//printf("%s\n", baton->sql.c_str());
stmt = baton->connection->m_connection->createStatement(baton->sql);
uint32_t index = 1;
int outputParam = -1;
for (std::vector<value_t*>::iterator iterator = baton->values.begin(), end = baton->values.end(); iterator != end; ++iterator, index++) {
value_t* val = *iterator;
switch(val->type) {
case VALUE_TYPE_STRING:
stmt->setString(index, *((std::string*)val->value));
break;
case VALUE_TYPE_OUTPUT:
stmt->registerOutParam(index, oracle::occi::OCCIINT);
outputParam = index;
break;
default:
baton->error = new std::string("unhandled value type");
goto error;
}
}
int outputParam = SetValuesOnStatement(stmt, baton->values);

int status = stmt->execute();
if(status == oracle::occi::Statement::UPDATE_COUNT_AVAILABLE) {
Expand All @@ -160,42 +165,20 @@ void Connection::EIO_Execute(eio_req* req) {
}
} else {
rs = stmt->executeQuery();
std::vector<oracle::occi::MetaData> columns = rs->getColumnListMetaData();
for (std::vector<oracle::occi::MetaData>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator) {
oracle::occi::MetaData metadata = *iterator;
column_t* col = new column_t();
col->name = metadata.getString(oracle::occi::MetaData::ATTR_NAME);
int type = metadata.getInt(oracle::occi::MetaData::ATTR_DATA_TYPE);
switch(type) {
default:
col->type = VALUE_TYPE_STRING;
break;
}
baton->columns.push_back(col);
}

CreateColumnsFromResultSet(rs, baton->columns);
baton->rows = new std::vector<row_t*>();

while(rs->next()) {
row_t* row = new row_t();
int colIndex = 1;
for (std::vector<column_t*>::iterator iterator = baton->columns.begin(), end = baton->columns.end(); iterator != end; ++iterator, colIndex++) {
column_t* col = *iterator;
switch(col->type) {
default:
case VALUE_TYPE_STRING:
row->values.push_back(new std::string(rs->getString(colIndex)));
break;
}
}
row_t* row = CreateRowFromCurrentResultSetRow(rs, baton->columns);
baton->rows->push_back(row);
}
}
} catch(oracle::occi::SQLException &ex) {
baton->error = new std::string(ex.getMessage());
} catch(NodeOracleException &ex) {
baton->error = new std::string(ex.getMessage());
}

error:
if(stmt && rs) {
stmt->closeResultSet(rs);
}
Expand All @@ -205,7 +188,7 @@ void Connection::EIO_Execute(eio_req* req) {
}

int Connection::EIO_AfterExecute(eio_req* req) {
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
ExecuteBaton* baton = static_cast<ExecuteBaton*>(req->data);
ev_unref(EV_DEFAULT_UC);
baton->connection->Unref();

Expand Down Expand Up @@ -236,9 +219,7 @@ int Connection::EIO_AfterExecute(eio_req* req) {
}
}
rows->Set(index, obj);
delete currentRow;
}
delete baton->rows;
argv[1] = rows;
} else {
Local<Object> obj = Object::New();
Expand All @@ -252,23 +233,6 @@ int Connection::EIO_AfterExecute(eio_req* req) {
}
baton->callback->Call(Context::GetCurrent()->Global(), 2, argv);

baton->callback.Dispose();

for (std::vector<column_t*>::iterator iterator = baton->columns.begin(), end = baton->columns.end(); iterator != end; ++iterator) {
column_t* col = *iterator;
delete col;
}

for (std::vector<value_t*>::iterator iterator = baton->values.begin(), end = baton->values.end(); iterator != end; ++iterator) {
value_t* val = *iterator;
if(val->type == VALUE_TYPE_STRING) {
delete (std::string*)val->value;
}
delete val;
}

if(baton->error) delete baton->error;

delete baton;
return 0;
}
Expand Down
6 changes: 6 additions & 0 deletions src/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <unistd.h>
#include <occi.h>
#include "utils.h"
#include "nodeOracleException.h"
#include "executeBaton.h"

using namespace node;
using namespace v8;
Expand All @@ -28,6 +30,10 @@ class Connection : ObjectWrap {
void setConnection(oracle::occi::Environment* environment, oracle::occi::Connection* connection);

private:
static int SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<value_t*> &values);
static void CreateColumnsFromResultSet(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns);
static row_t* CreateRowFromCurrentResultSetRow(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns);

oracle::occi::Connection* m_connection;
oracle::occi::Environment* m_environment;
};
Expand Down
61 changes: 61 additions & 0 deletions src/executeBaton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

#include "executeBaton.h"
#include "outParam.h"
#include "nodeOracleException.h"

ExecuteBaton::ExecuteBaton(Connection* connection, const char* sql, v8::Local<v8::Array>* values, v8::Handle<v8::Function>* callback) {
this->connection = connection;
this->sql = sql;
this->callback = Persistent<Function>::New(*callback);
this->returnParam = NULL;
CopyValuesToBaton(this, values);
}

ExecuteBaton::~ExecuteBaton() {
callback.Dispose();

for (std::vector<column_t*>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator) {
column_t* col = *iterator;
delete col;
}

for (std::vector<value_t*>::iterator iterator = values.begin(), end = values.end(); iterator != end; ++iterator) {
value_t* val = *iterator;
if(val->type == VALUE_TYPE_STRING) {
delete (std::string*)val->value;
}
delete val;
}

if(rows) {
for (std::vector<row_t*>::iterator iterator = rows->begin(), end = rows->end(); iterator != end; ++iterator) {
row_t* currentRow = *iterator;
delete currentRow;
}
delete rows;
}

if(error) delete error;
}

void ExecuteBaton::CopyValuesToBaton(ExecuteBaton* baton, v8::Local<v8::Array>* values) {
for(uint32_t i=0; i<(*values)->Length(); i++) {
v8::Local<v8::Value> val = (*values)->Get(i);

value_t *value = new value_t();
if(val->IsString()) {
v8::String::AsciiValue asciiVal(val);
value->type = VALUE_TYPE_STRING;
value->value = new std::string(*asciiVal);
baton->values.push_back(value);
} else if(val->IsObject() && val->ToObject()->FindInstanceInPrototypeChain(OutParam::constructorTemplate) != v8::Null()) {
value->type = VALUE_TYPE_OUTPUT;
value->value = NULL;
baton->values.push_back(value);
} else {
std::ostringstream message;
message << "Unhandled value type";
throw NodeOracleException(message.str());
}
}
}
Loading

0 comments on commit 84cd071

Please sign in to comment.