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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 APLOG_USE_MODULE(lua);
23 static APR_OPTIONAL_FN_TYPE(ap_dbd_close) *lua_ap_dbd_close = NULL;
24 static APR_OPTIONAL_FN_TYPE(ap_dbd_open) *lua_ap_dbd_open = NULL;
27 static request_rec *ap_lua_check_request_rec(lua_State *L, int index)
30 luaL_checkudata(L, index, "Apache2.Request");
31 r = lua_unboxpointer(L, index);
35 static lua_db_handle *lua_get_db_handle(lua_State *L)
37 luaL_checktype(L, 1, LUA_TTABLE);
39 luaL_checktype(L, -1, LUA_TUSERDATA);
40 return (lua_db_handle *) lua_topointer(L, -1);
43 static lua_db_result_set *lua_get_result_set(lua_State *L)
45 luaL_checktype(L, 1, LUA_TTABLE);
47 luaL_checktype(L, -1, LUA_TUSERDATA);
48 return (lua_db_result_set *) lua_topointer(L, -1);
53 =============================================================================
54 db:close(): Closes an open database connection.
55 =============================================================================
57 AP_LUA_DECLARE(int) lua_db_close(lua_State *L)
59 /*~~~~~~~~~~~~~~~~~~~~*/
62 /*~~~~~~~~~~~~~~~~~~~~*/
64 db = lua_get_db_handle(L);
65 if (db && db->alive) {
66 if (db->type == LUA_DBTYPE_MOD_DBD) {
67 rc = apr_dbd_close(db->driver, db->handle);
70 lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
71 if (lua_ap_dbd_close != NULL)
72 if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
73 if (db->pool) apr_pool_destroy(db->pool);
83 lua_pushnumber(L, rc);
88 =============================================================================
89 db:__gc(): Garbage collecting function.
90 =============================================================================
92 AP_LUA_DECLARE(int) lua_db_gc(lua_State *L)
96 /*~~~~~~~~~~~~~~~~~~~~*/
98 db = lua_touserdata(L, 1);
99 if (db && db->alive) {
100 if (db->type == LUA_DBTYPE_APR_DBD) {
101 apr_dbd_close(db->driver, db->handle);
102 if (db->pool) apr_pool_destroy(db->pool);
105 lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
106 if (lua_ap_dbd_close != NULL)
107 if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
119 =============================================================================
120 db:active(): Returns true if the connection to the db is still active.
121 =============================================================================
123 AP_LUA_DECLARE(int) lua_db_active(lua_State *L)
125 /*~~~~~~~~~~~~~~~~~~~~*/
126 lua_db_handle *db = 0;
128 /*~~~~~~~~~~~~~~~~~~~~*/
130 db = lua_get_db_handle(L);
131 if (db && db->alive) {
132 rc = apr_dbd_check_conn(db->driver, db->pool, db->handle);
133 if (rc == APR_SUCCESS) {
134 lua_pushboolean(L, 1);
139 lua_pushboolean(L, 0);
144 =============================================================================
145 db:query(statement): Executes the given database query and returns the
146 number of rows affected. If an error is encountered, returns nil as the
147 first parameter and the error message as the second.
148 =============================================================================
150 AP_LUA_DECLARE(int) lua_db_query(lua_State *L)
152 /*~~~~~~~~~~~~~~~~~~~~~~~*/
153 lua_db_handle *db = 0;
156 const char *statement;
157 /*~~~~~~~~~~~~~~~~~~~~~~~*/
158 luaL_checktype(L, 3, LUA_TSTRING);
159 statement = lua_tostring(L, 3);
160 db = lua_get_db_handle(L);
162 rc = apr_dbd_query(db->driver, db->handle, &x, statement);
168 if (rc == APR_SUCCESS)
169 lua_pushnumber(L, x);
172 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
173 const char *err = apr_dbd_error(db->driver, db->handle, rc);
174 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
178 lua_pushstring(L, err);
187 =============================================================================
188 db:escape(string): Escapes a string for safe use in the given database type.
189 =============================================================================
191 AP_LUA_DECLARE(int) lua_db_escape(lua_State *L)
193 /*~~~~~~~~~~~~~~~~~~~~~*/
194 lua_db_handle *db = 0;
195 const char *statement;
196 const char *escaped = 0;
198 /*~~~~~~~~~~~~~~~~~~~~~*/
200 r = ap_lua_check_request_rec(L, 2);
202 luaL_checktype(L, 3, LUA_TSTRING);
203 statement = lua_tostring(L, 3);
204 db = lua_get_db_handle(L);
205 if (db && db->alive) {
206 apr_dbd_init(r->pool);
207 escaped = apr_dbd_escape(db->driver, r->pool, statement,
210 lua_pushstring(L, escaped);
224 =============================================================================
225 resultset(N): Fetches one or more rows from a result set.
226 =============================================================================
228 static int lua_db_get_row(lua_State *L)
232 apr_dbd_row_t *row = 0;
233 lua_db_result_set *res = lua_get_result_set(L);
235 row_no = luaL_optinteger(L, 2, 0);
238 /* Fetch all rows at once? */
242 while (apr_dbd_get_row(res->driver, res->pool, res->results,
245 lua_pushinteger(L, row_no);
247 for (x = 0; x < res->cols; x++) {
248 entry = apr_dbd_get_entry(res->driver, row, x);
250 lua_pushinteger(L, x + 1);
251 lua_pushstring(L, entry);
261 /* Just fetch a single row */
262 if (apr_dbd_get_row(res->driver, res->pool, res->results,
267 for (x = 0; x < res->cols; x++) {
268 entry = apr_dbd_get_entry(res->driver, row, x);
270 lua_pushinteger(L, x + 1);
271 lua_pushstring(L, entry);
282 =============================================================================
283 db:select(statement): Queries the database for the given statement and
284 returns the rows/columns found as a table. If an error is encountered,
285 returns nil as the first parameter and the error message as the second.
286 =============================================================================
288 AP_LUA_DECLARE(int) lua_db_select(lua_State *L)
290 /*~~~~~~~~~~~~~~~~~~~~~~~*/
291 lua_db_handle *db = 0;
293 const char *statement;
295 /*~~~~~~~~~~~~~~~~~~~~~~~*/
296 r = ap_lua_check_request_rec(L, 2);
298 luaL_checktype(L, 3, LUA_TSTRING);
299 statement = lua_tostring(L, 3);
300 db = lua_get_db_handle(L);
301 if (db && db->alive) {
303 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
305 apr_dbd_results_t *results = 0;
306 lua_db_result_set* resultset = NULL;
307 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
309 rc = apr_dbd_select(db->driver, db->pool, db->handle,
310 &results, statement, 0);
311 if (rc == APR_SUCCESS) {
313 cols = apr_dbd_num_cols(db->driver, results);
317 resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
318 resultset->cols = cols;
319 resultset->driver = db->driver;
320 resultset->pool = db->pool;
321 resultset->rows = apr_dbd_num_tuples(db->driver, results);
322 resultset->results = results;
323 luaL_newmetatable(L, "lua_apr.dbselect");
324 lua_pushliteral(L, "__call");
325 lua_pushcfunction(L, lua_db_get_row);
327 lua_setmetatable(L, -3);
328 lua_rawseti(L, -2, 0);
335 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
336 const char *err = apr_dbd_error(db->driver, db->handle, rc);
337 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
341 lua_pushstring(L, err);
347 lua_pushboolean(L, 0);
357 =============================================================================
358 statement:select(var1, var2, var3...): Injects variables into a prepared
359 statement and returns the number of rows matching the query.
360 =============================================================================
362 static int lua_db_prepared_select(lua_State *L)
364 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
365 lua_db_prepared_statement *st = 0;
369 /*~~~~~~~~~~~~~~~~~~~~~~~*/
371 /* Fetch the prepared statement and the vars passed */
372 luaL_checktype(L, 1, LUA_TTABLE);
373 lua_rawgeti(L, 1, 0);
374 luaL_checktype(L, -1, LUA_TUSERDATA);
375 st = (lua_db_prepared_statement*) lua_topointer(L, -1);
377 /* Check if we got enough variables passed on to us.
378 * This, of course, only works for prepped statements made through lua. */
379 have = lua_gettop(L) - 2;
380 if (st->variables != -1 && have < st->variables ) {
381 lua_pushboolean(L, 0);
383 "Error in executing prepared statement: Expected %d arguments, got %d.",
384 st->variables, have);
387 vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
388 for (x = 0; x < have; x++) {
389 vars[x] = lua_tostring(L, x + 2);
392 /* Fire off the query */
393 if (st->db && st->db->alive) {
395 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
397 apr_dbd_results_t *results = 0;
398 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
400 rc = apr_dbd_pselect(st->db->driver, st->db->pool, st->db->handle,
401 &results, st->statement, 0, have, vars);
402 if (rc == APR_SUCCESS) {
404 /*~~~~~~~~~~~~~~~~~~~~~*/
405 lua_db_result_set *resultset;
406 /*~~~~~~~~~~~~~~~~~~~~~*/
408 cols = apr_dbd_num_cols(st->db->driver, results);
410 resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
411 resultset->cols = cols;
412 resultset->driver = st->db->driver;
413 resultset->pool = st->db->pool;
414 resultset->rows = apr_dbd_num_tuples(st->db->driver, results);
415 resultset->results = results;
416 luaL_newmetatable(L, "lua_apr.dbselect");
417 lua_pushliteral(L, "__call");
418 lua_pushcfunction(L, lua_db_get_row);
420 lua_setmetatable(L, -3);
421 lua_rawseti(L, -2, 0);
427 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
428 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
429 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
433 lua_pushstring(L, err);
440 lua_pushboolean(L, 0);
442 "Database connection seems to be closed, please reacquire it.");
448 =============================================================================
449 statement:query(var1, var2, var3...): Injects variables into a prepared
450 statement and returns the number of rows affected.
451 =============================================================================
453 static int lua_db_prepared_query(lua_State *L)
455 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
456 lua_db_prepared_statement *st = 0;
460 /*~~~~~~~~~~~~~~~~~~~~~~~*/
462 /* Fetch the prepared statement and the vars passed */
463 luaL_checktype(L, 1, LUA_TTABLE);
464 lua_rawgeti(L, 1, 0);
465 luaL_checktype(L, -1, LUA_TUSERDATA);
466 st = (lua_db_prepared_statement*) lua_topointer(L, -1);
468 /* Check if we got enough variables passed on to us.
469 * This, of course, only works for prepped statements made through lua. */
470 have = lua_gettop(L) - 2;
471 if (st->variables != -1 && have < st->variables ) {
472 lua_pushboolean(L, 0);
474 "Error in executing prepared statement: Expected %d arguments, got %d.",
475 st->variables, have);
478 vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
479 for (x = 0; x < have; x++) {
480 vars[x] = lua_tostring(L, x + 2);
483 /* Fire off the query */
484 if (st->db && st->db->alive) {
490 rc = apr_dbd_pquery(st->db->driver, st->db->pool, st->db->handle,
491 &affected, st->statement, have, vars);
492 if (rc == APR_SUCCESS) {
493 lua_pushinteger(L, affected);
498 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
499 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
500 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
504 lua_pushstring(L, err);
511 lua_pushboolean(L, 0);
513 "Database connection seems to be closed, please reacquire it.");
518 =============================================================================
519 db:prepare(statement): Prepares a statement for later query/select.
520 Returns a table with a :query and :select function, same as the db funcs.
521 =============================================================================
523 AP_LUA_DECLARE(int) lua_db_prepare(lua_State* L)
525 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
526 lua_db_handle *db = 0;
528 const char *statement, *at;
530 lua_db_prepared_statement* st;
532 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
534 r = ap_lua_check_request_rec(L, 2);
536 apr_dbd_prepared_t *pstatement = NULL;
537 luaL_checktype(L, 3, LUA_TSTRING);
538 statement = lua_tostring(L, 3);
540 /* Count number of variables in statement */
541 at = ap_strchr_c(statement,'%');
549 at = ap_strchr_c(at+1,'%');
553 db = lua_get_db_handle(L);
554 rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement,
556 if (rc != APR_SUCCESS) {
557 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
558 const char *err = apr_dbd_error(db->driver, db->handle, rc);
559 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
563 lua_pushstring(L, err);
569 /* Push the prepared statement table */
571 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
572 st->statement = pstatement;
573 st->variables = need;
576 lua_pushliteral(L, "select");
577 lua_pushcfunction(L, lua_db_prepared_select);
579 lua_pushliteral(L, "query");
580 lua_pushcfunction(L, lua_db_prepared_query);
582 lua_rawseti(L, -2, 0);
591 =============================================================================
592 db:prepared(statement): Fetches a prepared statement made through
594 =============================================================================
596 AP_LUA_DECLARE(int) lua_db_prepared(lua_State* L)
598 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
599 lua_db_handle *db = 0;
602 lua_db_prepared_statement* st;
603 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
605 r = ap_lua_check_request_rec(L, 2);
607 apr_dbd_prepared_t *pstatement = NULL;
608 db = lua_get_db_handle(L);
609 luaL_checktype(L, 3, LUA_TSTRING);
610 tag = lua_tostring(L, 3);
612 /* Look for the statement */
613 pstatement = apr_hash_get(db->dbdhandle->prepared, tag,
614 APR_HASH_KEY_STRING);
616 if (pstatement == NULL) {
619 "Could not find any prepared statement called %s!", tag);
624 /* Push the prepared statement table */
626 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
627 st->statement = pstatement;
628 st->variables = -1; /* we don't know :( */
630 lua_pushliteral(L, "select");
631 lua_pushcfunction(L, lua_db_prepared_select);
633 lua_pushliteral(L, "query");
634 lua_pushcfunction(L, lua_db_prepared_query);
636 lua_rawseti(L, -2, 0);
644 /* lua_push_db_handle: Creates a database table object with database functions
645 and a userdata at index 0, which will call lua_dbgc when garbage collected.
647 static lua_db_handle* lua_push_db_handle(lua_State *L, request_rec* r, int type,
652 luaL_register(L, NULL, lua_db_methods);
653 db = lua_newuserdata(L, sizeof(lua_db_handle));
658 db->server = r->server;
659 luaL_newmetatable(L, "lua_apr.dbacquire");
660 lua_pushliteral(L, "__gc");
661 lua_pushcfunction(L, lua_db_gc);
663 lua_setmetatable(L, -2);
664 lua_rawseti(L, -2, 0);
668 =============================================================================
669 dbacquire(dbType, dbString): Opens a new connection to a database of type
670 _dbType_ and with the connection parameters _dbString_. If successful,
671 returns a table with functions for using the database handle. If an error
672 occurs, returns nil as the first parameter and the error message as the
673 second. See the APR_DBD for a list of database types and connection strings
675 =============================================================================
677 AP_LUA_DECLARE(int) lua_db_acquire(lua_State *L)
679 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
681 const char *arguments;
682 const char *error = 0;
684 lua_db_handle *db = 0;
686 ap_dbd_t *dbdhandle = NULL;
687 apr_pool_t *pool = NULL;
688 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
690 r = ap_lua_check_request_rec(L, 1);
692 type = luaL_optstring(L, 2, "mod_dbd"); /* Defaults to mod_dbd */
694 if (!strcmp(type, "mod_dbd")) {
697 lua_ap_dbd_open = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_open);
699 dbdhandle = (ap_dbd_t *) lua_ap_dbd_open(
700 r->server->process->pool, r->server);
703 db = lua_push_db_handle(L, r, LUA_DBTYPE_MOD_DBD, dbdhandle->pool);
704 db->driver = dbdhandle->driver;
705 db->handle = dbdhandle->handle;
706 db->dbdhandle = dbdhandle;
711 if ( lua_ap_dbd_open == NULL )
713 "mod_dbd doesn't seem to have been loaded.");
717 "Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem.");
722 rc = apr_pool_create(&pool, NULL);
723 if (rc != APR_SUCCESS) {
725 lua_pushliteral(L, "Could not allocate memory for database!");
728 apr_pool_tag(pool, "lua_dbd_pool");
731 rc = apr_dbd_get_driver(r->server->process->pool, type, &db->driver);
732 if (rc == APR_SUCCESS) {
733 luaL_checktype(L, 3, LUA_TSTRING);
734 arguments = lua_tostring(L, 3);
736 if (strlen(arguments)) {
737 rc = apr_dbd_open_ex(db->driver, r->server->process->pool,
738 arguments, &db->handle, &error);
739 if (rc == APR_SUCCESS) {
740 db = lua_push_db_handle(L, r, LUA_DBTYPE_APR_DBD, pool);
741 db->driver = dbdhandle->driver;
742 db->handle = dbdhandle->handle;
743 db->dbdhandle = dbdhandle;
749 lua_pushstring(L, error);
759 "No database connection string was specified.");
764 if (APR_STATUS_IS_ENOTIMPL(rc)) {
766 "driver for %s not available", type);
768 else if (APR_STATUS_IS_EDSOOPEN(rc)) {
770 "can't find driver for %s", type);
772 else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) {
774 "driver for %s is invalid or corrupted",
779 "mod_lua not compatible with APR in get_driver");
781 lua_pushinteger(L, rc);