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_MOD_DBD) {
69 rc = apr_dbd_close(db->driver, db->handle);
72 lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
73 if (lua_ap_dbd_close != NULL)
74 if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
75 if (db->pool) apr_pool_destroy(db->pool);
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)
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);
240 /* Fetch all rows at once? */
244 while (apr_dbd_get_row(res->driver, res->pool, res->results,
247 lua_pushinteger(L, row_no);
249 for (x = 0; x < res->cols; x++) {
250 entry = apr_dbd_get_entry(res->driver, row, x);
252 lua_pushinteger(L, x + 1);
253 lua_pushstring(L, entry);
263 /* Just fetch a single row */
264 if (apr_dbd_get_row(res->driver, res->pool, res->results,
269 for (x = 0; x < res->cols; x++) {
270 entry = apr_dbd_get_entry(res->driver, row, x);
272 lua_pushinteger(L, x + 1);
273 lua_pushstring(L, entry);
284 =============================================================================
285 db:select(statement): Queries the database for the given statement and
286 returns the rows/columns found as a table. If an error is encountered,
287 returns nil as the first parameter and the error message as the second.
288 =============================================================================
290 int lua_db_select(lua_State *L)
292 /*~~~~~~~~~~~~~~~~~~~~~~~*/
293 lua_db_handle *db = 0;
295 const char *statement;
297 /*~~~~~~~~~~~~~~~~~~~~~~~*/
298 r = ap_lua_check_request_rec(L, 2);
300 luaL_checktype(L, 3, LUA_TSTRING);
301 statement = lua_tostring(L, 3);
302 db = lua_get_db_handle(L);
303 if (db && db->alive) {
305 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
307 apr_dbd_results_t *results = 0;
308 lua_db_result_set* resultset = NULL;
309 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
311 rc = apr_dbd_select(db->driver, db->pool, db->handle,
312 &results, statement, 0);
313 if (rc == APR_SUCCESS) {
315 cols = apr_dbd_num_cols(db->driver, results);
319 resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
320 resultset->cols = cols;
321 resultset->driver = db->driver;
322 resultset->pool = db->pool;
323 resultset->rows = apr_dbd_num_tuples(db->driver, results);
324 resultset->results = results;
325 luaL_newmetatable(L, "lua_apr.dbselect");
326 lua_pushliteral(L, "__call");
327 lua_pushcfunction(L, lua_db_get_row);
329 lua_setmetatable(L, -3);
330 lua_rawseti(L, -2, 0);
337 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
338 const char *err = apr_dbd_error(db->driver, db->handle, rc);
339 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
343 lua_pushstring(L, err);
349 lua_pushboolean(L, 0);
359 =============================================================================
360 statement:select(var1, var2, var3...): Injects variables into a prepared
361 statement and returns the number of rows matching the query.
362 =============================================================================
364 int lua_db_prepared_select(lua_State *L)
366 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
367 lua_db_prepared_statement *st = 0;
371 /*~~~~~~~~~~~~~~~~~~~~~~~*/
373 /* Fetch the prepared statement and the vars passed */
374 luaL_checktype(L, 1, LUA_TTABLE);
375 lua_rawgeti(L, 1, 0);
376 luaL_checktype(L, -1, LUA_TUSERDATA);
377 st = (lua_db_prepared_statement*) lua_topointer(L, -1);
379 /* Check if we got enough variables passed on to us.
380 * This, of course, only works for prepped statements made through lua. */
381 have = lua_gettop(L) - 2;
382 if (st->variables != -1 && have < st->variables ) {
383 lua_pushboolean(L, 0);
385 "Error in executing prepared statement: Expected %d arguments, got %d.",
386 st->variables, have);
389 vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
390 for (x = 0; x < have; x++) {
391 vars[x] = lua_tostring(L, x + 2);
394 /* Fire off the query */
395 if (st->db && st->db->alive) {
397 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
399 apr_dbd_results_t *results = 0;
400 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
402 rc = apr_dbd_pselect(st->db->driver, st->db->pool, st->db->handle,
403 &results, st->statement, 0, have, vars);
404 if (rc == APR_SUCCESS) {
406 /*~~~~~~~~~~~~~~~~~~~~~*/
407 lua_db_result_set *resultset;
408 /*~~~~~~~~~~~~~~~~~~~~~*/
410 cols = apr_dbd_num_cols(st->db->driver, results);
412 resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
413 resultset->cols = cols;
414 resultset->driver = st->db->driver;
415 resultset->pool = st->db->pool;
416 resultset->rows = apr_dbd_num_tuples(st->db->driver, results);
417 resultset->results = results;
418 luaL_newmetatable(L, "lua_apr.dbselect");
419 lua_pushliteral(L, "__call");
420 lua_pushcfunction(L, lua_db_get_row);
422 lua_setmetatable(L, -3);
423 lua_rawseti(L, -2, 0);
429 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
430 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
431 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
435 lua_pushstring(L, err);
442 lua_pushboolean(L, 0);
444 "Database connection seems to be closed, please reacquire it.");
450 =============================================================================
451 statement:query(var1, var2, var3...): Injects variables into a prepared
452 statement and returns the number of rows affected.
453 =============================================================================
455 int lua_db_prepared_query(lua_State *L)
457 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
458 lua_db_prepared_statement *st = 0;
462 /*~~~~~~~~~~~~~~~~~~~~~~~*/
464 /* Fetch the prepared statement and the vars passed */
465 luaL_checktype(L, 1, LUA_TTABLE);
466 lua_rawgeti(L, 1, 0);
467 luaL_checktype(L, -1, LUA_TUSERDATA);
468 st = (lua_db_prepared_statement*) lua_topointer(L, -1);
470 /* Check if we got enough variables passed on to us.
471 * This, of course, only works for prepped statements made through lua. */
472 have = lua_gettop(L) - 2;
473 if (st->variables != -1 && have < st->variables ) {
474 lua_pushboolean(L, 0);
476 "Error in executing prepared statement: Expected %d arguments, got %d.",
477 st->variables, have);
480 vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
481 for (x = 0; x < have; x++) {
482 vars[x] = lua_tostring(L, x + 2);
485 /* Fire off the query */
486 if (st->db && st->db->alive) {
492 rc = apr_dbd_pquery(st->db->driver, st->db->pool, st->db->handle,
493 &affected, st->statement, have, vars);
494 if (rc == APR_SUCCESS) {
495 lua_pushinteger(L, affected);
500 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
501 const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
502 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
506 lua_pushstring(L, err);
513 lua_pushboolean(L, 0);
515 "Database connection seems to be closed, please reacquire it.");
520 =============================================================================
521 db:prepare(statement): Prepares a statement for later query/select.
522 Returns a table with a :query and :select function, same as the db funcs.
523 =============================================================================
525 int lua_db_prepare(lua_State* L)
527 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
528 lua_db_handle *db = 0;
530 const char *statement, *at;
532 lua_db_prepared_statement* st;
534 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
536 r = ap_lua_check_request_rec(L, 2);
538 apr_dbd_prepared_t *pstatement = NULL;
539 luaL_checktype(L, 3, LUA_TSTRING);
540 statement = lua_tostring(L, 3);
542 /* Count number of variables in statement */
543 at = ap_strchr_c(statement,'%');
551 at = ap_strchr_c(at+1,'%');
555 db = lua_get_db_handle(L);
556 rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement,
558 if (rc != APR_SUCCESS) {
559 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
560 const char *err = apr_dbd_error(db->driver, db->handle, rc);
561 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
565 lua_pushstring(L, err);
571 /* Push the prepared statement table */
573 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
574 st->statement = pstatement;
575 st->variables = need;
578 lua_pushliteral(L, "select");
579 lua_pushcfunction(L, lua_db_prepared_select);
581 lua_pushliteral(L, "query");
582 lua_pushcfunction(L, lua_db_prepared_query);
584 lua_rawseti(L, -2, 0);
593 =============================================================================
594 db:prepared(statement): Fetches a prepared statement made through
596 =============================================================================
598 int lua_db_prepared(lua_State* L)
600 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
601 lua_db_handle *db = 0;
604 lua_db_prepared_statement* st;
605 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
607 r = ap_lua_check_request_rec(L, 2);
609 apr_dbd_prepared_t *pstatement = NULL;
610 db = lua_get_db_handle(L);
611 luaL_checktype(L, 3, LUA_TSTRING);
612 tag = lua_tostring(L, 3);
614 /* Look for the statement */
615 pstatement = apr_hash_get(db->dbdhandle->prepared, tag,
616 APR_HASH_KEY_STRING);
618 if (pstatement == NULL) {
621 "Could not find any prepared statement called %s!", tag);
626 /* Push the prepared statement table */
628 st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
629 st->statement = pstatement;
630 st->variables = -1; /* we don't know :( */
632 lua_pushliteral(L, "select");
633 lua_pushcfunction(L, lua_db_prepared_select);
635 lua_pushliteral(L, "query");
636 lua_pushcfunction(L, lua_db_prepared_query);
638 lua_rawseti(L, -2, 0);
646 /* lua_push_db_handle: Creates a database table object with database functions
647 and a userdata at index 0, which will call lua_dbgc when garbage collected.
649 static lua_db_handle* lua_push_db_handle(lua_State *L, request_rec* r, int type,
654 db = lua_newuserdata(L, sizeof(lua_db_handle));
659 db->server = r->server;
660 luaL_newmetatable(L, "lua_apr.dbacquire");
661 lua_pushliteral(L, "__gc");
662 lua_pushcfunction(L, lua_db_gc);
664 lua_setmetatable(L, -2);
665 lua_rawseti(L, -2, 0);
667 lua_pushliteral(L, "escape");
668 lua_pushcfunction(L, lua_db_escape);
671 lua_pushliteral(L, "close");
672 lua_pushcfunction(L, lua_db_close);
675 lua_pushliteral(L, "select");
676 lua_pushcfunction(L, lua_db_select);
679 lua_pushliteral(L, "query");
680 lua_pushcfunction(L, lua_db_query);
683 lua_pushliteral(L, "active");
684 lua_pushcfunction(L, lua_db_active);
687 lua_pushliteral(L, "prepare");
688 lua_pushcfunction(L, lua_db_prepare);
691 lua_pushliteral(L, "prepared");
692 lua_pushcfunction(L, lua_db_prepared);
698 =============================================================================
699 dbacquire(dbType, dbString): Opens a new connection to a database of type
700 _dbType_ and with the connection parameters _dbString_. If successful,
701 returns a table with functions for using the database handle. If an error
702 occurs, returns nil as the first parameter and the error message as the
703 second. See the APR_DBD for a list of database types and connection strings
705 =============================================================================
707 AP_LUA_DECLARE(int) lua_db_acquire(lua_State *L)
709 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
711 const char *arguments;
712 const char *error = 0;
714 lua_db_handle *db = 0;
716 ap_dbd_t *dbdhandle = NULL;
717 apr_pool_t *pool = NULL;
718 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
720 r = ap_lua_check_request_rec(L, 1);
722 type = luaL_optstring(L, 2, "mod_dbd"); /* Defaults to mod_dbd */
724 if (!strcmp(type, "mod_dbd")) {
727 lua_ap_dbd_open = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_open);
729 dbdhandle = (ap_dbd_t *) lua_ap_dbd_open(
730 r->server->process->pool, r->server);
733 db = lua_push_db_handle(L, r, LUA_DBTYPE_MOD_DBD, dbdhandle->pool);
734 db->driver = dbdhandle->driver;
735 db->handle = dbdhandle->handle;
736 db->dbdhandle = dbdhandle;
741 if ( lua_ap_dbd_open == NULL )
743 "mod_dbd doesn't seem to have been loaded.");
747 "Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem.");
752 rc = apr_pool_create(&pool, NULL);
753 if (rc != APR_SUCCESS) {
755 lua_pushliteral(L, "Could not allocate memory for database!");
758 apr_pool_tag(pool, "lua_dbd_pool");
760 dbdhandle = apr_pcalloc(pool, sizeof(ap_dbd_t));
761 rc = apr_dbd_get_driver(pool, type, &dbdhandle->driver);
762 if (rc == APR_SUCCESS) {
763 luaL_checktype(L, 3, LUA_TSTRING);
764 arguments = lua_tostring(L, 3);
767 if (strlen(arguments)) {
768 rc = apr_dbd_open_ex(dbdhandle->driver, pool,
769 arguments, &dbdhandle->handle, &error);
770 if (rc == APR_SUCCESS) {
771 db = lua_push_db_handle(L, r, LUA_DBTYPE_APR_DBD, pool);
772 db->driver = dbdhandle->driver;
773 db->handle = dbdhandle->handle;
774 db->dbdhandle = dbdhandle;
780 lua_pushstring(L, error);
790 "No database connection string was specified.");
791 apr_pool_destroy(pool);
796 if (APR_STATUS_IS_ENOTIMPL(rc)) {
798 "driver for %s not available", type);
800 else if (APR_STATUS_IS_EDSOOPEN(rc)) {
802 "can't find driver for %s", type);
804 else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) {
806 "driver for %s is invalid or corrupted",
811 "mod_lua not compatible with APR in get_driver");
813 lua_pushinteger(L, rc);
814 apr_pool_destroy(pool);