1 #include "dbd_db2.h" 2 #include "db2_common.h" 3 4 #define BIND_BUFFER_SIZE 1024 5 6 static lua_push_type_t db2_to_lua_push(unsigned int db2_type) { 7 lua_push_type_t lua_type; 8 9 switch(db2_type) { 10 case SQL_BOOLEAN: 11 lua_type = LUA_PUSH_BOOLEAN; 12 case SQL_SMALLINT: 13 case SQL_INTEGER: 14 lua_type = LUA_PUSH_INTEGER; 15 break; 16 case SQL_FLOAT: 17 case SQL_REAL: 18 case SQL_DOUBLE: 19 case SQL_DECIMAL: 20 lua_type = LUA_PUSH_NUMBER; 21 break; 22 break; 23 default: 24 lua_type = LUA_PUSH_STRING; 25 } 26 27 return lua_type; 28 } 29 30 /* 31 * num_affected_rows = statement:affected() 32 */ 33 static int statement_affected(lua_State *L) { 34 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 35 SQLINTEGER affected; 36 37 if (!statement->stmt) { 38 luaL_error(L, DBI_ERR_INVALID_STATEMENT); 39 } 40 41 (void)SQLRowCount(statement->stmt, &affected); 42 43 lua_pushinteger(L, affected); 44 45 return 1; 46 } 47 48 /* 49 * free cursor and associated memory STR2REAL(const std::string & s)50 */ 51 static void free_cursor(statement_t *statement) { 52 if (statement->cursor_open) { 53 SQLFreeStmt(statement->stmt, SQL_CLOSE); 54 statement->cursor_open = 0; 55 } 56 } 57 58 /* 59 * success = statement:close() 60 */ 61 static int statement_close(lua_State *L) { 62 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 63 64 free_cursor(statement); 65 66 if (statement->resultset) { 67 free(statement->resultset); 68 statement->resultset = NULL; 69 } 70 JSONUIDecoderJSONUIDecoder71 if (statement->parambuf) { 72 free(statement->parambuf); 73 statement->parambuf = NULL; 74 } 75 76 statement->num_result_columns = 0; 77 78 if (statement->stmt) { 79 SQLFreeHandle(SQL_HANDLE_STMT, statement->stmt); 80 statement->stmt = SQL_NULL_HSTMT; 81 } 82 83 return 0; 84 } 85 86 /* 87 * column_names = statement:columns() 88 */ 89 static int statement_columns(lua_State *L) { 90 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 91 92 int i; 93 int d; 94 95 if (!statement->resultset) { 96 lua_pushnil(L); 97 return 1; 98 } 99 100 d = 1; 101 lua_newtable(L); 102 for (i = 0; i < statement->num_result_columns; i++) { 103 const char *name = dbd_strlower((char *)statement->resultset[i].name); 104 LUA_PUSH_ARRAY_STRING(d, name); 105 } 106 107 return 1; 108 } 109 110 /* 111 * success = statement:execute(...) 112 */ 113 static int statement_execute(lua_State *L) { 114 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 115 int n = lua_gettop(L); ~JSONUIDecoderJSONUIDecoder116 int p; 117 int errflag = 0; 118 const char *errstr = NULL; 119 SQLRETURN rc = SQL_SUCCESS; 120 unsigned char *buffer = statement->parambuf; 121 int offset = 0; 122 123 SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1]; 124 125 if (!statement->stmt) { metadataJSONUIDecoder126 lua_pushboolean(L, 0); 127 lua_pushstring(L, DBI_ERR_EXECUTE_INVALID); 128 return 2; 129 } 130 131 /* If the cursor is open from a previous execute, close it */ 132 free_cursor(statement); 133 buildUserInterfaceJSONUIDecoder134 if (statement->num_params != n-1) { 135 /* 136 * SQLExecute does not handle this condition, 137 * and the client library will fill unset params 138 * with NULLs 139 */ 140 lua_pushboolean(L, 0); 141 lua_pushfstring(L, DBI_ERR_PARAM_MISCOUNT, statement->num_params, n-1); 142 return 2; 143 } 144 145 for (p = 2; p <= n; p++) { 146 int i = p - 1; 147 int type = lua_type(L, p); 148 char err[64]; 149 const char *str = NULL; 150 size_t len = 0; 151 double *num; 152 int *boolean; 153 const static SQLLEN nullvalue = SQL_NULL_DATA; 154 155 switch(type) { 156 case LUA_TNIL: 157 rc = SQLBindParameter(statement->stmt, i, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)0, 0, (SQLPOINTER)&nullvalue); 158 errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO; 159 break; 160 case LUA_TNUMBER: 161 num = (double *)(buffer + offset); 162 *num = lua_tonumber(L, p); 163 offset += sizeof(double); 164 rc = SQLBindParameter(statement->stmt, i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DECIMAL, 10, 0, (SQLPOINTER)num, 0, NULL); 165 errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO; 166 break; 167 case LUA_TSTRING: 168 str = lua_tolstring(L, p, &len); 169 rc = SQLBindParameter(statement->stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, (SQLPOINTER)str, len, NULL); 170 errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO; 171 break; 172 case LUA_TBOOLEAN: 173 boolean = (int *)(buffer + offset); 174 *boolean = lua_toboolean(L, p); 175 offset += sizeof(int); 176 rc = SQLBindParameter(statement->stmt, i, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)boolean, len, NULL); 177 errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO; 178 break; 179 default: 180 /* 181 * Unknown/unsupported value type 182 */ 183 errflag = 1; 184 snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type)); 185 errstr = err; 186 } 187 188 if (errflag) 189 break; 190 } 191 192 if (errflag) { 193 lua_pushboolean(L, 0); 194 195 if (errstr) { 196 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr); 197 } else { 198 db2_stmt_diag(statement->stmt, message, sizeof(message)); 199 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, message); 200 } 201 202 return 2; 203 } 204 205 rc = SQLExecute(statement->stmt); 206 if (rc != SQL_SUCCESS) { 207 db2_stmt_diag(statement->stmt, message, sizeof(message)); 208 lua_pushnil(L); 209 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, message); 210 return 2; 211 } 212 213 statement->cursor_open = 1; 214 215 lua_pushboolean(L, 1); 216 return 1; 217 } 218 219 220 221 /* 222 * must be called after an execute 223 */ 224 static int statement_fetch_impl(lua_State *L, statement_t *statement, 225 int named_columns) { 226 int i; 227 int d; 228 229 SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1]; 230 SQLRETURN rc; 231 232 if (!statement->cursor_open) 233 goto nodata; 234 proxy_dsp(const string & json)235 /* fetch each row, and display */ 236 rc = SQLFetch(statement->stmt); 237 if (rc == SQL_NO_DATA_FOUND) { 238 free_cursor(statement); 239 goto nodata; 240 } proxy_dsp(dsp * dsp)241 242 if (rc != SQL_SUCCESS) { 243 db2_stmt_diag(statement->stmt, message, sizeof(message)); 244 luaL_error(L, DBI_ERR_FETCH_FAILED, message); 245 } 246 247 d = 1; 248 lua_newtable(L); 249 for (i = 0; i < statement->num_result_columns; i++) { ~proxy_dsp()250 resultset_t *rs = &statement->resultset[i]; 251 SQLCHAR *name = rs->name; 252 lua_push_type_t lua_type = rs->lua_type; 253 resultset_data_t *data = &(rs->data); 254 getNumInputs()255 if (rs->actual_len == SQL_NULL_DATA) 256 lua_type = LUA_PUSH_NIL; 257 buildUserInterface(UI * ui)258 if (named_columns) 259 lua_pushstring(L, (const char *)name); 260 init(int samplingRate)261 switch (lua_type) { 262 case LUA_PUSH_NIL: 263 lua_pushnil(L); 264 break; 265 case LUA_PUSH_INTEGER: 266 lua_pushinteger(L, data->integer); 267 break; 268 case LUA_PUSH_NUMBER: 269 lua_pushnumber(L, data->number); 270 break; 271 case LUA_PUSH_BOOLEAN: 272 lua_pushboolean(L, data->boolean); 273 break; 274 case LUA_PUSH_STRING: 275 lua_pushstring(L, (const char *)data->str); 276 break; 277 default: 278 luaL_error(L, DBI_ERR_UNKNOWN_PUSH); 279 } 280 281 if (named_columns) 282 lua_rawset(L, -3); 283 else { 284 lua_rawseti(L, -2, d); 285 d++; 286 } 287 } 288 289 return 1; 290 nodata: 291 lua_pushnil(L); 292 return 1; 293 } 294 295 296 static int next_iterator(lua_State *L) { 297 statement_t *statement = (statement_t *)luaL_checkudata(L, lua_upvalueindex(1), DBD_DB2_STATEMENT); 298 int named_columns = lua_toboolean(L, lua_upvalueindex(2)); 299 300 return statement_fetch_impl(L, statement, named_columns); 301 } 302 303 /* 304 * table = statement:fetch(named_indexes) 305 */ 306 static int statement_fetch(lua_State *L) { 307 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 308 int named_columns = lua_toboolean(L, 2); 309 310 return statement_fetch_impl(L, statement, named_columns); 311 } 312 313 /* 314 * num_rows = statement:rowcount() 315 */ 316 static int statement_rowcount(lua_State *L) { 317 luaL_error(L, DBI_ERR_NOT_IMPLEMENTED, DBD_DB2_STATEMENT, "rowcount"); 318 319 return 0; 320 } 321 322 /* 323 * iterfunc = statement:rows(named_indexes) 324 */ 325 static int statement_rows(lua_State *L) { 326 if (lua_gettop(L) == 1) { 327 lua_pushvalue(L, 1); 328 lua_pushboolean(L, 0); 329 } else { 330 lua_pushvalue(L, 1); 331 lua_pushboolean(L, lua_toboolean(L, 2)); 332 } 333 334 lua_pushcclosure(L, next_iterator, 2); 335 return 1; 336 } 337 338 /* 339 * __gc 340 */ 341 static int statement_gc(lua_State *L) { 342 /* always free the handle */ 343 statement_close(L); 344 345 return 0; 346 } 347 348 /* 349 * __tostring 350 */ 351 static int statement_tostring(lua_State *L) { 352 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT); 353 354 lua_pushfstring(L, "%s: %p", DBD_DB2_STATEMENT, statement); 355 356 return 1; 357 } 358 359 int dbd_db2_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { 360 SQLRETURN rc = SQL_SUCCESS; 361 statement_t *statement = NULL; 362 SQLHANDLE stmt; 363 SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1]; 364 SQLCHAR *buffer = NULL; 365 int buflen; 366 SQLSMALLINT sqlctype; 367 SQLPOINTER dataptr; 368 int datalen; 369 370 resultset_t *resultset = NULL; 371 int i; 372 373 rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->db2, &stmt); 374 if (rc != SQL_SUCCESS) { 375 db2_dbc_diag(conn->db2, message, sizeof(message)); 376 lua_pushnil(L); 377 lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, message); 378 return 2; 379 } 380 381 /* 382 * turn off deferred prepare 383 * statements will be sent to the server at prepare time, 384 * and therefore we can catch errors now rather 385 * than at execute time 386 */ 387 rc = SQLSetStmtAttr(stmt,SQL_ATTR_DEFERRED_PREPARE,(SQLPOINTER)SQL_DEFERRED_PREPARE_OFF,0); 388 389 rc = SQLPrepare(stmt, (SQLCHAR *)sql_query, SQL_NTS); 390 if (rc != SQL_SUCCESS) { 391 db2_stmt_diag(stmt, message, sizeof(message)); 392 lua_pushnil(L); 393 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, message); 394 return 2; 395 } 396 397 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); 398 statement->stmt = stmt; 399 statement->db2 = conn->db2; 400 statement->resultset = NULL; 401 statement->cursor_open = 0; 402 statement->num_params = 0; 403 statement->parambuf = NULL; 404 405 /* 406 * identify the number of input parameters 407 */ 408 rc = SQLNumParams(stmt, &statement->num_params); 409 if (rc != SQL_SUCCESS) { 410 db2_stmt_diag(stmt, message, sizeof(message)); 411 lua_pushboolean(L, 0); 412 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, message); 413 return 2; 414 } 415 if (statement->num_params > 0) { 416 statement->parambuf = (unsigned char *)malloc(sizeof(double) * 417 statement->num_params); 418 } 419 420 /* 421 * identify the number of output columns 422 */ 423 rc = SQLNumResultCols(stmt, &statement->num_result_columns); 424 425 if (statement->num_result_columns > 0) { 426 resultset = (resultset_t *)malloc(sizeof(resultset_t) * 427 statement->num_result_columns); 428 memset(resultset, 0, sizeof(resultset_t) * 429 statement->num_result_columns); 430 431 buflen = 0; 432 for (i = 0; i < statement->num_result_columns; i++) { 433 /* 434 * return a set of attributes for a column 435 */ 436 rc = SQLDescribeCol(stmt, 437 (SQLSMALLINT)(i + 1), 438 resultset[i].name, 439 sizeof(resultset[i].name), 440 &resultset[i].name_len, 441 &resultset[i].type, 442 &resultset[i].size, 443 &resultset[i].scale, 444 NULL); 445 446 if (rc != SQL_SUCCESS) { 447 db2_stmt_diag(stmt, message, sizeof(message)); 448 lua_pushnil(L); 449 lua_pushfstring(L, DBI_ERR_DESC_RESULT, message); 450 return 2; 451 } 452 453 resultset[i].lua_type = db2_to_lua_push(resultset[i].type); 454 if (resultset[i].lua_type == LUA_PUSH_STRING) 455 buflen += (resultset[i].size + 1 + 3) & ~3; 456 } 457 458 if (buflen > 0) 459 buffer = malloc(buflen); 460 461 for (i = 0; i < statement->num_result_columns; i++) { 462 switch (resultset[i].lua_type) { 463 case LUA_PUSH_INTEGER: 464 sqlctype = SQL_C_LONG; 465 dataptr = &resultset[i].data.integer; 466 datalen = 0; 467 break; 468 case LUA_PUSH_NUMBER: 469 sqlctype = SQL_C_DOUBLE; 470 dataptr = &resultset[i].data.number; 471 datalen = 0; 472 break; 473 default: 474 sqlctype = SQL_C_CHAR; 475 resultset[i].data.str = buffer; 476 dataptr = buffer; 477 datalen = resultset[i].size + 1; 478 buffer += (datalen + 3) & ~3; 479 break; 480 } 481 482 rc = SQLBindCol(stmt, 483 (SQLSMALLINT)(i + 1), 484 sqlctype, 485 dataptr, 486 datalen, 487 &resultset[i].actual_len); 488 489 if (rc != SQL_SUCCESS) { 490 db2_stmt_diag(stmt, message, sizeof(message)); 491 lua_pushnil(L); 492 lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, message); 493 return 2; 494 } 495 } 496 497 statement->resultset = resultset; 498 } 499 luaL_getmetatable(L, DBD_DB2_STATEMENT); 500 lua_setmetatable(L, -2); 501 502 return 1; 503 } 504 505 int dbd_db2_statement(lua_State *L) { 506 static const luaL_Reg statement_methods[] = { 507 {"affected", statement_affected}, 508 {"close", statement_close}, 509 {"columns", statement_columns}, 510 {"execute", statement_execute}, 511 {"fetch", statement_fetch}, 512 {"rowcount", statement_rowcount}, 513 {"rows", statement_rows}, 514 {NULL, NULL} 515 }; 516 517 static const luaL_Reg statement_class_methods[] = { 518 {NULL, NULL} 519 }; 520 521 dbd_register(L, DBD_DB2_STATEMENT, 522 statement_methods, statement_class_methods, 523 statement_gc, statement_tostring); 524 525 return 1; 526 } 527