lua_dbd.c revision 4ca22cf27ccfcefab65ff6c66da12bba69e33948
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mod_lua.h"
#include "lua_apr.h"
#include "lua_dbd.h"
{
request_rec *r;
r = lua_unboxpointer(L, index);
return r;
}
{
lua_rawgeti(L, 1, 0);
}
{
lua_rawgeti(L, 1, 0);
}
/*
=============================================================================
db:close(): Closes an open database connection.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~*/
apr_status_t rc = 0;
/*~~~~~~~~~~~~~~~~~~~~*/
db = lua_get_db_handle(L);
}
else {
if (lua_ap_dbd_close != NULL)
}
}
lua_settop(L, 0);
lua_pushnumber(L, rc);
return 1;
}
/*
=============================================================================
db:__gc(): Garbage collecing function.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~*/
}
else {
if (lua_ap_dbd_close != NULL)
}
}
lua_settop(L, 0);
return 0;
}
/*
=============================================================================
db:active(): Returns true if the connection to the db is still active.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
apr_status_t rc = 0;
/*~~~~~~~~~~~~~~~~~~~~*/
db = lua_get_db_handle(L);
if (rc == APR_SUCCESS) {
lua_pushboolean(L, 1);
return 1;
}
}
lua_pushboolean(L, 0);
return 1;
}
/*
=============================================================================
db:query(statement): Executes the given database query and returns the
number of rows affected. If an error is encountered, returns nil as the
first parameter and the error message as the second.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
apr_status_t rc = 0;
int x = 0;
const char *statement;
/*~~~~~~~~~~~~~~~~~~~~~~~*/
db = lua_get_db_handle(L);
else {
rc = 0;
x = -1;
}
if (rc == APR_SUCCESS)
lua_pushnumber(L, x);
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
}
return 1;
}
/*
=============================================================================
db:escape(string): Escapes a string for safe use in the given database type.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
const char *statement;
const char *escaped = 0;
request_rec *r;
/*~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
db = lua_get_db_handle(L);
apr_dbd_init(r->pool);
if (escaped) {
lua_pushstring(L, escaped);
return 1;
}
}
else {
lua_pushnil(L);
}
return (1);
}
return 0;
}
/*
=============================================================================
resultset(N): Fetches one or more rows from a result set.
=============================================================================
*/
static int lua_db_get_row(lua_State *L)
{
int row_no,x;
const char *entry;
apr_dbd_row_t *row = 0;
lua_settop(L,0);
/* Fetch all rows at once? */
if (row_no == 0) {
row_no = 1;
lua_newtable(L);
{
lua_pushinteger(L, row_no);
lua_newtable(L);
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 */
{
lua_newtable(L);
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 nil as the first parameter and the error message as the second.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~~~*/
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) {
db = lua_get_db_handle(L);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int cols;
apr_dbd_results_t *results = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (rc == APR_SUCCESS) {
if (cols > 0) {
lua_newtable(L);
luaL_newmetatable(L, "lua_apr.dbselect");
lua_pushliteral(L, "__call");
lua_rawset(L, -3);
lua_setmetatable(L, -3);
lua_rawseti(L, -2, 0);
return 1;
}
return 0;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
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.
=============================================================================
*/
static 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 */
lua_rawgeti(L, 1, 0);
/* Check if we got enough variables passed on to us.
* This, of course, only works for prepped statements made through lua. */
lua_pushboolean(L, 0);
"Error in executing prepared statement: Expected %d arguments, got %d.",
return 2;
}
for (x = 0; x < have; x++) {
}
/* Fire off the query */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int cols;
apr_dbd_results_t *results = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (rc == APR_SUCCESS) {
/*~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~*/
lua_newtable(L);
luaL_newmetatable(L, "lua_apr.dbselect");
lua_pushliteral(L, "__call");
lua_rawset(L, -3);
lua_setmetatable(L, -3);
lua_rawseti(L, -2, 0);
return 1;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
}
lua_pushboolean(L, 0);
"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.
=============================================================================
*/
static 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 */
lua_rawgeti(L, 1, 0);
/* Check if we got enough variables passed on to us.
* This, of course, only works for prepped statements made through lua. */
lua_pushboolean(L, 0);
"Error in executing prepared statement: Expected %d arguments, got %d.",
return 2;
}
for (x = 0; x < have; x++) {
}
/* Fire off the query */
/*~~~~~~~~~~~~~~*/
int affected = 0;
/*~~~~~~~~~~~~~~*/
if (rc == APR_SUCCESS) {
lua_pushinteger(L, affected);
return 1;
}
else {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
}
lua_pushboolean(L, 0);
"Database connection seems to be closed, please reacquire it.");
return (2);
}
/*
=============================================================================
Returns a table with a :query and :select function, same as the db funcs.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
apr_status_t rc = 0;
request_rec *r;
int need = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
/* Count number of variables in statement */
at++;
}
else {
need++;
}
}
db = lua_get_db_handle(L);
NULL, &pstatement);
if (rc != APR_SUCCESS) {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_pushnil(L);
if (err) {
lua_pushstring(L, err);
return 2;
}
return 1;
}
/* Push the prepared statement table */
lua_newtable(L);
lua_pushliteral(L, "select");
lua_rawset(L, -4);
lua_pushliteral(L, "query");
lua_rawset(L, -4);
lua_rawseti(L, -2, 0);
return 1;
}
return 0;
}
/*
=============================================================================
db:prepared(statement): Fetches a prepared statement made through
DBDPrepareSQL.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
lua_db_handle *db = 0;
const char *tag;
request_rec *r;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 2);
if (r) {
db = lua_get_db_handle(L);
/* Look for the statement */
if (pstatement == NULL) {
lua_pushnil(L);
"Could not find any prepared statement called %s!", tag);
return 2;
}
/* Push the prepared statement table */
lua_newtable(L);
lua_pushliteral(L, "select");
lua_rawset(L, -4);
lua_pushliteral(L, "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.
*/
{
lua_newtable(L);
luaL_newmetatable(L, "lua_apr.dbacquire");
lua_pushliteral(L, "__gc");
lua_rawset(L, -3);
lua_setmetatable(L, -2);
lua_rawseti(L, -2, 0);
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.
=============================================================================
*/
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const char *type;
const char *arguments;
const char *error = 0;
request_rec *r;
lua_db_handle *db = 0;
apr_status_t rc = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
r = ap_lua_check_request_rec(L, 1);
if (r) {
lua_settop(L, 0);
if (lua_ap_dbd_open)
if (dbdhandle) {
return 1;
}
else {
lua_pushnil(L);
if ( lua_ap_dbd_open == NULL )
"mod_dbd doesn't seem to have been loaded.");
else
L,
"Could not acquire connection from mod_dbd. If your database is running, this may indicate a permission problem.");
return 2;
}
}
else {
if (rc != APR_SUCCESS) {
lua_pushnil(L);
lua_pushliteral(L, "Could not allocate memory for database!");
return 2;
}
if (rc == APR_SUCCESS) {
lua_settop(L, 0);
if (rc == APR_SUCCESS) {
return 1;
}
else {
lua_pushnil(L);
if (error) {
lua_pushstring(L, error);
return 2;
}
return 1;
}
}
lua_pushnil(L);
"No database connection string was specified.");
return (2);
}
else {
lua_pushnil(L);
if (APR_STATUS_IS_ENOTIMPL(rc)) {
"driver for %s not available", type);
}
else if (APR_STATUS_IS_EDSOOPEN(rc)) {
"can't find driver for %s", type);
}
else if (APR_STATUS_IS_ESYMNOTFOUND(rc)) {
"driver for %s is invalid or corrupted",
type);
}
else {
"mod_lua not compatible with APR in get_driver");
}
lua_pushinteger(L, rc);
return 3;
}
}
lua_pushnil(L);
return 1;
}
return 0;
}