1/** 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 19#include "mod_lua.h" 20#include "lua_dbd.h" 21 22APLOG_USE_MODULE(lua); 23static APR_OPTIONAL_FN_TYPE(ap_dbd_close) *lua_ap_dbd_close = NULL; 24static APR_OPTIONAL_FN_TYPE(ap_dbd_open) *lua_ap_dbd_open = NULL; 25 26 27 28 29static request_rec *ap_lua_check_request_rec(lua_State *L, int index) 30{ 31 request_rec *r; 32 luaL_checkudata(L, index, "Apache2.Request"); 33 r = lua_unboxpointer(L, index); 34 return r; 35} 36 37static lua_db_handle *lua_get_db_handle(lua_State *L) 38{ 39 luaL_checktype(L, 1, LUA_TTABLE); 40 lua_rawgeti(L, 1, 0); 41 luaL_checktype(L, -1, LUA_TUSERDATA); 42 return (lua_db_handle *) lua_topointer(L, -1); 43} 44 45static lua_db_result_set *lua_get_result_set(lua_State *L) 46{ 47 luaL_checktype(L, 1, LUA_TTABLE); 48 lua_rawgeti(L, 1, 0); 49 luaL_checktype(L, -1, LUA_TUSERDATA); 50 return (lua_db_result_set *) lua_topointer(L, -1); 51} 52 53 54/* 55 ============================================================================= 56 db:close(): Closes an open database connection. 57 ============================================================================= 58 */ 59int lua_db_close(lua_State *L) 60{ 61 /*~~~~~~~~~~~~~~~~~~~~*/ 62 lua_db_handle *db; 63 apr_status_t rc = 0; 64 /*~~~~~~~~~~~~~~~~~~~~*/ 65 66 db = lua_get_db_handle(L); 67 if (db && db->alive) { 68 if (db->type == LUA_DBTYPE_APR_DBD) { 69 rc = apr_dbd_close(db->driver, db->handle); 70 if (db->pool) apr_pool_destroy(db->pool); 71 } 72 else { 73 lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close); 74 if (lua_ap_dbd_close != NULL) 75 if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle); 76 } 77 78 db->driver = NULL; 79 db->handle = NULL; 80 db->alive = 0; 81 db->pool = NULL; 82 } 83 84 lua_settop(L, 0); 85 lua_pushnumber(L, rc); 86 return 1; 87} 88 89/* 90 ============================================================================= 91 db:__gc(): Garbage collecting function. 92 ============================================================================= 93 */ 94int lua_db_gc(lua_State *L) 95{ 96 /*~~~~~~~~~~~~~~~~*/ 97 lua_db_handle *db; 98 /*~~~~~~~~~~~~~~~~~~~~*/ 99 100 db = lua_touserdata(L, 1); 101 if (db && db->alive) { 102 if (db->type == LUA_DBTYPE_APR_DBD) { 103 apr_dbd_close(db->driver, db->handle); 104 if (db->pool) apr_pool_destroy(db->pool); 105 } 106 else { 107 lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close); 108 if (lua_ap_dbd_close != NULL) 109 if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle); 110 } 111 db->driver = NULL; 112 db->handle = NULL; 113 db->alive = 0; 114 db->pool = NULL; 115 } 116 lua_settop(L, 0); 117 return 0; 118} 119 120/* 121 ============================================================================= 122 db:active(): Returns true if the connection to the db is still active. 123 ============================================================================= 124 */ 125int lua_db_active(lua_State *L) 126{ 127 /*~~~~~~~~~~~~~~~~~~~~*/ 128 lua_db_handle *db = 0; 129 apr_status_t rc = 0; 130 /*~~~~~~~~~~~~~~~~~~~~*/ 131 132 db = lua_get_db_handle(L); 133 if (db && db->alive) { 134 rc = apr_dbd_check_conn(db->driver, db->pool, db->handle); 135 if (rc == APR_SUCCESS) { 136 lua_pushboolean(L, 1); 137 return 1; 138 } 139 } 140 141 lua_pushboolean(L, 0); 142 return 1; 143} 144 145/* 146 ============================================================================= 147 db:query(statement): Executes the given database query and returns the 148 number of rows affected. If an error is encountered, returns nil as the 149 first parameter and the error message as the second. 150 ============================================================================= 151 */ 152int lua_db_query(lua_State *L) 153{ 154 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 155 lua_db_handle *db = 0; 156 apr_status_t rc = 0; 157 int x = 0; 158 const char *statement; 159 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 160 luaL_checktype(L, 3, LUA_TSTRING); 161 statement = lua_tostring(L, 3); 162 db = lua_get_db_handle(L); 163 if (db && db->alive) 164 rc = apr_dbd_query(db->driver, db->handle, &x, statement); 165 else { 166 rc = 0; 167 x = -1; 168 } 169 170 if (rc == APR_SUCCESS) 171 lua_pushnumber(L, x); 172 else { 173 174 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 175 const char *err = apr_dbd_error(db->driver, db->handle, rc); 176 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 177 178 lua_pushnil(L); 179 if (err) { 180 lua_pushstring(L, err); 181 return 2; 182 } 183 } 184 185 return 1; 186} 187 188/* 189 ============================================================================= 190 db:escape(string): Escapes a string for safe use in the given database type. 191 ============================================================================= 192 */ 193int lua_db_escape(lua_State *L) 194{ 195 /*~~~~~~~~~~~~~~~~~~~~~*/ 196 lua_db_handle *db = 0; 197 const char *statement; 198 const char *escaped = 0; 199 request_rec *r; 200 /*~~~~~~~~~~~~~~~~~~~~~*/ 201 202 r = ap_lua_check_request_rec(L, 2); 203 if (r) { 204 luaL_checktype(L, 3, LUA_TSTRING); 205 statement = lua_tostring(L, 3); 206 db = lua_get_db_handle(L); 207 if (db && db->alive) { 208 apr_dbd_init(r->pool); 209 escaped = apr_dbd_escape(db->driver, r->pool, statement, 210 db->handle); 211 if (escaped) { 212 lua_pushstring(L, escaped); 213 return 1; 214 } 215 } 216 else { 217 lua_pushnil(L); 218 } 219 return (1); 220 } 221 222 return 0; 223} 224 225/* 226 ============================================================================= 227 resultset(N): Fetches one or more rows from a result set. 228 ============================================================================= 229 */ 230int lua_db_get_row(lua_State *L) 231{ 232 int row_no,x,alpha = 0; 233 const char *entry, *rowname; 234 apr_dbd_row_t *row = 0; 235 lua_db_result_set *res = lua_get_result_set(L); 236 237 row_no = luaL_optinteger(L, 2, 0); 238 if (lua_isboolean(L, 3)) { 239 alpha = lua_toboolean(L, 3); 240 } 241 lua_settop(L,0); 242 243 /* Fetch all rows at once? */ 244 245 if (row_no == 0) { 246 row_no = 1; 247 lua_newtable(L); 248 while (apr_dbd_get_row(res->driver, res->pool, res->results, 249 &row, -1) != -1) 250 { 251 lua_pushinteger(L, row_no); 252 lua_newtable(L); 253 for (x = 0; x < res->cols; x++) { 254 entry = apr_dbd_get_entry(res->driver, row, x); 255 if (entry) { 256 if (alpha == 1) { 257 rowname = apr_dbd_get_name(res->driver, 258 res->results, x); 259 lua_pushstring(L, rowname ? rowname : "(oob)"); 260 } 261 else { 262 lua_pushinteger(L, x + 1); 263 } 264 lua_pushstring(L, entry); 265 lua_rawset(L, -3); 266 } 267 } 268 lua_rawset(L, -3); 269 row_no++; 270 } 271 return 1; 272 } 273 274 /* Just fetch a single row */ 275 if (apr_dbd_get_row(res->driver, res->pool, res->results, 276 &row, row_no) != -1) 277 { 278 279 lua_newtable(L); 280 for (x = 0; x < res->cols; x++) { 281 entry = apr_dbd_get_entry(res->driver, row, x); 282 if (entry) { 283 if (alpha == 1) { 284 rowname = apr_dbd_get_name(res->driver, 285 res->results, x); 286 lua_pushstring(L, rowname ? rowname : "(oob)"); 287 } 288 else { 289 lua_pushinteger(L, x + 1); 290 } 291 lua_pushstring(L, entry); 292 lua_rawset(L, -3); 293 } 294 } 295 return 1; 296 } 297 return 0; 298} 299 300 301/* 302 ============================================================================= 303 db:select(statement): Queries the database for the given statement and 304 returns the rows/columns found as a table. If an error is encountered, 305 returns nil as the first parameter and the error message as the second. 306 ============================================================================= 307 */ 308int lua_db_select(lua_State *L) 309{ 310 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 311 lua_db_handle *db = 0; 312 apr_status_t rc = 0; 313 const char *statement; 314 request_rec *r; 315 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 316 r = ap_lua_check_request_rec(L, 2); 317 if (r) { 318 luaL_checktype(L, 3, LUA_TSTRING); 319 statement = lua_tostring(L, 3); 320 db = lua_get_db_handle(L); 321 if (db && db->alive) { 322 323 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 324 int cols; 325 apr_dbd_results_t *results = 0; 326 lua_db_result_set* resultset = NULL; 327 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 328 329 rc = apr_dbd_select(db->driver, db->pool, db->handle, 330 &results, statement, 0); 331 if (rc == APR_SUCCESS) { 332 333 cols = apr_dbd_num_cols(db->driver, results); 334 335 if (cols > 0) { 336 lua_newtable(L); 337 resultset = lua_newuserdata(L, sizeof(lua_db_result_set)); 338 resultset->cols = cols; 339 resultset->driver = db->driver; 340 resultset->pool = db->pool; 341 resultset->rows = apr_dbd_num_tuples(db->driver, results); 342 resultset->results = results; 343 luaL_newmetatable(L, "lua_apr.dbselect"); 344 lua_pushliteral(L, "__call"); 345 lua_pushcfunction(L, lua_db_get_row); 346 lua_rawset(L, -3); 347 lua_setmetatable(L, -3); 348 lua_rawseti(L, -2, 0); 349 return 1; 350 } 351 return 0; 352 } 353 else { 354 355 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 356 const char *err = apr_dbd_error(db->driver, db->handle, rc); 357 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 358 359 lua_pushnil(L); 360 if (err) { 361 lua_pushstring(L, err); 362 return 2; 363 } 364 } 365 } 366 367 lua_pushboolean(L, 0); 368 return 1; 369 } 370 371 return 0; 372} 373 374 375 376/* 377 ============================================================================= 378 statement:select(var1, var2, var3...): Injects variables into a prepared 379 statement and returns the number of rows matching the query. 380 ============================================================================= 381 */ 382int lua_db_prepared_select(lua_State *L) 383{ 384 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 385 lua_db_prepared_statement *st = 0; 386 apr_status_t rc = 0; 387 const char **vars; 388 int x, have; 389 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 390 391 /* Fetch the prepared statement and the vars passed */ 392 luaL_checktype(L, 1, LUA_TTABLE); 393 lua_rawgeti(L, 1, 0); 394 luaL_checktype(L, -1, LUA_TUSERDATA); 395 st = (lua_db_prepared_statement*) lua_topointer(L, -1); 396 397 /* Check if we got enough variables passed on to us. 398 * This, of course, only works for prepared statements made through lua. */ 399 have = lua_gettop(L) - 2; 400 if (st->variables != -1 && have < st->variables ) { 401 lua_pushboolean(L, 0); 402 lua_pushfstring(L, 403 "Error in executing prepared statement: Expected %d arguments, got %d.", 404 st->variables, have); 405 return 2; 406 } 407 vars = apr_pcalloc(st->db->pool, have*sizeof(char *)); 408 for (x = 0; x < have; x++) { 409 vars[x] = lua_tostring(L, x + 2); 410 } 411 412 /* Fire off the query */ 413 if (st->db && st->db->alive) { 414 415 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 416 int cols; 417 apr_dbd_results_t *results = 0; 418 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 419 420 rc = apr_dbd_pselect(st->db->driver, st->db->pool, st->db->handle, 421 &results, st->statement, 0, have, vars); 422 if (rc == APR_SUCCESS) { 423 424 /*~~~~~~~~~~~~~~~~~~~~~*/ 425 lua_db_result_set *resultset; 426 /*~~~~~~~~~~~~~~~~~~~~~*/ 427 428 cols = apr_dbd_num_cols(st->db->driver, results); 429 lua_newtable(L); 430 resultset = lua_newuserdata(L, sizeof(lua_db_result_set)); 431 resultset->cols = cols; 432 resultset->driver = st->db->driver; 433 resultset->pool = st->db->pool; 434 resultset->rows = apr_dbd_num_tuples(st->db->driver, results); 435 resultset->results = results; 436 luaL_newmetatable(L, "lua_apr.dbselect"); 437 lua_pushliteral(L, "__call"); 438 lua_pushcfunction(L, lua_db_get_row); 439 lua_rawset(L, -3); 440 lua_setmetatable(L, -3); 441 lua_rawseti(L, -2, 0); 442 return 1; 443 444 } 445 else { 446 447 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 448 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc); 449 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 450 451 lua_pushnil(L); 452 if (err) { 453 lua_pushstring(L, err); 454 return 2; 455 } 456 return 1; 457 } 458 } 459 460 lua_pushboolean(L, 0); 461 lua_pushliteral(L, 462 "Database connection seems to be closed, please reacquire it."); 463 return (2); 464} 465 466 467/* 468 ============================================================================= 469 statement:query(var1, var2, var3...): Injects variables into a prepared 470 statement and returns the number of rows affected. 471 ============================================================================= 472 */ 473int lua_db_prepared_query(lua_State *L) 474{ 475 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 476 lua_db_prepared_statement *st = 0; 477 apr_status_t rc = 0; 478 const char **vars; 479 int x, have; 480 /*~~~~~~~~~~~~~~~~~~~~~~~*/ 481 482 /* Fetch the prepared statement and the vars passed */ 483 luaL_checktype(L, 1, LUA_TTABLE); 484 lua_rawgeti(L, 1, 0); 485 luaL_checktype(L, -1, LUA_TUSERDATA); 486 st = (lua_db_prepared_statement*) lua_topointer(L, -1); 487 488 /* Check if we got enough variables passed on to us. 489 * This, of course, only works for prepared statements made through lua. */ 490 have = lua_gettop(L) - 2; 491 if (st->variables != -1 && have < st->variables ) { 492 lua_pushboolean(L, 0); 493 lua_pushfstring(L, 494 "Error in executing prepared statement: Expected %d arguments, got %d.", 495 st->variables, have); 496 return 2; 497 } 498 vars = apr_pcalloc(st->db->pool, have*sizeof(char *)); 499 for (x = 0; x < have; x++) { 500 vars[x] = lua_tostring(L, x + 2); 501 } 502 503 /* Fire off the query */ 504 if (st->db && st->db->alive) { 505 506 /*~~~~~~~~~~~~~~*/ 507 int affected = 0; 508 /*~~~~~~~~~~~~~~*/ 509 510 rc = apr_dbd_pquery(st->db->driver, st->db->pool, st->db->handle, 511 &affected, st->statement, have, vars); 512 if (rc == APR_SUCCESS) { 513 lua_pushinteger(L, affected); 514 return 1; 515 } 516 else { 517 518 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 519 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc); 520 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 521 522 lua_pushnil(L); 523 if (err) { 524 lua_pushstring(L, err); 525 return 2; 526 } 527 return 1; 528 } 529 } 530 531 lua_pushboolean(L, 0); 532 lua_pushliteral(L, 533 "Database connection seems to be closed, please reacquire it."); 534 return (2); 535} 536 537/* 538 ============================================================================= 539 db:prepare(statement): Prepares a statement for later query/select. 540 Returns a table with a :query and :select function, same as the db funcs. 541 ============================================================================= 542 */ 543int lua_db_prepare(lua_State* L) 544{ 545 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 546 lua_db_handle *db = 0; 547 apr_status_t rc = 0; 548 const char *statement, *at; 549 request_rec *r; 550 lua_db_prepared_statement* st; 551 int need = 0; 552 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 553 554 r = ap_lua_check_request_rec(L, 2); 555 if (r) { 556 apr_dbd_prepared_t *pstatement = NULL; 557 luaL_checktype(L, 3, LUA_TSTRING); 558 statement = lua_tostring(L, 3); 559 560 /* Count number of variables in statement */ 561 at = ap_strchr_c(statement,'%'); 562 while (at != NULL) { 563 if (at[1] == '%') { 564 at++; 565 } 566 else { 567 need++; 568 } 569 at = ap_strchr_c(at+1,'%'); 570 } 571 572 573 db = lua_get_db_handle(L); 574 rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement, 575 NULL, &pstatement); 576 if (rc != APR_SUCCESS) { 577 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 578 const char *err = apr_dbd_error(db->driver, db->handle, rc); 579 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 580 581 lua_pushnil(L); 582 if (err) { 583 lua_pushstring(L, err); 584 return 2; 585 } 586 return 1; 587 } 588 589 /* Push the prepared statement table */ 590 lua_newtable(L); 591 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement)); 592 st->statement = pstatement; 593 st->variables = need; 594 st->db = db; 595 596 lua_pushliteral(L, "select"); 597 lua_pushcfunction(L, lua_db_prepared_select); 598 lua_rawset(L, -4); 599 lua_pushliteral(L, "query"); 600 lua_pushcfunction(L, lua_db_prepared_query); 601 lua_rawset(L, -4); 602 lua_rawseti(L, -2, 0); 603 return 1; 604 } 605 return 0; 606} 607 608 609 610/* 611 ============================================================================= 612 db:prepared(statement): Fetches a prepared statement made through 613 DBDPrepareSQL. 614 ============================================================================= 615 */ 616int lua_db_prepared(lua_State* L) 617{ 618 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 619 lua_db_handle *db = 0; 620 const char *tag; 621 request_rec *r; 622 lua_db_prepared_statement* st; 623 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 624 625 r = ap_lua_check_request_rec(L, 2); 626 if (r) { 627 apr_dbd_prepared_t *pstatement = NULL; 628 db = lua_get_db_handle(L); 629 luaL_checktype(L, 3, LUA_TSTRING); 630 tag = lua_tostring(L, 3); 631 632 /* Look for the statement */ 633 pstatement = apr_hash_get(db->dbdhandle->prepared, tag, 634 APR_HASH_KEY_STRING); 635 636 if (pstatement == NULL) { 637 lua_pushnil(L); 638 lua_pushfstring(L, 639 "Could not find any prepared statement called %s!", tag); 640 return 2; 641 } 642 643 644 /* Push the prepared statement table */ 645 lua_newtable(L); 646 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement)); 647 st->statement = pstatement; 648 st->variables = -1; /* we don't know :( */ 649 st->db = db; 650 lua_pushliteral(L, "select"); 651 lua_pushcfunction(L, lua_db_prepared_select); 652 lua_rawset(L, -4); 653 lua_pushliteral(L, "query"); 654 lua_pushcfunction(L, lua_db_prepared_query); 655 lua_rawset(L, -4); 656 lua_rawseti(L, -2, 0); 657 return 1; 658 } 659 return 0; 660} 661 662 663 664/* lua_push_db_handle: Creates a database table object with database functions 665 and a userdata at index 0, which will call lua_dbgc when garbage collected. 666 */ 667static lua_db_handle* lua_push_db_handle(lua_State *L, request_rec* r, int type, 668 apr_pool_t* pool) 669{ 670 lua_db_handle* db; 671 lua_newtable(L); 672 db = lua_newuserdata(L, sizeof(lua_db_handle)); 673 db->alive = 1; 674 db->pool = pool; 675 db->type = type; 676 db->dbdhandle = 0; 677 db->server = r->server; 678 luaL_newmetatable(L, "lua_apr.dbacquire"); 679 lua_pushliteral(L, "__gc"); 680 lua_pushcfunction(L, lua_db_gc); 681 lua_rawset(L, -3); 682 lua_setmetatable(L, -2); 683 lua_rawseti(L, -2, 0); 684 685 lua_pushliteral(L, "escape"); 686 lua_pushcfunction(L, lua_db_escape); 687 lua_rawset(L, -3); 688 689 lua_pushliteral(L, "close"); 690 lua_pushcfunction(L, lua_db_close); 691 lua_rawset(L, -3); 692 693 lua_pushliteral(L, "select"); 694 lua_pushcfunction(L, lua_db_select); 695 lua_rawset(L, -3); 696 697 lua_pushliteral(L, "query"); 698 lua_pushcfunction(L, lua_db_query); 699 lua_rawset(L, -3); 700 701 lua_pushliteral(L, "active"); 702 lua_pushcfunction(L, lua_db_active); 703 lua_rawset(L, -3); 704 705 lua_pushliteral(L, "prepare"); 706 lua_pushcfunction(L, lua_db_prepare); 707 lua_rawset(L, -3); 708 709 lua_pushliteral(L, "prepared"); 710 lua_pushcfunction(L, lua_db_prepared); 711 lua_rawset(L, -3); 712 return db; 713} 714 715/* 716 ============================================================================= 717 dbacquire(dbType, dbString): Opens a new connection to a database of type 718 _dbType_ and with the connection parameters _dbString_. If successful, 719 returns a table with functions for using the database handle. If an error 720 occurs, returns nil as the first parameter and the error message as the 721 second. See the APR_DBD for a list of database types and connection strings 722 supported. 723 ============================================================================= 724 */ 725int lua_db_acquire(lua_State *L) 726{ 727 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 728 const char *type; 729 const char *arguments; 730 const char *error = 0; 731 request_rec *r; 732 lua_db_handle *db = 0; 733 apr_status_t rc = 0; 734 ap_dbd_t *dbdhandle = NULL; 735 apr_pool_t *pool = NULL; 736 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 737 738 r = ap_lua_check_request_rec(L, 1); 739 if (r) { 740 type = luaL_optstring(L, 2, "mod_dbd"); /* Defaults to mod_dbd */ 741 742 if (!strcmp(type, "mod_dbd")) { 743 744 lua_settop(L, 0); 745 lua_ap_dbd_open = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_open); 746 if (lua_ap_dbd_open) 747 dbdhandle = (ap_dbd_t *) lua_ap_dbd_open( 748 r->server->process->pool, r->server); 749 750 if (dbdhandle) { 751 db = lua_push_db_handle(L, r, LUA_DBTYPE_MOD_DBD, dbdhandle->pool); 752 db->driver = dbdhandle->driver; 753 db->handle = dbdhandle->handle; 754 db->dbdhandle = dbdhandle; 755 return 1; 756 } 757 else { 758 lua_pushnil(L); 759 if ( lua_ap_dbd_open == NULL ) 760 lua_pushliteral(L, 761 "mod_dbd doesn't seem to have been loaded."); 762 else 763 lua_pushliteral( 764 L, 765 "Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem."); 766 return 2; 767 } 768 } 769 else { 770 rc = apr_pool_create(&pool, NULL); 771 if (rc != APR_SUCCESS) { 772 lua_pushnil(L); 773 lua_pushliteral(L, "Could not allocate memory for database!"); 774 return 2; 775 } 776 apr_pool_tag(pool, "lua_dbd_pool"); 777 apr_dbd_init(pool); 778 dbdhandle = apr_pcalloc(pool, sizeof(ap_dbd_t)); 779 rc = apr_dbd_get_driver(pool, type, &dbdhandle->driver); 780 if (rc == APR_SUCCESS) { 781 luaL_checktype(L, 3, LUA_TSTRING); 782 arguments = lua_tostring(L, 3); 783 lua_settop(L, 0); 784 785 if (strlen(arguments)) { 786 rc = apr_dbd_open_ex(dbdhandle->driver, pool, 787 arguments, &dbdhandle->handle, &error); 788 if (rc == APR_SUCCESS) { 789 db = lua_push_db_handle(L, r, LUA_DBTYPE_APR_DBD, pool); 790 db->driver = dbdhandle->driver; 791 db->handle = dbdhandle->handle; 792 db->dbdhandle = dbdhandle; 793 return 1; 794 } 795 else { 796 lua_pushnil(L); 797 if (error) { 798 lua_pushstring(L, error); 799 return 2; 800 } 801 802 return 1; 803 } 804 } 805 806 lua_pushnil(L); 807 lua_pushliteral(L, 808 "No database connection string was specified."); 809 apr_pool_destroy(pool); 810 return (2); 811 } 812 else { 813 lua_pushnil(L); 814 if (APR_STATUS_IS_ENOTIMPL(rc)) { 815 lua_pushfstring(L, 816 "driver for %s not available", type); 817 } 818 else if (APR_STATUS_IS_EDSOOPEN(rc)) { 819 lua_pushfstring(L, 820 "can't find driver for %s", type); 821 } 822 else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) { 823 lua_pushfstring(L, 824 "driver for %s is invalid or corrupted", 825 type); 826 } 827 else { 828 lua_pushliteral(L, 829 "mod_lua not compatible with APR in get_driver"); 830 } 831 lua_pushinteger(L, rc); 832 apr_pool_destroy(pool); 833 return 3; 834 } 835 } 836 837 lua_pushnil(L); 838 return 1; 839 } 840 841 return 0; 842} 843 844