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