Asterisk func_odbc

SQL операции func_odbc.conf,
как функции диалплана Asterisk.
Подробное руководство. Примеры.

Основы func_odbc

Имена функций (контекстов) рекомендуется задавать в верхнем регистре, но, тем не менее, имена чувствительны к регистру.

 [TEST]

Каждый созданный контекст становиться отдельной функцией, которая и вызывается в диалплане.
Т.е., если в этом файле определен контекст [TEST], то выполнив перезагрузку модуля
module reload func_odbc.so мы увидим созданную функцию: core show function ODBC <Tab>

CLI> core show function ODBC
ODBC        ODBC_FETCH  ODBC_TEST

Для соединения с хранилищем определяется категория DSN из конфига Asterisk: res_odbc.conf

 dsn=mysql1

Переменные аргументов ${ARGn}

Вызывая функцию в диалплане, оператору SQL передаются аргументы, перечисленные через запятую:

ODBC_FUNCTION_NAME(<arg1>, <arg2> … <argN>)

Которые затем получаются оператором SQL в переменных ${ARG1},${ARG2},…${ARGn}:

 exten => _555,1,Dial(Local/${ODBC_FUNCTION_NAME(${EXTEN})}@from-internal/n,30,tr)
 readsql => SELECT src FROM cdr WHERE dst='${ARG1}' ORDER BY calldate DESC LIMIT 1;

Переменные значений ${VARn}

ODBC_FUNCTION_NAME(<arg1>, <arg2> … <argN>)=<val1>,<val2>…<valN>

Дополнительно возможно получить значения для записи в переменных ${VAR1},${VAR2},…${VARn} :

exten => h,1,Set(ODBC_FUNCTION_NAME(${UNIQUEID})=/record/${UNIQUEID}.mp3)

где, VAR1=/record/${UNIQUEID}.mp3, а ARG1=${UNIQUEID}:

writesql=UPDATE cdr SET userfield='${VAL1}' WHERE uniqueid='${ARG1}'

Полная строка ${VALUE}

И наконец, чтобы получить полную строку из диалплана, без разбора, используется переменная ${VALUE}:

 exten => _2666,1,set(ODBC_COS1()=${SQL_ESC(INSERT INTO cos1 (master,slave) VALUE (2666,3999))})
[COS1]
dsn=mysql2
writesql=${VALUE}

Чтобы экранировать данные, в которых могут использоваться одинарные кавычки « ' »
(иначе используются для выделения данных в SQL запросе),
используется функция диалплана SQL_ESC().

Функция ODBC_FETCH обрабатывает много-строчные SQL запросы и зависит от параметра mode=multirow:

Set(_i=${ODBC_FETCH(${ODBC_FOO(${foo})})})

general func_odbc.conf

single_db_connection

Asterisk использует отдельные соединения для каждой операции с базой данных.
Если 'single_db_connection' включена, то func_odbc будет использовать общее
подключение к базе данных по одному DSN.
Эта означает, что второй вызов func_odbc работает по тому же соединению.
Обратите внимание, что потребуются дополнительные действия в диалплане, чтобы это работало.
Вместо этого можно использовать хранимые процедуры (набор SQL-инструкций) на сервере SQL.
Эта опция по умолчанию отключена.

 [general]
 single_db_connection=no

Параметры функций func_odbc.conf

readhandle

Разделенный запятыми список DSN (из конфига res_odbc.conf.
Каждый DSN из списка испытывается пока не удастся успешная операция 'readsql'.
Можно указать до 5-ти DSN для каждого класса функций. По умолчанию не задано.

 readhandle=mysql1,mysql2

writehandle

Разделенный запятыми список DSN (из конфига res_odbc.conf.
Каждый DSN из списка испытывается пока не удастся успешная операция 'writesql'.
Можно указать до 5-ти DSN для каждого класса функций. Параметр 'dsn' синоним 'writehandle'.
По умолчанию не задано.

 writehandle=pgsql1,pgsql2

readsql,writesql

  • readsql - операция класса функций для чтения данных.
  • writesql - операция класса функцийй для записи данных.
  • insertsql - Данный параметр указан в оригинальном конфиге Asterisk, но судя по всему, не поддерживается (Asterisk 14)

prefix "ODBC"

По умолчанию все имена классов функций начинаются с «ODBC»
Задав префикс, можно изменить стандартное «ODBC» на ваш префикс. По умолчанию не задано.

 prefix=DIALER

escapecommas

Отключить экранирование запятых. По умолчанию экранируются.

Пример func_odbc escapecommas=no

Пример func_odbc escapecommas=no

пример: Получим значение поля 'transport' (список транcпортов sip пира)
из БД asterisk таблицы sip используемой FreePBX.
Значение по умолчанию (escapecommas=yes):
func_odbc.conf

[TEST]
dsn=asterisk
readsql=SELECT data FROM sip WHERE id = '${ARG1}' AND keyword = 'transport'
escapecommas=yes

extensions_custom.conf

exten => _4XXX,1,set(i=${ODBC_TEST(${EXTEN})})
   same =>  n,verbose(${i})
   same =>  n,hangup 

CLI>

-- Executing [4886@from-test-2:1] Set("PJSIP/fs_pjsip-00000112", "i=udp\,tcp\,tls") in new stack
-- Executing [4886@from-test-2:2] Verbose("PJSIP/fs_pjsip-00000112", "udp\,tcp\,tls") in new stack

func_odbc.conf

 escapecommas=no

extensions_custom.conf

exten => _4XXX,1,set(i=${ODBC_TEST(${EXTEN})})
   same =>  n,set(ARRAY(t1,t2,t3)=${i})
     same =>  n,verbose(${t1})
       same =>  n,verbose(${t2})
	 same =>  n,verbose(${t3})
   same =>  n,hangup 

CLI>

Set("PJSIP/fs_pjsip-00000118", "i=udp,tcp,tls") in new stack
Set("PJSIP/fs_pjsip-00000118", "ARRAY(t1,t2,t3)=udp,tcp,tls") in new stack
Verbose("PJSIP/fs_pjsip-00000118", "udp") in new stack 
Verbose("PJSIP/fs_pjsip-00000118", "tcp") in new stack
Verbose("PJSIP/fs_pjsip-00000118", "tls") in new stack

synopsis

Появится в описании функции вызываемом командой 'core show function <function name>'
в разделе synopsis:

 synopsis=def codes for spb mobile calls

mode=multirow

Этот параметр может быть установлен в 'multirow', чтобы разрешить функции возвращать множество строк.
Это меняет стандартный режим работы 'func_odbc'.
Вместо того, чтобы вернуть просто строку, он возвращает ID для функции ODBC_FETCH(),
которая, в свою очередь, возвращает уже каждую строку по отдельности.
Переменная ODBC_FETCH_STATUS возвращает значение SUCCESS или FAILURE, чтобы понять были ли получены какие-либо результаты.
По завершении должна быть выполнена команда ODBCFinish, чтобы очистить любые оставшиеся результаты.
Переменная ODBCROWS возвращает число полученных строк.

rowlimit

Задает предельное число строк, которое может быть сохранено для этого запроса.
В режиме 'multirow' функция может получить большое количество строк и переполнить память до предела.
Чтобы избежать этого задается лимит.

; ODBC_SQL - Allow an SQL statement to be built entirely in the dialplan
[SQL]
dsn=mysql1
readsql=${ARG1}

; ODBC_ANTIGF - A blacklist.
[ANTIGF]
dsn=mysql1,mysql2   ; Use mysql1 as the primary handle, but fall back to mysql2
                    ; if mysql1 is down.  Supports up to 5 comma-separated
                    ; DSNs.  "dsn" may also be specified as "readhandle" and
                    ; "writehandle", if it is important to separate reads and
                    ; writes to different databases.
readsql=SELECT COUNT(*) FROM exgirlfriends WHERE callerid='${SQL_ESC(${ARG1})}'
syntax=<callerid>
synopsis=Check if a specified callerid is contained in the ex-gf database

; ODBC_PRESENCE - Retrieve and update presence
[PRESENCE]
dsn=mysql1
readsql=SELECT location FROM presence WHERE id='${SQL_ESC(${ARG1})}'
writesql=UPDATE presence SET location='${SQL_ESC(${VAL1})}' WHERE id='${SQL_ESC(${ARG1})}'

Файлы конфигурации Asterisk

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

;
; func_odbc.conf
;
[general]
;
; Asterisk uses separate connections for every database operation.
; If single_db_connection is enabled then func_odbc will use a single
; database connection per DSN.
; This option exists for those who expect that a second func_odbc call
; works on the same connection. That allows you to do a LAST_INSERT_ID()
; in a second func_odbc call.
; Note that you'll need additional dialplan locks for this behaviour to work.
; There are better ways: using stored procedures/functions instead.
; This option is disabled by default.
;single_db_connection=no
;
;
; Each context is a separately defined function.  By convention, all
; functions are entirely uppercase, so the defined contexts should also
; be all-uppercase, but there is nothing that enforces this.  All functions
; are case-sensitive, however.
;
; For substitution, you have ${ARG1}, ${ARG2} ... ${ARGn}
; for the arguments to each SQL statement.
;
; In addition, for write statements, you have ${VAL1}, ${VAL2} ... ${VALn}
; parsed, just like arguments, for the values.  In addition, if you want the
; whole value, never mind the parsing, you can get that with ${VALUE}.
;
;
; If you have data which may potentially contain single ticks, you may wish
; to use the dialplan function SQL_ESC() to escape the data prior to its
; inclusion in the SQL statement.
;
;
; The following options are available in this configuration file:
;
; readhandle   A comma-separated list of DSNs (from res_odbc.conf) to use when
;              executing the readsql statement.  Each DSN is tried, in
;              succession, until the statement succeeds.  You may specify up to
;              5 DSNs per function class.  If not specified, it will default to
;              the value of writehandle or dsn, if specified.
; writehandle  A comma-separated list of DSNs (from res_odbc.conf) to use when
;              executing the writesql statement.  The same rules apply as to
;              readhandle.  "dsn" is a synonym for "writehandle".
; readsql      The statement to execute when reading from the function class.
; writesql     The statement to execute when writing to the function class.
; insertsql    The statement to execute when writing to the function class
;              succeeds, but initially indicates that 0 rows were affected.
; prefix       Normally, all function classes are prefixed with "ODBC" to keep
;              them uniquely named.  You may choose to change this prefix, which
;              may be useful to segregate a collection of certain function
;              classes from others.
; escapecommas This option may be used to turn off the default behavior of
;              escaping commas which occur within a field.  If commas are
;              escaped (the default behavior), then fields containing commas
;              will be treated as a single value when assigning to ARRAY() or
;              HASH().  If commas are not escaped, then values will be separated
;              at the comma within fields.  Please note that turning this option
;              off is incompatible with the functionality of HASH().
; synopsis     Appears in the synopsis field for the command
;              'core show function <function name>'
; mode         This option may be set to 'multirow' to allow the function
;              specified to return more than a single row.  However, this
;              changes the way that func_odbc normally works.  Instead of the
;              invocation of the function returning a row, it returns an opaque
;              ID, which may be passed to ODBC_FETCH() to return each row in
;              turn.  ODBC_FETCH_STATUS returns SUCCESS or FAILURE, to indicate
;              whether any results were stored, and you should call ODBC_Finish
;              on the ID to clean up any remaining results when you are done
;              with the query.  Also, the variable ODBCROWS is set initially,
;              which may be used in an iterative fashion to return each row in
;              the result.
;              Please note that multirow queries are isolated to the channel,
;              and rows may not be fetched outside of the channel where the
;              query was initially performed.  Additionally, as the results are
;              associated with a channel, mode=multirow is incompatible with
;              the global space.
; rowlimit     Rowlimit limits the total number of rows which can be stored for
;              that query.  For mode=multirow, otherwise, func_odbc will
;              attempt to store all rows in the resultset, up to the maximum
;              amount of memory.  In normal mode, rowlimit can be set to allow
;              additional rows to be fetched, rather than just the first one.
;              These additional rows can be returned by using the name of the
;              function which was called to retrieve the first row as an
;              argument to ODBC_FETCH().


; ODBC_SQL - Allow an SQL statement to be built entirely in the dialplan
[SQL]
dsn=mysql1
readsql=${ARG1}

; ODBC_ANTIGF - A blacklist.
[ANTIGF]
dsn=mysql1,mysql2   ; Use mysql1 as the primary handle, but fall back to mysql2
                    ; if mysql1 is down.  Supports up to 5 comma-separated
                    ; DSNs.  "dsn" may also be specified as "readhandle" and
                    ; "writehandle", if it is important to separate reads and
                    ; writes to different databases.
readsql=SELECT COUNT(*) FROM exgirlfriends WHERE callerid='${SQL_ESC(${ARG1})}'
syntax=<callerid>
synopsis=Check if a specified callerid is contained in the ex-gf database

; ODBC_PRESENCE - Retrieve and update presence
[PRESENCE]
dsn=mysql1
readsql=SELECT location FROM presence WHERE id='${SQL_ESC(${ARG1})}'
writesql=UPDATE presence SET location='${SQL_ESC(${VAL1})}' WHERE id='${SQL_ESC(${ARG1})}'
Только авторизованные участники могут оставлять комментарии.

Войти через: Google Facebook