Skip to content

Commit 84cd071

Browse files
committed
refactored baton to new file
1 parent 8bc49d3 commit 84cd071

File tree

6 files changed

+223
-120
lines changed

6 files changed

+223
-120
lines changed

src/connection.cpp

Lines changed: 83 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,6 @@
55

66
Persistent<FunctionTemplate> Connection::constructorTemplate;
77

8-
#define VALUE_TYPE_OUTPUT 1
9-
#define VALUE_TYPE_STRING 2
10-
11-
struct column_t {
12-
int type;
13-
std::string name;
14-
};
15-
16-
struct row_t {
17-
std::vector<void*> values;
18-
};
19-
20-
struct value_t {
21-
int type;
22-
void* value;
23-
};
24-
25-
struct execute_baton_t {
26-
Connection *connection;
27-
Persistent<Function> callback;
28-
std::vector<value_t*> values;
29-
std::string sql;
30-
std::vector<column_t*> columns;
31-
std::vector<row_t*>* rows;
32-
std::string* error;
33-
int updateCount;
34-
int* returnParam;
35-
};
36-
378
void Connection::Init(Handle<Object> target) {
389
HandleScope scope;
3910

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

7344
String::AsciiValue sqlVal(sql);
7445

75-
execute_baton_t* baton = new execute_baton_t();
76-
baton->connection = connection;
77-
baton->sql = *sqlVal;
78-
baton->callback = Persistent<Function>::New(callback);
79-
baton->returnParam = NULL;
80-
81-
for(uint32_t i=0; i<values->Length(); i++) {
82-
Local<Value> val = values->Get(i);
83-
84-
value_t *value = new value_t();
85-
if(val->IsString()) {
86-
String::AsciiValue asciiVal(val);
87-
value->type = VALUE_TYPE_STRING;
88-
value->value = new std::string(*asciiVal);
89-
baton->values.push_back(value);
90-
} else if(val->IsObject() && val->ToObject()->FindInstanceInPrototypeChain(OutParam::constructorTemplate) != Null()) {
91-
value->type = VALUE_TYPE_OUTPUT;
92-
value->value = NULL;
93-
baton->values.push_back(value);
94-
} else {
95-
Handle<Value> argv[2];
96-
argv[0] = Exception::Error(String::New("unhandled value type"));
97-
argv[1] = Undefined();
98-
baton->callback->Call(Context::GetCurrent()->Global(), 2, argv);
99-
return Undefined();
100-
}
46+
ExecuteBaton* baton;
47+
try {
48+
baton = new ExecuteBaton(connection, *sqlVal, &values, &callback);
49+
} catch(NodeOracleException &ex) {
50+
Handle<Value> argv[2];
51+
argv[0] = Exception::Error(String::New(ex.getMessage().c_str()));
52+
argv[1] = Undefined();
53+
callback->Call(Context::GetCurrent()->Global(), 2, argv);
54+
return Undefined();
10155
}
10256

10357
eio_custom(EIO_Execute, EIO_PRI_DEFAULT, EIO_AfterExecute, baton);
@@ -122,8 +76,75 @@ void Connection::closeConnection() {
12276
}
12377
}
12478

79+
int Connection::SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<value_t*> &values) {
80+
uint32_t index = 1;
81+
int outputParam = -1;
82+
for (std::vector<value_t*>::iterator iterator = values.begin(), end = values.end(); iterator != end; ++iterator, index++) {
83+
value_t* val = *iterator;
84+
switch(val->type) {
85+
case VALUE_TYPE_STRING:
86+
stmt->setString(index, *((std::string*)val->value));
87+
break;
88+
case VALUE_TYPE_OUTPUT:
89+
stmt->registerOutParam(index, oracle::occi::OCCIINT);
90+
outputParam = index;
91+
break;
92+
default:
93+
throw NodeOracleException("Unhandled value type");
94+
}
95+
}
96+
return outputParam;
97+
}
98+
99+
void Connection::CreateColumnsFromResultSet(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns) {
100+
std::vector<oracle::occi::MetaData> metadata = rs->getColumnListMetaData();
101+
for (std::vector<oracle::occi::MetaData>::iterator iterator = metadata.begin(), end = metadata.end(); iterator != end; ++iterator) {
102+
oracle::occi::MetaData metadata = *iterator;
103+
column_t* col = new column_t();
104+
col->name = metadata.getString(oracle::occi::MetaData::ATTR_NAME);
105+
int type = metadata.getInt(oracle::occi::MetaData::ATTR_DATA_TYPE);
106+
switch(type) {
107+
case oracle::occi::OCCI_TYPECODE_NUMBER:
108+
col->type = VALUE_TYPE_NUMBER;
109+
break;
110+
case oracle::occi::OCCI_TYPECODE_VARCHAR2:
111+
case oracle::occi::OCCI_TYPECODE_VARCHAR:
112+
col->type = VALUE_TYPE_STRING;
113+
break;
114+
default:
115+
std::ostringstream message;
116+
message << "Unhandled oracle data type: " << type;
117+
throw NodeOracleException(message.str());
118+
break;
119+
}
120+
columns.push_back(col);
121+
}
122+
}
123+
124+
row_t* Connection::CreateRowFromCurrentResultSetRow(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns) {
125+
row_t* row = new row_t();
126+
int colIndex = 1;
127+
for (std::vector<column_t*>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator, colIndex++) {
128+
column_t* col = *iterator;
129+
switch(col->type) {
130+
case VALUE_TYPE_STRING:
131+
row->values.push_back(new std::string(rs->getString(colIndex)));
132+
break;
133+
case VALUE_TYPE_NUMBER:
134+
row->values.push_back(new oracle::occi::Number(rs->getNumber(colIndex)));
135+
break;
136+
default:
137+
std::ostringstream message;
138+
message << "Unhandled type: " << col->type;
139+
throw NodeOracleException(message.str());
140+
break;
141+
}
142+
}
143+
return row;
144+
}
145+
125146
void Connection::EIO_Execute(eio_req* req) {
126-
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
147+
ExecuteBaton* baton = static_cast<ExecuteBaton*>(req->data);
127148

128149
baton->rows = NULL;
129150
baton->error = NULL;
@@ -133,23 +154,7 @@ void Connection::EIO_Execute(eio_req* req) {
133154
try {
134155
//printf("%s\n", baton->sql.c_str());
135156
stmt = baton->connection->m_connection->createStatement(baton->sql);
136-
uint32_t index = 1;
137-
int outputParam = -1;
138-
for (std::vector<value_t*>::iterator iterator = baton->values.begin(), end = baton->values.end(); iterator != end; ++iterator, index++) {
139-
value_t* val = *iterator;
140-
switch(val->type) {
141-
case VALUE_TYPE_STRING:
142-
stmt->setString(index, *((std::string*)val->value));
143-
break;
144-
case VALUE_TYPE_OUTPUT:
145-
stmt->registerOutParam(index, oracle::occi::OCCIINT);
146-
outputParam = index;
147-
break;
148-
default:
149-
baton->error = new std::string("unhandled value type");
150-
goto error;
151-
}
152-
}
157+
int outputParam = SetValuesOnStatement(stmt, baton->values);
153158

154159
int status = stmt->execute();
155160
if(status == oracle::occi::Statement::UPDATE_COUNT_AVAILABLE) {
@@ -160,42 +165,20 @@ void Connection::EIO_Execute(eio_req* req) {
160165
}
161166
} else {
162167
rs = stmt->executeQuery();
163-
std::vector<oracle::occi::MetaData> columns = rs->getColumnListMetaData();
164-
for (std::vector<oracle::occi::MetaData>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator) {
165-
oracle::occi::MetaData metadata = *iterator;
166-
column_t* col = new column_t();
167-
col->name = metadata.getString(oracle::occi::MetaData::ATTR_NAME);
168-
int type = metadata.getInt(oracle::occi::MetaData::ATTR_DATA_TYPE);
169-
switch(type) {
170-
default:
171-
col->type = VALUE_TYPE_STRING;
172-
break;
173-
}
174-
baton->columns.push_back(col);
175-
}
176-
168+
CreateColumnsFromResultSet(rs, baton->columns);
177169
baton->rows = new std::vector<row_t*>();
178170

179171
while(rs->next()) {
180-
row_t* row = new row_t();
181-
int colIndex = 1;
182-
for (std::vector<column_t*>::iterator iterator = baton->columns.begin(), end = baton->columns.end(); iterator != end; ++iterator, colIndex++) {
183-
column_t* col = *iterator;
184-
switch(col->type) {
185-
default:
186-
case VALUE_TYPE_STRING:
187-
row->values.push_back(new std::string(rs->getString(colIndex)));
188-
break;
189-
}
190-
}
172+
row_t* row = CreateRowFromCurrentResultSetRow(rs, baton->columns);
191173
baton->rows->push_back(row);
192174
}
193175
}
194176
} catch(oracle::occi::SQLException &ex) {
195177
baton->error = new std::string(ex.getMessage());
178+
} catch(NodeOracleException &ex) {
179+
baton->error = new std::string(ex.getMessage());
196180
}
197181

198-
error:
199182
if(stmt && rs) {
200183
stmt->closeResultSet(rs);
201184
}
@@ -205,7 +188,7 @@ void Connection::EIO_Execute(eio_req* req) {
205188
}
206189

207190
int Connection::EIO_AfterExecute(eio_req* req) {
208-
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
191+
ExecuteBaton* baton = static_cast<ExecuteBaton*>(req->data);
209192
ev_unref(EV_DEFAULT_UC);
210193
baton->connection->Unref();
211194

@@ -236,9 +219,7 @@ int Connection::EIO_AfterExecute(eio_req* req) {
236219
}
237220
}
238221
rows->Set(index, obj);
239-
delete currentRow;
240222
}
241-
delete baton->rows;
242223
argv[1] = rows;
243224
} else {
244225
Local<Object> obj = Object::New();
@@ -252,23 +233,6 @@ int Connection::EIO_AfterExecute(eio_req* req) {
252233
}
253234
baton->callback->Call(Context::GetCurrent()->Global(), 2, argv);
254235

255-
baton->callback.Dispose();
256-
257-
for (std::vector<column_t*>::iterator iterator = baton->columns.begin(), end = baton->columns.end(); iterator != end; ++iterator) {
258-
column_t* col = *iterator;
259-
delete col;
260-
}
261-
262-
for (std::vector<value_t*>::iterator iterator = baton->values.begin(), end = baton->values.end(); iterator != end; ++iterator) {
263-
value_t* val = *iterator;
264-
if(val->type == VALUE_TYPE_STRING) {
265-
delete (std::string*)val->value;
266-
}
267-
delete val;
268-
}
269-
270-
if(baton->error) delete baton->error;
271-
272236
delete baton;
273237
return 0;
274238
}

src/connection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <unistd.h>
88
#include <occi.h>
99
#include "utils.h"
10+
#include "nodeOracleException.h"
11+
#include "executeBaton.h"
1012

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

3032
private:
33+
static int SetValuesOnStatement(oracle::occi::Statement* stmt, std::vector<value_t*> &values);
34+
static void CreateColumnsFromResultSet(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns);
35+
static row_t* CreateRowFromCurrentResultSetRow(oracle::occi::ResultSet* rs, std::vector<column_t*> &columns);
36+
3137
oracle::occi::Connection* m_connection;
3238
oracle::occi::Environment* m_environment;
3339
};

src/executeBaton.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
#include "executeBaton.h"
3+
#include "outParam.h"
4+
#include "nodeOracleException.h"
5+
6+
ExecuteBaton::ExecuteBaton(Connection* connection, const char* sql, v8::Local<v8::Array>* values, v8::Handle<v8::Function>* callback) {
7+
this->connection = connection;
8+
this->sql = sql;
9+
this->callback = Persistent<Function>::New(*callback);
10+
this->returnParam = NULL;
11+
CopyValuesToBaton(this, values);
12+
}
13+
14+
ExecuteBaton::~ExecuteBaton() {
15+
callback.Dispose();
16+
17+
for (std::vector<column_t*>::iterator iterator = columns.begin(), end = columns.end(); iterator != end; ++iterator) {
18+
column_t* col = *iterator;
19+
delete col;
20+
}
21+
22+
for (std::vector<value_t*>::iterator iterator = values.begin(), end = values.end(); iterator != end; ++iterator) {
23+
value_t* val = *iterator;
24+
if(val->type == VALUE_TYPE_STRING) {
25+
delete (std::string*)val->value;
26+
}
27+
delete val;
28+
}
29+
30+
if(rows) {
31+
for (std::vector<row_t*>::iterator iterator = rows->begin(), end = rows->end(); iterator != end; ++iterator) {
32+
row_t* currentRow = *iterator;
33+
delete currentRow;
34+
}
35+
delete rows;
36+
}
37+
38+
if(error) delete error;
39+
}
40+
41+
void ExecuteBaton::CopyValuesToBaton(ExecuteBaton* baton, v8::Local<v8::Array>* values) {
42+
for(uint32_t i=0; i<(*values)->Length(); i++) {
43+
v8::Local<v8::Value> val = (*values)->Get(i);
44+
45+
value_t *value = new value_t();
46+
if(val->IsString()) {
47+
v8::String::AsciiValue asciiVal(val);
48+
value->type = VALUE_TYPE_STRING;
49+
value->value = new std::string(*asciiVal);
50+
baton->values.push_back(value);
51+
} else if(val->IsObject() && val->ToObject()->FindInstanceInPrototypeChain(OutParam::constructorTemplate) != v8::Null()) {
52+
value->type = VALUE_TYPE_OUTPUT;
53+
value->value = NULL;
54+
baton->values.push_back(value);
55+
} else {
56+
std::ostringstream message;
57+
message << "Unhandled value type";
58+
throw NodeOracleException(message.str());
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)