Index: res_config_mysql.c
===================================================================
--- res_config_mysql.c	(revision 349)
+++ res_config_mysql.c	(working copy)
@@ -379,7 +379,164 @@
 
 	return -1;
 }
+ 
+static int store_mysql(const char *database, const char *table, va_list ap)
+{
+	my_ulonglong insertid;
+	char sql[512];
+	char buf[511]; /* Keep this size uneven as it is 2n+1. */
+	char fields[512];
+	char values[512];
+	int valsz;
+	const char *newparam, *newval;
 
+	if(!table) {
+		ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+		return -1;
+	}
+	/* Get the first parameter and first value in our list of passed paramater/value pairs */
+	newparam = va_arg(ap, const char *);
+	newval = va_arg(ap, const char *);
+	if(!newparam || !newval)  {
+		ast_log(LOG_WARNING, "MySQL RealTime: Realtime storage requires at least 1 parameter and 1 value to search on.\n");
+		mysql_close(&mysql);
+		return -1;
+	}
+	/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
+	ast_mutex_lock(&mysql_lock);
+	if (!mysql_reconnect(database)) {
+		ast_mutex_unlock(&mysql_lock);
+		return -1;
+	}
+	/* Create the first part of the query using the first parameter/value pairs we just extracted
+		If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+	if ((valsz = strlen(newval)) * 1 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	if(newval) {
+		mysql_real_escape_string(&mysql, buf, newval, valsz);
+	} else { 
+		buf[0] = 0;
+	}
+	snprintf(fields, sizeof(fields), "%s",newparam);
+	snprintf(values, sizeof(values), "'%s'",buf);
+	while((newparam = va_arg(ap, const char *))) {
+		newval = va_arg(ap, const char *);
+		if(newval) {
+			if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+				valsz = (sizeof(buf) - 1) / 2;
+			mysql_real_escape_string(&mysql, buf, newval, valsz);
+		} else {
+			buf[0] = 0;
+		}
+		snprintf(fields + strlen(fields), sizeof(fields), ", %s",newparam);
+		snprintf(values + strlen(values), sizeof(values), ", '%s'",buf);
+	}
+	va_end(ap);
+	snprintf(sql, sizeof(sql), "INSERT into %s (%s) values (%s)", table, fields, values);
+	ast_log(LOG_DEBUG,"MySQL RealTime: Insert SQL: %s\n", sql);
+
+	/* Execution. */
+	if(mysql_real_query(&mysql, sql, strlen(sql))) {
+		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+		ast_mutex_unlock(&mysql_lock);
+		return -1;
+	}
+
+	insertid = mysql_insert_id(&mysql);
+	ast_mutex_unlock(&mysql_lock);
+
+	ast_log(LOG_DEBUG,"MySQL RealTime: row inserted on table: %s, id: %llu\n", table, insertid);
+
+	/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
+	 * An integer greater than zero indicates the number of rows affected
+	 * Zero indicates that no records were updated
+	 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
+	*/
+	if(insertid >= 0)
+		return (int)insertid;
+
+	return -1;
+}
+
+static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
+{
+	my_ulonglong numrows;
+	char sql[512];
+	char buf[511]; /* Keep this size uneven as it is 2n+1. */
+	int valsz;
+	const char *newparam, *newval;
+
+	if(!table) {
+		ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+		return -1;
+	}
+
+	/* Get the first parameter and first value in our list of passed paramater/value pairs */
+	/* newparam = va_arg(ap, const char *);
+	newval = va_arg(ap, const char *);*/
+	if(ast_strlen_zero(keyfield) || ast_strlen_zero(lookup))  {
+		ast_log(LOG_WARNING, "MySQL RealTime: Realtime destroying requires at least 1 parameter and 1 value to search on.\n");
+		mysql_close(&mysql);
+		return -1;
+	}
+
+	/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
+	ast_mutex_lock(&mysql_lock);
+	if (!mysql_reconnect(database)) {
+		ast_mutex_unlock(&mysql_lock);
+		return -1;
+	}
+
+	/* Create the first part of the query using the first parameter/value pairs we just extracted
+	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+
+	if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	mysql_real_escape_string(&mysql, buf, lookup, valsz);
+	snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s'", table, keyfield, buf);
+	while((newparam = va_arg(ap, const char *))) {
+		newval = va_arg(ap, const char *);
+		if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+			valsz = (sizeof(buf) - 1) / 2;
+		mysql_real_escape_string(&mysql, buf, newval, valsz);
+		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s = '%s'", newparam, buf);
+	}
+	va_end(ap);
+	//if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
+	//	valsz = (sizeof(buf) - 1) / 2;
+	//mysql_real_escape_string(&mysql, buf, lookup, valsz);
+	//snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, buf);
+
+	ast_log(LOG_DEBUG,"MySQL RealTime: Delete SQL: %s\n", sql);
+
+	/* Execution. */
+	if(mysql_real_query(&mysql, sql, strlen(sql))) {
+		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+		ast_mutex_unlock(&mysql_lock);
+		return -1;
+	}
+
+	numrows = mysql_affected_rows(&mysql);
+	ast_mutex_unlock(&mysql_lock);
+
+	ast_log(LOG_DEBUG,"MySQL RealTime: Deleted %llu rows on table: %s\n", numrows, table);
+
+	/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
+	 * An integer greater than zero indicates the number of rows affected
+	 * Zero indicates that no records were updated
+	 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
+	*/
+
+	if(numrows >= 0)
+		return (int)numrows;
+
+	return -1;
+}
+ 
 static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments)
 {
 	MYSQL_RES *result;
@@ -445,7 +602,8 @@
 				ast_category_append(cfg, cur_cat);
 			}
 			new_v = ast_variable_new(row[1], row[2]);
-			ast_variable_append(cur_cat, new_v);
+			if(cur_cat)
+				ast_variable_append(cur_cat, new_v);
 		}
 	} else {
 		ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
@@ -462,6 +620,8 @@
 	.load_func = config_mysql,
 	.realtime_func = realtime_mysql,
 	.realtime_multi_func = realtime_multi_mysql,
+	.store_func = store_mysql,
+	.destroy_func = destroy_mysql,
 	.update_func = update_mysql
 };
 
