50 #define SQL_BUF_SIZE 1024 65 #define ENCODE_CHUNK(buffer, s) \ 67 char *eptr = buffer; \ 68 const char *vptr = s; \ 69 for (; *vptr && eptr < buffer + sizeof(buffer); vptr++) { \ 70 if (strchr("^;", *vptr)) { \ 72 snprintf(eptr, buffer + sizeof(buffer) - eptr, "^%02hhX", *vptr); \ 78 if (eptr < buffer + sizeof(buffer)) { \ 81 buffer[sizeof(buffer) - 1] = '\0'; \ 87 for (; *chunk; chunk++) {
88 if (*chunk ==
'^' && strchr(
"0123456789ABCDEF", chunk[1]) && strchr(
"0123456789ABCDEF", chunk[2])) {
89 sscanf(chunk + 1,
"%02hhX", (
unsigned char *)chunk);
90 memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
97 return column->
type == SQL_CHAR || column->
type == SQL_VARCHAR || column->
type == SQL_LONGVARCHAR
98 || column->
type == SQL_WCHAR || column->
type == SQL_WVARCHAR || column->
type == SQL_WLONGVARCHAR;
103 int res, x = 1, count = 0;
106 char encodebuf[1024];
109 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
110 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
118 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
119 if (res == SQL_ERROR) {
123 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
127 for (field = cps->
fields; field; field = field->
next) {
128 const char *newval = field->
value;
130 if ((1LL << count++) & cps->
skip) {
131 ast_debug(1,
"Skipping field '%s'='%s' (%llo/%llo)\n", field->
name, newval, 1ULL << (count - 1), cps->
skip);
134 ast_debug(1,
"Parameter %d ('%s') = '%s'\n", x, field->
name, newval);
135 if (strchr(newval,
';') || strchr(newval,
'^')) {
140 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0,
NULL);
144 const char *newval = cps->
extra;
145 ast_debug(1,
"Parameter %d = '%s'\n", x, newval);
146 if (strchr(newval,
';') || strchr(newval,
'^')) {
151 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0,
NULL);
186 SQLSMALLINT colcount=0;
187 SQLSMALLINT datatype;
188 SQLSMALLINT decimaldigits;
189 SQLSMALLINT nullable;
194 if (!table || !field || !sql || !rowdata) {
200 ast_log(
LOG_ERROR,
"No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
204 op = !strchr(field->
name,
' ') ?
" =" :
"";
205 ast_str_set(&sql, 0,
"SELECT * FROM %s WHERE %s%s ?%s", table, field->
name, op,
207 while ((field = field->
next)) {
208 op = !strchr(field->
name,
' ') ?
" =" :
"";
227 res = SQLNumResultCols(stmt, &colcount);
228 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
230 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
235 res = SQLFetch(stmt);
236 if (res == SQL_NO_DATA) {
237 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
241 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
243 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
247 for (x = 0; x < colcount; x++) {
249 collen =
sizeof(coltitle);
250 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle,
sizeof(coltitle), &collen,
251 &datatype, &colsize, &decimaldigits, &nullable);
252 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
265 if (indicator == SQL_NULL_DATA) {
271 }
else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
281 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
290 if (!strncmp(coltitle,
"@", 1)) {
305 chunk =
strsep(&stringp,
";");
307 if (strchr(chunk,
'^')) {
323 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
349 const char *initfield;
362 SQLSMALLINT colcount=0;
363 SQLSMALLINT datatype;
364 SQLSMALLINT decimaldigits;
365 SQLSMALLINT nullable;
369 if (!table || !field || !sql || !rowdata) {
379 if ((op = strchr(initfield,
' '))) {
383 op = !strchr(field->
name,
' ') ?
" =" :
"";
384 ast_str_set(&sql, 0,
"SELECT * FROM %s WHERE %s%s ?%s", table, field->
name, op,
386 while ((field = field->
next)) {
387 op = !strchr(field->
name,
' ') ?
" =" :
"";
407 res = SQLNumResultCols(stmt, &colcount);
408 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
410 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
418 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
423 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
425 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
433 for (x=0;x<colcount;x++) {
435 collen =
sizeof(coltitle);
436 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle,
sizeof(coltitle), &collen,
437 &datatype, &colsize, &decimaldigits, &nullable);
438 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
449 if (indicator == SQL_NULL_DATA) {
453 if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
463 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
469 if (!strncmp(coltitle,
"@", 1)) {
478 chunk =
strsep(&stringp,
";");
480 if (strchr(chunk,
'^')) {
483 if (!strcmp(initfield, coltitle)) {
496 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
523 int res, count = 0, paramcount = 0;
529 if (!table || !field || !keyfield || !sql) {
540 ast_log(
LOG_WARNING,
"Key field '%s' does not exist in table '%s@%s'. Update will fail\n", keyfield, table, database);
552 cps.
skip |= (1LL << count);
558 cps.
skip |= (1LL << count);
580 res = SQLRowCount(stmt, &rowcount);
581 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
584 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
590 return (
int) rowcount;
606 int res, x = 1,
first = 1;
616 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
617 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
627 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
name), 0, (
void *)field->
value, 0,
NULL);
640 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
644 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
value), 0, (
void *)field->
value, 0,
NULL);
649 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
650 if (res == SQL_ERROR) {
654 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
691 ast_log(
LOG_ERROR,
"Could not retrieve metadata for table '%s@%s'. Update will fail!\n", table, database);
709 res = SQLRowCount(stmt, &rowcount);
710 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
713 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
722 return (
int) rowcount;
756 if (!table || !field || !keys || !vals || !sql) {
771 while ((field = field->
next)) {
775 ast_str_set(&sql, 0,
"INSERT INTO %s (%s) VALUES (%s)",
794 res = SQLRowCount(stmt, &rowcount);
795 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
798 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
804 return (
int)rowcount;
835 if (!table || !sql) {
844 ast_str_set(&sql, 0,
"DELETE FROM %s WHERE ", table);
845 for (field = fields; field; field = field->
next) {
864 res = SQLRowCount(stmt, &rowcount);
865 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
868 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
874 return (
int)rowcount;
896 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
897 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
898 ast_verb(4,
"Failure in AllocStatement %d\n", res);
903 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
904 ast_verb(4,
"Error in PREPARE %d\n", res);
905 SQLFreeHandle(SQL_HANDLE_STMT, sth);
920 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
921 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
922 ast_verb(4,
"Failure in AllocStatement %d\n", res);
927 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
928 ast_verb(4,
"Error in PREPARE %d\n", res);
929 SQLFreeHandle(SQL_HANDLE_STMT, sth);
948 unsigned int last_cat_metric = 0;
949 SQLSMALLINT rowcount = 0;
956 memset(&q, 0,
sizeof(q));
958 if (!file || !strcmp (file,
"res_config_odbc.conf") || !sql) {
966 ast_str_set(&sql, 0,
"SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'",
977 res = SQLNumResultCols(stmt, &rowcount);
979 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
981 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
993 if (SQLFetch(stmt) == SQL_NO_DATA) {
994 ast_log(
LOG_NOTICE,
"Failed to determine maximum length of a configuration value\n");
995 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1001 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1003 ast_str_set(&sql, 0,
"SELECT cat_metric, category, var_name, var_val FROM %s ", table);
1004 ast_str_append(&sql, 0,
"WHERE filename='%s' AND commented=0 ", file);
1005 ast_str_append(&sql, 0,
"ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
1011 ast_log(
LOG_WARNING,
"Could not create buffer for reading in configuration values for '%s'\n", file);
1024 res = SQLNumResultCols(stmt, &rowcount);
1026 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1028 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1043 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
1044 if (!strcmp (q.
var_name,
"#include")) {
1046 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1067 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1073 #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) 1074 #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) 1087 while ((elm = va_arg(ap,
char *))) {
1089 size = va_arg(ap,
int);
1092 if (strcmp(col->
name, elm) == 0) {
1094 switch (col->
type) {
1097 case SQL_LONGVARCHAR:
1098 #ifdef HAVE_ODBC_WCHAR 1101 case SQL_WLONGVARCHAR:
1105 case SQL_LONGVARBINARY:
1107 #define CHECK_SIZE(n) \ 1108 if (col->size < n) { \ 1109 warn_length(col, n); \ 1135 case SQL_TYPE_TIMESTAMP:
1144 #define WARN_TYPE_OR_LENGTH(n) \ 1145 if (!ast_rq_is_int(type)) { \ 1146 warn_type(col, type); \ 1148 warn_length(col, n); \ 1155 case SQL_C_STINYINT:
1207 #undef WARN_TYPE_OR_LENGTH 1218 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->
type, elm);
1224 ast_log(
LOG_WARNING,
"Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
1276 .requires =
"extconfig,res_odbc",
static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
struct ast_variable * next
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
require_type
Types used in ast_realtime_require_field.
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
struct odbc_cache_tables * tableptr
static int unload_odbc(const char *a, const char *b)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data)
static SQLHSTMT length_determination_odbc_prepare(struct odbc_obj *obj, void *data)
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
static struct ast_config * realtime_multi_odbc(const char *database, const char *table, const struct ast_variable *fields)
Excute an Select query and return ast_config list.
const struct ast_variable * update_fields
#define ast_str_make_space(buf, new_len)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Structure for variables, used for configurations and for channel variables.
static int load_module(void)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define ast_odbc_request_obj2(a, b)
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
void ast_category_destroy(struct ast_category *cat)
These structures are used for adaptive capabilities.
#define ast_verb(level,...)
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)
static int unload_module(void)
Configuration engine structure, used to define realtime drivers.
#define ast_strlen_zero(foo)
const struct ast_variable * fields
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
void ast_category_rename(struct ast_category *cat, const char *name)
#define ast_debug(level,...)
Log a DEBUG message.
General Asterisk PBX channel definitions.
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
static int store_odbc(const char *database, const char *table, const struct ast_variable *fields)
Excute an INSERT query.
struct sla_ringing_trunk * last
#define AST_RWLIST_TRAVERSE
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
#define ast_variable_new(name, value, filename)
static struct ast_threadstorage rowdata_buf
static struct ast_config_engine odbc_engine
static struct ast_variable * realtime_odbc(const char *database, const char *table, const struct ast_variable *fields)
Excute an SQL query and return ast_variable list.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Core PBX routines and definitions.
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
unsigned long var_val_size
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
#define warn_length(col, size)
struct sla_ringing_trunk * first
static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Excute an DELETE query.
char * strcasestr(const char *, const char *)
static int require_odbc(const char *database, const char *table, va_list ap)
#define ast_odbc_request_obj(a, b)
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...
static struct ast_threadstorage sql_buf
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
Structure used to handle boolean flags.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
char * strsep(char **str, const char *delims)
#define WARN_TYPE_OR_LENGTH(n)
const ast_string_field encoding[256]
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
static void decode_chunk(char *chunk)
static int reload_module(void)
#define warn_type(col, type)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
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)
const struct ast_variable * lookup_fields
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
#define ASTERISK_GPL_KEY
The text the key() function should return.
static int is_text(const struct odbc_cache_columns *column)
Asterisk module definitions.
#define ENCODE_CHUNK(buffer, s)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Excute an UPDATE query.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
static int update2_odbc(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
Execute an UPDATE query.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
struct odbc_cache_tables::_columns columns