lua_dbd.c revision 822bf3c5fe5ae502a7327369e54805581ce60ba5
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova/**
e9458b1a7a19a63aa4c179f9ab20f4d50681c168Jens Elkner * Licensed to the Apache Software Foundation (ASF) under one or more
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * contributor license agreements. See the NOTICE file distributed with
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * this work for additional information regarding copyright ownership.
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * The ASF licenses this file to You under the Apache License, Version 2.0
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * (the "License"); you may not use this file except in compliance with
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * the License. You may obtain a copy of the License at
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova *
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * http://www.apache.org/licenses/LICENSE-2.0
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova *
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * Unless required by applicable law or agreed to in writing, software
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * distributed under the License is distributed on an "AS IS" BASIS,
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * See the License for the specific language governing permissions and
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * limitations under the License.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova */
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova#include "mod_lua.h"
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova#include "lua_apr.h"
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova#include "lua_dbd.h"
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina SojakovaAPLOG_USE_MODULE(lua);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic APR_OPTIONAL_FN_TYPE(ap_dbd_close) *lua_ap_dbd_close = NULL;
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakovastatic APR_OPTIONAL_FN_TYPE(ap_dbd_open) *lua_ap_dbd_open = NULL;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakovastatic request_rec *ap_lua_check_request_rec(lua_State *L, int index)
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova{
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova request_rec *r;
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova luaL_checkudata(L, index, "Apache2.Request");
118add2c5ac398465f6f66adb165852dffe1264dKristina Sojakova r = lua_unboxpointer(L, index);
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova return r;
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova}
118add2c5ac398465f6f66adb165852dffe1264dKristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakovastatic lua_db_handle *lua_get_db_handle(lua_State *L)
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova{
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova luaL_checktype(L, 1, LUA_TTABLE);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova lua_rawgeti(L, 1, 0);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova luaL_checktype(L, -1, LUA_TUSERDATA);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova return (lua_db_handle *) lua_topointer(L, -1);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova}
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic lua_db_result_set *lua_get_result_set(lua_State *L)
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova{
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova luaL_checktype(L, 1, LUA_TTABLE);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova lua_rawgeti(L, 1, 0);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova luaL_checktype(L, -1, LUA_TUSERDATA);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova return (lua_db_result_set *) lua_topointer(L, -1);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova}
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova/*
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova =============================================================================
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova db:close(): Closes an open database connection.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova =============================================================================
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova */
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakovaint lua_db_close(lua_State *L)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder{
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~*/
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova lua_db_handle *db;
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova apr_status_t rc = 0;
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova /*~~~~~~~~~~~~~~~~~~~~*/
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova db = lua_get_db_handle(L);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (db && db->alive) {
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (db->type == LUA_DBTYPE_MOD_DBD) {
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova rc = apr_dbd_close(db->driver, db->handle);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova }
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova else {
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (lua_ap_dbd_close != NULL)
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder if (db->pool) apr_pool_destroy(db->pool);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder }
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db->driver = NULL;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db->handle = NULL;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder db->alive = 0;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db->pool = NULL;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova }
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova lua_settop(L, 0);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova lua_pushnumber(L, rc);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova return 1;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder}
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova/*
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder =============================================================================
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db:__gc(): Garbage collecting function.
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova =============================================================================
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova */
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakovaint lua_db_gc(lua_State *L)
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova{
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova /*~~~~~~~~~~~~~~~~*/
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder lua_db_handle *db;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder /*~~~~~~~~~~~~~~~~~~~~*/
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder db = lua_touserdata(L, 1);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder if (db && db->alive) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder if (db->type == LUA_DBTYPE_APR_DBD) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder apr_dbd_close(db->driver, db->handle);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (db->pool) apr_pool_destroy(db->pool);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova }
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova else {
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova if (lua_ap_dbd_close != NULL)
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder }
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova db->driver = NULL;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db->handle = NULL;
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova db->alive = 0;
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova db->pool = NULL;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder }
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova lua_settop(L, 0);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder return 0;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder}
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova/*
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova =============================================================================
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova db:active(): Returns true if the connection to the db is still active.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova =============================================================================
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder */
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakovaint lua_db_active(lua_State *L)
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova{
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~*/
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova lua_db_handle *db = 0;
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova apr_status_t rc = 0;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder /*~~~~~~~~~~~~~~~~~~~~*/
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db = lua_get_db_handle(L);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (db && db->alive) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder rc = apr_dbd_check_conn(db->driver, db->pool, db->handle);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (rc == APR_SUCCESS) {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova lua_pushboolean(L, 1);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova return 1;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova }
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova }
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder lua_pushboolean(L, 0);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova return 1;
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova}
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova/*
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova =============================================================================
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova db:query(statement): Executes the given database query and returns the
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova number of rows affected. If an error is encountered, returns nil as the
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder first parameter and the error message as the second.
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova =============================================================================
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder */
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederint lua_db_query(lua_State *L)
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova{
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~~~~*/
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova lua_db_handle *db = 0;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova apr_status_t rc = 0;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova int x = 0;
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova const char *statement;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder /*~~~~~~~~~~~~~~~~~~~~~~~*/
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder luaL_checktype(L, 3, LUA_TSTRING);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova statement = lua_tostring(L, 3);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder db = lua_get_db_handle(L);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova if (db && db->alive)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder rc = apr_dbd_query(db->driver, db->handle, &x, statement);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova else {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder rc = 0;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova x = -1;
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova }
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (rc == APR_SUCCESS)
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova lua_pushnumber(L, x);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova else {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova const char *err = apr_dbd_error(db->driver, db->handle, rc);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder lua_pushnil(L);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder if (err) {
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova lua_pushstring(L, err);
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova return 2;
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova }
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova }
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder return 1;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder}
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder/*
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova =============================================================================
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db:escape(string): Escapes a string for safe use in the given database type.
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova =============================================================================
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova */
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederint lua_db_escape(lua_State *L)
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova{
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova /*~~~~~~~~~~~~~~~~~~~~~*/
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova lua_db_handle *db = 0;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova const char *statement;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova const char *escaped = 0;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder request_rec *r;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /*~~~~~~~~~~~~~~~~~~~~~*/
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder r = ap_lua_check_request_rec(L, 2);
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder if (r) {
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova luaL_checktype(L, 3, LUA_TSTRING);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova statement = lua_tostring(L, 3);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db = lua_get_db_handle(L);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (db && db->alive) {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova apr_dbd_init(r->pool);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova escaped = apr_dbd_escape(db->driver, r->pool, statement,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova db->handle);
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova if (escaped) {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder lua_pushstring(L, escaped);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova return 1;
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova }
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova }
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova else {
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder lua_pushnil(L);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova }
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova return (1);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova }
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova return 0;
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder}
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova/*
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder =============================================================================
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder resultset(N): Fetches one or more rows from a result set.
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova =============================================================================
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova */
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovaint lua_db_get_row(lua_State *L)
3c0bf20712a0f21aaedc0a9a9c8376bc1e90e799Kristina Sojakova{
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova int row_no,x;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova const char *entry;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova apr_dbd_row_t *row = 0;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova lua_db_result_set *res = lua_get_result_set(L);
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder row_no = luaL_optinteger(L, 2, 0);
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova lua_settop(L,0);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /* Fetch all rows at once? */
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova if (row_no == 0) {
row_no = 1;
lua_newtable(L);
while (apr_dbd_get_row(res->driver, res->pool, res->results,
&row, -1) != -1)
{
lua_pushinteger(L, row_no);
lua_newtable(L);
for (x = 0; x < res->cols; x++) {
entry = apr_dbd_get_entry(res->driver, row, x);
if (entry) {
lua_pushinteger(L, x + 1);
lua_pushstring(L, entry);
lua_rawset(L, -3);
}
}
lua_rawset(L, -3);
row_no++;
}
return 1;
}
/* Just fetch a single row */
if (apr_dbd_get_row(res->driver, res->pool, res->results,
&row, row_no) != -1)
{
lua_newtable(L);
for (x = 0; x < res->cols; x++) {
entry = apr_dbd_get_entry(res->driver, row, x);
if (entry) {
lua_pushinteger(L, x + 1);
lua_pushstring(L, entry);
lua_rawset(L, -3);
}
}
return 1;
}
return 0;
}
/*
=============================================================================
db:select(statement): Queries the database for the given statement and
returns the rows/columns found as a table. If an error is encountered,
returns nil as the first parameter and the error message as the second.
=============================================================================
*/
int lua_db_select(lua_State *L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
apr_status_t rc = 0;
const char *statement;
request_rec *r;
/*~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
luaL_checktype(L, 3, LUA_TSTRING);
statement = lua_tostring(L, 3);
db = lua_get_db_handle(L);
if (db && db->alive) {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int cols;
apr_dbd_results_t *results = 0;
lua_db_result_set* resultset = NULL;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
rc = apr_dbd_select(db->driver, db->pool, db->handle,
&results, statement, 0);
if (rc == APR_SUCCESS) {
cols = apr_dbd_num_cols(db->driver, results);
if (cols > 0) {
lua_newtable(L);
resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
resultset->cols = cols;
resultset->driver = db->driver;
resultset->pool = db->pool;
resultset->rows = apr_dbd_num_tuples(db->driver, results);
resultset->results = results;
luaL_newmetatable(L, "lua_apr.dbselect");
lua_pushliteral(L, "__call");
lua_pushcfunction(L, lua_db_get_row);
lua_rawset(L, -3);
lua_setmetatable(L, -3);
lua_rawseti(L, -2, 0);
return 1;
}
return 0;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *err = apr_dbd_error(db->driver, db->handle, rc);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
}
}
lua_pushboolean(L, 0);
return 1;
}
return 0;
}
/*
=============================================================================
statement:select(var1, var2, var3...): Injects variables into a prepared
statement and returns the number of rows matching the query.
=============================================================================
*/
int lua_db_prepared_select(lua_State *L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_prepared_statement *st = 0;
apr_status_t rc = 0;
const char **vars;
int x, have;
/*~~~~~~~~~~~~~~~~~~~~~~~*/
/* Fetch the prepared statement and the vars passed */
luaL_checktype(L, 1, LUA_TTABLE);
lua_rawgeti(L, 1, 0);
luaL_checktype(L, -1, LUA_TUSERDATA);
st = (lua_db_prepared_statement*) lua_topointer(L, -1);
/* Check if we got enough variables passed on to us.
* This, of course, only works for prepped statements made through lua. */
have = lua_gettop(L) - 2;
if (st->variables != -1 && have < st->variables ) {
lua_pushboolean(L, 0);
lua_pushfstring(L,
"Error in executing prepared statement: Expected %d arguments, got %d.",
st->variables, have);
return 2;
}
vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
for (x = 0; x < have; x++) {
vars[x] = lua_tostring(L, x + 2);
}
/* Fire off the query */
if (st->db && st->db->alive) {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int cols;
apr_dbd_results_t *results = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
rc = apr_dbd_pselect(st->db->driver, st->db->pool, st->db->handle,
&results, st->statement, 0, have, vars);
if (rc == APR_SUCCESS) {
/*~~~~~~~~~~~~~~~~~~~~~*/
lua_db_result_set *resultset;
/*~~~~~~~~~~~~~~~~~~~~~*/
cols = apr_dbd_num_cols(st->db->driver, results);
lua_newtable(L);
resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
resultset->cols = cols;
resultset->driver = st->db->driver;
resultset->pool = st->db->pool;
resultset->rows = apr_dbd_num_tuples(st->db->driver, results);
resultset->results = results;
luaL_newmetatable(L, "lua_apr.dbselect");
lua_pushliteral(L, "__call");
lua_pushcfunction(L, lua_db_get_row);
lua_rawset(L, -3);
lua_setmetatable(L, -3);
lua_rawseti(L, -2, 0);
return 1;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
}
lua_pushboolean(L, 0);
lua_pushliteral(L,
"Database connection seems to be closed, please reacquire it.");
return (2);
}
/*
=============================================================================
statement:query(var1, var2, var3...): Injects variables into a prepared
statement and returns the number of rows affected.
=============================================================================
*/
int lua_db_prepared_query(lua_State *L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_prepared_statement *st = 0;
apr_status_t rc = 0;
const char **vars;
int x, have;
/*~~~~~~~~~~~~~~~~~~~~~~~*/
/* Fetch the prepared statement and the vars passed */
luaL_checktype(L, 1, LUA_TTABLE);
lua_rawgeti(L, 1, 0);
luaL_checktype(L, -1, LUA_TUSERDATA);
st = (lua_db_prepared_statement*) lua_topointer(L, -1);
/* Check if we got enough variables passed on to us.
* This, of course, only works for prepped statements made through lua. */
have = lua_gettop(L) - 2;
if (st->variables != -1 && have < st->variables ) {
lua_pushboolean(L, 0);
lua_pushfstring(L,
"Error in executing prepared statement: Expected %d arguments, got %d.",
st->variables, have);
return 2;
}
vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
for (x = 0; x < have; x++) {
vars[x] = lua_tostring(L, x + 2);
}
/* Fire off the query */
if (st->db && st->db->alive) {
/*~~~~~~~~~~~~~~*/
int affected = 0;
/*~~~~~~~~~~~~~~*/
rc = apr_dbd_pquery(st->db->driver, st->db->pool, st->db->handle,
&affected, st->statement, have, vars);
if (rc == APR_SUCCESS) {
lua_pushinteger(L, affected);
return 1;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
}
lua_pushboolean(L, 0);
lua_pushliteral(L,
"Database connection seems to be closed, please reacquire it.");
return (2);
}
/*
=============================================================================
db:prepare(statement): Prepares a statement for later query/select.
Returns a table with a :query and :select function, same as the db funcs.
=============================================================================
*/
int lua_db_prepare(lua_State* L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
apr_status_t rc = 0;
const char *statement, *at;
request_rec *r;
lua_db_prepared_statement* st;
int need = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
apr_dbd_prepared_t *pstatement = NULL;
luaL_checktype(L, 3, LUA_TSTRING);
statement = lua_tostring(L, 3);
/* Count number of variables in statement */
at = ap_strchr_c(statement,'%');
while (at != NULL) {
if (at[1] == '%') {
at++;
}
else {
need++;
}
at = ap_strchr_c(at+1,'%');
}
db = lua_get_db_handle(L);
rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement,
NULL, &pstatement);
if (rc != APR_SUCCESS) {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *err = apr_dbd_error(db->driver, db->handle, rc);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
/* Push the prepared statement table */
lua_newtable(L);
st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
st->statement = pstatement;
st->variables = need;
st->db = db;
lua_pushliteral(L, "select");
lua_pushcfunction(L, lua_db_prepared_select);
lua_rawset(L, -4);
lua_pushliteral(L, "query");
lua_pushcfunction(L, lua_db_prepared_query);
lua_rawset(L, -4);
lua_rawseti(L, -2, 0);
return 1;
}
return 0;
}
/*
=============================================================================
db:prepared(statement): Fetches a prepared statement made through
DBDPrepareSQL.
=============================================================================
*/
int lua_db_prepared(lua_State* L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
const char *tag;
request_rec *r;
lua_db_prepared_statement* st;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
apr_dbd_prepared_t *pstatement = NULL;
db = lua_get_db_handle(L);
luaL_checktype(L, 3, LUA_TSTRING);
tag = lua_tostring(L, 3);
/* Look for the statement */
pstatement = apr_hash_get(db->dbdhandle->prepared, tag,
APR_HASH_KEY_STRING);
if (pstatement == NULL) {
lua_pushnil(L);
lua_pushfstring(L,
"Could not find any prepared statement called %s!", tag);
return 2;
}
/* Push the prepared statement table */
lua_newtable(L);
st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
st->statement = pstatement;
st->variables = -1; /* we don't know :( */
st->db = db;
lua_pushliteral(L, "select");
lua_pushcfunction(L, lua_db_prepared_select);
lua_rawset(L, -4);
lua_pushliteral(L, "query");
lua_pushcfunction(L, lua_db_prepared_query);
lua_rawset(L, -4);
lua_rawseti(L, -2, 0);
return 1;
}
return 0;
}
/* lua_push_db_handle: Creates a database table object with database functions
and a userdata at index 0, which will call lua_dbgc when garbage collected.
*/
static lua_db_handle* lua_push_db_handle(lua_State *L, request_rec* r, int type,
apr_pool_t* pool)
{
lua_db_handle* db;
lua_newtable(L);
db = lua_newuserdata(L, sizeof(lua_db_handle));
db->alive = 1;
db->pool = pool;
db->type = type;
db->dbdhandle = 0;
db->server = r->server;
luaL_newmetatable(L, "lua_apr.dbacquire");
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, lua_db_gc);
lua_rawset(L, -3);
lua_setmetatable(L, -2);
lua_rawseti(L, -2, 0);
lua_pushliteral(L, "escape");
lua_pushcfunction(L, lua_db_escape);
lua_rawset(L, -3);
lua_pushliteral(L, "close");
lua_pushcfunction(L, lua_db_close);
lua_rawset(L, -3);
lua_pushliteral(L, "select");
lua_pushcfunction(L, lua_db_select);
lua_rawset(L, -3);
lua_pushliteral(L, "query");
lua_pushcfunction(L, lua_db_query);
lua_rawset(L, -3);
lua_pushliteral(L, "active");
lua_pushcfunction(L, lua_db_active);
lua_rawset(L, -3);
lua_pushliteral(L, "prepare");
lua_pushcfunction(L, lua_db_prepare);
lua_rawset(L, -3);
lua_pushliteral(L, "prepared");
lua_pushcfunction(L, lua_db_prepared);
lua_rawset(L, -3);
return db;
}
/*
=============================================================================
dbacquire(dbType, dbString): Opens a new connection to a database of type
_dbType_ and with the connection parameters _dbString_. If successful,
returns a table with functions for using the database handle. If an error
occurs, returns nil as the first parameter and the error message as the
second. See the APR_DBD for a list of database types and connection strings
supported.
=============================================================================
*/
AP_LUA_DECLARE(int) lua_db_acquire(lua_State *L)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *type;
const char *arguments;
const char *error = 0;
request_rec *r;
lua_db_handle *db = 0;
apr_status_t rc = 0;
ap_dbd_t *dbdhandle = NULL;
apr_pool_t *pool = NULL;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 1);
if (r) {
type = luaL_optstring(L, 2, "mod_dbd"); /* Defaults to mod_dbd */
if (!strcmp(type, "mod_dbd")) {
lua_settop(L, 0);
lua_ap_dbd_open = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_open);
if (lua_ap_dbd_open)
dbdhandle = (ap_dbd_t *) lua_ap_dbd_open(
r->server->process->pool, r->server);
if (dbdhandle) {
db = lua_push_db_handle(L, r, LUA_DBTYPE_MOD_DBD, dbdhandle->pool);
db->driver = dbdhandle->driver;
db->handle = dbdhandle->handle;
db->dbdhandle = dbdhandle;
return 1;
}
else {
lua_pushnil(L);
if ( lua_ap_dbd_open == NULL )
lua_pushliteral(L,
"mod_dbd doesn't seem to have been loaded.");
else
lua_pushliteral(
L,
"Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem.");
return 2;
}
}
else {
rc = apr_pool_create(&pool, NULL);
if (rc != APR_SUCCESS) {
lua_pushnil(L);
lua_pushliteral(L, "Could not allocate memory for database!");
return 2;
}
apr_pool_tag(pool, "lua_dbd_pool");
apr_dbd_init(pool);
rc = apr_dbd_get_driver(r->server->process->pool, type, &db->driver);
if (rc == APR_SUCCESS) {
luaL_checktype(L, 3, LUA_TSTRING);
arguments = lua_tostring(L, 3);
lua_settop(L, 0);
if (strlen(arguments)) {
rc = apr_dbd_open_ex(db->driver, r->server->process->pool,
arguments, &db->handle, &error);
if (rc == APR_SUCCESS) {
db = lua_push_db_handle(L, r, LUA_DBTYPE_APR_DBD, pool);
db->driver = dbdhandle->driver;
db->handle = dbdhandle->handle;
db->dbdhandle = dbdhandle;
return 1;
}
else {
lua_pushnil(L);
if (error) {
lua_pushstring(L, error);
return 2;
}
return 1;
}
}
lua_pushnil(L);
lua_pushliteral(L,
"No database connection string was specified.");
return (2);
}
else {
lua_pushnil(L);
if (APR_STATUS_IS_ENOTIMPL(rc)) {
lua_pushfstring(L,
"driver for %s not available", type);
}
else if (APR_STATUS_IS_EDSOOPEN(rc)) {
lua_pushfstring(L,
"can't find driver for %s", type);
}
else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) {
lua_pushfstring(L,
"driver for %s is invalid or corrupted",
type);
}
else {
lua_pushliteral(L,
"mod_lua not compatible with APR in get_driver");
}
lua_pushinteger(L, rc);
return 3;
}
}
lua_pushnil(L);
return 1;
}
return 0;
}