5
5
6
6
Persistent<FunctionTemplate> Connection::constructorTemplate;
7
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
8
void Connection::Init (Handle<Object> target) {
38
9
HandleScope scope;
39
10
@@ -72,32 +43,15 @@ Handle<Value> Connection::Execute(const Arguments& args) {
72
43
73
44
String::AsciiValue sqlVal (sql);
74
45
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 ();
101
55
}
102
56
103
57
eio_custom (EIO_Execute, EIO_PRI_DEFAULT, EIO_AfterExecute, baton);
@@ -122,8 +76,75 @@ void Connection::closeConnection() {
122
76
}
123
77
}
124
78
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
+
125
146
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 );
127
148
128
149
baton->rows = NULL ;
129
150
baton->error = NULL ;
@@ -133,23 +154,7 @@ void Connection::EIO_Execute(eio_req* req) {
133
154
try {
134
155
// printf("%s\n", baton->sql.c_str());
135
156
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 );
153
158
154
159
int status = stmt->execute ();
155
160
if (status == oracle::occi::Statement::UPDATE_COUNT_AVAILABLE) {
@@ -160,42 +165,20 @@ void Connection::EIO_Execute(eio_req* req) {
160
165
}
161
166
} else {
162
167
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 );
177
169
baton->rows = new std::vector<row_t *>();
178
170
179
171
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 );
191
173
baton->rows ->push_back (row);
192
174
}
193
175
}
194
176
} catch (oracle::occi::SQLException &ex) {
195
177
baton->error = new std::string (ex.getMessage ());
178
+ } catch (NodeOracleException &ex) {
179
+ baton->error = new std::string (ex.getMessage ());
196
180
}
197
181
198
- error:
199
182
if (stmt && rs) {
200
183
stmt->closeResultSet (rs);
201
184
}
@@ -205,7 +188,7 @@ void Connection::EIO_Execute(eio_req* req) {
205
188
}
206
189
207
190
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 );
209
192
ev_unref (EV_DEFAULT_UC);
210
193
baton->connection ->Unref ();
211
194
@@ -236,9 +219,7 @@ int Connection::EIO_AfterExecute(eio_req* req) {
236
219
}
237
220
}
238
221
rows->Set (index, obj);
239
- delete currentRow;
240
222
}
241
- delete baton->rows ;
242
223
argv[1 ] = rows;
243
224
} else {
244
225
Local<Object> obj = Object::New ();
@@ -252,23 +233,6 @@ int Connection::EIO_AfterExecute(eio_req* req) {
252
233
}
253
234
baton->callback ->Call (Context::GetCurrent ()->Global (), 2 , argv);
254
235
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
236
delete baton;
273
237
return 0 ;
274
238
}
0 commit comments