50 #define SQL_BUF_SIZE 1024
52 static const char *res_config_odbc_conf =
"res_config_odbc.conf";
53 static int order_multi_row_results_by_initial_column = 1;
65 unsigned long long skip;
68 #define ENCODE_CHUNK(buffer, s) \
70 char *eptr = buffer; \
71 const char *vptr = s; \
72 for (; *vptr && eptr < buffer + sizeof(buffer); vptr++) { \
73 if (strchr("^;", *vptr)) { \
75 snprintf(eptr, buffer + sizeof(buffer) - eptr, "^%02hhX", *vptr); \
81 if (eptr < buffer + sizeof(buffer)) { \
84 buffer[sizeof(buffer) - 1] = '\0'; \
88 static void decode_chunk(
char *chunk)
90 for (; *chunk; chunk++) {
91 if (*chunk ==
'^' && strchr(
"0123456789ABCDEF", chunk[1]) && strchr(
"0123456789ABCDEF", chunk[2])) {
92 sscanf(chunk + 1,
"%02hhX", (
unsigned char *)chunk);
93 memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
100 return column->type == SQL_CHAR || column->type == SQL_VARCHAR || column->type == SQL_LONGVARCHAR
101 || column->type == SQL_WCHAR || column->type == SQL_WVARCHAR || column->type == SQL_WLONGVARCHAR;
104 static SQLHSTMT custom_prepare(
struct odbc_obj *obj,
void *data)
106 int res, x = 1, count = 0;
109 char encodebuf[1024];
112 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
113 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
114 ast_log(LOG_WARNING,
"SQL Alloc Handle failed!\n");
118 ast_debug(1,
"Skip: %llu; SQL: %s\n", cps->skip, cps->sql);
121 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
122 if (res == SQL_ERROR) {
125 ast_log(LOG_WARNING,
"SQL Prepare failed! [%s]\n", cps->sql);
126 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
130 for (field = cps->fields; field; field = field->
next) {
131 const char *newval = field->
value;
133 if ((1LL << count++) & cps->skip) {
134 ast_debug(1,
"Skipping field '%s'='%s' (%llo/%llo)\n", field->
name, newval, 1ULL << (count - 1), cps->skip);
137 ast_debug(1,
"Parameter %d ('%s') = '%s'\n", x, field->
name, newval);
138 if (strchr(newval,
';') || strchr(newval,
'^')) {
139 ENCODE_CHUNK(encodebuf, newval);
141 newval = cps->encoding[x];
143 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0, NULL);
146 if (!ast_strlen_zero(cps->extra)) {
147 const char *newval = cps->extra;
148 ast_debug(1,
"Parameter %d = '%s'\n", x, newval);
149 if (strchr(newval,
';') || strchr(newval,
'^')) {
150 ENCODE_CHUNK(encodebuf, newval);
152 newval = cps->encoding[x];
154 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0, NULL);
189 SQLSMALLINT colcount=0;
190 SQLSMALLINT datatype;
191 SQLSMALLINT decimaldigits;
192 SQLSMALLINT nullable;
195 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
197 if (!table || !field || !sql || !rowdata) {
203 ast_log(LOG_ERROR,
"No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
207 op = !strchr(field->
name,
' ') ?
" =" :
"";
208 ast_str_set(&sql, 0,
"SELECT * FROM %s WHERE %s%s ?%s", table, field->
name, op,
210 while ((field = field->
next)) {
211 op = !strchr(field->
name,
' ') ?
" =" :
"";
230 res = SQLNumResultCols(stmt, &colcount);
231 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
232 ast_log(LOG_WARNING,
"SQL Column Count error! [%s]\n",
ast_str_buffer(sql));
233 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
238 res = SQLFetch(stmt);
239 if (res == SQL_NO_DATA) {
240 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
244 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
245 ast_log(LOG_WARNING,
"SQL Fetch error! [%s]\n",
ast_str_buffer(sql));
246 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
250 for (x = 0; x < colcount; x++) {
252 collen =
sizeof(coltitle);
253 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle,
sizeof(coltitle), &collen,
254 &datatype, &colsize, &decimaldigits, &nullable);
255 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
256 ast_log(LOG_WARNING,
"SQL Describe Column error! [%s]\n",
ast_str_buffer(sql));
268 if (indicator == SQL_NULL_DATA) {
274 }
else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
277 ast_str_make_space(&rowdata, indicator + 1);
284 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
285 ast_log(LOG_WARNING,
"SQL Get Data error! [%s]\n",
ast_str_buffer(sql));
293 if (!strncmp(coltitle,
"@", 1)) {
299 prev->next = ast_variable_new(coltitle,
S_OR(stringp,
" "),
"");
304 prev = var = ast_variable_new(coltitle,
S_OR(stringp,
" "),
"");
308 chunk = strsep(&stringp,
";");
309 if (!ast_strlen_zero(
ast_strip(chunk))) {
310 if (strchr(chunk,
'^')) {
314 prev->next = ast_variable_new(coltitle, chunk,
"");
319 prev = var = ast_variable_new(coltitle, chunk,
"");
326 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
352 const char *initfield;
363 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
365 SQLSMALLINT colcount=0;
366 SQLSMALLINT datatype;
367 SQLSMALLINT decimaldigits;
368 SQLSMALLINT nullable;
372 if (!table || !field || !sql || !rowdata) {
382 if ((op = strchr(initfield,
' '))) {
386 op = !strchr(field->
name,
' ') ?
" =" :
"";
387 ast_str_set(&sql, 0,
"SELECT * FROM %s WHERE %s%s ?%s", table, field->
name, op,
389 while ((field = field->
next)) {
390 op = !strchr(field->
name,
' ') ?
" =" :
"";
395 if (order_multi_row_results_by_initial_column) {
413 res = SQLNumResultCols(stmt, &colcount);
414 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
415 ast_log(LOG_WARNING,
"SQL Column Count error! [%s]\n",
ast_str_buffer(sql));
416 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
423 ast_log(LOG_WARNING,
"Out of memory!\n");
424 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
429 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
431 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
432 ast_log(LOG_WARNING,
"SQL Fetch error! [%s]\n",
ast_str_buffer(sql));
439 for (x=0;x<colcount;x++) {
441 collen =
sizeof(coltitle);
442 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle,
sizeof(coltitle), &collen,
443 &datatype, &colsize, &decimaldigits, &nullable);
444 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
445 ast_log(LOG_WARNING,
"SQL Describe Column error! [%s]\n",
ast_str_buffer(sql));
446 ast_category_destroy(cat);
455 if (indicator == SQL_NULL_DATA) {
459 if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
462 ast_str_make_space(&rowdata, indicator + 1);
469 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
470 ast_log(LOG_WARNING,
"SQL Get Data error! [%s]\n",
ast_str_buffer(sql));
471 ast_category_destroy(cat);
475 if (!strncmp(coltitle,
"@", 1)) {
480 var = ast_variable_new(coltitle,
S_OR(stringp,
" "),
"");
481 ast_variable_append(cat, var);
484 chunk = strsep(&stringp,
";");
485 if (!ast_strlen_zero(
ast_strip(chunk))) {
486 if (strchr(chunk,
'^')) {
489 if (!strcmp(initfield, coltitle)) {
490 ast_category_rename(cat, chunk);
492 var = ast_variable_new(coltitle, chunk,
"");
493 ast_variable_append(cat, var);
502 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
522 static int update_odbc(
const char *database,
const char *table,
const char *keyfield,
const char *lookup,
const struct ast_variable *fields)
529 int res, count = 0, paramcount = 0;
533 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
535 if (!table || !field || !keyfield || !sql) {
546 ast_log(LOG_WARNING,
"Key field '%s' does not exist in table '%s@%s'. Update will fail\n", keyfield, table, database);
556 if (count < 64 && ast_strlen_zero(field->
value) && column->nullable && !is_text(column)) {
558 cps.skip |= (1LL << count);
564 cps.skip |= (1LL << count);
586 res = SQLRowCount(stmt, &rowcount);
587 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
590 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
591 ast_log(LOG_WARNING,
"SQL Row Count error! [%s]\n",
ast_str_buffer(sql));
596 return (
int) rowcount;
603 const char *database;
610 static SQLHSTMT update2_prepare(
struct odbc_obj *obj,
void *data)
612 int res, x = 1, first = 1;
622 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
623 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
624 ast_log(LOG_WARNING,
"SQL Alloc Handle failed!\n");
628 ast_str_set(&sql, 0,
"UPDATE %s SET ", ups->table);
630 for (field = ups->update_fields; field; field = field->
next) {
633 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
name), 0, (
void *)field->
value, 0, NULL);
636 ast_log(LOG_NOTICE,
"Not updating column '%s' in '%s@%s' because that column does not exist!\n", field->
name, ups->table, ups->database);
643 for (field = ups->lookup_fields; field; field = field->
next) {
645 ast_log(LOG_ERROR,
"One or more of the criteria columns '%s' on '%s@%s' for this update does not exist!\n", field->
name, ups->table, ups->database);
646 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
650 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
value), 0, (
void *)field->
value, 0, NULL);
655 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
656 if (res == SQL_ERROR) {
659 ast_log(LOG_WARNING,
"SQL Prepare failed! [%s]\n",
ast_str_buffer(sql));
660 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
685 .database = database,
687 .lookup_fields = lookup_fields,
688 .update_fields = update_fields,
696 ast_log(LOG_ERROR,
"Could not retrieve metadata for table '%s@%s'. Update will fail!\n", table, database);
714 res = SQLRowCount(stmt, &rowcount);
715 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
718 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
721 ast_assert(sql != NULL);
722 ast_log(LOG_WARNING,
"SQL Row Count error! [%s]\n",
ast_str_buffer(sql));
727 return (
int) rowcount;
757 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
761 if (!table || !field || !keys || !vals || !sql) {
776 while ((field = field->
next)) {
780 ast_str_set(&sql, 0,
"INSERT INTO %s (%s) VALUES (%s)",
799 res = SQLRowCount(stmt, &rowcount);
800 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
803 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
804 ast_log(LOG_WARNING,
"SQL Row Count error! [%s]\n",
ast_str_buffer(sql));
809 return (
int)rowcount;
829 static int destroy_odbc(
const char *database,
const char *table,
const char *keyfield,
const char *lookup,
const struct ast_variable *fields)
838 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
840 if (!table || !sql) {
849 ast_str_set(&sql, 0,
"DELETE FROM %s WHERE ", table);
850 for (field = fields; field; field = field->
next) {
869 res = SQLRowCount(stmt, &rowcount);
870 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
873 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
874 ast_log(LOG_WARNING,
"SQL Row Count error! [%s]\n",
ast_str_buffer(sql));
879 return (
int)rowcount;
886 unsigned long cat_metric;
890 unsigned long var_val_size;
895 static SQLHSTMT length_determination_odbc_prepare(
struct odbc_obj *obj,
void *data)
901 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
902 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
903 ast_verb(4,
"Failure in AllocStatement %d\n", res);
908 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
909 ast_verb(4,
"Error in PREPARE %d\n", res);
910 SQLFreeHandle(SQL_HANDLE_STMT, sth);
914 SQLBindCol(sth, 1, SQL_C_ULONG, &q->var_val_size,
sizeof(q->var_val_size), &q->err);
919 static SQLHSTMT config_odbc_prepare(
struct odbc_obj *obj,
void *data)
925 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
926 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
927 ast_verb(4,
"Failure in AllocStatement %d\n", res);
932 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
933 ast_verb(4,
"Error in PREPARE %d\n", res);
934 SQLFreeHandle(SQL_HANDLE_STMT, sth);
938 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric,
sizeof(q->cat_metric), &q->err);
939 SQLBindCol(sth, 2, SQL_C_CHAR, q->category,
sizeof(q->category), &q->err);
940 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name,
sizeof(q->var_name), &q->err);
941 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, q->var_val_size, &q->err);
946 static struct ast_config *config_odbc(
const char *database,
const char *table,
const char *file,
struct ast_config *cfg,
struct ast_flags flags,
const char *sugg_incl,
const char *who_asked)
953 unsigned int last_cat_metric = 0;
954 SQLSMALLINT rowcount = 0;
959 struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
961 memset(&q, 0,
sizeof(q));
963 if (!file || !strcmp (file, res_config_odbc_conf) || !sql) {
971 ast_str_set(&sql, 0,
"SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'",
977 ast_log(LOG_WARNING,
"SQL select error! [%s]\n",
ast_str_buffer(sql));
982 res = SQLNumResultCols(stmt, &rowcount);
984 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
985 ast_log(LOG_WARNING,
"SQL NumResultCols error! [%s]\n",
ast_str_buffer(sql));
986 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
992 ast_log(LOG_NOTICE,
"found nothing\n");
998 if (SQLFetch(stmt) == SQL_NO_DATA) {
999 ast_log(LOG_NOTICE,
"Failed to determine maximum length of a configuration value\n");
1000 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1006 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1008 ast_str_set(&sql, 0,
"SELECT cat_metric, category, var_name, var_val FROM %s ", table);
1009 ast_str_append(&sql, 0,
"WHERE filename='%s' AND commented=0 ", file);
1010 ast_str_append(&sql, 0,
"ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
1013 q.var_val_size += 1;
1016 ast_log(LOG_WARNING,
"Could not create buffer for reading in configuration values for '%s'\n", file);
1023 ast_log(LOG_WARNING,
"SQL select error! [%s]\n",
ast_str_buffer(sql));
1025 ast_free(q.var_val);
1029 res = SQLNumResultCols(stmt, &rowcount);
1031 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1032 ast_log(LOG_WARNING,
"SQL NumResultCols error! [%s]\n",
ast_str_buffer(sql));
1033 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1035 ast_free(q.var_val);
1040 ast_log(LOG_NOTICE,
"found nothing\n");
1042 ast_free(q.var_val);
1048 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
1049 if (!strcmp (q.var_name,
"#include")) {
1050 if (!ast_config_internal_load(q.var_val, cfg, loader_flags,
"", who_asked)) {
1051 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1053 ast_free(q.var_val);
1058 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
1063 strcpy(last, q.category);
1064 last_cat_metric = q.cat_metric;
1068 new_v = ast_variable_new(q.var_name, q.var_val,
"");
1069 ast_variable_append(cur_cat, new_v);
1072 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1074 ast_free(q.var_val);
1078 #define warn_length(col, size) ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is not long enough to contain realtime data (needs %d)\n", table, database, col->name, size)
1079 #define warn_type(col, type) ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is of the incorrect type (%d) to contain the required realtime data\n", table, database, col->name, col->type)
1081 static int require_odbc(
const char *database,
const char *table, va_list ap)
1092 while ((elm = va_arg(ap,
char *))) {
1094 size = va_arg(ap,
int);
1096 AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) {
1097 if (strcmp(col->name, elm) == 0) {
1099 switch (col->type) {
1102 case SQL_LONGVARCHAR:
1103 #ifdef HAVE_ODBC_WCHAR
1106 case SQL_WLONGVARCHAR:
1110 case SQL_LONGVARBINARY:
1112 #define CHECK_SIZE(n) \
1113 if (col->size < n) { \
1114 warn_length(col, n); \
1118 case RQ_UINTEGER1: CHECK_SIZE(3)
1119 case RQ_INTEGER1: CHECK_SIZE(4)
1120 case RQ_UINTEGER2: CHECK_SIZE(5)
1121 case RQ_INTEGER2: CHECK_SIZE(6)
1123 case RQ_INTEGER3: CHECK_SIZE(8)
1125 case RQ_UINTEGER4: CHECK_SIZE(10)
1126 case RQ_INTEGER4: CHECK_SIZE(11)
1128 case RQ_UINTEGER8: CHECK_SIZE(19)
1129 case RQ_INTEGER8: CHECK_SIZE(20)
1131 case RQ_CHAR: CHECK_SIZE(size)
1136 if (type != RQ_DATE) {
1137 warn_type(col, type);
1140 case SQL_TYPE_TIMESTAMP:
1143 if (type != RQ_DATE && type != RQ_DATETIME) {
1144 warn_type(col, type);
1148 warn_length(col, size);
1150 #define WARN_TYPE_OR_LENGTH(n) \
1151 if (!ast_rq_is_int(type)) { \
1152 warn_type(col, type); \
1154 warn_length(col, n); \
1157 if (type != RQ_UINTEGER1) {
1158 WARN_TYPE_OR_LENGTH(size)
1161 case SQL_C_STINYINT:
1162 if (type != RQ_INTEGER1) {
1163 WARN_TYPE_OR_LENGTH(size)
1167 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
1168 WARN_TYPE_OR_LENGTH(size)
1173 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
1174 WARN_TYPE_OR_LENGTH(size)
1178 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1179 type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1180 type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1181 type != RQ_INTEGER4) {
1182 WARN_TYPE_OR_LENGTH(size)
1187 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1188 type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1189 type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1190 type != RQ_INTEGER4) {
1191 WARN_TYPE_OR_LENGTH(size)
1195 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1196 type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1197 type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1198 type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1199 type != RQ_INTEGER8) {
1200 WARN_TYPE_OR_LENGTH(size)
1205 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1206 type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1207 type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1208 type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1209 type != RQ_INTEGER8) {
1210 WARN_TYPE_OR_LENGTH(size)
1213 #undef WARN_TYPE_OR_LENGTH
1220 warn_type(col, type);
1224 ast_log(LOG_WARNING,
"Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm);
1230 ast_log(LOG_WARNING,
"Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
1239 static int unload_odbc(
const char *a,
const char *b)
1246 .load_func = config_odbc,
1253 .require_func = require_odbc,
1254 .unload_func = unload_odbc,
1257 static void load_config(
const char *filename)
1264 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
1265 if (config == CONFIG_STATUS_FILEINVALID) {
1266 ast_log(LOG_WARNING,
"Unable to load config '%s'. Using defaults.\n", filename);
1268 order_multi_row_results_by_initial_column = 1;
1273 s = ast_variable_retrieve(config,
"general",
"order_multi_row_results_by_initial_column");
1274 order_multi_row_results_by_initial_column = !s ||
ast_true(s);
1279 static int load_module(
void)
1283 load_config(res_config_odbc_conf);
1288 static int reload_module(
void)
1290 load_config(res_config_odbc_conf);
1294 static int unload_module(
void)
1300 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"Realtime ODBC configuration",
1301 .support_level = AST_MODULE_SUPPORT_CORE,
1302 .load = load_module,
1303 .unload = unload_module,
1304 .reload = reload_module,
1306 .requires =
"extconfig,res_odbc",
struct ast_variable * next
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
require_type
Types used in ast_realtime_require_field.
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
static struct ast_config * realtime_multi_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an Select query and return ast_config list.
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
Structure for variables, used for configurations and for channel variables.
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
These structures are used for adaptive capabilities.
Configuration engine structure, used to define realtime drivers.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
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.
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static int store_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an INSERT query.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
static struct ast_variable * realtime_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an SQL query and return ast_variable list.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Core PBX routines and definitions.
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
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".
Support for dynamic strings.
static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an DELETE query.
int ast_odbc_clear_cache(const char *database, const char *tablename)
Remove a cache entry from memory This function may be called to clear entries created and cached by t...
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
Structure used to handle boolean flags.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an UPDATE query.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
static int update2_odbc(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
Execute an UPDATE query.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.