[svn-commits] twilson: branch twilson/res_config_sqlite3 r334213 - /team/twilson/res_config...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Aug 31 19:33:46 CDT 2011


Author: twilson
Date: Wed Aug 31 19:33:42 2011
New Revision: 334213

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=334213
Log:
Add minimal realtime_require support

Automatically adds needed columns, still need to add
requirements=warn|createclose|createtext support.

Todo: cleanup/helper functions, multiple db support, transaction option

Modified:
    team/twilson/res_config_sqlite3/res/res_config_sqlite3.c

Modified: team/twilson/res_config_sqlite3/res/res_config_sqlite3.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/res_config_sqlite3/res/res_config_sqlite3.c?view=diff&rev=334213&r1=334212&r2=334213
==============================================================================
--- team/twilson/res_config_sqlite3/res/res_config_sqlite3.c (original)
+++ team/twilson/res_config_sqlite3/res/res_config_sqlite3.c Wed Aug 31 19:33:42 2011
@@ -43,6 +43,7 @@
 #include "asterisk/module.h"
 #include "asterisk/config.h"
 #include "asterisk/paths.h"
+#include "asterisk/astobj2.h"
 
 
 /*** DOCUMENTATION
@@ -478,12 +479,142 @@
 	return tmp;
 }
 
+static const char *get_sqlite_column_type(int type)
+{
+	/* SQLite 3 has NULL, INTEGER, REAL, TEXT, and BLOB types. Any column other than
+	 * an INTEGER PRIMARY KEY will actually store any kind of data due to its dynamic
+	 * typing. When we create columns, we'll go ahead and use these base types instead
+	 * of messing with column widths, etc. */
+
+	switch(type) {
+	case RQ_INTEGER1 :
+	case RQ_UINTEGER1 :
+	case RQ_INTEGER2 :
+	case RQ_UINTEGER2 :
+	case RQ_INTEGER3 :
+	case RQ_UINTEGER3 :
+	case RQ_INTEGER4 :
+	case RQ_UINTEGER4 :
+	case RQ_INTEGER8 :
+	case RQ_UINTEGER8 :
+		return "INTEGER";
+	case RQ_CHAR :
+	case RQ_DATE :
+	case RQ_DATETIME :
+		return "TEXT";
+	case RQ_FLOAT :
+		return "REAL";
+	default :
+		return "TEXT";
+	}
+
+	return "TEXT";
+}
+
+static int create_sqlite3_column(const char *table, const char *column, int type, size_t sz)
+{
+	char *sql, *errmsg;
+	const char *sqltype = get_sqlite_column_type(type);
+
+	if (!(sql = sqlite3_mprintf("ALTER TABLE %q ADD COLUMN %Q %s", table, column, sqltype))) {
+		return -1;
+	}
+
+	ast_mutex_lock(&db_lock);
+	if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
+		ast_log(LOG_WARNING, "Could not execute '%s': %s\n", sql, errmsg);
+		sqlite3_free(errmsg);
+		sqlite3_free(sql);
+		return -1;
+	}
+	ast_mutex_unlock(&db_lock);
+
+	sqlite3_free(sql);
+	ast_log(LOG_NOTICE, "Creating column '%s', type %s for table %s\n", column, sqltype, table);
+	return 0;
+}
+
+static int str_hash_fn(const void *obj, const int flags)
+{
+	return ast_str_hash((const char *) obj);
+}
+
+static int str_cmp_fn(void *obj, void *arg, int flags) {
+	return !strcasecmp((const char *) obj, (const char *) arg);
+}
+
+static int add_column_name(void *arg, int num_columns, char **values, char **columns)
+{
+	char *column;
+	struct ao2_container *cnames = arg;
+
+
+	if (!(column = ao2_alloc(strlen(values[1]) + 1, NULL))) {
+		return -1;
+	}
+
+	strcpy(column, values[1]);
+	
+	ao2_link(cnames, column);
+	ao2_ref(column, -1);
+
+	return 0;
+}
+
 /*!
  * \retval 0 Required fields met specified standards
  * \retval -1 One or more fields was missing or insufficient
  */
 static int realtime_sqlite3_require(const char *database, const char *table, va_list ap)
 {
+
+	/* SQLite3 columns are dynamically typed, with type affinity. Built-in functions will
+	 * return the results as char * anyway. The only field that that cannot contain text
+	 * data is an INTEGER PRIMARY KEY, which must be a 64-bit isigned integer. So, for
+	 * the purposes here we really only care whether the column exists and not what its
+	 * type or length is. */
+
+	const char *column;
+	int type;
+	size_t sz;
+	char *sql, *errmsg;
+	struct ao2_container *columns;
+
+	if (!(columns = ao2_container_alloc(31, str_hash_fn, str_cmp_fn))) {
+	   return -1;
+	}	   
+
+	if (!(sql = sqlite3_mprintf("PRAGMA table_info(%q)", table))) {
+		ao2_ref(columns, -1);
+		return -1;
+	}
+
+	ast_mutex_lock(&db_lock);
+	if (sqlite3_exec(db, sql, add_column_name, columns, &errmsg) != SQLITE_OK) {
+		ast_mutex_unlock(&db_lock);
+		ao2_ref(columns, -1);
+		sqlite3_free(sql);
+		return -1;
+	}
+	ast_mutex_unlock(&db_lock);
+
+	sqlite3_free(sql);
+
+	while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
+		char *found;
+		if (!(found = ao2_find(columns, column, OBJ_POINTER | OBJ_UNLINK))) {
+			if (create_sqlite3_column(table, column, type, sz)) {
+				ao2_ref(columns, -1);
+				return -1;
+			}
+		} else {
+			ao2_ref(found, -1);
+		}
+	}
+
+	/* Should unlink the column names causing them to be destroyed */
+	ao2_ref(columns, -1);
+
 	return 0;
 }
 




More information about the svn-commits mailing list