Hello, fellow dev@ people, it's time for my monthly mod_lua rambling!

This time, I have set my eyes on creating bindings for the apr_dbd
features and mod_dbd in httpd. The purpose of this would be to both
enable people to easily use databases for Lua scripts, as well as lua
"modules" (hooks) in a way that both minimizes the need for external
libraries and takes advantage of mod_dbd if the module is loaded and in use.

While this could also be solved using an external library that was
required()'d in the Lua scripts, I feel that it would greatly boost the
usage and popularity of mod_lua if it were to be included as a core
feature. Otherwise, people would have to go look for external libraries,
which would both be redundant, since we already have db features inside
httpd, as well as make it more difficult to get things running with
mod_lua, as people would have to either resort to luarocks (which I find
to be quite lacking) or write/compile libraries themselves.

I do not wish to attempt to compare mod_lua to the likes of mod_php,
mod_python etc, but the ease of which these modules are hooked up with
databases of all sorts is perhaps one of the key elements in their
popularity, and I want mod_lua to be just as accessible for the _basic_
needs of a programmer/sysadmin (no, I do not want to bloat it, but I
want the core features that you need on a modern web site to be
available, and as such, db connectivity is a must)

The use-cases for this is many; Authenticating against a database with a
different approach than mod_auth_dbd, mass virtual hosting using cached
database lookups, web sites like our comments.a.o (which uses the exact
same Lua bindings as the one I am proposing, so it's been tested and is
working ;) ), my own paste bin site apaste.info (people from #httpd
probably know and use this one) and other nifty sorts of hooks and scripts.

Database objects will be assigned a metatable with a garbage collector
routine that automatically frees database handles when they are no
longer used, or they can be manually closed (which is preferred).

The bindings I propose can roughly be summarized with these example
snippets:

-------------------------
Connecting to a database:
-------------------------
function handler(r)
    local db, error = r:dbopen("mod_dbd") -- Open a mod_dbd connection
    if error then ... end
    -- or...
    local db, error = r:dbopen("mysql",
"server=localhost,user=root,database=somedb")
    -- essentially the same as mod_dbd's connection string.
    do_stuff()
    db:close() -- close the db handle (can also be done by GC)
    local still_running = db:active() -- returns false, since we closed
                                      -- the connection.
end

---------
Querying:
---------
-- Run a command and get the no. of rows affected:
local affected, err = db:do(r, "DELETE FROM `table` WHERE 1")
if err then
    print("DB error: " .. err)
else
    print("Deleted " .. affected .. " rows!")
end

-- Run a query and get the rows returned:
local rows, err = db:query(r, "SELECT `name` FROM `table` WHERE 1")
if rows then
    r:puts("We got " .. #rows " .. " results!")
    for k, row in pairs(rows) do
        print("Name: " .. row[1] .. "<br/>")
    end
else
    r:puts("DB error: " .. err)
end

-- Run a prepared statement and inject values into it:
local rows, err = db:inject(r, "SELECT `name` FROM `tbl` WHERE `id` =
%u", 1234)
if rows then
    ....
else
    ....
end


--------------
Miscellaneous:
--------------

-- escaping strings for use in db queries:
local escaped = db:escape(r, [[foo"bar'&|baz]])


So, any comments, suggestions, remarks, objections and so on is very
much welcomed. If there are no big objections to implementing this
feature, I will consider it as lazy consensus and commit the bindings to
trunk sometime soon along with updated documentation.

With regards,
Daniel.

PS: I _have_ checked and double checked the code properly this time, so
it conforms to the style requirements and works with maintainer mode. I
know I usually get something wrong, but this time I think it's as close
to perfect as it can get :) (but then again, I always write something
bad, so apologies in advance if you find a bug)

Reply via email to