SQL операции func_odbc.conf,
как функции диалплана Asterisk.
Подробное руководство. Примеры.
Имена функций (контекстов) рекомендуется задавать в верхнем регистре, но, тем не менее, имена чувствительны к регистру.
[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
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})}'