D.69. ODBC_funktionsname()

ODBC_funktionsname(arg1[,arg2[,...]]])

Wichtig

Diese Funktionsbeschreibung dient als Platzhalter für eigene, vom Anwender in der Datei func_odbc.conf definierte ODBC_...()-Funktionen.
In der Asterisk-Konfigurationsdatei func_odbc.conf können eigene Funktionen zum Lesen aus einer und zum Schreiben in eine ODBC[225]-Datenbank definiert werden. Diese Funktionen stehen dann im Dialplan als normale Funktionen zur Verfügung.

/etc/asterisk/res_odbc.conf

Für Asterisk muss diese Datenquelle in der /etc/asterisk/res_odbc.conf eingetragen werden:
[meine_db_verbindung]
dsn => meine_db_verbindung
;username => myuser
;password => mypass
pre-connect => yes
enabled => yes
pre-connect besagt, dass die Verbindung zu dieser Datenbank schon aufgebaut wird, bevor sie von einer Funktion benötigt wird.
Nach einem Neustart von Asterisk wird diese Datenquelle auf dem Asterisk-CLI angezeigt:
*CLI> odbc show 
Name: meine_db_verbindung
DSN: meine_db_verbindung
Pooled: no
Connected: yes

/etc/asterisk/func_odbc.conf

Die einzelnen ODBC-Funktionen für Asterisk werden in der /etc/asterisk/func_odbc.conf definiert. Jeder Abschnitt definiert eine eigene Funktion. Funktionsnamen bestehen in Asterisk normalerweise immer aus Großbuchstaben. Hier hat man die Wahl, das entweder so zu übernehmen oder Kleinbuchstaben zu verwenden. Beachten Sie dabei, dass im Dialplan bei den Funktionsnamen zwischen Groß- und Kleinschreibung unterschieden wird.
Eine mit [BEISPIEL] definierte Funktion würde im Dialplan als ODBC_BEISPIEL() aufgerufen. Wer will, kann durch Angabe von prefix=XYZ auch ein anderes Präfix verwenden. Im Dialplan hieße die Funktion dann XYZ_BEISPIEL().
Für jede Funktion zwingend notwendig ist die Angabe des ODBC-DSN mit dem Parameter dsn=Datenquelle. Mit read=SQL-Abfrage kann man die SQL-Abfrage zum Lesen angeben (ab Asterisk 1.6: readsql), mit write=SQL-Befehl den SQL-Befehl zum Schreiben (ab Asterisk 1.6: writesql).

Anmerkung

In Asterisk 1.4 sollte man für read nur solche Abfragen verwenden, die nicht mehr als eine Ergebniszeile zurückliefern, denn auf die weiteren kann im Dialplan nicht zugegriffen werden. Ab Asterisk 1.6 gibt es den optionalen Parameter mode=multirow, siehe Abschnitt D.68, „ODBC_FETCH().

Beispiel, um Anrufe von Exfreundinnen nicht durchzustellen:

MySQL-Tabelle:
CREATE TABLE `exfreundinnen` (
 `callerid` varchar(20) character set ascii NOT NULL,
 `vorname`  varchar(50) collate utf8_unicode_ci NOT NULL,
 `nachname` varchar(50) collate utf8_unicode_ci NOT NULL,
 UNIQUE KEY `callerid` (`callerid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
func_odbc.conf:
[ANTI_EXFREUNDIN]
dsn = meine_db_verbindung
read = SELECT COUNT(*) FROM `exfreundinnen` WHERE `callerid`='${SQL_ESC(${ARG1})}'
Die Argumente des Aufrufs im Dialplan werden hier als ${ARG1}, ${ARG2} usw. übergeben. Dabei ist es wichtig, Argumente (vor allem Strings) immer in einfachen Anführungszeichen zu schreiben und wie im Beispiel mit SQL_ESC() (Abschnitt D.96, „SQL_ESC()) zu maskieren.
Die obige Funktion zum Lesen (read) würde im Dialplan folgendermaßen aufgerufen:
20 => {
    // Lesen:
    Set(ARRAY(anz)=${ODBC_ANTI_EXFREUNDIN(${CALLERID(num)})});
    Verbose(1,### ODBC-Ergebnis: ${anz});
    if ("${anz}" != "0") {
        Busy(5);
    }
    else {
        Dial(SIP/xyz);
    }
    Hangup();
}

Beispiel für eine Rückwärtssuche aus einer Kontaktliste:

MySQL-Tabelle:
CREATE TABLE `kontakte` (
 `telnr`    varchar(20) character set ascii NOT NULL,
 `vorname`  varchar(50) collate utf8_unicode_ci NOT NULL,
 `nachname` varchar(50) collate utf8_unicode_ci NOT NULL,
 UNIQUE KEY `telnr` (`telnr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
func_odbc.conf:
[RUECKWAERTSSUCHE]
dsn = meine_db_verbindung
read = SELECT `vorname`, `nachname` FROM `kontakte` WHERE `telnr`='${SQL_ESC(${ARG1})}'
Dialplan:
_X. => {
    // Lesen:
    Set(ARRAY(vn,nn)=${ODBC_RUECKWAERTSSUCHE(${CALLERID(num)})});
    Verbose(1,### ODBC-Ergebnis: ${vn}\,${nn});
    Set(CALLERID(name)=${vn} ${nn});
    Dial(SIP/${EXTEN});
    Hangup();
}

Tipp

Ab Asterisk 1.6 bietet es sich bei den ODBC_*-Funktionen an, statt mit ARRAY() mit HASH() (Abschnitt D.43, „HASH()) zu arbeiten. Beispiel:
Set(HASH(kontakt)=${ODBC_RUECKWAERTSSUCHE(${CALLERID(num)})});
Verbose(1,### Vorname  : ${HASH(kontakt,vorname)});
Verbose(1,### Nachname : ${HASH(kontakt,nachname)});

Beispiel für eine Nicht-Stören-Funktion (DND):

MySQL-Tabelle:
CREATE TABLE `dndstates` (
 `extension` varchar(4) character set ascii NOT NULL,
 `dnd`       tinyint(1) unsigned NOT NULL default '0',
 `modified`  int(10) unsigned NOT NULL default '0',
 PRIMARY KEY  (`extension`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
func_odbc.conf:
[DND]
dsn = meine_db_verbindung
read = SELECT `dnd`, `modified` FROM `dndstates` WHERE `extension`='${SQL_ESC(${ARG1})}'
write = REPLACE INTO `dndstates` SET `extension`='${SQL_ESC(${ARG1})}', `dnd`='${SQL_ESC(${VAL1})}', `modified`='${SQL_ESC(${VAL2})}'
Dialplan:
// DND aktivieren/deaktivieren
_*2[01] => {
    Set(an_aus=${EXTEN:2:1});
    Set(nst=${CALLERID(num)});
    if (${LEN(${nst})} < 5) {
        Verbose(1,### Setze DND fuer Nst. ${nst} auf ${an_aus});
        // Schreiben:
        Set(ODBC_DND(${nst})=${an_aus}\,${EPOCH});
    }
    Hangup();
}

// Nst. anrufen
_X. => {
    // Lesen:
    Set(ARRAY(dnd,modified)=${ODBC_DND(${EXTEN})});
    if ("${dnd}" = "1") {
        Verbose(1,### DND fuer Nst. ${EXTEN} ist aktiviert seit ${STRFTIME(${modified},Europe/Berlin,%c)});
        Busy(5);
    }
    else {
        Verbose(1,### DND fuer Nst. ${EXTEN} ist nicht aktiviert);
        Dial(SIP/${nst});
    }
    Hangup();
}

Wichtig

Bitte beachten Sie, dass – wie im Beispiel oben gezeigt – beim Schreiben von mehreren Werten diese durch \, getrennt werden müssen.

Beispiel für beliebige SQL-Befehle:

Ein Spezialfall, der sich in der func_odbc.conf definieren lässt, ist folgendes Konstrukt:
[SQL]
dsn = meine_db_verbindung
read = ${ARG1}
write = ${ARG1}
Damit können vom Dialplan aus beliebige SQL-Befehle ausgeführt werden, ohne dass sie vorher in der func_odbc.conf festgelegt wurden. Dabei ist natürlich zu beachten, dass das Maskieren von Sonderzeichen mit SQL_ESC() dann im Dialplan erfolgen muss. Das obige Beispiel zur Rückwärtssuche ließe sich also auch so realisieren:
Dialplan:
_X. => {
    // Lesen:
    Set(ARRAY(vn,nn)=${ODBC_SQL(SELECT `vorname`\, `nachname` FROM `kontakte` WHERE `telnr`='${SQL_ESC(${CALLERID(num)})}')});;
    Verbose(1,### ODBC-Ergebnis: ${vn} ${nn});
    Set(CALLERID(name)=${vn} ${nn});
    Dial(SIP/${EXTEN});
    Hangup();
}

Wichtig

Bitte beachten Sie, dass alle Kommas (,) im SQL-Befehl maskiert werden müssen, also als \, geschrieben werden.

Wichtig

Die unten angegebenen Asterisk-Versionen und der interne Hilfetext sind nur ein Beispiel. Dieser Hilfetext würde von Asterisk für jede selbst definierte ODBC-Funktion ausgegeben.
Asterisk-Versionen:
        |     |        | 1.4 |————————| 1.6 |————————
Interner Hilfetext zu dieser Funktion in Asterisk 1.4:
  -= Info about function 'ODBC_funktionsname' =-

[Syntax]
ODBC_funktionsname(<arg1>[...[,<argN>]])

[Synopsis]
Runs the referenced query with the specified arguments

[Description]
Runs the following query, as defined in func_odbc.conf, performing
substitution of the arguments into the query as specified by ${ARG1},
${ARG2}, ... ${ARGn}.  When setting the function, the values are provided
either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.

[...]
Differenz des internen Hilfetexts von Asterisk 1.2 zu 1.4:
- in Asterisk 1.2 nicht vorhanden -
Differenz des internen Hilfetexts von Asterisk 1.4 zu 1.6:
- keine -


[227] Alternative Methode zum Abfragen der registrierten Treiber: odbcinst -q -d

[228] Für weitere Beispiele siehe /usr/share/doc/libmyodbc/examples/odbc.ini

[229] Spezifische Optionen für den MySQL-ODBC-Treiber MyODBC können Sie unter http://dev.mysql.com/doc/refman/5.1/de/myodbc-configuration-connection-parameters.html nachlesen.