Skip to content

Commit 43fee35

Browse files
committed
first commit
0 parents  commit 43fee35

13 files changed

+707
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
module.exports = require('./lib/oracle');

lib/oracle.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
var bindings = require("../build/Release/oracle_bindings");
3+
var oracle = new bindings.OracleClient();
4+
5+
exports.connect = function(settings, callback) {
6+
oracle.connect(settings, callback);
7+
}
8+
9+
exports.OutParam = bindings.OutParam;

src/connection.cpp

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
2+
#include "connection.h"
3+
#include "outParam.h"
4+
#include <vector>
5+
6+
Persistent<FunctionTemplate> Connection::constructorTemplate;
7+
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+
37+
void Connection::Init(Handle<Object> target) {
38+
HandleScope scope;
39+
40+
Local<FunctionTemplate> t = FunctionTemplate::New(New);
41+
constructorTemplate = Persistent<FunctionTemplate>::New(t);
42+
constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
43+
constructorTemplate->SetClassName(String::NewSymbol("Connection"));
44+
45+
NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "execute", Execute);
46+
NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "close", Close);
47+
48+
target->Set(String::NewSymbol("Connection"), constructorTemplate->GetFunction());
49+
}
50+
51+
Handle<Value> Connection::New(const Arguments& args) {
52+
HandleScope scope;
53+
54+
Connection *connection = new Connection();
55+
connection->Wrap(args.This());
56+
return args.This();
57+
}
58+
59+
Connection::Connection() {
60+
}
61+
62+
Connection::~Connection() {
63+
closeConnection();
64+
}
65+
66+
Handle<Value> Connection::Execute(const Arguments& args) {
67+
Connection* connection = ObjectWrap::Unwrap<Connection>(args.This());
68+
69+
REQ_STRING_ARG(0, sql);
70+
REQ_ARRAY_ARG(1, values);
71+
REQ_FUN_ARG(2, callback);
72+
73+
String::AsciiValue sqlVal(sql);
74+
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+
}
101+
}
102+
103+
eio_custom(EIO_Execute, EIO_PRI_DEFAULT, EIO_AfterExecute, baton);
104+
ev_ref(EV_DEFAULT_UC);
105+
106+
connection->Ref();
107+
108+
return Undefined();
109+
}
110+
111+
Handle<Value> Connection::Close(const Arguments& args) {
112+
Connection* connection = ObjectWrap::Unwrap<Connection>(args.This());
113+
connection->closeConnection();
114+
115+
return Undefined();
116+
}
117+
118+
void Connection::closeConnection() {
119+
if(m_environment && m_connection) {
120+
m_environment->terminateConnection(m_connection);
121+
m_connection = NULL;
122+
}
123+
}
124+
125+
void Connection::EIO_Execute(eio_req* req) {
126+
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
127+
128+
baton->rows = NULL;
129+
baton->error = NULL;
130+
131+
oracle::occi::Statement* stmt = NULL;
132+
oracle::occi::ResultSet* rs = NULL;
133+
try {
134+
//printf("%s\n", baton->sql.c_str());
135+
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+
}
153+
154+
int status = stmt->execute();
155+
if(status == oracle::occi::Statement::UPDATE_COUNT_AVAILABLE) {
156+
baton->updateCount = stmt->getUpdateCount();
157+
if(outputParam >= 0) {
158+
baton->returnParam = new int;
159+
*(baton->returnParam) = stmt->getInt(outputParam);
160+
}
161+
} else {
162+
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+
177+
baton->rows = new std::vector<row_t*>();
178+
179+
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+
}
191+
baton->rows->push_back(row);
192+
}
193+
}
194+
} catch(oracle::occi::SQLException &ex) {
195+
baton->error = new std::string(ex.getMessage());
196+
}
197+
198+
error:
199+
if(stmt && rs) {
200+
stmt->closeResultSet(rs);
201+
}
202+
if(stmt) {
203+
baton->connection->m_connection->terminateStatement(stmt);
204+
}
205+
}
206+
207+
int Connection::EIO_AfterExecute(eio_req* req) {
208+
execute_baton_t* baton = static_cast<execute_baton_t*>(req->data);
209+
ev_unref(EV_DEFAULT_UC);
210+
baton->connection->Unref();
211+
212+
Handle<Value> argv[2];
213+
if(baton->error) {
214+
argv[0] = Exception::Error(String::New(baton->error->c_str()));
215+
argv[1] = Undefined();
216+
} else {
217+
argv[0] = Undefined();
218+
219+
if(baton->rows) {
220+
size_t totalRows = baton->rows->size();
221+
Local<Array> rows = Array::New(totalRows);
222+
uint32_t index = 0;
223+
for (std::vector<row_t*>::iterator iterator = baton->rows->begin(), end = baton->rows->end(); iterator != end; ++iterator, index++) {
224+
row_t* currentRow = *iterator;
225+
Local<Object> obj = Object::New();
226+
uint32_t colIndex = 0;
227+
for (std::vector<column_t*>::iterator iterator = baton->columns.begin(), end = baton->columns.end(); iterator != end; ++iterator, colIndex++) {
228+
column_t* col = *iterator;
229+
void* val = currentRow->values[colIndex];
230+
switch(col->type) {
231+
case VALUE_TYPE_STRING:
232+
std::string* v = (std::string*)val;
233+
obj->Set(String::New(col->name.c_str()), String::New(v->c_str()));
234+
delete v;
235+
break;
236+
}
237+
}
238+
rows->Set(index, obj);
239+
delete currentRow;
240+
}
241+
delete baton->rows;
242+
argv[1] = rows;
243+
} else {
244+
Local<Object> obj = Object::New();
245+
obj->Set(String::New("updateCount"), Integer::New(baton->updateCount));
246+
if(baton->returnParam) {
247+
obj->Set(String::New("returnParam"), Integer::New(*baton->returnParam));
248+
delete baton->returnParam;
249+
}
250+
argv[1] = obj;
251+
}
252+
}
253+
baton->callback->Call(Context::GetCurrent()->Global(), 2, argv);
254+
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+
272+
delete baton;
273+
return 0;
274+
}
275+
276+
void Connection::setConnection(oracle::occi::Environment* environment, oracle::occi::Connection* connection) {
277+
m_environment = environment;
278+
m_connection = connection;
279+
}

src/connection.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
#ifndef _connection_h_
3+
#define _connection_h_
4+
5+
#include <v8.h>
6+
#include <node.h>
7+
#include <unistd.h>
8+
#include <occi.h>
9+
#include "utils.h"
10+
11+
using namespace node;
12+
using namespace v8;
13+
14+
class Connection : ObjectWrap {
15+
public:
16+
static void Init(Handle<Object> target);
17+
static Handle<Value> New(const Arguments& args);
18+
static Handle<Value> Execute(const Arguments& args);
19+
static Handle<Value> Close(const Arguments& args);
20+
static Persistent<FunctionTemplate> constructorTemplate;
21+
static void EIO_Execute(eio_req* req);
22+
static int EIO_AfterExecute(eio_req* req);
23+
void closeConnection();
24+
25+
Connection();
26+
~Connection();
27+
28+
void setConnection(oracle::occi::Environment* environment, oracle::occi::Connection* connection);
29+
30+
private:
31+
oracle::occi::Connection* m_connection;
32+
oracle::occi::Environment* m_environment;
33+
};
34+
35+
#endif

0 commit comments

Comments
 (0)