You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/db2_ops
Victor Seva a28575161d
Imported Upstream version 4.4.2
10 years ago
..
doc Imported Upstream version 4.0.6 12 years ago
Makefile Imported Upstream version 4.3.0 11 years ago
README Imported Upstream version 4.4.2 10 years ago
db2_ops.c Imported Upstream version 4.3.0 11 years ago

README

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 wh
en writing to db driver (string/int/double/float/datetime), valueable especially
 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 [ "/" extr
a_ops ]
        update = [database "/"] "update/" table "/" fields "/" where "/" ops "/"
 values [ "/" extra_ops ]
        replace = [database "/"] "replace/" table "/" fields "/" values [ "/" ex
tra_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.uid
");
modparam("db_ops", "declare_query", "sel2=select/subscriber/email_address,greeti
ng/uid,allow_find///%$uidparam,1");
modparam("db_ops", "declare_query", "sel3=select/silo/body/uid//inc_time/%$f.uid
");
modparam("db_ops", "declare_query", "del1=delete from location where expires<now
()"); # 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 I
NTO 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 f
oo 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 b
ody 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_nex
t_handle)) { # SELECT src_addr,dest_addr,body FROM silo WHERE uid = "%$t.uid" OR
DER BY inc_time
    @db.fetch.my_next_handle.row[-1].field[1]   .. get last dest_addr, not suppo
rted 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,received
//////"); #key=location_key,key_omit=i:3");
modparam("db_ops", "declare_query", "q2=select/location/uid,aor,contact,received
/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 loc
ation 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,i
nstance,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@bubak,
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.qu
ery.q1.count\n");
}

route["print_record"] {
        xplog("L_INFO","row_no: %@db.fetch.h0.row_no, record: %@db.fetch.h0.fiel
d[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");
}