103 #define DEFAULT_SINGLE_DB_CONNECTION 0 116 char readhandle[5][30];
117 char writehandle[5][30];
157 #define DSN_BUCKETS 37 161 static int dsn_hash(
const void *obj,
const int flags)
163 const struct dsn *object;
181 static int dsn_cmp(
void *obj,
void *arg,
int flags)
183 const struct dsn *object_left = obj;
184 const struct dsn *object_right = arg;
185 const char *right_key = arg;
190 right_key = object_right->
name;
193 cmp = strcmp(object_left->
name, right_key);
196 cmp = strncmp(object_left->
name, right_key, strlen(right_key));
240 strcpy(dsn->
name, name);
275 res = SQLGetConnectAttr(connection->
con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
276 if (SQL_SUCCEEDED(res)) {
277 return dead == SQL_CD_TRUE ? 1 : 0;
288 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
368 obj = (*dsn)->connection;
398 (*dsn)->connection =
NULL;
410 }
else if (obj && *obj) {
460 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->
con, &stmt);
461 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
467 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
468 if (res == SQL_ERROR && !silent) {
470 SQLINTEGER nativeerror=0, numfields=0;
471 SQLSMALLINT diagbytes=0;
472 unsigned char state[10], diagnostic[256];
474 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
475 for (i = 0; i < numfields; i++) {
476 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic,
sizeof(diagnostic), &diagbytes);
477 ast_log(
LOG_WARNING,
"SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
479 ast_log(
LOG_WARNING,
"Oh, that was good. There are really %d diagnostics?\n", (
int)numfields);
488 SQLCloseCursor(stmt);
489 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
513 char *t, varname[15];
514 int i, dsn_num, bogus_chan = 0;
515 int transactional = 0;
522 SQLHSTMT stmt =
NULL;
526 const char *
status =
"FAILURE";
529 if (!buf || !insertbuf) {
535 if (!strcmp(query->acf->name, cmd)) {
550 if (
args.argc < query->minargs) {
552 args.argc, cmd, query->minargs);
571 if (query->sql_insert) {
590 snprintf(varname,
sizeof(varname),
"%u",
args.argc);
592 for (i = 0; i <
args.argc; i++) {
593 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
599 for (i = 0; i <
values.argc; i++) {
600 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
608 if (query->sql_insert) {
618 for (i = 0; i <
args.argc; i++) {
619 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
623 for (i = 0; i <
values.argc; i++) {
624 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
636 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
640 ast_log(
LOG_WARNING,
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
653 if (!transactional) {
660 SQLRowCount(stmt, &rows);
661 SQLCloseCursor(stmt);
662 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
667 }
else if (query->sql_insert) {
668 if (!transactional) {
672 for (transactional = 0, dsn_num = 0; dsn_num < 5; dsn_num++) {
676 ast_log(
LOG_WARNING,
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
693 SQLRowCount(stmt, &rows);
694 SQLCloseCursor(stmt);
695 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
709 snprintf(varname,
sizeof(varname),
"%d", (
int)rows);
714 if (!transactional) {
729 char varname[15], rowcount[12] =
"-1";
731 int res, x, y, buflen = 0, escapecommas, rowlimit = 1, multirow = 0, dsn_num, bogus_chan = 0;
735 SQLHSTMT stmt =
NULL;
736 SQLSMALLINT colcount=0;
738 SQLSMALLINT collength;
742 const char *
status =
"FAILURE";
745 if (!sql || !colnames) {
756 if (!strcmp(query->acf->name, cmd)) {
772 if (
args.argc < query->minargs) {
774 args.argc, cmd, query->minargs);
791 snprintf(varname,
sizeof(varname),
"%u",
args.argc);
793 for (x = 0; x <
args.argc; x++) {
794 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
806 for (x = 0; x <
args.argc; x++) {
807 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
815 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
823 if (query->rowlimit) {
824 rowlimit = query->rowlimit;
829 }
else if (!bogus_chan) {
830 if (query->rowlimit > 1) {
831 rowlimit = query->rowlimit;
832 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
844 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
869 res = SQLNumResultCols(stmt, &colcount);
870 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
872 SQLCloseCursor(stmt);
873 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
886 SQLCloseCursor(stmt);
887 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
898 res = SQLFetch(stmt);
899 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
901 if (res == SQL_NO_DATA) {
909 status =
"FETCHERROR";
911 SQLCloseCursor(stmt);
912 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
925 for (y = 0; y < rowlimit; y++) {
927 for (x = 0; x < colcount; x++) {
934 SQLCloseCursor(stmt);
935 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
946 SQLLEN octetlength = 0;
948 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname,
sizeof(colname), &collength,
NULL,
NULL,
NULL,
NULL);
949 ast_debug(3,
"Got collength of %d for column '%s' (offset %d)\n", (
int)collength, colname, x);
950 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
951 snprintf(colname,
sizeof(colname),
"field%d", x);
954 SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH,
NULL, 0,
NULL, &octetlength);
968 SQLCloseCursor(stmt);
969 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
979 strcpy((
char *)resultset +
sizeof(*resultset),
ast_str_buffer(colnames));
983 buflen = strlen(buf);
985 if (indicator == SQL_NULL_DATA) {
991 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1001 buf[buflen++] =
',';
1007 if (escapecommas && (ptrcoldata[i] ==
'\\' || ptrcoldata[i] ==
',')) {
1008 buf[buflen++] =
'\\';
1010 buf[buflen++] = ptrcoldata[i];
1012 if (buflen >= len - 2) {
1016 if (ptrcoldata[i] ==
'\0') {
1022 ast_debug(2,
"buf is now set to '%s'\n", buf);
1024 ast_debug(2,
"buf is now set to '%s'\n", buf);
1027 row =
ast_calloc(1,
sizeof(*row) + buflen + 1);
1029 ast_log(
LOG_ERROR,
"Unable to allocate space for more rows in this resultset.\n");
1030 status =
"MEMERROR";
1033 strcpy((
char *)row +
sizeof(*row), buf);
1037 res = SQLFetch(stmt);
1038 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1039 if (res != SQL_NO_DATA) {
1051 snprintf(rowcount,
sizeof(rowcount),
"%d", y);
1060 snprintf(buf, len,
"%d", uid);
1075 ast_log(
LOG_ERROR,
"Rows retrieved, but unable to store it in the channel. Results fail.\n");
1077 SQLCloseCursor(stmt);
1078 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1084 odbc_store->
data = resultset;
1090 SQLCloseCursor(stmt);
1091 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1093 if (resultset && !multirow) {
1095 if (!
acf_fetch(chan,
"", buf, buf, len)) {
1109 for (; *data && out - buf <
len; data++) {
1110 if (*data ==
'\'') {
1145 resultset = store->
data;
1166 .
name =
"ODBC_FETCH",
1191 if (query->acf->name)
1192 ast_free((
char *)query->acf->name);
1207 const char *tmp2 =
NULL;
1210 if (!cfg || !catg) {
1214 if (!(*query =
ast_calloc(1,
sizeof(**query)))) {
1224 for (i = 0; i < 5; i++) {
1226 ast_copy_string((*query)->writehandle[i], writeconf.dsn[i],
sizeof((*query)->writehandle[i]));
1236 for (i = 0; i < 5; i++) {
1238 ast_copy_string((*query)->readhandle[i], readconf.dsn[i],
sizeof((*query)->readhandle[i]));
1242 for (i = 0; i < 5; i++) {
1244 ast_copy_string((*query)->readhandle[i], (*query)->writehandle[i],
sizeof((*query)->readhandle[i]));
1251 ast_log(
LOG_WARNING,
"Parameter 'read' is deprecated for category %s. Please use 'readsql' instead.\n", catg);
1255 if (!((*query)->sql_read =
ast_strdup(tmp))) {
1266 ast_log(
LOG_ERROR,
"There is SQL, but no ODBC class to be used for reading: %s\n", catg);
1273 ast_log(
LOG_WARNING,
"Parameter 'write' is deprecated for category %s. Please use 'writesql' instead.\n", catg);
1277 if (!((*query)->sql_write =
ast_strdup(tmp))) {
1285 if ((*query)->sql_write &&
ast_strlen_zero((*query)->writehandle[0])) {
1288 ast_log(
LOG_ERROR,
"There is SQL, but no ODBC class to be used for writing: %s\n", catg);
1294 if (!((*query)->sql_insert =
ast_strdup(tmp))) {
1310 if (strcasecmp(tmp,
"multirow") == 0)
1313 sscanf(tmp,
"%30d", &((*query)->rowlimit));
1317 sscanf(tmp,
"%30d", &((*query)->minargs));
1321 if (!(*query)->acf) {
1333 if (
ast_asprintf((
char **)&((*query)->acf->name),
"%s_%s", tmp, catg) < 0) {
1334 (*query)->acf->name =
NULL;
1337 if (
ast_asprintf((
char **)&((*query)->acf->name),
"ODBC_%s", catg) < 0) {
1338 (*query)->acf->name =
NULL;
1342 if (!(*query)->acf->name) {
1372 if ((*query)->sql_read && (*query)->sql_write) {
1374 "Runs the following query, as defined in func_odbc.conf, performing\n" 1375 "substitution of the arguments into the query as specified by ${ARG1},\n" 1376 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n" 1377 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 1379 "\nRead:\n%s\n\nWrite:\n%s%s%s",
1380 (*query)->sql_insert ?
1381 "If the write query affects no rows, the insert query will be\n" 1382 "performed.\n" :
"",
1384 (*query)->sql_write,
1385 (*query)->sql_insert ?
"\n\nInsert:\n" :
"",
1386 (*query)->sql_insert ? (*query)->sql_insert :
"");
1387 }
else if ((*query)->sql_read) {
1389 "Runs the following query, as defined in func_odbc.conf, performing\n" 1390 "substitution of the arguments into the query as specified by ${ARG1},\n" 1391 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s",
1392 (*query)->sql_read);
1393 }
else if ((*query)->sql_write) {
1395 "Runs the following query, as defined in func_odbc.conf, performing\n" 1396 "substitution of the arguments into the query as specified by ${ARG1},\n" 1397 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n" 1398 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 1399 "This function may only be set.\n%s\nSQL:\n%s%s%s",
1400 (*query)->sql_insert ?
1401 "If the write query affects no rows, the insert query will be\n" 1402 "performed.\n" :
"",
1403 (*query)->sql_write,
1404 (*query)->sql_insert ?
"\n\nInsert:\n" :
"",
1405 (*query)->sql_insert ? (*query)->sql_insert :
"");
1409 ast_log(
LOG_WARNING,
"Section '%s' was found, but there was no SQL to execute. Ignoring.\n", catg);
1419 if ((*query)->sql_read) {
1423 if ((*query)->sql_write) {
1436 char *char_args, varname[15];
1445 "Usage: odbc read <name> <args> [exec]\n" 1446 " Evaluates the SQL provided in the ODBC function <name>, and\n" 1447 " optionally executes the function. This function is intended for\n" 1448 " testing purposes. Remember to quote arguments containing spaces.\n";
1452 int wordlen = strlen(a->
word), which = 0;
1456 if (!strncasecmp(query->acf->name, a->
word, wordlen)) {
1457 if (++which > a->
n) {
1466 }
else if (a->
pos == 4) {
1467 static const char *
const completions[] = {
"exec",
NULL };
1485 if (!strcmp(query->acf->name, a->
argv[2])) {
1496 if (!query->sql_read) {
1497 ast_cli(a->
fd,
"The function %s has no readsql parameter.\n", a->
argv[2]);
1514 for (i = 0; i <
args.argc; i++) {
1515 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
1522 if (a->
argc == 5 && !strcmp(a->
argv[4],
"exec")) {
1526 int dsn_num, executed = 0;
1528 int rows = 0, res, x;
1529 SQLSMALLINT colcount = 0, collength;
1539 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
1547 ast_debug(1,
"Found handle %s\n", query->readhandle[dsn_num]);
1556 res = SQLNumResultCols(stmt, &colcount);
1557 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1559 SQLCloseCursor(stmt);
1560 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
1566 if (colcount <= 0) {
1567 SQLCloseCursor(stmt);
1568 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
1570 ast_cli(a->
fd,
"Returned %d columns. Query executed on handle %d:%s [%s]\n", colcount, dsn_num, query->readhandle[dsn_num],
ast_str_buffer(sql));
1575 res = SQLFetch(stmt);
1576 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1577 SQLCloseCursor(stmt);
1578 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1580 if (res == SQL_NO_DATA) {
1581 ast_cli(a->
fd,
"Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn_num, query->readhandle[dsn_num],
ast_str_buffer(sql));
1590 for (x = 0; x < colcount; x++) {
1591 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname,
sizeof(colname), &collength,
NULL,
NULL,
NULL,
NULL);
1592 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
1593 snprintf(colname,
sizeof(colname),
"field%d", x);
1597 SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH,
NULL, 0,
NULL, &octetlength);
1600 if (indicator == SQL_NULL_DATA) {
1605 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1607 SQLCloseCursor(stmt);
1608 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1619 res = SQLFetch(stmt);
1620 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1623 ast_cli(a->
fd,
"%-20.20s %s\n",
"----------",
"----------");
1625 SQLCloseCursor(stmt);
1626 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1628 ast_cli(a->
fd,
"Returned %d row%s. Query executed on handle %d [%s]\n", rows, rows == 1 ?
"" :
"s", dsn_num, query->readhandle[dsn_num]);
1652 char *char_args, *char_values, varname[15];
1661 "Usage: odbc write <name> <args> <value> [exec]\n" 1662 " Evaluates the SQL provided in the ODBC function <name>, and\n" 1663 " optionally executes the function. This function is intended for\n" 1664 " testing purposes. Remember to quote arguments containing spaces.\n";
1668 int wordlen = strlen(a->
word), which = 0;
1672 if (!strncasecmp(query->acf->name, a->
word, wordlen)) {
1673 if (++which > a->
n) {
1682 }
else if (a->
pos == 5) {
1683 static const char *
const completions[] = {
"exec",
NULL };
1701 if (!strcmp(query->acf->name, a->
argv[2])) {
1712 if (!query->sql_write) {
1713 ast_cli(a->
fd,
"The function %s has no writesql parameter.\n", a->
argv[2]);
1734 for (i = 0; i <
args.argc; i++) {
1735 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
1741 for (i = 0; i <
values.argc; i++) {
1742 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
1753 if (a->
argc == 6 && !strcmp(a->
argv[5],
"exec")) {
1757 int dsn_num, executed = 0;
1761 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
1774 SQLRowCount(stmt, &rows);
1775 SQLCloseCursor(stmt);
1776 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1778 ast_cli(a->
fd,
"Affected %d rows. Query executed on handle %d [%s]\n", (
int)rows, dsn_num, query->writehandle[dsn_num]);
1784 ast_cli(a->
fd,
"Failed to execute query.\n");
1842 if (!strcasecmp(catg,
"general")) {
1849 else if (err == EINVAL)
1952 if (!strcasecmp(catg,
"general")) {
1977 .requires =
"res_odbc",
static const char synopsis[]
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
#define ast_rwlock_rdlock(a)
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
#define AST_CLI_DEFINE(fn, txt,...)
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_realloc(p, len)
A wrapper for realloc()
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
static char * app_odbcfinish
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
String manipulation functions.
static struct ast_custom_function fetch_function
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
The arg parameter is a search key, but is not an object.
#define ast_test_flag(p, flag)
static SQLHSTMT silent_execute(struct odbc_obj *obj, void *data)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define ast_set_flag(p, flag)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define ast_str_make_space(buf, new_len)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static int unload_module(void)
#define CONFIG_STATUS_FILEINVALID
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static struct ast_threadstorage sql_buf
static int exec_odbcfinish(struct ast_channel *chan, const char *data)
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
struct odbc_obj * connection
Assume that the ao2_container is already locked.
Structure for a data store type.
char * ast_str_append_escapecommas(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas...
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
#define ao2_link_flags(container, obj, flags)
struct odbc_datastore_row::@212 list
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
#define DEFAULT_SINGLE_DB_CONNECTION
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, without removing any previously set value...
void ast_cli(int fd, const char *fmt,...)
#define ast_rwlock_unlock(a)
static SQLHSTMT generic_execute(struct odbc_obj *obj, void *data)
int ast_unregister_application(const char *app)
Unregister an application.
#define ast_verb(level,...)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
static struct ast_custom_function escape_function
struct odbc_obj * ast_odbc_retrieve_transaction_obj(struct ast_channel *chan, const char *objname)
Retrieve an ODBC transaction connection with the given ODBC class name.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_strlen_zero(foo)
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
unsigned int ast_odbc_get_max_connections(const char *name)
Return the current configured maximum number of connections for a class.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static int dsn_hash(const void *obj, const int flags)
#define AST_RWLIST_INSERT_HEAD
#define ast_debug(level,...)
Log a DEBUG message.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
#define ast_config_load(filename, flags)
Load a config file.
static int single_db_connection
General Asterisk PBX channel definitions.
static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, const char *value)
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Data structure associated with a custom dialplan function.
#define AST_RWLIST_TRAVERSE
#define ao2_ref(o, delta)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
static int load_module(void)
#define ast_strdupa(s)
duplicate a string in memory from the stack
static struct ast_threadstorage coldata_buf
static void dsn_destructor(void *obj)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static char * cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
#define CONFIG_STATUS_FILEUNCHANGED
static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, char *buf, size_t len)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
static int connection_dead(struct odbc_obj *connection)
Determine if the connection has died.
static int acf_fetch(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
Executes an non prepared statement and returns the resulting statement handle.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static struct ast_threadstorage sql2_buf
#define ao2_alloc(data_size, destructor_fn)
static char * cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static void odbc_datastore_free(void *data)
#define ast_channel_unlock(chan)
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_odbc_request_obj(a, b)
#define AST_RWLIST_REMOVE_HEAD
Module has failed to load, may be in an inconsistent state.
#define ao2_find(container, arg, flags)
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Structure used to handle boolean flags.
#define ast_clear_flag(p, flag)
static struct dsn * create_dsn(const char *name)
Create a DSN and connect to the database.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define ast_rwlock_wrlock(a)
static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_query **query)
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a nonprepared SQL query.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
static struct ast_cli_entry cli_func_odbc[]
The arg parameter is an object of the same type.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
static struct dsn * get_dsn(const char *name)
Retrieve a DSN, or create it if it does not exist.
static int dsn_cmp(void *obj, void *arg, int flags)
static void release_obj_or_dsn(struct odbc_obj **obj, struct dsn **dsn)
Release an ODBC obj or a DSN.
SQLRETURN ast_odbc_ast_str_SQLGetData(struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
Wrapper for SQLGetData to use with dynamic strings.
#define ast_datastore_alloc(info, uid)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Search option field mask.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
static struct ast_threadstorage colnames_buf
static const struct ast_datastore_info odbc_info
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_container * dsns
static ast_rwlock_t single_db_connection_lock
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
#define ast_custom_function_register(acf)
Register a custom function.
static struct odbc_obj * get_odbc_obj(const char *dsn_name, struct dsn **dsn)
Get a DB handle via a DSN or directly.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
#define AST_APP_ARG(name)
Define an application argument.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
static int free_acf_query(struct acf_odbc_query *query)