dbd/oracle/statement.c

changeset 17
21c4feaeafe7
child 18
b705ba343e94
equal deleted inserted replaced
16:318e5dfd03b8 17:21c4feaeafe7
1 #include "dbd_oracle.h"
2
3 /*
4 * Converts SQLite types to Lua types
5 */
6 static lua_push_type_t oracle_to_lua_push(unsigned int oracle_type, int null) {
7 lua_push_type_t lua_type;
8
9 if (null)
10 return LUA_PUSH_NIL;
11
12 switch(oracle_type) {
13 case SQLT_NUM:
14 case SQLT_FLT:
15 lua_type = LUA_PUSH_NUMBER;
16 break;
17 case SQLT_INT:
18 lua_type = LUA_PUSH_INTEGER;
19 break;
20 default:
21 lua_type = LUA_PUSH_STRING;
22 }
23
24 return lua_type;
25 }
26
27 /*
28 * success = statement:close()
29 */
30 int statement_close(lua_State *L) {
31 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_ORACLE_STATEMENT);
32 int ok = 0;
33
34 if (statement->stmt) {
35 int rc;
36
37 rc = OCIHandleFree((dvoid *)statement->stmt, OCI_HTYPE_STMT); /* Free handles */
38
39 statement->stmt = NULL;
40 }
41
42 lua_pushboolean(L, ok);
43 return 1;
44 }
45
46 /*
47 * success,err = statement:execute(...)
48 */
49 int statement_execute(lua_State *L) {
50 int n = lua_gettop(L);
51 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_ORACLE_STATEMENT);
52 int p;
53 int errflag = 0;
54 const char *errstr = NULL;
55 int expected_params;
56 int num_bind_params = n - 1;
57 int num_columns;
58 int rc;
59
60 char errbuf[100];
61 int errcode;
62
63 ub2 type;
64
65 if (!statement->stmt) {
66 lua_pushboolean(L, 0);
67 lua_pushstring(L, DBI_ERR_EXECUTE_INVALID);
68 return 2;
69 }
70
71 for (p = 2; p <= n; p++) {
72 int i = p - 1;
73 int type = lua_type(L, p);
74 char err[64];
75 const char *value;
76
77 OCIBind *bnd = (OCIBind *)0;
78
79 switch(type) {
80 case LUA_TNIL:
81 errflag = OCIBindByPos(
82 statement->stmt,
83 &bnd,
84 statement->conn->err,
85 i,
86 NULL,
87 0,
88 SQLT_CHR,
89 (dvoid *)0,
90 (ub2 *)0,
91 (ub2 *)0,
92 (ub4)0,
93 (ub4 *)0,
94 OCI_DEFAULT);
95 break;
96 case LUA_TNUMBER:
97 case LUA_TSTRING:
98 case LUA_TBOOLEAN:
99 value = lua_tostring(L, p);
100
101 errflag = OCIBindByPos(
102 statement->stmt,
103 &bnd,
104 statement->conn->err,
105 i,
106 value,
107 strlen(value),
108 SQLT_CHR,
109 (dvoid *)0,
110 (ub2 *)0,
111 (ub2 *)0,
112 (ub4)0,
113 (ub4 *)0,
114 (ub4)OCI_DEFAULT);
115 break;
116 default:
117 /*
118 * Unknown/unsupported value type
119 */
120 errflag = 1;
121 snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type));
122 errstr = err;
123 }
124
125 if (errflag)
126 break;
127 }
128
129 if (errflag) {
130 lua_pushboolean(L, 0);
131 if (errstr)
132 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr);
133 else {
134 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
135
136 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errbuf);
137 }
138
139 return 2;
140 }
141
142 /*
143 * statement type
144 */
145 rc = OCIAttrGet(
146 (dvoid *)statement->stmt,
147 (ub4)OCI_HTYPE_STMT,
148 (dvoid *)&type,
149 (ub4 *)0,
150 (ub4)OCI_ATTR_STMT_TYPE,
151 statement->conn->err
152 );
153
154 if (rc) {
155 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
156
157 lua_pushboolean(L, 0);
158 lua_pushfstring(L, "Error getting type: %s", errbuf);
159
160 return 2;
161 }
162
163 /*
164 * execute statement
165 */
166 rc = OCIStmtExecute(
167 statement->conn->svc,
168 statement->stmt,
169 statement->conn->err,
170 type == OCI_STMT_SELECT ? 0 : 1,
171 (ub4)0,
172 (CONST OCISnapshot *)NULL,
173 (OCISnapshot *)NULL,
174 statement->conn->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT
175 );
176
177 if (rc) {
178 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
179
180 lua_pushboolean(L, 0);
181 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errbuf);
182
183 return 2;
184 }
185
186 /*
187 * get number of columns
188 */
189 rc = OCIAttrGet(
190 (dvoid *)statement->stmt,
191 (ub4)OCI_HTYPE_STMT,
192 (dvoid *)&num_columns,
193 (ub4 *)0,
194 (ub4)OCI_ATTR_PARAM_COUNT,
195 statement->conn->err
196 );
197
198 if (rc) {
199 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
200
201 lua_pushboolean(L, 0);
202 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errbuf);
203
204 return 2;
205 }
206
207 statement->num_columns = num_columns;
208
209 lua_pushboolean(L, 1);
210 return 1;
211 }
212
213 /*
214 * must be called after an execute
215 */
216 static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) {
217 int rc;
218 sword status;
219 int i;
220 bindparams_t *bind;
221
222 char errbuf[100];
223 int errcode;
224
225 if (!statement->stmt) {
226 luaL_error(L, DBI_ERR_FETCH_INVALID);
227 return 0;
228 }
229
230 bind = (bindparams_t *)malloc(sizeof(bindparams_t) * statement->num_columns);
231 memset(bind, 0, sizeof(bindparams_t) * statement->num_columns);
232
233 for (i = 0; i < statement->num_columns; i++) {
234 rc = OCIParamGet(statement->stmt, OCI_HTYPE_STMT, statement->conn->err, (dvoid **)&bind[i].param, i+1);
235 if (rc) {
236 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
237 luaL_error(L, "param get %s", errbuf);
238 }
239
240 rc = OCIAttrGet(bind[i].param, OCI_DTYPE_PARAM, (dvoid *)&(bind[i].name), (ub4 *)&(bind[i].name_len), OCI_ATTR_NAME, statement->conn->err);
241 if (rc) {
242 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
243 luaL_error(L, "name get %s", errbuf);
244 }
245
246 rc = OCIAttrGet(bind[i].param, OCI_DTYPE_PARAM, (dvoid *)&(bind[i].data_type), (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->conn->err);
247 if (rc) {
248 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
249 luaL_error(L, "datatype get %s", errbuf);
250 }
251
252 rc = OCIAttrGet(bind[i].param, OCI_DTYPE_PARAM, (dvoid *)&(bind[i].max_len), 0, OCI_ATTR_DATA_SIZE, statement->conn->err);
253 if (rc) {
254 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
255 luaL_error(L, "datasize get %s", errbuf);
256 }
257
258 bind[i].data = calloc(bind[i].max_len+1, sizeof(char));
259 rc = OCIDefineByPos(statement->stmt, &bind[i].define, statement->conn->err, (ub4)i+1, bind[i].data, bind[i].max_len, SQLT_STR, (dvoid *)&(bind[i].null), (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT);
260 if (rc) {
261 OCIErrorGet((dvoid *)statement->conn->err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
262 luaL_error(L, "define by pos %s", errbuf);
263 }
264 }
265
266 status = OCIStmtFetch(statement->stmt, statement->conn->err, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
267
268 if (status == OCI_NO_DATA) {
269 /* No more rows */
270 lua_pushnil(L);
271 return 1;
272 } else if (status != OCI_SUCCESS) {
273 OCIErrorGet((dvoid *)statement->conn->err, (ub4)1, (text *)NULL, &errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
274 luaL_error(L, DBI_ERR_FETCH_FAILED, errbuf);
275 }
276
277 if (statement->num_columns) {
278 int i;
279 int d = 1;
280
281 lua_newtable(L);
282
283 for (i = 0; i < statement->num_columns; i++) {
284 lua_push_type_t lua_push = oracle_to_lua_push(bind[i].data_type, bind[i].null);
285 const char *name = strlower(bind[i].name);
286 const char *data = bind[i].data;
287
288 if (lua_push == LUA_PUSH_NIL) {
289 if (named_columns) {
290 LUA_PUSH_ATTRIB_NIL(name);
291 } else {
292 LUA_PUSH_ARRAY_NIL(d);
293 }
294 } else if (lua_push == LUA_PUSH_INTEGER) {
295 int val = atoi(data);
296
297 if (named_columns) {
298 LUA_PUSH_ATTRIB_INT(name, val);
299 } else {
300 LUA_PUSH_ARRAY_INT(d, val);
301 }
302 } else if (lua_push == LUA_PUSH_NUMBER) {
303 double val = strtod(data, NULL);
304
305 if (named_columns) {
306 LUA_PUSH_ATTRIB_FLOAT(name, val);
307 } else {
308 LUA_PUSH_ARRAY_FLOAT(d, val);
309 }
310 } else if (lua_push == LUA_PUSH_STRING) {
311 if (named_columns) {
312 LUA_PUSH_ATTRIB_STRING(name, data);
313 } else {
314 LUA_PUSH_ARRAY_STRING(d, data);
315 }
316 } else if (lua_push == LUA_PUSH_BOOLEAN) {
317 int val = 1;
318
319 if (named_columns) {
320 LUA_PUSH_ATTRIB_BOOL(name, val);
321 } else {
322 LUA_PUSH_ARRAY_BOOL(d, val);
323 }
324 } else {
325 luaL_error(L, DBI_ERR_UNKNOWN_PUSH);
326 }
327 }
328 } else {
329 /*
330 * no columns returned by statement?
331 */
332 lua_pushnil(L);
333 }
334
335 return 1;
336 }
337
338 static int next_iterator(lua_State *L) {
339 statement_t *statement = (statement_t *)luaL_checkudata(L, lua_upvalueindex(1), DBD_ORACLE_STATEMENT);
340 int named_columns = lua_toboolean(L, lua_upvalueindex(2));
341
342 return statement_fetch_impl(L, statement, named_columns);
343 }
344
345 /*
346 * table = statement:fetch(named_indexes)
347 */
348 static int statement_fetch(lua_State *L) {
349 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_ORACLE_STATEMENT);
350 int named_columns = lua_toboolean(L, 2);
351
352 return statement_fetch_impl(L, statement, named_columns);
353 }
354
355 /*
356 * iterfunc = statement:rows(named_indexes)
357 */
358 static int statement_rows(lua_State *L) {
359 if (lua_gettop(L) == 1) {
360 lua_pushvalue(L, 1);
361 lua_pushboolean(L, 0);
362 } else {
363 lua_pushvalue(L, 1);
364 lua_pushboolean(L, lua_toboolean(L, 2));
365 }
366
367 lua_pushcclosure(L, next_iterator, 2);
368 return 1;
369 }
370
371 /*
372 * __gc
373 */
374 static int statement_gc(lua_State *L) {
375 /* always free the handle */
376 statement_close(L);
377
378 return 0;
379 }
380
381 int dbd_oracle_statement_create(lua_State *L, connection_t *conn, const char *sql_query) {
382 int rc;
383 statement_t *statement = NULL;
384 OCIStmt *stmt;
385 char *new_sql;
386
387 /*
388 * convert SQL string into a Oracle API compatible SQL statement
389 */
390 new_sql = replace_placeholders(L, ':', sql_query);
391
392 rc = OCIHandleAlloc((dvoid *)conn->oracle, (dvoid **)&stmt, OCI_HTYPE_STMT, 0, (dvoid **)0);
393 rc = OCIStmtPrepare(stmt, conn->err, new_sql, strlen(new_sql), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);
394
395 free(new_sql);
396
397 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t));
398 statement->conn = conn;
399 statement->stmt = stmt;
400 statement->num_columns = 0;
401
402 luaL_getmetatable(L, DBD_ORACLE_STATEMENT);
403 lua_setmetatable(L, -2);
404
405 return 1;
406 }
407
408 int dbd_oracle_statement(lua_State *L) {
409 static const luaL_Reg statement_methods[] = {
410 {"close", statement_close},
411 {"execute", statement_execute},
412 {"fetch", statement_fetch},
413 {"rows", statement_rows},
414 {NULL, NULL}
415 };
416
417 static const luaL_Reg statement_class_methods[] = {
418 {NULL, NULL}
419 };
420
421 luaL_newmetatable(L, DBD_ORACLE_STATEMENT);
422 luaL_register(L, 0, statement_methods);
423 lua_pushvalue(L,-1);
424 lua_setfield(L, -2, "__index");
425
426 lua_pushcfunction(L, statement_gc);
427 lua_setfield(L, -2, "__gc");
428
429 luaL_register(L, DBD_ORACLE_STATEMENT, statement_class_methods);
430
431 return 1;
432 }

mercurial