store and destroy implementations for sqlite (closes issue #10446) and odbc (closes issue #10447)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@79860 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.0
Tilghman Lesher 18 years ago
parent 646234bd10
commit c78ddffb04

@ -450,6 +450,145 @@ static int update_odbc(const char *database, const char *table, const char *keyf
return -1;
}
/*!
* \brief Excute an INSERT query
* \param database
* \param table
* \param ap list 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.
*
* \retval number of rows affected
* \retval -1 on failure
*/
static int store_odbc(const char *database, const char *table, va_list ap)
{
struct odbc_obj *obj;
SQLHSTMT stmt;
char sql[256];
char keys[256];
char vals[256];
SQLLEN rowcount=0;
const char *newparam, *newval;
int res;
va_list aq;
struct custom_prepare_struct cps = { .sql = sql, .extra = NULL };
va_copy(cps.ap, ap);
va_copy(aq, ap);
if (!table)
return -1;
obj = ast_odbc_request_obj(database, 0);
if (!obj)
return -1;
newparam = va_arg(aq, const char *);
if (!newparam) {
ast_odbc_release_obj(obj);
return -1;
}
newval = va_arg(aq, const char *);
snprintf(keys, sizeof(keys), "%s", newparam);
snprintf(vals, sizeof(vals), "?");
while ((newparam = va_arg(aq, const char *))) {
snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam);
snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?");
newval = va_arg(aq, const char *);
}
va_end(aq);
snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals);
stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
if (!stmt) {
ast_odbc_release_obj(obj);
return -1;
}
res = SQLRowCount(stmt, &rowcount);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
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;
return -1;
}
/*!
* \brief Excute an DELETE query
* \param database
* \param table
* \param keyfield where clause field
* \param lookup value of field for where clause
* \param ap list containing one or more field/value set(s)
* Dlete 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.
*
* \retval number of rows affected
* \retval -1 on failure
*/
static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
{
struct odbc_obj *obj;
SQLHSTMT stmt;
char sql[256];
SQLLEN rowcount=0;
const char *newparam, *newval;
int res;
va_list aq;
struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
va_copy(cps.ap, ap);
va_copy(aq, ap);
if (!table)
return -1;
obj = ast_odbc_request_obj(database, 0);
if (!obj)
return -1;
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table);
while((newparam = va_arg(aq, const char *))) {
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam);
newval = va_arg(aq, const char *);
}
va_end(aq);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield);
stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
if (!stmt) {
ast_odbc_release_obj(obj);
return -1;
}
res = SQLRowCount(stmt, &rowcount);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
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;
return -1;
}
struct config_odbc_obj {
char *sql;
unsigned long cat_metric;
@ -575,6 +714,8 @@ static struct ast_config_engine odbc_engine = {
.load_func = config_odbc,
.realtime_func = realtime_odbc,
.realtime_multi_func = realtime_multi_odbc,
.store_func = store_odbc,
.destroy_func = destroy_odbc,
.update_func = update_odbc
};

@ -432,6 +432,46 @@ static int realtime_update_handler(const char *database, const char *table,
const char *keyfield, const char *entity,
va_list ap);
/*!
* \brief Asterisk callback function for RealTime configuration (variable
* create/store).
*
* Asterisk will call this function each time a variable has been created
* internally and must be stored in the backend engine.
* are used to find the row to update, e.g. ap is a list of parameters and
* values with the same format as the other realtime functions.
*
* \param database the database to use (ignored)
* \param table the table to use
* \param ap list of parameters and new values to insert into the database
* \retval the rowid of inserted row.
* \retval -1 if an error occurred.
*/
static int realtime_store_handler(const char *database, const char *table,
va_list ap);
/*!
* \brief Asterisk callback function for RealTime configuration (destroys
* variable).
*
* Asterisk will call this function each time a variable has been destroyed
* internally and must be removed from the backend engine. keyfield and entity
* are used to find the row to delete, e.g. <code>DELETE FROM table WHERE
* keyfield = 'entity';</code>. ap is a list of parameters and values with the
* same format as the other realtime functions.
*
* \param database the database to use (ignored)
* \param table the table to use
* \param keyfield the column of the matching cell
* \param entity the value of the matching cell
* \param ap list of additional parameters for cell matching
* \retval the number of affected rows.
* \retval -1 if an error occurred.
*/
static int realtime_destroy_handler(const char *database, const char *table,
const char *keyfield, const char *entity,
va_list ap);
/*!
* \brief Asterisk callback function for the CLI status command.
*
@ -476,6 +516,8 @@ static struct ast_config_engine sqlite_engine =
.load_func = config_handler,
.realtime_func = realtime_handler,
.realtime_multi_func = realtime_multi_handler,
.store_func = realtime_store_handler,
.destroy_func = realtime_destroy_handler,
.update_func = realtime_update_handler
};
@ -1171,6 +1213,176 @@ static int realtime_update_handler(const char *database, const char *table,
return rows_num;
}
static int realtime_store_handler(const char *database, const char *table, va_list ap) {
char *errormsg, *tmp_str, *tmp_keys, *tmp_keys2, *tmp_vals, *tmp_vals2;
const char **params, **vals;
size_t params_count;
int error, rows_id;
size_t i;
if (!table) {
ast_log(LOG_WARNING, "Table name unspecified\n");
return -1;
}
if (!(params_count = get_params(ap, &params, &vals)))
return -1;
/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "INSERT into '%q' (%s) VALUES (%s);"
/* \endcond */
tmp_keys2 = NULL;
tmp_vals2 = NULL;
for (i = 0; i < params_count; i++) {
if ( tmp_keys2 ) {
tmp_keys = sqlite_mprintf("%s, %q", tmp_keys2, params[i]);
sqlite_freemem(tmp_keys2);
} else {
tmp_keys = sqlite_mprintf("%q", params[i]);
}
if (!tmp_keys) {
ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
ast_free(params);
ast_free(vals);
return -1;
}
if ( tmp_vals2 ) {
tmp_vals = sqlite_mprintf("%s, '%q'", tmp_vals2, params[i]);
sqlite_freemem(tmp_vals2);
} else {
tmp_vals = sqlite_mprintf("'%q'", params[i]);
}
if (!tmp_vals) {
ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
ast_free(params);
ast_free(vals);
return -1;
}
tmp_keys2 = tmp_keys;
tmp_vals2 = tmp_vals;
}
ast_free(params);
ast_free(vals);
if (!(tmp_str = sqlite_mprintf(QUERY, table, tmp_keys, tmp_vals))) {
ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
return -1;
}
sqlite_freemem(tmp_keys);
sqlite_freemem(tmp_vals);
ast_debug(1, "SQL query: %s\n", tmp_str);
ast_mutex_lock(&mutex);
RES_SQLITE_BEGIN
error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg);
RES_SQLITE_END(error)
if (!error) {
rows_id = sqlite_last_insert_rowid(db);
} else {
rows_id = -1;
}
ast_mutex_unlock(&mutex);
sqlite_freemem(tmp_str);
if (error) {
ast_log(LOG_WARNING, "%s\n", errormsg);
ast_free(errormsg);
}
return rows_id;
}
static int realtime_destroy_handler(const char *database, const char *table,
const char *keyfield, const char *entity,
va_list ap)
{
char *query, *errormsg, *tmp_str;
const char **params, **vals;
size_t params_count;
int error, rows_num;
size_t i;
if (!table) {
ast_log(LOG_WARNING, "Table name unspecified\n");
return -1;
}
if (!(params_count = get_params(ap, &params, &vals)))
return -1;
/* \cond DOXYGEN_CAN_PARSE_THIS */
#undef QUERY
#define QUERY "DELETE FROM '%q' WHERE"
/* \endcond */
if (!(query = sqlite_mprintf(QUERY, table))) {
ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
ast_free(params);
ast_free(vals);
return -1;
}
for (i = 0; i < params_count; i++) {
tmp_str = sqlite_mprintf("%s %q = '%q' AND", query, params[i], vals[i]);
sqlite_freemem(query);
if (!tmp_str) {
ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
ast_free(params);
ast_free(vals);
return -1;
}
query = tmp_str;
}
ast_free(params);
ast_free(vals);
if (!(tmp_str = sqlite_mprintf("%s %q = '%q';", query, keyfield, entity))) {
ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
return -1;
}
sqlite_freemem(query);
query = tmp_str;
ast_debug(1, "SQL query: %s\n", query);
ast_mutex_lock(&mutex);
RES_SQLITE_BEGIN
error = sqlite_exec(db, query, NULL, NULL, &errormsg);
RES_SQLITE_END(error)
if (!error)
rows_num = sqlite_changes(db);
else
rows_num = -1;
ast_mutex_unlock(&mutex);
sqlite_freemem(query);
if (error) {
ast_log(LOG_WARNING, "%s\n", errormsg);
ast_free(errormsg);
}
return rows_num;
}
static int cli_status(int fd, int argc, char *argv[])
{
ast_cli(fd, "SQLite database path: %s\n", dbfile);

Loading…
Cancel
Save