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;
29 static request_rec *ap_lua_check_request_rec(lua_State *L, int index)
32 luaL_checkudata(L, index, "Apache2.Request");
33 r = lua_unboxpointer(L, index);
37 static lua_db_handle *lua_get_db_handle(lua_State *L)
39 luaL_checktype(L, 1, LUA_TTABLE);
41 luaL_checktype(L, -1, LUA_TUSERDATA);
42 return (lua_db_handle *) lua_topointer(L, -1);
45 static lua_db_result_set *lua_get_result_set(lua_State *L)
47 luaL_checktype(L, 1, LUA_TTABLE);
49 luaL_checktype(L, -1, LUA_TUSERDATA);
50 return (lua_db_result_set *) lua_topointer(L, -1);
55 =============================================================================
56 db:close(): Closes an open database connection.
57 =============================================================================
59 int lua_db_close(lua_State *L)
61 /*~~~~~~~~~~~~~~~~~~~~*/
64 /*~~~~~~~~~~~~~~~~~~~~*/
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);
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);
85 lua_pushnumber(L, rc);
90 =============================================================================
91 db:__gc(): Garbage collecting function.
92 =============================================================================
94 int lua_db_gc(lua_State *L)
98 /*~~~~~~~~~~~~~~~~~~~~*/
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);
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);
121 =============================================================================
122 db:active(): Returns true if the connection to the db is still active.
123 =============================================================================
125 int lua_db_active(lua_State *L)
127 /*~~~~~~~~~~~~~~~~~~~~*/
128 lua_db_handle *db = 0;
130 /*~~~~~~~~~~~~~~~~~~~~*/
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);
141 lua_pushboolean(L, 0);
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 =============================================================================
152 int lua_db_query(lua_State *L)
154 /*~~~~~~~~~~~~~~~~~~~~~~~*/
155 lua_db_handle *db = 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);
164 rc = apr_dbd_query(db->driver, db->handle, &x, statement);
170 if (rc == APR_SUCCESS)
171 lua_pushnumber(L, x);
174 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
175 const char *err = apr_dbd_error(db->driver, db->handle, rc);
176 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
180 lua_pushstring(L, err);
189 =============================================================================
190 db:escape(string): Escapes a string for safe use in the given database type.
191 =============================================================================
193 int lua_db_escape(lua_State *L)
195 /*~~~~~~~~~~~~~~~~~~~~~*/
196 lua_db_handle *db = 0;
197 const char *statement;
198 const char *escaped = 0;
200 /*~~~~~~~~~~~~~~~~~~~~~*/
202 r = ap_lua_check_request_rec(L, 2);
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,
212 lua_pushstring(L, escaped);
226 =============================================================================
227 resultset(N): Fetches one or more rows from a result set.
228 =============================================================================
230 int lua_db_get_row(lua_State *L)
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);
237 row_no = luaL_optinteger(L, 2, 0);
238 if (lua_isboolean(L, 3)) {
239 alpha = lua_toboolean(L, 3);
243 /* Fetch all rows at once? */
248 while (apr_dbd_get_row(res->driver, res->pool, res->results,
251 lua_pushinteger(L, row_no);
253 for (x = 0; x < res->cols; x++) {
254 entry = apr_dbd_get_entry(res->driver, row, x);
257 rowname = apr_dbd_get_name(res->driver,
259 lua_pushstring(L, rowname ? rowname : "(oob)");
262 lua_pushinteger(L, x + 1);
264 lua_pushstring(L, entry);
274 /* Just fetch a single row */
275 if (apr_dbd_get_row(res->driver, res->pool, res->results,
280 for (x = 0; x < res->cols; x++) {
281 entry = apr_dbd_get_entry(res->driver, row, x);
284 rowname = apr_dbd_get_name(res->driver,
286 lua_pushstring(L, rowname ? rowname : "(oob)");
289 lua_pushinteger(L, x + 1);
291 lua_pushstring(L, entry);
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 =============================================================================
308 int lua_db_select(lua_State *L)
310 /*~~~~~~~~~~~~~~~~~~~~~~~*/
311 lua_db_handle *db = 0;
313 const char *statement;
315 /*~~~~~~~~~~~~~~~~~~~~~~~*/
316 r = ap_lua_check_request_rec(L, 2);
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) {
323 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
325 apr_dbd_results_t *results = 0;
326 lua_db_result_set* resultset = NULL;
327 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
329 rc = apr_dbd_select(db->driver, db->pool, db->handle,
330 &results, statement, 0);
331 if (rc == APR_SUCCESS) {
333 cols = apr_dbd_num_cols(db->driver, results);
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);
347 lua_setmetatable(L, -3);
348 lua_rawseti(L, -2, 0);
355 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
356 const char *err = apr_dbd_error(db->driver, db->handle, rc);
357 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
361 lua_pushstring(L, err);
367 lua_pushboolean(L, 0);
377 =============================================================================
378 statement:select(var1, var2, var3...): Injects variables into a prepared
379 statement and returns the number of rows matching the query.
380 =============================================================================
382 int lua_db_prepared_select(lua_State *L)
384 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
385 lua_db_prepared_statement *st = 0;
389 /*~~~~~~~~~~~~~~~~~~~~~~~*/
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);
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);
403 "Error in executing prepared statement: Expected %d arguments, got %d.",
404 st->variables, have);
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);
412 /* Fire off the query */
413 if (st->db && st->db->alive) {
415 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
417 apr_dbd_results_t *results = 0;
418 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
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) {
424 /*~~~~~~~~~~~~~~~~~~~~~*/
425 lua_db_result_set *resultset;
426 /*~~~~~~~~~~~~~~~~~~~~~*/
428 cols = apr_dbd_num_cols(st->db->driver, results);
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);
440 lua_setmetatable(L, -3);
441 lua_rawseti(L, -2, 0);
447 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
448 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
449 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
453 lua_pushstring(L, err);
460 lua_pushboolean(L, 0);
462 "Database connection seems to be closed, please reacquire it.");
468 =============================================================================
469 statement:query(var1, var2, var3...): Injects variables into a prepared
470 statement and returns the number of rows affected.
471 =============================================================================
473 int lua_db_prepared_query(lua_State *L)
475 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
476 lua_db_prepared_statement *st = 0;
480 /*~~~~~~~~~~~~~~~~~~~~~~~*/
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);
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);
494 "Error in executing prepared statement: Expected %d arguments, got %d.",
495 st->variables, have);
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);
503 /* Fire off the query */
504 if (st->db && st->db->alive) {
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);
518 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
519 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
520 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
524 lua_pushstring(L, err);
531 lua_pushboolean(L, 0);
533 "Database connection seems to be closed, please reacquire it.");
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 =============================================================================
543 int lua_db_prepare(lua_State* L)
545 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
546 lua_db_handle *db = 0;
548 const char *statement, *at;
550 lua_db_prepared_statement* st;
552 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
554 r = ap_lua_check_request_rec(L, 2);
556 apr_dbd_prepared_t *pstatement = NULL;
557 luaL_checktype(L, 3, LUA_TSTRING);
558 statement = lua_tostring(L, 3);
560 /* Count number of variables in statement */
561 at = ap_strchr_c(statement,'%');
569 at = ap_strchr_c(at+1,'%');
573 db = lua_get_db_handle(L);
574 rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement,
576 if (rc != APR_SUCCESS) {
577 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
578 const char *err = apr_dbd_error(db->driver, db->handle, rc);
579 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
583 lua_pushstring(L, err);
589 /* Push the prepared statement table */
591 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
592 st->statement = pstatement;
593 st->variables = need;
596 lua_pushliteral(L, "select");
597 lua_pushcfunction(L, lua_db_prepared_select);
599 lua_pushliteral(L, "query");
600 lua_pushcfunction(L, lua_db_prepared_query);
602 lua_rawseti(L, -2, 0);
611 =============================================================================
612 db:prepared(statement): Fetches a prepared statement made through
614 =============================================================================
616 int lua_db_prepared(lua_State* L)
618 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
619 lua_db_handle *db = 0;
622 lua_db_prepared_statement* st;
623 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
625 r = ap_lua_check_request_rec(L, 2);
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);
632 /* Look for the statement */
633 pstatement = apr_hash_get(db->dbdhandle->prepared, tag,
634 APR_HASH_KEY_STRING);
636 if (pstatement == NULL) {
639 "Could not find any prepared statement called %s!", tag);
644 /* Push the prepared statement table */
646 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
647 st->statement = pstatement;
648 st->variables = -1; /* we don't know :( */
650 lua_pushliteral(L, "select");
651 lua_pushcfunction(L, lua_db_prepared_select);
653 lua_pushliteral(L, "query");
654 lua_pushcfunction(L, lua_db_prepared_query);
656 lua_rawseti(L, -2, 0);
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.
667 static lua_db_handle* lua_push_db_handle(lua_State *L, request_rec* r, int type,
672 db = lua_newuserdata(L, sizeof(lua_db_handle));
677 db->server = r->server;
678 luaL_newmetatable(L, "lua_apr.dbacquire");
679 lua_pushliteral(L, "__gc");
680 lua_pushcfunction(L, lua_db_gc);
682 lua_setmetatable(L, -2);
683 lua_rawseti(L, -2, 0);
685 lua_pushliteral(L, "escape");
686 lua_pushcfunction(L, lua_db_escape);
689 lua_pushliteral(L, "close");
690 lua_pushcfunction(L, lua_db_close);
693 lua_pushliteral(L, "select");
694 lua_pushcfunction(L, lua_db_select);
697 lua_pushliteral(L, "query");
698 lua_pushcfunction(L, lua_db_query);
701 lua_pushliteral(L, "active");
702 lua_pushcfunction(L, lua_db_active);
705 lua_pushliteral(L, "prepare");
706 lua_pushcfunction(L, lua_db_prepare);
709 lua_pushliteral(L, "prepared");
710 lua_pushcfunction(L, lua_db_prepared);
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
723 =============================================================================
725 int lua_db_acquire(lua_State *L)
727 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
729 const char *arguments;
730 const char *error = 0;
732 lua_db_handle *db = 0;
734 ap_dbd_t *dbdhandle = NULL;
735 apr_pool_t *pool = NULL;
736 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
738 r = ap_lua_check_request_rec(L, 1);
740 type = luaL_optstring(L, 2, "mod_dbd"); /* Defaults to mod_dbd */
742 if (!strcmp(type, "mod_dbd")) {
745 lua_ap_dbd_open = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_open);
747 dbdhandle = (ap_dbd_t *) lua_ap_dbd_open(
748 r->server->process->pool, r->server);
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;
759 if ( lua_ap_dbd_open == NULL )
761 "mod_dbd doesn't seem to have been loaded.");
765 "Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem.");
770 rc = apr_pool_create(&pool, NULL);
771 if (rc != APR_SUCCESS) {
773 lua_pushliteral(L, "Could not allocate memory for database!");
776 apr_pool_tag(pool, "lua_dbd_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);
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;
798 lua_pushstring(L, error);
808 "No database connection string was specified.");
809 apr_pool_destroy(pool);
814 if (APR_STATUS_IS_ENOTIMPL(rc)) {
816 "driver for %s not available", type);
818 else if (APR_STATUS_IS_EDSOOPEN(rc)) {
820 "can't find driver for %s", type);
822 else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) {
824 "driver for %s is invalid or corrupted",
829 "mod_lua not compatible with APR in get_driver");
831 lua_pushinteger(L, rc);
832 apr_pool_destroy(pool);