You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by hu...@apache.org on 2013/01/27 16:31:45 UTC

svn commit: r1439099 - in /httpd/httpd/branches/2.4.x: CHANGES STATUS docs/manual/mod/mod_lua.xml modules/lua/NWGNUmakefile modules/lua/config.m4 modules/lua/lua_dbd.c modules/lua/lua_dbd.h modules/lua/lua_request.c modules/lua/mod_lua.dsp

Author: humbedooh
Date: Sun Jan 27 15:31:45 2013
New Revision: 1439099

URL: http://svn.apache.org/viewvc?rev=1439099&view=rev
Log:
Backport lua dbd bindings to 2.4

Added:
    httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h
Modified:
    httpd/httpd/branches/2.4.x/CHANGES
    httpd/httpd/branches/2.4.x/STATUS
    httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml
    httpd/httpd/branches/2.4.x/modules/lua/NWGNUmakefile
    httpd/httpd/branches/2.4.x/modules/lua/config.m4
    httpd/httpd/branches/2.4.x/modules/lua/lua_request.c
    httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp

Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Sun Jan 27 15:31:45 2013
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.4.4
 
+  *) mod_lua: Add bindings for mod_dbd/apr_dbd database access.
+     [Daniel Gruno]
+     
   *) mod_proxy: Allow for persistence of local changes made via the
      balancer-manager between graceful/normal restarts and power
      cycles. [Jim Jagielski]

Modified: httpd/httpd/branches/2.4.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/STATUS (original)
+++ httpd/httpd/branches/2.4.x/STATUS Sun Jan 27 15:31:45 2013
@@ -100,22 +100,7 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
                http://mail-archives.apache.org/mod_mbox/httpd-dev/201301.mbox/%3C20130103112044.GA19653%40redhat.com%3E
         kbrand: configure option added in r1429228
 
-    * mod_lua: Add bindings for mod_dbd/apr_dbd database access.
-      trunk patch: http://svn.apache.org/r1430225
-                   http://svn.apache.org/r1430265
-                   http://svn.apache.org/r1430472
-                   http://svn.apache.org/r1430656
-                   http://svn.apache.org/r1431236 (CodeWarrior workaround)
-                   http://svn.apache.org/r1431322
-                   http://svn.apache.org/r1431930 (Windows patch)
-                   http://svn.apache.org/r1432418 (Debian patch)
-                   http://svn.apache.org/r1432892 (fix for external drivers)
-      2.4.x patch: http://www.humbedooh.com/apache/lua_dbd.patch
-                   + CHANGES
-      +1: humbedooh, covener
-      +1: fuankg (compiles/links fine now for NetWare; no functional tests yet)
-      gsmith notes: compiles/links on Windows now.
-      
+
    * mod_status: Add useful mod_status info... try to determine last time
      a specific vhost was accessed/used.
      trunk patch: https://svn.apache.org/viewvc?view=revision&revision=1417529

Modified: httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml (original)
+++ httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml Sun Jan 27 15:31:45 2013
@@ -425,6 +425,11 @@ r:parsebody([sizeLimit]) -- parse the re
         <highlight language="lua">
         r:write("a single string") -- print to response body
         </highlight>
+        
+        <highlight language="lua">
+r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and returns a database class.
+                                -- See '<a href="#databases">Database connectivity</a>' for details.
+        </highlight>
         </dd>
     </dl>
 
@@ -468,6 +473,166 @@ r:parsebody([sizeLimit]) -- parse the re
 <p>(Other HTTP status codes are not yet implemented.)</p>
 </section>
 
+<section id="databases">
+    <title>Database connectivity</title>
+    <p>
+    Mod_lua implements a simple database feature for querying and running commands
+    on the most popular database engines (mySQL, PostgreSQL, FreeTDS, ODBC, SQLite, Oracle)
+    as well as mod_dbd.
+    </p>
+    <p>Connecting and firing off queries is as easy as:</p>
+    <highlight language="lua">
+function handler(r)
+    local database, err = r:dbacquire("mysql", "server=localhost&amp;user=root&amp;database=mydb")
+    if not err then
+        local results, err = database:select(r, "SELECT `name`, `age` FROM `people` WHERE 1")
+        if not err then
+            local rows = results(0) -- fetch all rows synchronously
+            for k, row in pairs(rows) do
+                r:puts( string.format("Name: %s, Age: %s&lt;br/&gt;", row[1], row[2]) )
+            end
+        else
+            r:puts("Database query error: " .. err)
+        end
+        database:close()
+    else
+        r:puts("Could not connect to the database: " .. err)
+    end
+end
+    </highlight>
+    <p>
+    To utilize <module name="mod_dbd">mod_dbd</module>, simply specify <code>mod_dbd</code>
+    as the database type, or leave the field blank:
+    </p>
+    <highlight language="lua">
+    local database = r:dbacquire("mod_dbd")
+    </highlight>
+    <section id="database_object">
+        <title>Database object and contained functions</title>
+        <p>The database object returned by <code>dbacquire</code> has the following methods:</p>
+        <p><strong>Normal select and query from a database:</strong></p>
+    <highlight language="lua">
+-- Run a statement and return the number of rows affected:
+local affected, errmsg = database:query(r, "DELETE FROM `tbl` WHERE 1")
+
+-- Run a statement and return a result set that can be used synchronously or async:
+local result, errmsg = database:select(r, "SELECT * FROM `people` WHERE 1")
+    </highlight>
+        <p><strong>Using prepared statements (recommended):</strong></p>
+    <highlight language="lua">
+-- Create and run a prepared statement:
+local statement, errmsg = database:prepare(r, "DELETE FROM `tbl` WHERE `age` > %u")
+if not errmsg then
+    local result, errmsg = statement:query(20) -- run the statement with age >20
+end
+
+-- Fetch a prepared statement from a DBDPrepareSQL directive:
+local statement, errmsg = database:prepared(r, "someTag")
+if not errmsg then
+    local result, errmsg = statement:select("John Doe", 123) -- inject the values "John Doe" and 123 into the statement
+end
+
+</highlight>
+        <p><strong>Escaping values, closing databases etc:</strong></p>
+    <highlight language="lua">
+-- Escape a value for use in a statement:
+local escaped = database:escape(r, [["'|blabla]])
+
+-- Close a database connection and free up handles:
+database:close()
+
+-- Check whether a database connection is up and running:
+local connected = database:active()
+    </highlight>
+    </section>
+    <section id="result_sets">
+    <title>Working with result sets</title>
+    <p>The result set returned by <code>db:select</code> or by the prepared statement functions 
+    created through <code>db:prepare</code> can be used to
+    fetch rows synchronously or asynchronously, depending on the row number specified:<br/>
+    <code>result(0)</code> fetches all rows in a synchronous manner, returning a table of rows.<br/>
+    <code>result(-1)</code> fetches the next available row in the set, asynchronously.<br/>
+    <code>result(N)</code> fetches row number <code>N</code>, asynchronously:
+    </p>
+    <highlight language="lua">
+-- fetch a result set using a regular query:
+local result, err = db:select(r, "SELECT * FROM `tbl` WHERE 1")
+
+local rows = result(0) -- Fetch ALL rows synchronously
+local row = result(-1) -- Fetch the next available row, asynchronously
+local row = result(1234) -- Fetch row number 1234, asynchronously
+    </highlight>
+    <p>One can construct a function that returns an iterative function to iterate over all rows 
+    in a synchronous or asynchronous way, depending on the async argument:
+    </p>
+    <highlight language="lua">
+function rows(resultset, async)
+    local a = 0
+    local function getnext()
+        a = a + 1
+        local row = resultset(-1)
+        return row and a or nil, row
+    end
+    if not async then
+        return pairs(resultset(0))
+    else
+        return getnext, self
+    end
+end
+
+local statement, err = db:prepare(r, "SELECT * FROM `tbl` WHERE `age` > %u")
+if not err then
+     -- fetch rows asynchronously:
+    local result, err = statement:select(20)
+    if not err then
+        for index, row in rows(result, true) do
+            ....
+        end
+    end
+
+     -- fetch rows synchronously:
+    local result, err = statement:select(20)
+    if not err then
+        for index, row in rows(result, false) do
+            ....
+        end
+    end
+end
+    </highlight>
+    </section>
+    <section id="closing_databases">
+        <title>Closing a database connection</title>
+
+    <p>Database handles should be closed using <code>database:close()</code> when they are no longer
+    needed. If you do not close them manually, they will eventually be garbage collected and 
+    closed by mod_lua, but you may end up having too many unused connections to the database 
+    if you leave the closing up to mod_lua. Essentially, the following two measures are
+    the same:
+    </p>
+    <highlight language="lua">
+-- Method 1: Manually close a handle
+local database = r:dbacquire("mod_dbd")
+database:close() -- All done
+
+-- Method 2: Letting the garbage collector close it
+local database = r:dbacquire("mod_dbd")
+database = nil -- throw away the reference
+collectgarbage() -- close the handle via GC
+</highlight>
+    </section>
+    <section id="database_caveat">
+    <title>Precautions when working with databases</title>
+    <p>Although the standard <code>query</code> and <code>run</code> functions are freely 
+    available, it is recommended that you use prepared statements whenever possible, to 
+    both optimize performance (if your db handle lives on for a long time) and to minimize 
+    the risk of SQL injection attacks. <code>run</code> and <code>query</code> should only
+    be used when there are no variables inserted into a statement (a static statement). 
+    When using dynamic statements, use <code>db:prepare</code> or <code>db:prepared</code>.
+    </p>
+    </section>
+
+</section>
+
 <directivesynopsis>
 <name>LuaRoot</name>
 <description>Specify the base path for resolving relative paths for mod_lua directives</description>

Modified: httpd/httpd/branches/2.4.x/modules/lua/NWGNUmakefile
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/NWGNUmakefile?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/NWGNUmakefile (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/NWGNUmakefile Sun Jan 27 15:31:45 2013
@@ -27,6 +27,7 @@ XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
 			$(AP_WORK)/include \
+			$(AP_WORK)/modules/database \
 			$(AP_WORK)/modules/http \
 			$(AP_WORK)/modules/ssl \
 			$(NWOS) \

Modified: httpd/httpd/branches/2.4.x/modules/lua/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/config.m4?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/config.m4 (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/config.m4 Sun Jan 27 15:31:45 2013
@@ -136,7 +136,7 @@ else
 fi 
 ])
 
-lua_objects="lua_apr.lo lua_config.lo mod_lua.lo lua_request.lo lua_vmprep.lo"
+lua_objects="lua_apr.lo lua_config.lo mod_lua.lo lua_request.lo lua_vmprep.lo lua_dbd.lo"
 
 APACHE_MODULE(lua, Apache Lua Framework, $lua_objects, , , [
   CHECK_LUA()

Added: httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c?rev=1439099&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c (added)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c Sun Jan 27 15:31:45 2013
@@ -0,0 +1,825 @@
+/**
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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"
+
+APLOG_USE_MODULE(lua);
+static APR_OPTIONAL_FN_TYPE(ap_dbd_close) *lua_ap_dbd_close = NULL;
+static APR_OPTIONAL_FN_TYPE(ap_dbd_open) *lua_ap_dbd_open = NULL;
+
+
+
+
+static request_rec *ap_lua_check_request_rec(lua_State *L, int index)
+{
+    request_rec *r;
+    luaL_checkudata(L, index, "Apache2.Request");
+    r = lua_unboxpointer(L, index);
+    return r;
+}
+
+static lua_db_handle *lua_get_db_handle(lua_State *L)
+{
+    luaL_checktype(L, 1, LUA_TTABLE);
+    lua_rawgeti(L, 1, 0);
+    luaL_checktype(L, -1, LUA_TUSERDATA);
+    return (lua_db_handle *) lua_topointer(L, -1);
+}
+
+static lua_db_result_set *lua_get_result_set(lua_State *L)
+{
+    luaL_checktype(L, 1, LUA_TTABLE);
+    lua_rawgeti(L, 1, 0);
+    luaL_checktype(L, -1, LUA_TUSERDATA);
+    return (lua_db_result_set *) lua_topointer(L, -1);
+}
+
+
+/*
+   =============================================================================
+    db:close(): Closes an open database connection.
+   =============================================================================
+ */
+int lua_db_close(lua_State *L)
+{
+    /*~~~~~~~~~~~~~~~~~~~~*/
+    lua_db_handle   *db;
+    apr_status_t     rc = 0;
+    /*~~~~~~~~~~~~~~~~~~~~*/
+    
+    db = lua_get_db_handle(L);
+    if (db && db->alive) {
+        if (db->type == LUA_DBTYPE_MOD_DBD) {
+            rc = apr_dbd_close(db->driver, db->handle);
+        }
+        else {
+            lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
+            if (lua_ap_dbd_close != NULL)
+                if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
+            if (db->pool) apr_pool_destroy(db->pool);
+        }
+
+        db->driver = NULL;
+        db->handle = NULL;
+        db->alive = 0;
+        db->pool = NULL;
+    }
+
+    lua_settop(L, 0);
+    lua_pushnumber(L, rc);
+    return 1;
+} 
+
+/*
+   =============================================================================
+     db:__gc(): Garbage collecting function.
+   =============================================================================
+ */
+int lua_db_gc(lua_State *L)
+{
+    /*~~~~~~~~~~~~~~~~*/
+    lua_db_handle    *db;
+    /*~~~~~~~~~~~~~~~~~~~~*/
+
+    db = lua_touserdata(L, 1);
+    if (db && db->alive) {
+        if (db->type == LUA_DBTYPE_APR_DBD) {
+            apr_dbd_close(db->driver, db->handle);
+            if (db->pool) apr_pool_destroy(db->pool);
+        }
+        else {
+            lua_ap_dbd_close = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_close);
+            if (lua_ap_dbd_close != NULL)
+                if (db->dbdhandle) lua_ap_dbd_close(db->server, db->dbdhandle);
+        }
+        db->driver = NULL;
+        db->handle = NULL;
+        db->alive = 0;
+        db->pool = NULL;
+    }
+    lua_settop(L, 0);
+    return 0;
+}
+
+/*
+   =============================================================================
+    db:active(): Returns true if the connection to the db is still active.
+   =============================================================================
+ */
+int lua_db_active(lua_State *L)
+{
+    /*~~~~~~~~~~~~~~~~~~~~*/
+    lua_db_handle   *db = 0;
+    apr_status_t     rc = 0;
+    /*~~~~~~~~~~~~~~~~~~~~*/
+
+    db = lua_get_db_handle(L);
+    if (db && db->alive) {
+        rc = apr_dbd_check_conn(db->driver, db->pool, db->handle);
+        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.
+   =============================================================================
+ */
+int lua_db_query(lua_State *L)
+{
+    /*~~~~~~~~~~~~~~~~~~~~~~~*/
+    lua_db_handle   *db = 0;
+    apr_status_t     rc = 0;
+    int              x = 0;
+    const char      *statement;
+    /*~~~~~~~~~~~~~~~~~~~~~~~*/
+    luaL_checktype(L, 3, LUA_TSTRING);
+    statement = lua_tostring(L, 3);
+    db = lua_get_db_handle(L);
+    if (db && db->alive)
+        rc = apr_dbd_query(db->driver, db->handle, &x, statement);
+    else {
+        rc = 0;
+        x = -1;
+    }
+
+    if (rc == APR_SUCCESS)
+        lua_pushnumber(L, x);
+    else {
+
+        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+        const char  *err = apr_dbd_error(db->driver, db->handle, rc);
+        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+        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.
+   =============================================================================
+ */
+int lua_db_escape(lua_State *L)
+{
+    /*~~~~~~~~~~~~~~~~~~~~~*/
+    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) {
+        luaL_checktype(L, 3, LUA_TSTRING);
+        statement = lua_tostring(L, 3);
+        db = lua_get_db_handle(L);
+        if (db && db->alive) {
+            apr_dbd_init(r->pool);
+            escaped = apr_dbd_escape(db->driver, r->pool, statement,
+                                     db->handle);
+            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.
+   =============================================================================
+ */
+int lua_db_get_row(lua_State *L) 
+{
+    int row_no,x;
+    const char      *entry;
+    apr_dbd_row_t   *row = 0;
+    lua_db_result_set *res = lua_get_result_set(L);
+    
+    row_no = luaL_optinteger(L, 2, 0);
+    lua_settop(L,0);
+    
+    /* Fetch all rows at once? */
+    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);
+            dbdhandle = apr_pcalloc(pool, sizeof(ap_dbd_t));
+            rc = apr_dbd_get_driver(pool, type, &dbdhandle->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(dbdhandle->driver, pool, 
+                            arguments, &dbdhandle->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.");
+                apr_pool_destroy(pool);
+                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);
+                apr_pool_destroy(pool);
+                return 3;
+            }
+        }
+
+        lua_pushnil(L);
+        return 1;
+    }
+
+    return 0;
+}
+

Added: httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h?rev=1439099&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h (added)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h Sun Jan 27 15:31:45 2013
@@ -0,0 +1,66 @@
+/**
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef _LUA_DBD_H_
+#define _LUA_DBD_H_
+
+#include "mod_lua.h"
+#include "apr.h"
+#include "apr_dbd.h"
+#include "mod_dbd.h"
+
+#define LUA_DBTYPE_APR_DBD 0
+#define LUA_DBTYPE_MOD_DBD 1
+typedef struct
+{
+    apr_dbd_t               *handle;
+    const apr_dbd_driver_t  *driver;
+    int                     alive;
+    apr_pool_t              *pool;
+    char                    type;
+    ap_dbd_t *              dbdhandle;
+    server_rec              *server;
+} lua_db_handle;
+
+typedef struct {
+    const apr_dbd_driver_t  *driver;
+    int                     rows;
+    int                     cols;
+    apr_dbd_results_t       *results;
+    apr_pool_t              *pool;
+} lua_db_result_set;
+
+typedef struct {
+    apr_dbd_prepared_t      *statement;
+    int                     variables;
+    lua_db_handle           *db;
+} lua_db_prepared_statement;
+
+AP_LUA_DECLARE(int) lua_db_acquire(lua_State* L);
+int lua_db_escape(lua_State* L);
+int lua_db_close(lua_State* L);
+int lua_db_prepare(lua_State* L);
+int lua_db_prepared(lua_State* L);
+int lua_db_select(lua_State* L);
+int lua_db_query(lua_State* L);
+int lua_db_prepared_select(lua_State* L);
+int lua_db_prepared_query(lua_State* L);
+int lua_db_get_row(lua_State* L);
+int lua_db_gc(lua_State* L);
+int lua_db_active(lua_State* L);
+
+#endif /* !_LUA_DBD_H_ */

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_request.c?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_request.c (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_request.c Sun Jan 27 15:31:45 2013
@@ -18,6 +18,7 @@
 #include "mod_lua.h"
 #include "util_script.h"
 #include "lua_apr.h"
+#include "lua_dbd.h"
 
 APLOG_USE_MODULE(lua);
 
@@ -751,6 +752,8 @@ AP_LUA_DECLARE(void) ap_lua_load_request
                  makefun(&req_notes, APL_REQ_FUNTYPE_TABLE, p));
     apr_hash_set(dispatch, "subprocess_env", APR_HASH_KEY_STRING,
                  makefun(&req_subprocess_env, APL_REQ_FUNTYPE_TABLE, p));
+    apr_hash_set(dispatch, "dbacquire", APR_HASH_KEY_STRING,
+                 makefun(&lua_db_acquire, APL_REQ_FUNTYPE_LUACFUN, p));
 
 
     lua_pushlightuserdata(L, dispatch);

Modified: httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp?rev=1439099&r1=1439098&r2=1439099&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp Sun Jan 27 15:31:45 2013
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/lua/src" /I "../ssl" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_LUA_DECLARE_EXPORT" /Fd"Release\mod_lua_src" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/lua/src" /I "../ssl" /I "../database" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_LUA_DECLARE_EXPORT" /Fd"Release\mod_lua_src" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -75,7 +75,7 @@ PostBuild_Cmds=if exist $(TargetPath).ma
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/lua/src" /I "../ssl" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_LUA_DECLARE_EXPORT" /Fd"Debug\mod_lua_src" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/lua/src" /I "../ssl" /I "../database" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_LUA_DECLARE_EXPORT" /Fd"Debug\mod_lua_src" /FD /c
 # ADD BASE MTL /nologo /D "_DEBUG" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -141,6 +141,14 @@ SOURCE=.\mod_lua.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\lua_dbd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lua_dbd.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\build\win32\httpd.rc
 # End Source File
 # End Target