--- config.c.orig 2005-05-21 22:06:05.000000000 +0200 +++ config.c 2005-05-22 13:44:11.000000000 +0200 @@ -1013,6 +1013,39 @@ return res; } +int ast_insert_realtime(const char *family, ...) +{ + struct ast_config_engine *eng; + char db[256]=""; + char table[256]=""; + int res=-1; + va_list ap; + + va_start(ap, family); + eng = find_engine(family, db, sizeof(db), table, sizeof(table)); + if (eng && eng->realtime_func) + res = eng->insert_func(db, table, ap); + va_end(ap); + return res; +} + +int ast_delete_realtime(const char *family, ...) +{ + struct ast_config_engine *eng; + char db[256]=""; + char table[256]=""; + int res=-1; + va_list ap; + + va_start(ap, family); + eng = find_engine(family, db, sizeof(db), table, sizeof(table)); + if (eng && eng->realtime_func) + res = eng->delete_func(db, table, ap); + va_end(ap); + + return res; +} + static int config_command(int fd, int argc, char **argv) { struct ast_config_engine *eng; --- include/asterisk/config.h.orig 2005-05-21 22:07:49.000000000 +0200 +++ include/asterisk/config.h 2005-05-22 14:49:39.000000000 +0200 @@ -42,6 +42,8 @@ typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap); typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap); typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap); +typedef int realtime_insert(const char *database, const char *table, va_list ap); +typedef int realtime_delete(const char *database, const char *table, va_list ap); struct ast_config_engine { char *name; @@ -49,6 +51,8 @@ realtime_var_get *realtime_func; realtime_multi_get *realtime_multi_func; realtime_update *update_func; + realtime_insert *insert_func; + realtime_delete *delete_func; struct ast_config_engine *next; }; @@ -174,6 +178,25 @@ */ int ast_update_realtime(const char *family, const char *keyfield, const char *lookup, ...); +/*! Insert realtime configuration */ +/*! + * \param family which family/config to be updated + * \param variable which variable should be updated in the config, NULL to end list + * \param value the value to be assigned to that variable in the given entity. + * This function is used to insert a entry in realtime configuration space. + * + */ +int ast_insert_realtime(const char *family, ...); + +/*! Delete realtime configuration */ +/*! + * \param family which family/config to be updated + * \param query sql query to pass + * This function is used to execute a query in realtime configuration space typicaly UPDATE/DELETE/INSERT. + * + */ +int ast_delete_realtime(const char *family, ...); + /*! Free variable list */ /*! * \param var the linked list of variables to free --- res/res_config_odbc.c.orig 2005-05-21 22:09:08.000000000 +0200 +++ res/res_config_odbc.c 2005-05-22 14:47:10.000000000 +0200 @@ -408,6 +408,172 @@ return -1; } +static int insert_odbc(const char *database, const char *table, va_list ap) +{ + odbc_obj *obj; + SQLHSTMT stmt; + char values[1024]; + char data[1024]; + char sql[2048]; + const char *newparam, *newval; + int res; + int x; + SQLLEN rowcount=0; + va_list aq; + + va_copy(aq, ap); + + + if (!table) + return -1; + + obj = fetch_odbc_obj(database, 0); + if (!obj) + return -1; + + res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); + return -1; + } + + newparam = va_arg(aq, const char *); + if (!newparam) { + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + newval = va_arg(aq, const char *); + + strncpy(values, newparam, sizeof(values)); + snprintf(data, sizeof(data), "'%s'", newval); + + while((newparam = va_arg(aq, const char *))) { + newval = va_arg(aq, const char *); + snprintf(values + strlen(values),sizeof(values) - strlen(values), ",%s",newparam); + snprintf(data + strlen(data),sizeof(data) - strlen(data), ",'%s'", newval); + } + va_end(aq); + + snprintf(sql,sizeof(sql),"INSERT INTO %s (%s) VALUES (%s)",table,values,data); + + res = SQLPrepare(stmt, sql, SQL_NTS); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + /* Now bind the parameters */ + x = 1; + + while((newparam = va_arg(ap, const char *))) { + newval = va_arg(ap, const char *); + SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); + } + + res = odbc_smart_execute(obj, stmt); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + res = SQLRowCount(stmt, &rowcount); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); + return -1; + } + + if (rowcount >= 0) + return (int)rowcount; + else + return -1; +} + +static int delete_odbc(const char *database, const char *table, va_list ap) +{ + odbc_obj *obj; + SQLHSTMT stmt; + char sql[2048]; + const char *newparam, *newval; + int res; + int x; + SQLLEN rowcount=0; + va_list aq; + + va_copy(aq, ap); + + + if (!table) + return -1; + + obj = fetch_odbc_obj(database, 0); + if (!obj) + return -1; + + res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); + return -1; + } + + newparam = va_arg(aq, const char *); + if (!newparam) { + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + newval = va_arg(aq, const char *); + + snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s'", table, newparam, newval); + + while((newparam = va_arg(aq, const char *))) { + newval = va_arg(aq, const char *); + snprintf(sql+strlen(sql), sizeof(sql)-strlen(sql), "AND %s = '%s'", newparam, newval); + } + va_end(aq); + + res = SQLPrepare(stmt, sql, SQL_NTS); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + /* Now bind the parameters */ + x = 1; + + while((newparam = va_arg(ap, const char *))) { + newval = va_arg(ap, const char *); + SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); + } + + res = odbc_smart_execute(obj, stmt); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + return -1; + } + + res = SQLRowCount(stmt, &rowcount); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); + return -1; + } + + if (rowcount >= 0) + return (int)rowcount; + else + return -1; +} + static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg) { struct ast_variable *new_v; @@ -496,7 +662,9 @@ .load_func = config_odbc, .realtime_func = realtime_odbc, .realtime_multi_func = realtime_multi_odbc, - .update_func = update_odbc + .update_func = update_odbc, + .insert_func = insert_odbc, + .delete_func = delete_odbc }; int unload_module (void)