#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/res_odbc.h"
#include "asterisk/utils.h"
#include "asterisk/stringfields.h"
Go to the source code of this file.
Data Structures | |
struct | config_odbc_obj |
struct | custom_prepare_struct |
struct | update2_prepare_struct |
Defines | |
#define | CHECK_SIZE(n) |
#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) |
#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) |
#define | WARN_TYPE_OR_LENGTH(n) |
Functions | |
static void | __init_sql_buf (void) |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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) |
static SQLHSTMT | config_odbc_prepare (struct odbc_obj *obj, void *data) |
static SQLHSTMT | custom_prepare (struct odbc_obj *obj, void *data) |
static void | decode_chunk (char *chunk) |
static int | destroy_odbc (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
Excute an DELETE query. | |
static int | load_module (void) |
static struct ast_config * | realtime_multi_odbc (const char *database, const char *table, va_list ap) |
Excute an Select query and return ast_config list. | |
static struct ast_variable * | realtime_odbc (const char *database, const char *table, va_list ap) |
Excute an SQL query and return ast_variable list. | |
static int | reload_module (void) |
static int | require_odbc (const char *database, const char *table, va_list ap) |
static int | store_odbc (const char *database, const char *table, va_list ap) |
Excute an INSERT query. | |
static int | unload_module (void) |
static int | update2_odbc (const char *database, const char *table, va_list ap) |
Execute an UPDATE query. | |
static SQLHSTMT | update2_prepare (struct odbc_obj *obj, void *data) |
static int | update_odbc (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
Excute an UPDATE query. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Realtime ODBC configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_config_engine | odbc_engine |
static struct ast_threadstorage | sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } |
Anthony Minessale II <anthmct@yahoo.com>
Definition in file res_config_odbc.c.
#define CHECK_SIZE | ( | n | ) |
#define WARN_TYPE_OR_LENGTH | ( | n | ) |
Value:
if (!ast_rq_is_int(type)) { \ warn_type(col, type); \ } else { \ warn_length(col, n); \ }
Referenced by require_odbc().
static void __init_sql_buf | ( | void | ) | [static] |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1159 of file res_config_odbc.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1159 of file res_config_odbc.c.
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 | |||
) | [static] |
Definition at line 875 of file res_config_odbc.c.
References ast_build_string(), ast_category_append(), ast_category_new(), ast_config_get_current_category(), ast_config_internal_load(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_variable_append(), ast_variable_new(), config_odbc_prepare(), last, LOG_NOTICE, LOG_WARNING, and RES_ODBC_CONNECTED.
00876 { 00877 struct ast_variable *new_v; 00878 struct ast_category *cur_cat; 00879 int res = 0; 00880 struct odbc_obj *obj; 00881 char sqlbuf[1024] = ""; 00882 char *sql = sqlbuf; 00883 size_t sqlleft = sizeof(sqlbuf); 00884 unsigned int last_cat_metric = 0; 00885 SQLSMALLINT rowcount = 0; 00886 SQLHSTMT stmt; 00887 char last[128] = ""; 00888 struct config_odbc_obj q; 00889 struct ast_flags loader_flags = { 0 }; 00890 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00891 00892 memset(&q, 0, sizeof(q)); 00893 00894 if (!file || !strcmp (file, "res_config_odbc.conf")) 00895 return NULL; /* cant configure myself with myself ! */ 00896 00897 obj = ast_odbc_request_obj2(database, connected_flag); 00898 if (!obj) 00899 return NULL; 00900 00901 ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); 00902 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file); 00903 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00904 q.sql = sqlbuf; 00905 00906 stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q); 00907 00908 if (!stmt) { 00909 ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); 00910 ast_odbc_release_obj(obj); 00911 return NULL; 00912 } 00913 00914 res = SQLNumResultCols(stmt, &rowcount); 00915 00916 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00917 ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql); 00918 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00919 ast_odbc_release_obj(obj); 00920 return NULL; 00921 } 00922 00923 if (!rowcount) { 00924 ast_log(LOG_NOTICE, "found nothing\n"); 00925 ast_odbc_release_obj(obj); 00926 return cfg; 00927 } 00928 00929 cur_cat = ast_config_get_current_category(cfg); 00930 00931 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { 00932 if (!strcmp (q.var_name, "#include")) { 00933 if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) { 00934 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00935 ast_odbc_release_obj(obj); 00936 return NULL; 00937 } 00938 continue; 00939 } 00940 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) { 00941 cur_cat = ast_category_new(q.category, "", 99999); 00942 if (!cur_cat) { 00943 ast_log(LOG_WARNING, "Out of memory!\n"); 00944 break; 00945 } 00946 strcpy(last, q.category); 00947 last_cat_metric = q.cat_metric; 00948 ast_category_append(cfg, cur_cat); 00949 } 00950 00951 new_v = ast_variable_new(q.var_name, q.var_val, ""); 00952 ast_variable_append(cur_cat, new_v); 00953 } 00954 00955 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00956 ast_odbc_release_obj(obj); 00957 return cfg; 00958 }
static SQLHSTMT config_odbc_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 848 of file res_config_odbc.c.
References ast_verb, config_odbc_obj::cat_metric, config_odbc_obj::category, odbc_obj::con, config_odbc_obj::err, config_odbc_obj::sql, config_odbc_obj::var_name, and config_odbc_obj::var_val.
Referenced by config_odbc().
00849 { 00850 struct config_odbc_obj *q = data; 00851 SQLHSTMT sth; 00852 int res; 00853 00854 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth); 00855 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00856 ast_verb(4, "Failure in AllocStatement %d\n", res); 00857 return NULL; 00858 } 00859 00860 res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS); 00861 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00862 ast_verb(4, "Error in PREPARE %d\n", res); 00863 SQLFreeHandle(SQL_HANDLE_STMT, sth); 00864 return NULL; 00865 } 00866 00867 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err); 00868 SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err); 00869 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err); 00870 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err); 00871 00872 return sth; 00873 }
static SQLHSTMT custom_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 71 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_debug, ast_log(), ast_string_field_set, ast_strlen_zero(), odbc_obj::con, custom_prepare_struct::encoding, encoding, custom_prepare_struct::extra, LOG_WARNING, custom_prepare_struct::skip, and custom_prepare_struct::sql.
Referenced by destroy_odbc(), realtime_multi_odbc(), realtime_odbc(), store_odbc(), and update_odbc().
00072 { 00073 int res, x = 1, count = 0; 00074 struct custom_prepare_struct *cps = data; 00075 const char *newparam, *newval; 00076 char encodebuf[1024]; 00077 SQLHSTMT stmt; 00078 va_list ap; 00079 00080 va_copy(ap, cps->ap); 00081 00082 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00083 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00084 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00085 return NULL; 00086 } 00087 00088 ast_debug(1, "Skip: %lld; SQL: %s\n", cps->skip, cps->sql); 00089 00090 res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS); 00091 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00092 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql); 00093 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00094 return NULL; 00095 } 00096 00097 while ((newparam = va_arg(ap, const char *))) { 00098 newval = va_arg(ap, const char *); 00099 if ((1LL << count++) & cps->skip) { 00100 ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", newparam, newval, 1LL << (count - 1), cps->skip); 00101 continue; 00102 } 00103 ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, newparam, newval); 00104 if (strchr(newval, ';') || strchr(newval, '^')) { 00105 char *eptr = encodebuf; 00106 const char *vptr = newval; 00107 for (; *vptr && eptr < encodebuf + sizeof(encodebuf); vptr++) { 00108 if (strchr("^;", *vptr)) { 00109 /* We use ^XX, instead of %XX because '%' is a special character in SQL */ 00110 snprintf(eptr, encodebuf + sizeof(encodebuf) - eptr, "^%02hhX", *vptr); 00111 eptr += 3; 00112 } else { 00113 *eptr++ = *vptr; 00114 } 00115 } 00116 if (eptr < encodebuf + sizeof(encodebuf)) { 00117 *eptr = '\0'; 00118 } else { 00119 encodebuf[sizeof(encodebuf) - 1] = '\0'; 00120 } 00121 ast_string_field_set(cps, encoding[x], encodebuf); 00122 newval = cps->encoding[x]; 00123 } 00124 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00125 } 00126 va_end(ap); 00127 00128 if (!ast_strlen_zero(cps->extra)) 00129 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL); 00130 return stmt; 00131 }
static void decode_chunk | ( | char * | chunk | ) | [static] |
Definition at line 61 of file res_config_odbc.c.
Referenced by realtime_multi_odbc(), and realtime_odbc().
00062 { 00063 for (; *chunk; chunk++) { 00064 if (*chunk == '^' && strchr("0123456789ABCDEF", chunk[1]) && strchr("0123456789ABCDEF", chunk[2])) { 00065 sscanf(chunk + 1, "%02hhX", chunk); 00066 memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1); 00067 } 00068 } 00069 }
static int destroy_odbc | ( | const char * | database, | |
const char * | table, | |||
const char * | keyfield, | |||
const char * | lookup, | |||
va_list | ap | |||
) | [static] |
Excute an DELETE query.
database | ||
table | ||
keyfield | where clause field | |
lookup | value of field for where clause | |
ap | list containing one or more field/value set(s) |
number | of rows affected | |
-1 | on failure |
Definition at line 786 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.
00787 { 00788 struct odbc_obj *obj; 00789 SQLHSTMT stmt; 00790 char sql[256]; 00791 SQLLEN rowcount=0; 00792 const char *newparam, *newval; 00793 int res; 00794 va_list aq; 00795 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00796 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00797 00798 va_copy(cps.ap, ap); 00799 va_copy(aq, ap); 00800 00801 if (!table) 00802 return -1; 00803 00804 obj = ast_odbc_request_obj2(database, connected_flag); 00805 if (!obj) 00806 return -1; 00807 00808 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table); 00809 while((newparam = va_arg(aq, const char *))) { 00810 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam); 00811 newval = va_arg(aq, const char *); 00812 } 00813 va_end(aq); 00814 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield); 00815 00816 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00817 00818 if (!stmt) { 00819 ast_odbc_release_obj(obj); 00820 return -1; 00821 } 00822 00823 res = SQLRowCount(stmt, &rowcount); 00824 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00825 ast_odbc_release_obj(obj); 00826 00827 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00828 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00829 return -1; 00830 } 00831 00832 if (rowcount >= 0) 00833 return (int)rowcount; 00834 00835 return -1; 00836 }
static int load_module | ( | void | ) | [static] |
Definition at line 1142 of file res_config_odbc.c.
References ast_config_engine_register(), ast_verb, and odbc_engine.
01143 { 01144 ast_config_engine_register(&odbc_engine); 01145 ast_verb(1, "res_config_odbc loaded.\n"); 01146 return 0; 01147 }
static struct ast_config* realtime_multi_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Excute an Select query and return ast_config list.
database | ||
table | ||
ap | list containing one or more field/operator/value set. |
var | on success | |
NULL | on failure |
Definition at line 310 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_category_append(), ast_category_destroy(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_log(), ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_strdupa, ast_string_field_free_memory, ast_string_field_init, ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), custom_prepare(), decode_chunk(), LOG_WARNING, RES_ODBC_CONNECTED, custom_prepare_struct::sql, strcasestr(), strsep(), and var.
00311 { 00312 struct odbc_obj *obj; 00313 SQLHSTMT stmt; 00314 char sql[1024]; 00315 char coltitle[256]; 00316 char rowdata[2048]; 00317 const char *initfield=NULL; 00318 char *op; 00319 const char *newparam, *newval; 00320 char *stringp; 00321 char *chunk; 00322 SQLSMALLINT collen; 00323 int res; 00324 int x; 00325 struct ast_variable *var=NULL; 00326 struct ast_config *cfg=NULL; 00327 struct ast_category *cat=NULL; 00328 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00329 SQLULEN colsize; 00330 SQLSMALLINT colcount=0; 00331 SQLSMALLINT datatype; 00332 SQLSMALLINT decimaldigits; 00333 SQLSMALLINT nullable; 00334 SQLLEN indicator; 00335 struct custom_prepare_struct cps = { .sql = sql }; 00336 va_list aq; 00337 00338 if (!table || ast_string_field_init(&cps, 256)) { 00339 return NULL; 00340 } 00341 va_copy(cps.ap, ap); 00342 va_copy(aq, ap); 00343 00344 00345 obj = ast_odbc_request_obj2(database, connected_flag); 00346 if (!obj) { 00347 ast_string_field_free_memory(&cps); 00348 return NULL; 00349 } 00350 00351 newparam = va_arg(aq, const char *); 00352 if (!newparam) { 00353 ast_odbc_release_obj(obj); 00354 ast_string_field_free_memory(&cps); 00355 return NULL; 00356 } 00357 initfield = ast_strdupa(newparam); 00358 if ((op = strchr(initfield, ' '))) 00359 *op = '\0'; 00360 newval = va_arg(aq, const char *); 00361 op = !strchr(newparam, ' ') ? " =" : ""; 00362 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00363 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00364 while((newparam = va_arg(aq, const char *))) { 00365 op = !strchr(newparam, ' ') ? " =" : ""; 00366 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00367 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00368 newval = va_arg(aq, const char *); 00369 } 00370 if (initfield) 00371 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); 00372 va_end(aq); 00373 00374 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00375 00376 if (!stmt) { 00377 ast_odbc_release_obj(obj); 00378 ast_string_field_free_memory(&cps); 00379 return NULL; 00380 } 00381 00382 res = SQLNumResultCols(stmt, &colcount); 00383 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00384 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00385 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00386 ast_odbc_release_obj(obj); 00387 ast_string_field_free_memory(&cps); 00388 return NULL; 00389 } 00390 00391 cfg = ast_config_new(); 00392 if (!cfg) { 00393 ast_log(LOG_WARNING, "Out of memory!\n"); 00394 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00395 ast_odbc_release_obj(obj); 00396 ast_string_field_free_memory(&cps); 00397 return NULL; 00398 } 00399 00400 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) { 00401 var = NULL; 00402 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00403 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00404 continue; 00405 } 00406 cat = ast_category_new("","",99999); 00407 if (!cat) { 00408 ast_log(LOG_WARNING, "Out of memory!\n"); 00409 continue; 00410 } 00411 for (x=0;x<colcount;x++) { 00412 rowdata[0] = '\0'; 00413 collen = sizeof(coltitle); 00414 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00415 &datatype, &colsize, &decimaldigits, &nullable); 00416 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00417 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00418 ast_category_destroy(cat); 00419 continue; 00420 } 00421 00422 indicator = 0; 00423 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00424 if (indicator == SQL_NULL_DATA) 00425 continue; 00426 00427 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00428 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00429 ast_category_destroy(cat); 00430 continue; 00431 } 00432 stringp = rowdata; 00433 while (stringp) { 00434 chunk = strsep(&stringp, ";"); 00435 if (!ast_strlen_zero(ast_strip(chunk))) { 00436 if (strchr(chunk, '^')) { 00437 decode_chunk(chunk); 00438 } 00439 if (initfield && !strcmp(initfield, coltitle)) { 00440 ast_category_rename(cat, chunk); 00441 } 00442 var = ast_variable_new(coltitle, chunk, ""); 00443 ast_variable_append(cat, var); 00444 } 00445 } 00446 } 00447 ast_category_append(cfg, cat); 00448 } 00449 00450 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00451 ast_odbc_release_obj(obj); 00452 ast_string_field_free_memory(&cps); 00453 return cfg; 00454 }
static struct ast_variable* realtime_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Excute an SQL query and return ast_variable list.
database | ||
table | ||
ap | list containing one or more field/operator/value set. |
var | on success | |
NULL | on failure |
Definition at line 146 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_copy_string(), ast_log(), ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_string_field_free_memory, ast_string_field_init, ast_strip(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), custom_prepare(), decode_chunk(), LOG_ERROR, LOG_WARNING, RES_ODBC_CONNECTED, custom_prepare_struct::sql, strcasestr(), strsep(), and var.
00147 { 00148 struct odbc_obj *obj; 00149 SQLHSTMT stmt; 00150 char sql[1024]; 00151 char coltitle[256]; 00152 char rowdata[2048]; 00153 char *op; 00154 const char *newparam, *newval; 00155 char *stringp; 00156 char *chunk; 00157 SQLSMALLINT collen; 00158 int res; 00159 int x; 00160 struct ast_variable *var=NULL, *prev=NULL; 00161 SQLULEN colsize; 00162 SQLSMALLINT colcount=0; 00163 SQLSMALLINT datatype; 00164 SQLSMALLINT decimaldigits; 00165 SQLSMALLINT nullable; 00166 SQLLEN indicator; 00167 va_list aq; 00168 struct custom_prepare_struct cps = { .sql = sql }; 00169 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00170 00171 if (ast_string_field_init(&cps, 256)) { 00172 return NULL; 00173 } 00174 va_copy(cps.ap, ap); 00175 va_copy(aq, ap); 00176 00177 if (!table) { 00178 ast_string_field_free_memory(&cps); 00179 return NULL; 00180 } 00181 00182 obj = ast_odbc_request_obj2(database, connected_flag); 00183 00184 if (!obj) { 00185 ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database); 00186 ast_string_field_free_memory(&cps); 00187 return NULL; 00188 } 00189 00190 newparam = va_arg(aq, const char *); 00191 if (!newparam) { 00192 ast_odbc_release_obj(obj); 00193 ast_string_field_free_memory(&cps); 00194 return NULL; 00195 } 00196 newval = va_arg(aq, const char *); 00197 op = !strchr(newparam, ' ') ? " =" : ""; 00198 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00199 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00200 while((newparam = va_arg(aq, const char *))) { 00201 op = !strchr(newparam, ' ') ? " =" : ""; 00202 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00203 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00204 newval = va_arg(aq, const char *); 00205 } 00206 va_end(aq); 00207 00208 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00209 00210 if (!stmt) { 00211 ast_odbc_release_obj(obj); 00212 ast_string_field_free_memory(&cps); 00213 return NULL; 00214 } 00215 00216 res = SQLNumResultCols(stmt, &colcount); 00217 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00218 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00219 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00220 ast_odbc_release_obj(obj); 00221 ast_string_field_free_memory(&cps); 00222 return NULL; 00223 } 00224 00225 res = SQLFetch(stmt); 00226 if (res == SQL_NO_DATA) { 00227 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00228 ast_odbc_release_obj(obj); 00229 ast_string_field_free_memory(&cps); 00230 return NULL; 00231 } 00232 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00233 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00234 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00235 ast_odbc_release_obj(obj); 00236 ast_string_field_free_memory(&cps); 00237 return NULL; 00238 } 00239 for (x = 0; x < colcount; x++) { 00240 rowdata[0] = '\0'; 00241 collen = sizeof(coltitle); 00242 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00243 &datatype, &colsize, &decimaldigits, &nullable); 00244 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00245 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00246 if (var) 00247 ast_variables_destroy(var); 00248 ast_odbc_release_obj(obj); 00249 ast_string_field_free_memory(&cps); 00250 return NULL; 00251 } 00252 00253 indicator = 0; 00254 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00255 if (indicator == SQL_NULL_DATA) 00256 rowdata[0] = '\0'; 00257 else if (ast_strlen_zero(rowdata)) { 00258 /* Because we encode the empty string for a NULL, we will encode 00259 * actual empty strings as a string containing a single whitespace. */ 00260 ast_copy_string(rowdata, " ", sizeof(rowdata)); 00261 } 00262 00263 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00264 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00265 if (var) 00266 ast_variables_destroy(var); 00267 ast_odbc_release_obj(obj); 00268 return NULL; 00269 } 00270 stringp = rowdata; 00271 while (stringp) { 00272 chunk = strsep(&stringp, ";"); 00273 if (!ast_strlen_zero(ast_strip(chunk))) { 00274 if (strchr(chunk, '^')) { 00275 decode_chunk(chunk); 00276 } 00277 if (prev) { 00278 prev->next = ast_variable_new(coltitle, chunk, ""); 00279 if (prev->next) { 00280 prev = prev->next; 00281 } 00282 } else { 00283 prev = var = ast_variable_new(coltitle, chunk, ""); 00284 } 00285 } 00286 } 00287 } 00288 00289 00290 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00291 ast_odbc_release_obj(obj); 00292 ast_string_field_free_memory(&cps); 00293 return var; 00294 }
static int reload_module | ( | void | ) | [static] |
static int require_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 963 of file res_config_odbc.c.
References ast_log(), ast_odbc_find_table(), ast_rq_is_int(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CHECK_SIZE, odbc_cache_tables::columns, odbc_cache_columns::list, LOG_WARNING, odbc_cache_columns::name, RQ_CHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, RQ_UINTEGER8, odbc_cache_columns::size, odbc_cache_columns::type, type, warn_length, warn_type, and WARN_TYPE_OR_LENGTH.
00964 { 00965 struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table); 00966 struct odbc_cache_columns *col; 00967 char *elm; 00968 int type, size; 00969 00970 if (!tableptr) { 00971 return -1; 00972 } 00973 00974 while ((elm = va_arg(ap, char *))) { 00975 type = va_arg(ap, require_type); 00976 size = va_arg(ap, int); 00977 /* Check if the field matches the criteria */ 00978 AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) { 00979 if (strcmp(col->name, elm) == 0) { 00980 /* Type check, first. Some fields are more particular than others */ 00981 switch (col->type) { 00982 case SQL_CHAR: 00983 case SQL_VARCHAR: 00984 case SQL_LONGVARCHAR: 00985 #ifdef HAVE_ODBC_WCHAR 00986 case SQL_WCHAR: 00987 case SQL_WVARCHAR: 00988 case SQL_WLONGVARCHAR: 00989 #endif 00990 case SQL_BINARY: 00991 case SQL_VARBINARY: 00992 case SQL_LONGVARBINARY: 00993 case SQL_GUID: 00994 #define CHECK_SIZE(n) \ 00995 if (col->size < n) { \ 00996 warn_length(col, n); \ 00997 } \ 00998 break; 00999 switch (type) { 01000 case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */ 01001 case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */ 01002 case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */ 01003 case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */ 01004 case RQ_UINTEGER3: /* 16777215 */ 01005 case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */ 01006 case RQ_DATE: /* 2008-06-09 */ 01007 case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */ 01008 case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */ 01009 case RQ_DATETIME: /* 2008-06-09 16:03:47 */ 01010 case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */ 01011 case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */ 01012 case RQ_FLOAT: 01013 case RQ_CHAR: CHECK_SIZE(size) 01014 } 01015 #undef CHECK_SIZE 01016 break; 01017 case SQL_TYPE_DATE: 01018 if (type != RQ_DATE) { 01019 warn_type(col, type); 01020 } 01021 break; 01022 case SQL_TYPE_TIMESTAMP: 01023 case SQL_TIMESTAMP: 01024 if (type != RQ_DATE && type != RQ_DATETIME) { 01025 warn_type(col, type); 01026 } 01027 break; 01028 case SQL_BIT: 01029 warn_length(col, size); 01030 break; 01031 #define WARN_TYPE_OR_LENGTH(n) \ 01032 if (!ast_rq_is_int(type)) { \ 01033 warn_type(col, type); \ 01034 } else { \ 01035 warn_length(col, n); \ 01036 } 01037 case SQL_TINYINT: 01038 if (type != RQ_UINTEGER1) { 01039 WARN_TYPE_OR_LENGTH(size) 01040 } 01041 break; 01042 case SQL_C_STINYINT: 01043 if (type != RQ_INTEGER1) { 01044 WARN_TYPE_OR_LENGTH(size) 01045 } 01046 break; 01047 case SQL_C_USHORT: 01048 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { 01049 WARN_TYPE_OR_LENGTH(size) 01050 } 01051 break; 01052 case SQL_SMALLINT: 01053 case SQL_C_SSHORT: 01054 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { 01055 WARN_TYPE_OR_LENGTH(size) 01056 } 01057 break; 01058 case SQL_C_ULONG: 01059 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01060 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01061 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01062 type != RQ_INTEGER4) { 01063 WARN_TYPE_OR_LENGTH(size) 01064 } 01065 break; 01066 case SQL_INTEGER: 01067 case SQL_C_SLONG: 01068 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01069 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01070 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01071 type != RQ_INTEGER4) { 01072 WARN_TYPE_OR_LENGTH(size) 01073 } 01074 break; 01075 case SQL_C_UBIGINT: 01076 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01077 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01078 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01079 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01080 type != RQ_INTEGER8) { 01081 WARN_TYPE_OR_LENGTH(size) 01082 } 01083 break; 01084 case SQL_BIGINT: 01085 case SQL_C_SBIGINT: 01086 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01087 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01088 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01089 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01090 type != RQ_INTEGER8) { 01091 WARN_TYPE_OR_LENGTH(size) 01092 } 01093 break; 01094 #undef WARN_TYPE_OR_LENGTH 01095 case SQL_NUMERIC: 01096 case SQL_DECIMAL: 01097 case SQL_FLOAT: 01098 case SQL_REAL: 01099 case SQL_DOUBLE: 01100 if (!ast_rq_is_int(type) && type != RQ_FLOAT) { 01101 warn_type(col, type); 01102 } 01103 break; 01104 default: 01105 ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm); 01106 } 01107 break; 01108 } 01109 } 01110 if (!col) { 01111 ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm); 01112 } 01113 } 01114 va_end(ap); 01115 AST_RWLIST_UNLOCK(&tableptr->columns); 01116 return 0; 01117 }
static int store_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Excute an INSERT query.
database | ||
table | ||
ap | list containing one or more field/value set(s) |
number | of rows affected | |
-1 | on failure |
Definition at line 709 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_copy_string(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.
00710 { 00711 struct odbc_obj *obj; 00712 SQLHSTMT stmt; 00713 char sql[256]; 00714 char keys[256]; 00715 char vals[256]; 00716 SQLLEN rowcount=0; 00717 const char *newparam, *newval; 00718 int res; 00719 va_list aq; 00720 struct custom_prepare_struct cps = { .sql = sql, .extra = NULL }; 00721 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00722 00723 va_copy(cps.ap, ap); 00724 va_copy(aq, ap); 00725 00726 if (!table) 00727 return -1; 00728 00729 obj = ast_odbc_request_obj2(database, connected_flag); 00730 if (!obj) 00731 return -1; 00732 00733 newparam = va_arg(aq, const char *); 00734 if (!newparam) { 00735 ast_odbc_release_obj(obj); 00736 return -1; 00737 } 00738 newval = va_arg(aq, const char *); 00739 snprintf(keys, sizeof(keys), "%s", newparam); 00740 ast_copy_string(vals, "?", sizeof(vals)); 00741 while ((newparam = va_arg(aq, const char *))) { 00742 snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam); 00743 snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?"); 00744 newval = va_arg(aq, const char *); 00745 } 00746 va_end(aq); 00747 snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals); 00748 00749 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00750 00751 if (!stmt) { 00752 ast_odbc_release_obj(obj); 00753 return -1; 00754 } 00755 00756 res = SQLRowCount(stmt, &rowcount); 00757 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00758 ast_odbc_release_obj(obj); 00759 00760 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00761 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00762 return -1; 00763 } 00764 00765 if (rowcount >= 0) 00766 return (int)rowcount; 00767 00768 return -1; 00769 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1134 of file res_config_odbc.c.
References ast_config_engine_deregister(), ast_verb, and odbc_engine.
01135 { 01136 ast_config_engine_deregister(&odbc_engine); 01137 01138 ast_verb(1, "res_config_odbc unloaded.\n"); 01139 return 0; 01140 }
static int update2_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Execute an UPDATE query.
database | ||
table | ||
ap | list containing one or more field/value set(s). |
number | of rows affected | |
-1 | on failure |
Definition at line 658 of file res_config_odbc.c.
References update2_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj, ast_str_buffer(), ast_str_thread_get(), update2_prepare_struct::database, LOG_WARNING, sql_buf, and update2_prepare().
00659 { 00660 struct odbc_obj *obj; 00661 SQLHSTMT stmt; 00662 struct update2_prepare_struct ups = { .database = database, .table = table, }; 00663 struct ast_str *sql; 00664 int res; 00665 SQLLEN rowcount = 0; 00666 00667 va_copy(ups.ap, ap); 00668 00669 if (!(obj = ast_odbc_request_obj(database, 0))) { 00670 return -1; 00671 } 00672 00673 if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) { 00674 ast_odbc_release_obj(obj); 00675 return -1; 00676 } 00677 00678 res = SQLRowCount(stmt, &rowcount); 00679 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00680 ast_odbc_release_obj(obj); 00681 00682 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00683 /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */ 00684 sql = ast_str_thread_get(&sql_buf, 16); 00685 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql)); 00686 return -1; 00687 } 00688 00689 if (rowcount >= 0) { 00690 return (int)rowcount; 00691 } 00692 00693 return -1; 00694 }
static SQLHSTMT update2_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 561 of file res_config_odbc.c.
References update2_prepare_struct::ap, ast_log(), ast_odbc_find_column(), ast_odbc_find_table(), ast_odbc_release_table, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), odbc_obj::con, update2_prepare_struct::database, first, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sql_buf, and update2_prepare_struct::table.
Referenced by update2_odbc().
00562 { 00563 int res, x = 1, first = 1; 00564 struct update2_prepare_struct *ups = data; 00565 const char *newparam, *newval; 00566 struct ast_str *sql = ast_str_thread_get(&sql_buf, 16); 00567 SQLHSTMT stmt; 00568 va_list ap; 00569 struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table); 00570 struct odbc_cache_columns *column; 00571 00572 if (!sql) { 00573 if (tableptr) { 00574 ast_odbc_release_table(tableptr); 00575 } 00576 return NULL; 00577 } 00578 00579 if (!tableptr) { 00580 ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", ups->table, ups->database); 00581 return NULL; 00582 } 00583 00584 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00585 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00586 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00587 ast_odbc_release_table(tableptr); 00588 return NULL; 00589 } 00590 00591 ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table); 00592 00593 /* Start by finding the second set of parameters */ 00594 va_copy(ap, ups->ap); 00595 00596 while ((newparam = va_arg(ap, const char *))) { 00597 newval = va_arg(ap, const char *); 00598 } 00599 00600 while ((newparam = va_arg(ap, const char *))) { 00601 newval = va_arg(ap, const char *); 00602 if ((column = ast_odbc_find_column(tableptr, newparam))) { 00603 ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", newparam); 00604 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00605 first = 0; 00606 } else { 00607 ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", newparam, ups->table, ups->database); 00608 } 00609 } 00610 va_end(ap); 00611 00612 /* Restart search, because we need to add the search parameters */ 00613 va_copy(ap, ups->ap); 00614 ast_str_append(&sql, 0, "WHERE"); 00615 first = 1; 00616 00617 while ((newparam = va_arg(ap, const char *))) { 00618 newval = va_arg(ap, const char *); 00619 if (!(column = ast_odbc_find_column(tableptr, newparam))) { 00620 ast_log(LOG_ERROR, "One or more of the criteria columns '%s' on '%s@%s' for this update does not exist!\n", newparam, ups->table, ups->database); 00621 ast_odbc_release_table(tableptr); 00622 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00623 return NULL; 00624 } 00625 ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", newparam); 00626 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00627 first = 0; 00628 } 00629 va_end(ap); 00630 00631 /* Done with the table metadata */ 00632 ast_odbc_release_table(tableptr); 00633 00634 res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS); 00635 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00636 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql)); 00637 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00638 return NULL; 00639 } 00640 00641 return stmt; 00642 }
static int update_odbc | ( | const char * | database, | |
const char * | table, | |||
const char * | keyfield, | |||
const char * | lookup, | |||
va_list | ap | |||
) | [static] |
Excute an UPDATE query.
database | ||
table | ||
keyfield | where clause field | |
lookup | value of field for where clause | |
ap | list containing one or more field/value set(s). |
number | of rows affected | |
-1 | on failure |
Definition at line 471 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_log(), ast_odbc_find_column(), ast_odbc_find_table(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_release_table, ast_odbc_request_obj2, ast_string_field_free_memory, ast_string_field_init, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, custom_prepare_struct::skip, and custom_prepare_struct::sql.
00472 { 00473 struct odbc_obj *obj; 00474 SQLHSTMT stmt; 00475 char sql[256]; 00476 SQLLEN rowcount=0; 00477 const char *newparam, *newval; 00478 int res, count = 1; 00479 va_list aq; 00480 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00481 struct odbc_cache_tables *tableptr; 00482 struct odbc_cache_columns *column; 00483 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00484 00485 if (!table) { 00486 return -1; 00487 } 00488 00489 va_copy(cps.ap, ap); 00490 va_copy(aq, ap); 00491 00492 if (ast_string_field_init(&cps, 256)) { 00493 return -1; 00494 } 00495 00496 tableptr = ast_odbc_find_table(database, table); 00497 if (!(obj = ast_odbc_request_obj2(database, connected_flag))) { 00498 ast_odbc_release_table(tableptr); 00499 ast_string_field_free_memory(&cps); 00500 return -1; 00501 } 00502 00503 newparam = va_arg(aq, const char *); 00504 if (!newparam) { 00505 ast_odbc_release_obj(obj); 00506 ast_odbc_release_table(tableptr); 00507 ast_string_field_free_memory(&cps); 00508 return -1; 00509 } 00510 newval = va_arg(aq, const char *); 00511 00512 if (tableptr && !(column = ast_odbc_find_column(tableptr, newparam))) { 00513 ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", newparam, table, database); 00514 } 00515 00516 snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam); 00517 while((newparam = va_arg(aq, const char *))) { 00518 newval = va_arg(aq, const char *); 00519 if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count > 63) { 00520 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam); 00521 } else { /* the column does not exist in the table */ 00522 cps.skip |= (1LL << count); 00523 } 00524 count++; 00525 } 00526 va_end(aq); 00527 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield); 00528 ast_odbc_release_table(tableptr); 00529 00530 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00531 00532 if (!stmt) { 00533 ast_odbc_release_obj(obj); 00534 ast_string_field_free_memory(&cps); 00535 return -1; 00536 } 00537 00538 res = SQLRowCount(stmt, &rowcount); 00539 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00540 ast_odbc_release_obj(obj); 00541 ast_string_field_free_memory(&cps); 00542 00543 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00544 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00545 return -1; 00546 } 00547 00548 if (rowcount >= 0) { 00549 return (int) rowcount; 00550 } 00551 00552 return -1; 00553 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Realtime ODBC configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static] |
Definition at line 1159 of file res_config_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1159 of file res_config_odbc.c.
struct ast_config_engine odbc_engine [static] |
Definition at line 1121 of file res_config_odbc.c.
Referenced by load_module(), and unload_module().
struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } [static] |
Definition at line 49 of file res_config_odbc.c.