
db2_ops module

Tomas Mandys

   Iptel.org

   Copyright © 2007 Tomas Mandys
     _________________________________________________________________

   Table of Contents

   1. Admin Guide

        1. Overview
        2. Dependencies
        3. ABNF syntax
        4. Parameters

              4.1. db_url (string)
              4.2. declare_query (string)
              4.3. declare_handle (string)

        5. Functions

              5.1. db_query(query | query_id [,handle] ) 
              5.2. db_close(handle) 
              5.3. db_first(handle) 
              5.4. db_next(handle) 
              5.5. db_seek(handle, row_no) 
              5.6. db_foreach(handle, route) 
              5.7. db_proper() 
              5.8. @db.query.query_id 
              5.9. @db.query.query_id.count 
              5.10. @db.query.query_id.is_empty 
              5.11. @db.query.query_id.field[m] 
              5.12. @db.query.query_id.row[n] 
              5.13. @db.query.query_id.row[n].field[m] 
              5.14. @db.fetch.handle 
              5.15. @db.fetch.handle.row_no 

        6. Examples

   List of Examples

   1.1. Example db_url
   1.2. Example declare_query
   1.3. Example declare_handle
   1.4. db_query usage
   1.5. db_close usage
   1.6. db_first usage
   1.7. db_next usage
   1.8. db_seek usage
   1.9. db_foreach usage
   1.10. db_proper usage
   1.11. db.query.query_id usage
   1.12. db.query.query_id.count usage
   1.13. db.query.query_id.is_empty usage
   1.14. db.query.query_id.field[m] usage
   1.15. db.query.query_id.row[n] usage
   1.16. db.query.query_id.row[n].field[m] usage
   1.17. db.fetch.handle usage
   1.18. db.fetch.handle.row_no usage
   1.19. db_ops common example

Chapter 1. Admin Guide

   Table of Contents

   1. Overview
   2. Dependencies
   3. ABNF syntax
   4. Parameters

        4.1. db_url (string)
        4.2. declare_query (string)
        4.3. declare_handle (string)

   5. Functions

        5.1. db_query(query | query_id [,handle] ) 
        5.2. db_close(handle) 
        5.3. db_first(handle) 
        5.4. db_next(handle) 
        5.5. db_seek(handle, row_no) 
        5.6. db_foreach(handle, route) 
        5.7. db_proper() 
        5.8. @db.query.query_id 
        5.9. @db.query.query_id.count 
        5.10. @db.query.query_id.is_empty 
        5.11. @db.query.query_id.field[m] 
        5.12. @db.query.query_id.row[n] 
        5.13. @db.query.query_id.row[n].field[m] 
        5.14. @db.fetch.handle 
        5.15. @db.fetch.handle.row_no 

   6. Examples

1. Overview

   The module introduces possibility to run SQL queries from script.

2. Dependencies

   none

3. ABNF syntax

        xltext = text_parsed_by_xl_lib
        database = type "://" user:psw "@" host "/" database_name
        field = xltext
        fields = field [ "," field ... ]
        op = "=" | "<" | ">" | "<=" | ">=" | "<>" | "!="
        where = fields
        ops = op [ "," op ... ]
        order = field
        type = "s" | "i" | "d" | "f" | "t" ; enables to force particular type w
hen writing to db driver (string/int/double/float/datetime), valueable especial
ly for datetime
        value = [type ":"] xltext
        values = value [ "," value ...]
        extra_op = name "=" [type ":"] text
        extra_ops = extra_op [ "," extra_op]

        select = [database "/"] "select/" table "/" fields "/" where "/" ops "/
" order "/" values [ "/" extra_ops ]
        insert = [database "/"] "insert/" table "/" fields "/" values [ "/" ext
ra_ops ]
        update = [database "/"] "update/" table "/" fields "/" where "/" ops "/
" values [ "/" extra_ops ]
        replace = [database "/"] "replace/" table "/" fields "/" values [ "/" e
xtra_ops ]
        delete = [database "/"] "delete/" table "/" where "/" ops "/" values [
"/" extra_ops ]
        raw_query = [database "/"] "select ...." | "insert ..." [[ / "values" [
 "/" extra_ops ]]  # not delimited by "/"
        query = (select | insert | update | replace | delete | raw_query)
        query_id = alphanum
        handle = alphanum  (plain text possible but alphanum recommended)
        declare_query_param = query_id "=" query
        declare_handle_param = handle

4. Parameters

   4.1. db_url (string)
   4.2. declare_query (string)
   4.3. declare_handle (string)

4.1. db_url (string)

   Default database URL.

   The format is:
                        db_url = database

   Example 1.1. Example db_url
        ...
        modparam("db_ops", "db_url", "mysql://ser:123@127.0.0.1:12345/ser");
        ...

4.2. declare_query (string)

   Declare query_id for @db.query_id (see select syntax) or for reference
   from  db_query(query_id).  Queries are pre-compiled therefore volatile
   stuff must be passed via parameters (AVP or so).

   The format is:
                        declare_query = declare_query_param

   Example 1.2. Example declare_query
        ...
        modparam("db_ops", "declare_query", "sel1=select/location/received/uid/
//%$f.uid");
        ...

4.3. declare_handle (string)

   Declare handle for fetching.

   The format is:
                        declare_handle = declare_handle_param

   Example 1.3. Example declare_handle
        ...
        modparam("db_ops", "declare_handle", "my_handle");
        ...

5. Functions

   5.1. db_query(query | query_id [,handle] ) 
   5.2. db_close(handle) 
   5.3. db_first(handle) 
   5.4. db_next(handle) 
   5.5. db_seek(handle, row_no) 
   5.6. db_foreach(handle, route) 
   5.7. db_proper() 
   5.8. @db.query.query_id 
   5.9. @db.query.query_id.count 
   5.10. @db.query.query_id.is_empty 
   5.11. @db.query.query_id.field[m] 
   5.12. @db.query.query_id.row[n] 
   5.13. @db.query.query_id.row[n].field[m] 
   5.14. @db.fetch.handle 
   5.15. @db.fetch.handle.row_no 

5.1.  db_query(query | query_id [,handle] )

   Executes  query and in case of SELECT returns result via handle, seeks
   the first record and returns TRUE if table is not empty. The result is
   accesible  using  @db.fetch  select. See also declare_handle. Query_id
   references to query declared using declare_query, handle references to
   query declared using declare_handle.

   Example 1.4. db_query usage
        ...
        db_query("delete/silo///");
        if (db_query("select/silo/body/uid//inc_time/%$f.uid", my_handle)) {
        ...
        }
        ...
        if (db_query(sel1, my_handle)) {

        }

5.2.  db_close(handle)

   Close  table that has been opened using db_query. Note all close after
   script processing automatically.

   Example 1.5. db_close usage
        ...
        db_close(my_handle);
        ...

5.3.  db_first(handle)

   Returns  TRUE  if  table  is  not empty. Note that rewind might not be
   supported by particular db driver.

   Example 1.6. db_first usage
        ...
        if (db_first(my_handle)) {
        ...
        }
        ...

5.4.  db_next(handle)

   Moves to the next record and returns TRUE if not EOF.

   Example 1.7. db_next usage
        ...
        if (db_next(my_handle)) {
        ...
        }
        ...

5.5.  db_seek(handle, row_no)

   Seeks  at  the  row  no  (origin  is zero) and Returns TRUE in case of
   success. Backward seek might not be supported by db driver.

   Example 1.8. db_seek usage
        ...
        if (db_seek(my_handle, $row_no)) {
        ...
        }
        ...

5.6.  db_foreach(handle, route)

   Call specific route for each row, loop is interrupted if route returns
   code <= 0. Return code of the last route call is returned as result of
   db_foreach (or -1 when no select is empty).

   Example 1.9. db_foreach usage
        route["print_row"] {
        ....
        }

        ...
        if (db_foreach(my_handle, print_row)) {
        ...
        }
        ...

5.7.  db_proper()

   Hack  which  enables using db_ops queries in failure route. Call it at
   the beginning of failure_route block.

   Example 1.10. db_proper usage
        failure_route["my_failure"] {
                db_proper();
                db_query(my_query, my_handle);
        ....
        }

5.8.  @db.query.query_id

   Returns value of the first row and the first field.

   Example 1.11. db.query.query_id usage
        if (@db.query.my_query == "my") {
        ....
        }

5.9.  @db.query.query_id.count

   Returns number of rows in select query.

   Example 1.12. db.query.query_id.count usage
        if (@db.query.my_query.count == "2") {
        ....
        }

5.10.  @db.query.query_id.is_empty

   Returns 1 if select query is empty.

   Example 1.13. db.query.query_id.is_empty usage
        if (@db.query.my_query.is_query == "1") {
                # query is empty
        }

5.11.  @db.query.query_id.field[m]

   Returns  value  of the first row and the m-th field. @*.field supports
   select_any_uri and select_any_nameaddr.

   Example 1.14. db.query.query_id.field[m] usage
        if (@db.query.my_query.field[2] == "xyz") {
                ...
        }

5.12.  @db.query.query_id.row[n]

   Returns  value  of  the  n-th row and the first field, negative values
   count from the end (-1 == last row).

   Example 1.15. db.query.query_id.row[n] usage
        if (@db.query.my_query.row[2] == "xyz") {
                ...
        }

5.13.  @db.query.query_id.row[n].field[m]

   Returns  value  of  the n-th row and the m-th field. @*.field supports
   select_any_uri and select_any_nameaddr.

   Example 1.16. db.query.query_id.row[n].field[m] usage
        if (@db.query.my_query.row[2].field[1] == "xyz") {
                ...
        }

5.14.  @db.fetch.handle

   Similar   functionality  as  @db.query  selects  with  exception  that
   operation is performed at query has been opened by db_query.

   @db.fetch.handle.count      invalidates     current     record,     do
   db_seek/db_first!

   Note all opened queries are closed in POST_SCRIPT callback not to leak
   memory.

   Example 1.17. db.fetch.handle usage
        db_query(sel1, my_handle);
        if (@db.fetch.my_handle.is_empty == "0") {
                if (@db.fetch.my_handle == "xyz") {

                }
        }
        db_close(my_handle);

5.15.  @db.fetch.handle.row_no

   Returns current row number (origin is zero).

   Example 1.18. db.fetch.handle.row_no usage
        db_query(sel1, my_handle);
        ...
        db_next(my_handle);
        if (@db.handle == "xyz") {
                db_next(my_handle);
        }
        if (@db.fetch.my_handle.row_no == "1") {

                }
        }
        if (@db.fetch.my_handle.count == "10") {
                ...
        }
        if (@db.fetch.my_handle.row_no == "1") {        # always false because
.count has invalidated current record!

        }
        db_close(my_handle);

6. Examples

   Example 1.19. db_ops common example
modparam("db_ops", "declare_query", "sel1=select/location/received/uid///%$f.ui
d");
modparam("db_ops", "declare_query", "sel2=select/subscriber/email_address,greet
ing/uid,allow_find///%$uidparam,1");
modparam("db_ops", "declare_query", "sel3=select/silo/body/uid//inc_time/%$f.ui
d");
modparam("db_ops", "declare_query", "del1=delete from location where expires<no
w()"); # raw query

# @db.query.sel1             ..  SELECT received FROM location WHERE uid = "%$f
.uid"
# @db.query.sel1.count       ..  SELECT count(*) FROM location WHERE uid = "%$f
.uid"
# @db.query.sel2.field[0]    ..  SELECT email_address FROM subscriber WHERE uid
 = "%$f.uid" AND allow_find=1
# @db.query.sel2.field[1]    ..  SELECT greeting FROM subscriber WHERE uid = "%
$f.uid" AND allow_find=1
# @db.query.sel3.count       ..  SELECT count(*) FROM silo WHERE uid = "%$f.uid
"
# @db.query.sel1.is_empty


db_query("delete/silo///");     #  DELETE FROM silo
db_query("delete/silo/expired/<=/%Ts");     #  DELETE FROM silo WHERE expired <
= now;
db_query("insert/foo/bar,rab,abr,rbs/%$f.id,'hello world %fu',1,2");  # INSERT
INTO foo(bar,rab,abr,rbs) VALUES ("%$f.id","hello world %fu",1,2)
db_query("update/foo/rab,abr/bar//'hello world %f',1,2,%$f.id");      # UPDATE
foo SET rab="hello world %fu",rbs=45 WHERE bar="%$f.id"

db_query("mysql://pretorian:sandra@net/delete/fbi/identities//");

if (db_query("select/silo/body/uid//inc_time/%$f.uid", my_handle)) { #  SELECT
body FROM silo WHERE uid = "%$f.uid" ORDER BY inc_time
    @db.fetch.my_handle             ..  get first raw
    if (db_next(my_handle)) {
        @db.fetch.my_handle      ..  get second raw
    }
}

if (db_query("select/silo/src_addr,dest_addr,body/uid//inc_time/%$t.uid", my_ne
xt_handle)) { # SELECT src_addr,dest_addr,body FROM silo WHERE uid = "%$t.uid"
ORDER BY inc_time
    @db.fetch.my_next_handle.row[-1].field[1]   .. get last dest_addr, not supp
orted now!
}
db_close(my_handle);
db_close(my_next_handle);

# parametrization of queries
$uidparam="xx";
@db.query.sel2

$uidparam="yy";
@db.query.sel2

$uidparam="zz";
db_query(sel2, my_handle);

$uidparam="qq";
db_query(sel2, my_next_handle);
if (@db.fetch.my_handle == @db.fetch.my_next_handle) ....

db_close(my_handle);
db_close(my_next_handle);

db_query(sel3, my_handle);
forach(my_handle, PROCESS_ROW_ROUTE);
loadmodule "mysql.so"
loadmodule "xprint.so"
loadmodule "db_ops.so"
loadmodule "timer.so"

modparam("timer", "declare_timer", "timer_route,1000,,enable");

# -------------------------  request routing logic -------------------

modparam("db_ops", "db_url", "mysql://admin:123456789@127.0.0.1:12345/ser");

modparam("db_ops", "declare_query", "q1=select/location/uid,aor,contact,receive
d//////"); #key=location_key,key_omit=i:3");
modparam("db_ops", "declare_query", "q2=select/location/uid,aor,contact,receive
d/uid///%$f.uid/key=location_key,key_omit=i:1");
# select raw query not yet supported
modparam("db_ops", "declare_query", "q3=select uid,aor,contact,received from lo
cation where uid=?/%$f.uid");
modparam("db_ops", "declare_query", "q4=mysql://admin:123456789@127.0.0.1:12345
/ser/replace/location/uid,aor,contact,received,expires,q,callid,cseq,user_agent
,instance,path,service_route,assoc_uri,flags,nated_contact,term_toi/QWERTY,aor@
qqq,1.2.3.4:5678,1.2.3.4:5678;proto=tcp,d:1000,0.8,CAALL,6543,bubak,INSTANCE@bu
bak,sip:path_to_localhost,,,0,1,,");
modparam("db_ops", "declare_query", "q5=mysql://admin:123456789@127.0.0.1:12345
/ser/delete from location where uid=?/s:QWERTY");

modparam("db_ops", "declare_handle", "h0");
modparam("db_ops", "declare_handle", "h1");

route["print_count"] {
# testing count
        xplog("L_INFO", "print count\n");
        db_query("q1", "h1");
        xplog("L_INFO", "fetch: row_no: %@db.fetch.h1.row_no, count: %@db.fetch
.h1.count, row_no: %@db.fetch.h1.row_no, is_empty: %@db.fetch.h1.is_empty, row_
no: %@db.fetch.h1.row_no\n");

        xplog("L_INFO", "query: is_empty: %@db.query.q1.is_empty, count: %@db.q
uery.q1.count\n");
}

route["print_record"] {
        xplog("L_INFO","row_no: %@db.fetch.h0.row_no, record: %@db.fetch.h0.fie
ld[0], %@db.fetch.h0.field[1],  %@db.fetch.h0.field[2],  %@db.fetch.h0.field[3]
\n");

}

route["print_tbl"] {
        route("print_record");
        if (!db_next("h0")) return;
        route("print_record");
        if (!db_next("h0")) return;
        route("print_record");
        if(!db_seek("h0", 5)) return;
        route("print_record");
        if (!db_first("h0")) return;
        route("print_record");

}

route["db_test"] {

        route("print_count");

        $f.uid="QWERTY";
        xplog("L_INFO", "query #1\n");
        if (db_query("q1", "h0")) {
                route("print_tbl");
        }
        db_close("h0");

        xplog("L_INFO", "replace\n");
        db_query("q4");

        xplog("L_INFO", "query #2\n");
        if (db_query("q2", "h0")) {
                route("print_tbl");
        }
        db_close("h0");

        xplog("L_INFO", "query #3\n");
        if (db_query("q3", "h0")) {
                route("print_tbl");
        }
        db_close("h0");

        route("print_count");


        db_query("q5");
        route("print_count");


        xplog("L_INFO", "foreach\n");
        db_query("q1", "h0");
        db_foreach("h0", "print_record");

        xplog("L_INFO", "query test\n");
        xplog("L_INFO", "#0: %@db.query.q1.row[0].field[0], %@db.query.q1.row[0
].field[1], %@db.query.q1.row[0].field[2], %@db.query.q1.row[0].field[3]\n");
        xplog("L_INFO", "#1: %@db.query.q1.row[1].field[0], %@db.query.q1.row[1
].field[1], %@db.query.q1.row[1].field[2], %@db.query.q1.row[1].field[3]\n");
        xplog("L_INFO", "#3: %@db.query.q1.row[3].field[0], %@db.query.q1.row[3
].field[1], %@db.query.q1.row[3].field[2], %@db.query.q1.row[3].field[3]\n");


}

route["timer_route"] {
        xplog("L_INFO", "\n\n\ntimer\n");
        route("db_test");

        timer_enable(0, 0);
        xplog("L_INFO", "\n\n\n");
}
