Wed Jan 8 2020 09:50:18

Asterisk developer's documentation


res_config_odbc.c File Reference

odbc+odbc plugin for portable configuration engine More...

#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
 

Macros

#define CHECK_SIZE(n)
 
#define ENCODE_CHUNK(buffer, s)
 
#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_rowdata_buf (void)
 
static void __init_sql_buf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static struct ast_configconfig_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. More...
 
static int is_text (const struct odbc_cache_columns *column)
 
static SQLHSTMT length_determination_odbc_prepare (struct odbc_obj *obj, void *data)
 
static int load_module (void)
 
static struct ast_configrealtime_multi_odbc (const char *database, const char *table, va_list ap)
 Excute an Select query and return ast_config list. More...
 
static struct ast_variablerealtime_odbc (const char *database, const char *table, va_list ap)
 Excute an SQL query and return ast_variable list. More...
 
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. More...
 
static int unload_module (void)
 
static int unload_odbc (const char *a, const char *b)
 
static int update2_odbc (const char *database, const char *table, va_list ap)
 Execute an UPDATE query. More...
 
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. More...
 

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_config_engine odbc_engine
 
static struct ast_threadstorage rowdata_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_rowdata_buf , .custom_init = NULL , }
 
static struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , }
 

Detailed Description

odbc+odbc plugin for portable configuration engine

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Anthony Minessale II anthm.nosp@m.ct@y.nosp@m.ahoo..nosp@m.com

Definition in file res_config_odbc.c.

Macro Definition Documentation

#define CHECK_SIZE (   n)
Value:
if (col->size < n) { \
warn_length(col, n); \
} \
break;
#define warn_length(col, size)

Referenced by require_odbc().

#define ENCODE_CHUNK (   buffer,
 
)

Definition at line 63 of file res_config_odbc.c.

Referenced by custom_prepare().

#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)

Definition at line 1099 of file res_config_odbc.c.

Referenced by require_odbc().

#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)

Definition at line 1100 of file res_config_odbc.c.

Referenced by require_odbc().

#define WARN_TYPE_OR_LENGTH (   n)
Value:
warn_type(col, type); \
} else { \
warn_length(col, n); \
}
#define warn_length(col, size)
static const char type[]
Definition: chan_nbs.c:57
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
Definition: config.h:768
#define warn_type(col, type)

Referenced by require_odbc().

Function Documentation

static void __init_rowdata_buf ( void  )
static

Definition at line 51 of file res_config_odbc.c.

53 {
static void __init_sql_buf ( void  )
static

Definition at line 50 of file res_config_odbc.c.

53 {
static void __reg_module ( void  )
static

Definition at line 1302 of file res_config_odbc.c.

static void __unreg_module ( void  )
static

Definition at line 1302 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 962 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_free, ast_log(), ast_malloc, ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_variable_append(), ast_variable_new(), config_odbc_obj::cat_metric, config_odbc_obj::category, config_odbc_prepare(), last, length_determination_odbc_prepare(), LOG_NOTICE, LOG_WARNING, RES_ODBC_CONNECTED, config_odbc_obj::sql, config_odbc_obj::var_name, config_odbc_obj::var_val, and config_odbc_obj::var_val_size.

963 {
964  struct ast_variable *new_v;
965  struct ast_category *cur_cat;
966  int res = 0;
967  struct odbc_obj *obj;
968  char sqlbuf[1024] = "";
969  char *sql = sqlbuf;
970  size_t sqlleft = sizeof(sqlbuf);
971  unsigned int last_cat_metric = 0;
972  SQLSMALLINT rowcount = 0;
973  SQLHSTMT stmt;
974  char last[128] = "";
975  struct config_odbc_obj q;
976  struct ast_flags loader_flags = { 0 };
977  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
978 
979  memset(&q, 0, sizeof(q));
980 
981  if (!file || !strcmp (file, "res_config_odbc.conf"))
982  return NULL; /* cant configure myself with myself ! */
983 
984  obj = ast_odbc_request_obj2(database, connected_flag);
985  if (!obj)
986  return NULL;
987 
988  q.sql = sqlbuf;
989 
990  ast_build_string(&sql, &sqlleft, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'", table, file);
991 
993 
994  if (!stmt) {
995  ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
997  return NULL;
998  }
999 
1000  res = SQLNumResultCols(stmt, &rowcount);
1001 
1002  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1003  ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
1004  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1005  ast_odbc_release_obj(obj);
1006  return NULL;
1007  }
1008 
1009  if (!rowcount) {
1010  ast_log(LOG_NOTICE, "found nothing\n");
1011  ast_odbc_release_obj(obj);
1012  return cfg;
1013  }
1014 
1015  /* There will be only one result for this, the maximum length of a variable value */
1016  if (SQLFetch(stmt) == SQL_NO_DATA) {
1017  ast_log(LOG_NOTICE, "Failed to determine maximum length of a configuration value\n");
1018  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1019  ast_odbc_release_obj(obj);
1020  return NULL;
1021  }
1022 
1023  /* Reset stuff to a fresh state for the actual query which will retrieve all configuration */
1024  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1025  sql = sqlbuf;
1026  sqlleft = sizeof(sqlbuf);
1027 
1028  ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
1029  ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file);
1030  ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
1031 
1032  q.var_val_size += 1;
1033  q.var_val = ast_malloc(q.var_val_size);
1034  if (!q.var_val) {
1035  ast_log(LOG_WARNING, "Could not create buffer for reading in configuration values for '%s'\n", file);
1036  ast_odbc_release_obj(obj);
1037  return NULL;
1038  }
1039 
1041 
1042  if (!stmt) {
1043  ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
1044  ast_odbc_release_obj(obj);
1045  ast_free(q.var_val);
1046  return NULL;
1047  }
1048 
1049  res = SQLNumResultCols(stmt, &rowcount);
1050 
1051  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1052  ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
1053  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1054  ast_odbc_release_obj(obj);
1055  ast_free(q.var_val);
1056  return NULL;
1057  }
1058 
1059  if (!rowcount) {
1060  ast_log(LOG_NOTICE, "found nothing\n");
1061  ast_odbc_release_obj(obj);
1062  ast_free(q.var_val);
1063  return cfg;
1064  }
1065 
1066  cur_cat = ast_config_get_current_category(cfg);
1067 
1068  while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
1069  if (!strcmp (q.var_name, "#include")) {
1070  if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
1071  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1072  ast_odbc_release_obj(obj);
1073  ast_free(q.var_val);
1074  return NULL;
1075  }
1076  continue;
1077  }
1078  if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
1079  cur_cat = ast_category_new(q.category, "", 99999);
1080  if (!cur_cat) {
1081  ast_log(LOG_WARNING, "Out of memory!\n");
1082  break;
1083  }
1084  strcpy(last, q.category);
1085  last_cat_metric = q.cat_metric;
1086  ast_category_append(cfg, cur_cat);
1087  }
1088 
1089  new_v = ast_variable_new(q.var_name, q.var_val, "");
1090  ast_variable_append(cur_cat, new_v);
1091  }
1092 
1093  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1094  ast_odbc_release_obj(obj);
1095  ast_free(q.var_val);
1096  return cfg;
1097 }
static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
static SQLHSTMT length_determination_odbc_prepare(struct odbc_obj *obj, void *data)
#define LOG_WARNING
Definition: logger.h:144
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
Definition: config.c:1055
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
Definition: config.c:673
static char * table
Definition: cdr_odbc.c:50
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:1521
ODBC container.
Definition: res_odbc.h:46
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: config.c:483
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define ast_free(a)
Definition: astmm.h:97
Structure used to handle boolean flags.
Definition: utils.h:200
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.
Definition: res_odbc.c:622
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Definition: config.c:719
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: config.c:2459
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
#define ast_malloc(a)
Definition: astmm.h:91
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
static SQLHSTMT config_odbc_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 935 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, config_odbc_obj::var_val, and config_odbc_obj::var_val_size.

Referenced by config_odbc().

936 {
937  struct config_odbc_obj *q = data;
938  SQLHSTMT sth;
939  int res;
940 
941  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
942  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
943  ast_verb(4, "Failure in AllocStatement %d\n", res);
944  return NULL;
945  }
946 
947  res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
948  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
949  ast_verb(4, "Error in PREPARE %d\n", res);
950  SQLFreeHandle(SQL_HANDLE_STMT, sth);
951  return NULL;
952  }
953 
954  SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
955  SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
956  SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
957  SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, q->var_val_size, &q->err);
958 
959  return sth;
960 }
SQLHDBC con
Definition: res_odbc.h:48
unsigned long cat_metric
#define ast_verb(level,...)
Definition: logger.h:243
unsigned long var_val_size
static SQLHSTMT custom_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 99 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, ENCODE_CHUNK, encoding, custom_prepare_struct::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().

100 {
101  int res, x = 1, count = 0;
102  struct custom_prepare_struct *cps = data;
103  const char *newparam, *newval;
104  char encodebuf[1024];
105  SQLHSTMT stmt;
106  va_list ap;
107 
108  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
109  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
110  ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
111  return NULL;
112  }
113 
114  ast_debug(1, "Skip: %llu; SQL: %s\n", cps->skip, cps->sql);
115 
116  res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS);
117  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
118  ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql);
119  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
120  return NULL;
121  }
122 
123  va_copy(ap, cps->ap);
124  while ((newparam = va_arg(ap, const char *))) {
125  newval = va_arg(ap, const char *);
126  if ((1LL << count++) & cps->skip) {
127  ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", newparam, newval, 1ULL << (count - 1), cps->skip);
128  continue;
129  }
130  ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, newparam, newval);
131  if (strchr(newval, ';') || strchr(newval, '^')) {
132  ENCODE_CHUNK(encodebuf, newval);
133  ast_string_field_set(cps, encoding[x], encodebuf);
134  newval = cps->encoding[x];
135  }
136  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
137  }
138  va_end(ap);
139 
140  if (!ast_strlen_zero(cps->extra)) {
141  const char *newval = cps->extra;
142  if (strchr(newval, ';') || strchr(newval, '^')) {
143  ENCODE_CHUNK(encodebuf, newval);
144  ast_string_field_set(cps, encoding[x], encodebuf);
145  newval = cps->encoding[x];
146  }
147  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
148  }
149 
150  return stmt;
151 }
SQLHDBC con
Definition: res_odbc.h:48
static char * encoding
Definition: cdr_pgsql.c:56
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
const ast_string_field encoding[256]
#define ENCODE_CHUNK(buffer, s)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
unsigned long long skip
static void decode_chunk ( char *  chunk)
static

Definition at line 83 of file res_config_odbc.c.

Referenced by realtime_multi_odbc(), and realtime_odbc().

84 {
85  for (; *chunk; chunk++) {
86  if (*chunk == '^' && strchr("0123456789ABCDEF", chunk[1]) && strchr("0123456789ABCDEF", chunk[2])) {
87  sscanf(chunk + 1, "%02hhX", (unsigned char *)chunk);
88  memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
89  }
90  }
91 }
static int destroy_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
va_list  ap 
)
static

Excute an DELETE query.

Parameters
database
table
keyfieldwhere clause field
lookupvalue of field for where clause
aplist containing one or more field/value set(s)

Delete a row from a database table, prepare the sql statement using keyfield and lookup control the number of records to change. Additional params to match rows are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values
numberof rows affected
-1on failure

Definition at line 840 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, ast_string_field_free_memory, ast_string_field_init, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.

841 {
842  struct odbc_obj *obj;
843  SQLHSTMT stmt;
844  char sql[256];
845  SQLLEN rowcount=0;
846  const char *newparam;
847  int res;
848  va_list aq;
849  struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
850  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
851 
852  if (!table) {
853  return -1;
854  }
855 
856  obj = ast_odbc_request_obj2(database, connected_flag);
857  if (!obj) {
858  return -1;
859  }
860 
861  snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table);
862 
863  va_copy(aq, ap);
864  while((newparam = va_arg(aq, const char *))) {
865  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam);
866  va_arg(aq, const char *);
867  }
868  va_end(aq);
869  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield);
870 
871  if (ast_string_field_init(&cps, 256)) {
873  return -1;
874  }
875  va_copy(cps.ap, ap);
876  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
877  va_end(cps.ap);
879 
880  if (!stmt) {
882  return -1;
883  }
884 
885  res = SQLRowCount(stmt, &rowcount);
886  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
888 
889  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
890  ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
891  return -1;
892  }
893 
894  if (rowcount >= 0)
895  return (int)rowcount;
896 
897  return -1;
898 }
#define LOG_WARNING
Definition: logger.h:144
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
static char * table
Definition: cdr_odbc.c:50
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
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.
Definition: res_odbc.c:622
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static int is_text ( const struct odbc_cache_columns column)
inlinestatic

Definition at line 93 of file res_config_odbc.c.

References odbc_cache_columns::type.

Referenced by update_odbc().

94 {
95  return column->type == SQL_CHAR || column->type == SQL_VARCHAR || column->type == SQL_LONGVARCHAR
96  || column->type == SQL_WCHAR || column->type == SQL_WVARCHAR || column->type == SQL_WLONGVARCHAR;
97 }
SQLSMALLINT type
Definition: res_odbc.h:66
static SQLHSTMT length_determination_odbc_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 911 of file res_config_odbc.c.

References ast_verb, odbc_obj::con, config_odbc_obj::err, config_odbc_obj::sql, and config_odbc_obj::var_val_size.

Referenced by config_odbc().

912 {
913  struct config_odbc_obj *q = data;
914  SQLHSTMT sth;
915  int res;
916 
917  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
918  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
919  ast_verb(4, "Failure in AllocStatement %d\n", res);
920  return NULL;
921  }
922 
923  res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
924  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
925  ast_verb(4, "Error in PREPARE %d\n", res);
926  SQLFreeHandle(SQL_HANDLE_STMT, sth);
927  return NULL;
928  }
929 
930  SQLBindCol(sth, 1, SQL_C_ULONG, &q->var_val_size, sizeof(q->var_val_size), &q->err);
931 
932  return sth;
933 }
SQLHDBC con
Definition: res_odbc.h:48
#define ast_verb(level,...)
Definition: logger.h:243
unsigned long var_val_size
static int load_module ( void  )
static

Definition at line 1285 of file res_config_odbc.c.

References ast_config_engine_register(), and ast_verb.

1286 {
1288  ast_verb(1, "res_config_odbc loaded.\n");
1289  return 0;
1290 }
#define ast_verb(level,...)
Definition: logger.h:243
static struct ast_config_engine odbc_engine
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: config.c:2378
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.

Parameters
database
table
aplist containing one or more field/operator/value set.

Select database and preform query on table, prepare the sql statement Sub-in the values to the prepared statement and execute it. Execute this prepared query against several ODBC connected databases. Return results as an ast_config variable.

Return values
varon success
NULLon failure

Definition at line 335 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_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_str_strlen(), ast_str_thread_get(), ast_str_update(), 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, rowdata_buf, custom_prepare_struct::sql, strcasestr(), strsep(), and var.

336 {
337  struct odbc_obj *obj;
338  SQLHSTMT stmt;
339  char sql[1024];
340  char coltitle[256];
341  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
342  const char *initfield;
343  char *op;
344  const char *newparam;
345  char *stringp;
346  char *chunk;
347  SQLSMALLINT collen;
348  int res;
349  int x;
350  struct ast_variable *var=NULL;
351  struct ast_config *cfg=NULL;
352  struct ast_category *cat=NULL;
353  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
354  SQLULEN colsize;
355  SQLSMALLINT colcount=0;
356  SQLSMALLINT datatype;
357  SQLSMALLINT decimaldigits;
358  SQLSMALLINT nullable;
359  SQLLEN indicator;
360  struct custom_prepare_struct cps = { .sql = sql };
361  va_list aq;
362 
363  if (!table) {
364  return NULL;
365  }
366 
367  obj = ast_odbc_request_obj2(database, connected_flag);
368  if (!obj) {
369  return NULL;
370  }
371 
372  va_copy(aq, ap);
373  newparam = va_arg(aq, const char *);
374  if (!newparam) {
375  va_end(aq);
377  return NULL;
378  }
379 
380  initfield = ast_strdupa(newparam);
381  if ((op = strchr(initfield, ' '))) {
382  *op = '\0';
383  }
384 
385  va_arg(aq, const char *);
386  op = !strchr(newparam, ' ') ? " =" : "";
387  snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
388  strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
389  while((newparam = va_arg(aq, const char *))) {
390  op = !strchr(newparam, ' ') ? " =" : "";
391  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
392  strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
393  va_arg(aq, const char *);
394  }
395  va_end(aq);
396 
397  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
398 
399  if (ast_string_field_init(&cps, 256)) {
401  return NULL;
402  }
403  va_copy(cps.ap, ap);
404  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
405  va_end(cps.ap);
407 
408  if (!stmt) {
410  return NULL;
411  }
412 
413  res = SQLNumResultCols(stmt, &colcount);
414  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
415  ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
416  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
418  return NULL;
419  }
420 
421  cfg = ast_config_new();
422  if (!cfg) {
423  ast_log(LOG_WARNING, "Out of memory!\n");
424  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
426  return NULL;
427  }
428 
429  while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
430  var = NULL;
431  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
432  ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
433  continue;
434  }
435  cat = ast_category_new("","",99999);
436  if (!cat) {
437  ast_log(LOG_WARNING, "Out of memory!\n");
438  continue;
439  }
440  for (x=0;x<colcount;x++) {
441  colsize = 0;
442  collen = sizeof(coltitle);
443  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
444  &datatype, &colsize, &decimaldigits, &nullable);
445  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
446  ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
448  goto next_sql_fetch;
449  }
450 
451  ast_str_reset(rowdata);
452  indicator = 0;
453 
454  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
455  ast_str_update(rowdata);
456  if (indicator == SQL_NULL_DATA) {
457  continue;
458  }
459 
460  if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
461  if (indicator != ast_str_strlen(rowdata)) {
462  /* If the available space was not enough to contain the row data enlarge and read in the rest */
463  ast_str_make_space(&rowdata, indicator + 1);
464  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
465  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
466  ast_str_update(rowdata);
467  }
468  }
469 
470  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
471  ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
473  goto next_sql_fetch;
474  }
475  stringp = ast_str_buffer(rowdata);
476  while (stringp) {
477  chunk = strsep(&stringp, ";");
478  if (!ast_strlen_zero(ast_strip(chunk))) {
479  if (strchr(chunk, '^')) {
480  decode_chunk(chunk);
481  }
482  if (!strcmp(initfield, coltitle)) {
483  ast_category_rename(cat, chunk);
484  }
485  var = ast_variable_new(coltitle, chunk, "");
486  ast_variable_append(cat, var);
487  }
488  }
489  }
490  ast_category_append(cfg, cat);
491 next_sql_fetch:;
492  }
493 
494  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
496  return cfg;
497 }
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Definition: res_odbc.c:1118
char * strsep(char **str, const char *delims)
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:482
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
Definition: config.c:673
static char * table
Definition: cdr_odbc.c:50
void ast_category_destroy(struct ast_category *cat)
Definition: config.c:762
ODBC container.
Definition: res_odbc.h:46
int ast_str_make_space(struct ast_str **buf, size_t new_len)
Definition: strings.h:588
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
static struct ast_threadstorage rowdata_buf
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: config.c:483
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: config.c:888
Structure used to handle boolean flags.
Definition: utils.h:200
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
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.
Definition: res_odbc.c:622
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:446
static void decode_chunk(char *chunk)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Definition: config.c:719
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
void ast_category_rename(struct ast_category *cat, const char *name)
Definition: config.c:867
char * strcasestr(const char *, const char *)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
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.

Parameters
database
table
aplist containing one or more field/operator/value set.

Select database and preform query on table, prepare the sql statement Sub-in the values to the prepared statement and execute it. Return results as a ast_variable list.

Return values
varon success
NULLon failure

Definition at line 166 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_log(), ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_set(), ast_str_size(), ast_str_strlen(), ast_str_thread_get(), ast_str_update(), 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, rowdata_buf, custom_prepare_struct::sql, strcasestr(), strsep(), and var.

167 {
168  struct odbc_obj *obj;
169  SQLHSTMT stmt;
170  char sql[1024];
171  char coltitle[256];
172  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
173  char *op;
174  const char *newparam;
175  char *stringp;
176  char *chunk;
177  SQLSMALLINT collen;
178  int res;
179  int x;
180  struct ast_variable *var=NULL, *prev=NULL;
181  SQLULEN colsize;
182  SQLSMALLINT colcount=0;
183  SQLSMALLINT datatype;
184  SQLSMALLINT decimaldigits;
185  SQLSMALLINT nullable;
186  SQLLEN indicator;
187  va_list aq;
188  struct custom_prepare_struct cps = { .sql = sql };
189  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
190 
191  if (!table) {
192  return NULL;
193  }
194 
195  obj = ast_odbc_request_obj2(database, connected_flag);
196 
197  if (!obj) {
198  ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
199  return NULL;
200  }
201 
202  va_copy(aq, ap);
203  newparam = va_arg(aq, const char *);
204  if (!newparam) {
205  va_end(aq);
207  return NULL;
208  }
209  va_arg(aq, const char *);
210  op = !strchr(newparam, ' ') ? " =" : "";
211  snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
212  strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
213  while((newparam = va_arg(aq, const char *))) {
214  op = !strchr(newparam, ' ') ? " =" : "";
215  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
216  strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
217  va_arg(aq, const char *);
218  }
219  va_end(aq);
220 
221  if (ast_string_field_init(&cps, 256)) {
223  return NULL;
224  }
225  va_copy(cps.ap, ap);
226  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
227  va_end(cps.ap);
229 
230  if (!stmt) {
232  return NULL;
233  }
234 
235  res = SQLNumResultCols(stmt, &colcount);
236  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
237  ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
238  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
240  return NULL;
241  }
242 
243  res = SQLFetch(stmt);
244  if (res == SQL_NO_DATA) {
245  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
247  return NULL;
248  }
249  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
250  ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
251  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
253  return NULL;
254  }
255  for (x = 0; x < colcount; x++) {
256  colsize = 0;
257  collen = sizeof(coltitle);
258  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
259  &datatype, &colsize, &decimaldigits, &nullable);
260  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
261  ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
262  if (var)
265  return NULL;
266  }
267 
268  ast_str_reset(rowdata);
269  indicator = 0;
270 
271  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
272  ast_str_update(rowdata);
273  if (indicator == SQL_NULL_DATA) {
274  ast_str_reset(rowdata);
275  } else if (!ast_str_strlen(rowdata)) {
276  /* Because we encode the empty string for a NULL, we will encode
277  * actual empty strings as a string containing a single whitespace. */
278  ast_str_set(&rowdata, -1, "%s", " ");
279  } else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
280  if (indicator != ast_str_strlen(rowdata)) {
281  /* If the available space was not enough to contain the row data enlarge and read in the rest */
282  ast_str_make_space(&rowdata, indicator + 1);
283  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
284  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
285  ast_str_update(rowdata);
286  }
287  }
288 
289  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
290  ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
291  if (var)
294  return NULL;
295  }
296 
297  stringp = ast_str_buffer(rowdata);
298  while (stringp) {
299  chunk = strsep(&stringp, ";");
300  if (!ast_strlen_zero(ast_strip(chunk))) {
301  if (strchr(chunk, '^')) {
302  decode_chunk(chunk);
303  }
304  if (prev) {
305  prev->next = ast_variable_new(coltitle, chunk, "");
306  if (prev->next) {
307  prev = prev->next;
308  }
309  } else {
310  prev = var = ast_variable_new(coltitle, chunk, "");
311  }
312  }
313  }
314  }
315 
316  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
318  return var;
319 }
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Definition: res_odbc.c:1118
char * strsep(char **str, const char *delims)
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:482
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
static char * table
Definition: cdr_odbc.c:50
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
ODBC container.
Definition: res_odbc.h:46
int ast_str_make_space(struct ast_str **buf, size_t new_len)
Definition: strings.h:588
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
static struct ast_threadstorage rowdata_buf
#define LOG_ERROR
Definition: logger.h:155
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
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.
Definition: res_odbc.c:622
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:446
static void decode_chunk(char *chunk)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
char * strcasestr(const char *, const char *)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
static int reload_module ( void  )
static

Definition at line 1292 of file res_config_odbc.c.

1293 {
1294  return 0;
1295 }
static int require_odbc ( const char *  database,
const char *  table,
va_list  ap 
)
static

Definition at line 1102 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, 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, type, odbc_cache_columns::type, warn_length, warn_type, and WARN_TYPE_OR_LENGTH.

1103 {
1104  struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
1105  struct odbc_cache_columns *col;
1106  char *elm;
1107  int type, size;
1108 
1109  if (!tableptr) {
1110  return -1;
1111  }
1112 
1113  while ((elm = va_arg(ap, char *))) {
1114  type = va_arg(ap, require_type);
1115  size = va_arg(ap, int);
1116  /* Check if the field matches the criteria */
1117  AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) {
1118  if (strcmp(col->name, elm) == 0) {
1119  /* Type check, first. Some fields are more particular than others */
1120  switch (col->type) {
1121  case SQL_CHAR:
1122  case SQL_VARCHAR:
1123  case SQL_LONGVARCHAR:
1124 #ifdef HAVE_ODBC_WCHAR
1125  case SQL_WCHAR:
1126  case SQL_WVARCHAR:
1127  case SQL_WLONGVARCHAR:
1128 #endif
1129  case SQL_BINARY:
1130  case SQL_VARBINARY:
1131  case SQL_LONGVARBINARY:
1132  case SQL_GUID:
1133 #define CHECK_SIZE(n) \
1134  if (col->size < n) { \
1135  warn_length(col, n); \
1136  } \
1137  break;
1138  switch (type) {
1139  case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */
1140  case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */
1141  case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */
1142  case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */
1143  case RQ_UINTEGER3: /* 16777215 */
1144  case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */
1145  case RQ_DATE: /* 2008-06-09 */
1146  case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */
1147  case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */
1148  case RQ_DATETIME: /* 2008-06-09 16:03:47 */
1149  case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */
1150  case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */
1151  case RQ_FLOAT:
1152  case RQ_CHAR: CHECK_SIZE(size)
1153  }
1154 #undef CHECK_SIZE
1155  break;
1156  case SQL_TYPE_DATE:
1157  if (type != RQ_DATE) {
1158  warn_type(col, type);
1159  }
1160  break;
1161  case SQL_TYPE_TIMESTAMP:
1162  case SQL_TIMESTAMP:
1163  if (type != RQ_DATE && type != RQ_DATETIME) {
1164  warn_type(col, type);
1165  }
1166  break;
1167  case SQL_BIT:
1168  warn_length(col, size);
1169  break;
1170 #define WARN_TYPE_OR_LENGTH(n) \
1171  if (!ast_rq_is_int(type)) { \
1172  warn_type(col, type); \
1173  } else { \
1174  warn_length(col, n); \
1175  }
1176  case SQL_TINYINT:
1177  if (type != RQ_UINTEGER1) {
1178  WARN_TYPE_OR_LENGTH(size)
1179  }
1180  break;
1181  case SQL_C_STINYINT:
1182  if (type != RQ_INTEGER1) {
1183  WARN_TYPE_OR_LENGTH(size)
1184  }
1185  break;
1186  case SQL_C_USHORT:
1187  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
1188  WARN_TYPE_OR_LENGTH(size)
1189  }
1190  break;
1191  case SQL_SMALLINT:
1192  case SQL_C_SSHORT:
1193  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
1194  WARN_TYPE_OR_LENGTH(size)
1195  }
1196  break;
1197  case SQL_C_ULONG:
1198  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1199  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1200  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1201  type != RQ_INTEGER4) {
1202  WARN_TYPE_OR_LENGTH(size)
1203  }
1204  break;
1205  case SQL_INTEGER:
1206  case SQL_C_SLONG:
1207  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1208  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1209  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1210  type != RQ_INTEGER4) {
1211  WARN_TYPE_OR_LENGTH(size)
1212  }
1213  break;
1214  case SQL_C_UBIGINT:
1215  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1216  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1217  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1218  type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1219  type != RQ_INTEGER8) {
1220  WARN_TYPE_OR_LENGTH(size)
1221  }
1222  break;
1223  case SQL_BIGINT:
1224  case SQL_C_SBIGINT:
1225  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1226  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1227  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1228  type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1229  type != RQ_INTEGER8) {
1230  WARN_TYPE_OR_LENGTH(size)
1231  }
1232  break;
1233 #undef WARN_TYPE_OR_LENGTH
1234  case SQL_NUMERIC:
1235  case SQL_DECIMAL:
1236  case SQL_FLOAT:
1237  case SQL_REAL:
1238  case SQL_DOUBLE:
1239  if (!ast_rq_is_int(type) && type != RQ_FLOAT) {
1240  warn_type(col, type);
1241  }
1242  break;
1243  default:
1244  ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm);
1245  }
1246  break;
1247  }
1248  }
1249  if (!col) {
1250  ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
1251  }
1252  }
1253  AST_RWLIST_UNLOCK(&tableptr->columns);
1254  return 0;
1255 }
#define CHECK_SIZE(n)
#define LOG_WARNING
Definition: logger.h:144
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
These structures are used for adaptive capabilities.
Definition: res_odbc.h:64
static char * table
Definition: cdr_odbc.c:50
Definition: config.h:68
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:449
#define warn_length(col, size)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
SQLINTEGER size
Definition: res_odbc.h:67
static const char type[]
Definition: chan_nbs.c:57
#define WARN_TYPE_OR_LENGTH(n)
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
Definition: config.h:768
#define warn_type(col, type)
SQLSMALLINT type
Definition: res_odbc.h:66
require_type
Types used in ast_realtime_require_field.
Definition: config.h:57
Definition: config.h:70
struct odbc_cache_tables::_columns columns
static int store_odbc ( const char *  database,
const char *  table,
va_list  ap 
)
static

Excute an INSERT query.

Parameters
database
table
aplist containing one or more field/value set(s)

Insert a new record into database table, prepare the sql statement. All values to be changed are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values
numberof rows affected
-1on failure

Definition at line 754 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, ast_string_field_free_memory, ast_string_field_init, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.

755 {
756  struct odbc_obj *obj;
757  SQLHSTMT stmt;
758  char sql[256];
759  char keys[256];
760  char vals[256];
761  SQLLEN rowcount=0;
762  const char *newparam;
763  int res;
764  va_list aq;
765  struct custom_prepare_struct cps = { .sql = sql, .extra = NULL };
766  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
767 
768  if (!table) {
769  return -1;
770  }
771 
772  obj = ast_odbc_request_obj2(database, connected_flag);
773  if (!obj) {
774  return -1;
775  }
776 
777  va_copy(aq, ap);
778 
779  newparam = va_arg(aq, const char *);
780  if (!newparam) {
781  va_end(aq);
783  return -1;
784  }
785  va_arg(aq, const char *);
786  snprintf(keys, sizeof(keys), "%s", newparam);
787  ast_copy_string(vals, "?", sizeof(vals));
788  while ((newparam = va_arg(aq, const char *))) {
789  snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam);
790  snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?");
791  va_arg(aq, const char *);
792  }
793  va_end(aq);
794  snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals);
795 
796  if (ast_string_field_init(&cps, 256)) {
798  return -1;
799  }
800  va_copy(cps.ap, ap);
801  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
802  va_end(cps.ap);
804 
805  if (!stmt) {
807  return -1;
808  }
809 
810  res = SQLRowCount(stmt, &rowcount);
811  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
813 
814  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
815  ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
816  return -1;
817  }
818 
819  if (rowcount >= 0)
820  return (int)rowcount;
821 
822  return -1;
823 }
#define LOG_WARNING
Definition: logger.h:144
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
static char * table
Definition: cdr_odbc.c:50
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
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.
Definition: res_odbc.c:622
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static int unload_module ( void  )
static

Definition at line 1277 of file res_config_odbc.c.

References ast_config_engine_deregister(), and ast_verb.

1278 {
1280 
1281  ast_verb(1, "res_config_odbc unloaded.\n");
1282  return 0;
1283 }
#define ast_verb(level,...)
Definition: logger.h:243
static struct ast_config_engine odbc_engine
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: config.c:2397
static int unload_odbc ( const char *  a,
const char *  b 
)
static

Definition at line 1259 of file res_config_odbc.c.

References ast_odbc_clear_cache().

1260 {
1261  return ast_odbc_clear_cache(a, b);
1262 }
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...
Definition: res_odbc.c:577
static int update2_odbc ( const char *  database,
const char *  table,
va_list  ap 
)
static

Execute an UPDATE query.

Parameters
database
table
aplist containing one or more field/value set(s).

Update a database table, preparing the sql statement from a list of key/value pairs specified in ap. The lookup pairs are specified first and are separated from the update pairs by a sentinel value. Sub-in the values to the prepared statement and execute it.

Return values
numberof rows affected
-1on failure

Definition at line 702 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, table, and update2_prepare().

703 {
704  struct odbc_obj *obj;
705  SQLHSTMT stmt;
706  struct update2_prepare_struct ups = { .database = database, .table = table, };
707  struct ast_str *sql;
708  int res;
709  SQLLEN rowcount = 0;
710 
711  if (!(obj = ast_odbc_request_obj(database, 0))) {
712  return -1;
713  }
714 
715  va_copy(ups.ap, ap);
716  if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) {
717  va_end(ups.ap);
719  return -1;
720  }
721  va_end(ups.ap);
722 
723  res = SQLRowCount(stmt, &rowcount);
724  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
726 
727  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
728  /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
729  sql = ast_str_thread_get(&sql_buf, 16);
730  ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql));
731  return -1;
732  }
733 
734  if (rowcount >= 0) {
735  return (int)rowcount;
736  }
737 
738  return -1;
739 }
static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data)
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
static char * table
Definition: cdr_odbc.c:50
ODBC container.
Definition: res_odbc.h:46
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_odbc_request_obj(a, b)
Definition: res_odbc.h:123
static struct ast_threadstorage sql_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.
Definition: res_odbc.c:622
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
static SQLHSTMT update2_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 604 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().

605 {
606  int res, x = 1, first = 1;
607  struct update2_prepare_struct *ups = data;
608  const char *newparam, *newval;
609  struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
610  SQLHSTMT stmt;
611  va_list ap;
612  struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table);
613 
614  if (!sql) {
615  if (tableptr) {
616  ast_odbc_release_table(tableptr);
617  }
618  return NULL;
619  }
620 
621  if (!tableptr) {
622  ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", ups->table, ups->database);
623  return NULL;
624  }
625 
626  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
627  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
628  ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
629  ast_odbc_release_table(tableptr);
630  return NULL;
631  }
632 
633  ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table);
634 
635  /* Start by finding the second set of parameters */
636  va_copy(ap, ups->ap);
637 
638  while ((newparam = va_arg(ap, const char *))) {
639  newval = va_arg(ap, const char *);
640  }
641 
642  while ((newparam = va_arg(ap, const char *))) {
643  newval = va_arg(ap, const char *);
644  if (ast_odbc_find_column(tableptr, newparam)) {
645  ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", newparam);
646  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
647  first = 0;
648  } else {
649  ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", newparam, ups->table, ups->database);
650  }
651  }
652  va_end(ap);
653 
654  ast_str_append(&sql, 0, "WHERE");
655  first = 1;
656 
657  /* Restart search, because we need to add the search parameters */
658  va_copy(ap, ups->ap);
659 
660  while ((newparam = va_arg(ap, const char *))) {
661  newval = va_arg(ap, const char *);
662  if (!ast_odbc_find_column(tableptr, newparam)) {
663  va_end(ap);
664  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);
665  ast_odbc_release_table(tableptr);
666  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
667  return NULL;
668  }
669  ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", newparam);
670  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
671  first = 0;
672  }
673  va_end(ap);
674 
675  /* Done with the table metadata */
676  ast_odbc_release_table(tableptr);
677 
678  res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS);
679  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
680  ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql));
681  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
682  return NULL;
683  }
684 
685  return stmt;
686 }
SQLHDBC con
Definition: res_odbc.h:48
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
Definition: res_odbc.h:213
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
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.
Definition: res_odbc.c:566
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:449
#define LOG_ERROR
Definition: logger.h:155
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static struct ast_threadstorage sql_buf
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
static int update_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
va_list  ap 
)
static

Excute an UPDATE query.

Parameters
database
table
keyfieldwhere clause field
lookupvalue of field for where clause
aplist containing one or more field/value set(s).

Update a database table, prepare the sql statement using keyfield and lookup control the number of records to change. All values to be changed are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values
numberof rows affected
-1on failure

Definition at line 514 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_log(), ast_odbc_allow_empty_string_in_nontext(), 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, ast_strlen_zero(), custom_prepare(), is_text(), LOG_WARNING, odbc_cache_columns::nullable, RES_ODBC_CONNECTED, custom_prepare_struct::skip, and custom_prepare_struct::sql.

515 {
516  struct odbc_obj *obj;
517  SQLHSTMT stmt;
518  char sql[256];
519  SQLLEN rowcount=0;
520  const char *newparam, *newval;
521  int res, count = 0, paramcount = 0;
522  va_list aq;
523  struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
524  struct odbc_cache_tables *tableptr;
525  struct odbc_cache_columns *column = NULL;
526  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
527 
528  if (!table || !keyfield) {
529  return -1;
530  }
531 
532  tableptr = ast_odbc_find_table(database, table);
533  if (!(obj = ast_odbc_request_obj2(database, connected_flag))) {
534  ast_odbc_release_table(tableptr);
535  return -1;
536  }
537 
538  if (tableptr && !ast_odbc_find_column(tableptr, keyfield)) {
539  ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", keyfield, table, database);
540  }
541 
542  va_copy(aq, ap);
543 
544  snprintf(sql, sizeof(sql), "UPDATE %s SET ", table);
545  while((newparam = va_arg(aq, const char *))) {
546  newval = va_arg(aq, const char *);
547  if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count >= 64) {
548  if (paramcount++) {
549  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", ");
550  }
551  /* NULL test for non-text columns */
552  if (count < 64 && ast_strlen_zero(newval) && column->nullable && !is_text(column) && !ast_odbc_allow_empty_string_in_nontext(obj)) {
553  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=NULL", newparam);
554  cps.skip |= (1LL << count);
555  } else {
556  /* Value is not an empty string, or column accepts empty strings, or we couldn't fit any more into cps.skip (count >= 64 ?!). */
557  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", newparam);
558  }
559  } else { /* the column does not exist in the table */
560  cps.skip |= (1LL << count);
561  }
562  ++count;
563  }
564  va_end(aq);
565  snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
566  ast_odbc_release_table(tableptr);
567 
568  if (ast_string_field_init(&cps, 256)) {
570  return -1;
571  }
572  va_copy(cps.ap, ap);
573  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
574  va_end(cps.ap);
576 
577  if (!stmt) {
579  return -1;
580  }
581 
582  res = SQLRowCount(stmt, &rowcount);
583  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
585 
586  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
587  ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
588  return -1;
589  }
590 
591  if (rowcount >= 0) {
592  return (int) rowcount;
593  }
594 
595  return -1;
596 }
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
Definition: res_odbc.h:213
#define LOG_WARNING
Definition: logger.h:144
SQLSMALLINT nullable
Definition: res_odbc.h:70
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:122
These structures are used for adaptive capabilities.
Definition: res_odbc.h:64
static char * table
Definition: cdr_odbc.c:50
ODBC container.
Definition: res_odbc.h:46
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.
Definition: res_odbc.c:566
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:449
int ast_odbc_allow_empty_string_in_nontext(struct odbc_obj *obj)
Checks if the database natively supports implicit conversion from an empty string to a number (0)...
Definition: res_odbc.c:1123
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
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.
Definition: res_odbc.c:622
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
static int is_text(const struct odbc_cache_columns *column)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
unsigned long long skip

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
static

Definition at line 1302 of file res_config_odbc.c.

Definition at line 1302 of file res_config_odbc.c.

struct ast_config_engine odbc_engine
static

Definition at line 1264 of file res_config_odbc.c.

struct ast_threadstorage rowdata_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_rowdata_buf , .custom_init = NULL , }
static

Definition at line 51 of file res_config_odbc.c.

Referenced by realtime_multi_odbc(), and realtime_odbc().

struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , }
static

Definition at line 50 of file res_config_odbc.c.

Referenced by update2_odbc(), and update2_prepare().