[asterisk-addons-commits] tilghman: trunk r644 - /trunk/res/res_config_mysql.c
SVN commits to the Asterisk addons project
asterisk-addons-commits at lists.digium.com
Thu Jun 12 22:55:26 CDT 2008
Author: tilghman
Date: Thu Jun 12 22:55:23 2008
New Revision: 644
URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=644
Log:
Also alter columns if the requirements type allows it (rather than just adding columns)
Modified:
trunk/res/res_config_mysql.c
Modified: trunk/res/res_config_mysql.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/res/res_config_mysql.c?view=diff&rev=644&r1=643&r2=644
==============================================================================
--- trunk/res/res_config_mysql.c (original)
+++ trunk/res/res_config_mysql.c Thu Jun 12 22:55:23 2008
@@ -80,6 +80,8 @@
struct columns {
char *name;
char *type;
+ char *dflt;
+ char null;
int len;
AST_LIST_ENTRY(columns) list;
};
@@ -99,7 +101,7 @@
static char *handle_cli_realtime_mysql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn);
-enum { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } requirements;
+static enum { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } requirements = RQ_WARN;
static struct ast_cli_entry cli_realtime_mysql_status[] = {
AST_CLI_DEFINE(handle_cli_realtime_mysql_status, "Shows connection information for the MySQL RealTime driver"),
@@ -123,7 +125,7 @@
struct columns *column;
struct tables *table;
struct ast_str *sql = ast_str_create(30);
- char *fname, *ftype, *flen;
+ char *fname, *ftype, *flen, *fdflt, *fnull;
MYSQL_RES *result;
MYSQL_ROW row;
@@ -167,9 +169,15 @@
while ((row = mysql_fetch_row(result))) {
fname = row[0];
ftype = row[1];
+ fnull = row[2];
+ fdflt = row[4];
ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
- if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + 2))) {
+ if (fdflt == NULL) {
+ fdflt = "";
+ }
+
+ if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + strlen(fdflt) + 3))) {
ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", tablename, fname);
destroy_table(table);
AST_LIST_UNLOCK(&mysql_tables);
@@ -186,8 +194,11 @@
column->name = (char *)column + sizeof(*column);
column->type = (char *)column + sizeof(*column) + strlen(fname) + 1;
+ column->dflt = (char *)column + sizeof(*column) + strlen(fname) + 1 + strlen(ftype) + 1;
strcpy(column->name, fname);
strcpy(column->type, ftype);
+ strcpy(column->dflt, fdflt);
+ column->null = (strcmp(fnull, "YES") == 0 ? 1 : 0);
AST_LIST_INSERT_TAIL(&table->columns, column, list);
}
mysql_free_result(result);
@@ -533,6 +544,7 @@
ast_str_append(&sql, 0, ", %s = '%s'", newparam, buf->str);
}
va_end(ap);
+ ast_mutex_unlock(&table->lock);
if ((valsz = strlen(lookup)) * 2 + 1 > buf->len) {
ast_str_make_space(&buf, valsz * 2 + 1);
@@ -548,7 +560,6 @@
ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
ast_mutex_unlock(&dbwrite.lock);
- ast_mutex_unlock(&table->lock);
ast_free(sql);
ast_free(buf);
return -1;
@@ -812,6 +823,100 @@
return cur ? 0 : -1;
}
+static int modify_mysql(const char *tablename, struct columns *column, require_type type, int len)
+{
+ struct ast_str *sql = ast_str_create(100), *escbuf = ast_str_create(strlen(column->dflt) * 2 + 1);
+ struct ast_str *typestr = ast_str_create(30);
+ int waschar = strncasecmp(column->type, "char", 4) == 0 ? 1 : 0;
+ int wasvarchar = strncasecmp(column->type, "varchar", 7) == 0 ? 1 : 0;
+ int res = 0;
+
+ do {
+ if (type == RQ_CHAR || waschar || wasvarchar) {
+ if (wasvarchar) {
+ ast_str_set(&typestr, 0, "VARCHAR(%d)", len);
+ } else {
+ ast_str_set(&typestr, 0, "CHAR(%d)", len);
+ }
+ } else if (type == RQ_UINTEGER1) {
+ ast_str_set(&typestr, 0, "tinyint(3) unsigned");
+ } else if (type == RQ_INTEGER1) {
+ ast_str_set(&typestr, 0, "tinyint(4)");
+ } else if (type == RQ_UINTEGER2) {
+ ast_str_set(&typestr, 0, "smallint(5) unsigned");
+ } else if (type == RQ_INTEGER2) {
+ ast_str_set(&typestr, 0, "smallint(6)");
+ } else if (type == RQ_UINTEGER3) {
+ ast_str_set(&typestr, 0, "mediumint(8) unsigned");
+ } else if (type == RQ_INTEGER3) {
+ ast_str_set(&typestr, 0, "mediumint(8)");
+ } else if (type == RQ_UINTEGER4) {
+ ast_str_set(&typestr, 0, "int(10) unsigned");
+ } else if (type == RQ_INTEGER4) {
+ ast_str_set(&typestr, 0, "int(11)");
+ } else if (type == RQ_UINTEGER8) {
+ ast_str_set(&typestr, 0, "bigint(19) unsigned");
+ } else if (type == RQ_INTEGER8) {
+ ast_str_set(&typestr, 0, "bigint(20)");
+ } else if (type == RQ_DATETIME) {
+ ast_str_set(&typestr, 0, "datetime");
+ } else if (type == RQ_DATE) {
+ ast_str_set(&typestr, 0, "date");
+ } else if (type == RQ_FLOAT) {
+ ast_str_set(&typestr, 0, "FLOAT(%d,2)", len);
+ } else {
+ ast_log(LOG_ERROR, "Unknown type (should NEVER happen)\n");
+ res = -1;
+ break;
+ }
+ ast_str_set(&sql, 0, "ALTER TABLE %s MODIFY %s %s", tablename, column->name, typestr->str);
+ if (!column->null) {
+ ast_str_append(&sql, 0, " NOT NULL");
+ }
+ if (!ast_strlen_zero(column->dflt)) {
+ ast_str_makespace(&escbuf, strlen(column->dflt) * 2 + 1);
+ mysql_real_escape_string(&dbwrite.handle, escbuf->str, column->dflt, strlen(column->dflt));
+ ast_str_append(&sql, 0, " DEFAULT '%s'", escbuf->str);
+ }
+
+ ast_mutex_lock(&dbwrite.lock);
+ if (!mysql_reconnect(&dbwrite)) {
+ ast_mutex_unlock(&dbwrite.lock);
+ ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str);
+ res = -1;
+ break;
+ }
+
+ /* Execution. */
+ if (mysql_real_query(&dbwrite.handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
+ res = -1;
+ }
+ ast_mutex_unlock(&dbwrite.lock);
+ } while (0);
+
+ ast_free(sql);
+ ast_free(typestr);
+ ast_free(escbuf);
+ return res;
+}
+
+#define PICK_WHICH_ALTER_ACTION(stringtype) \
+ if (requirements == RQ_WARN) { \
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \
+ "the required data length: %d (detected stringtype)\n", \
+ tablename, database, column->name, size); \
+ res = -1; \
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) { \
+ table_altered = 1; \
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) { \
+ table_altered = 1; \
+ } else { \
+ res = -1; \
+ }
+
static int require_mysql(const char *database, const char *tablename, va_list ap)
{
struct columns *column;
@@ -832,38 +937,50 @@
/* Char can hold anything, as long as it is large enough */
if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) {
if ((size > column->len) && column->len != -1) {
- ast_log(LOG_WARNING, "Column '%s' should be at least %d long, but is only %d long.\n", column->name, size, column->len);
- res = -1;
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column '%s' should be at least %d long, but is only %d long.\n", database, tablename, column->name, size, column->len);
+ res = -1;
+ } else if (modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
}
} else if (strcasestr(column->type, "unsigned")) {
if (!ast_rq_is_int(type)) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", database, tablename, column->name, column->type,
- type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "a rather stiff drink");
- res = -1;
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
+ database, tablename, column->name, column->type,
+ type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" :
+ type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "a rather stiff drink");
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
} else if (strncasecmp(column->type, "tinyint", 1) == 0) {
if (type != RQ_UINTEGER1) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned tinyint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(unsigned tinyint)
}
} else if (strncasecmp(column->type, "smallint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned smallint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(unsigned smallint)
}
} else if (strncasecmp(column->type, "mediumint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
type != RQ_UINTEGER3) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned mediumint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(unsigned mediumint)
}
} else if (strncasecmp(column->type, "int", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
type != RQ_UINTEGER4) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned int)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(unsigned int)
}
} else if (strncasecmp(column->type, "bigint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
@@ -871,39 +988,45 @@
type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
type != RQ_UINTEGER8) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned bigint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(unsigned bigint)
}
}
} else if (strcasestr(column->type, "int")) {
if (!ast_rq_is_int(type)) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", database, tablename, column->name, column->type,
- type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "to get a life, rather than writing silly error messages");
- res = -1;
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
+ database, tablename, column->name, column->type,
+ type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" :
+ type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" :
+ "to get a life, rather than writing silly error messages");
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
} else if (strncasecmp(column->type, "tinyint", 1) == 0) {
if (type != RQ_INTEGER1) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned tinyint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(tinyint)
}
} else if (strncasecmp(column->type, "smallint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned smallint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(smallint)
}
} else if (strncasecmp(column->type, "mediumint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
type != RQ_INTEGER3) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned mediumint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(mediumint)
}
} else if (strncasecmp(column->type, "int", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
type != RQ_INTEGER4) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned int)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(int)
}
} else if (strncasecmp(column->type, "bigint", 1) == 0) {
if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
@@ -911,16 +1034,52 @@
type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
type != RQ_INTEGER8) {
- ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for the required data length: %d (detected unsigned bigint)\n", tablename, database, column->name, size);
- res = -1;
+ PICK_WHICH_ALTER_ACTION(bigint)
}
}
} else if (strncmp(column->type, "float", 5) == 0 && !ast_rq_is_int(type) && type != RQ_FLOAT) {
- ast_log(LOG_WARNING, "Column %s cannot be a %s\n", column->name, column->type);
- res = -1;
- } else { /* There are other types that no module implements yet */
- ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name);
- res = -1;
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if ((strncmp(column->type, "datetime", 8) == 0 || strncmp(column->type, "timestamp", 9)) && type != RQ_DATETIME) {
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if ((strncmp(column->type, "date", 4) == 0) && type != RQ_DATE) {
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else { /* Other, possibly unsupported types? */
+ if (requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name);
+ res = -1;
+ } else if (requirements == RQ_CREATECLOSE && modify_mysql(tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (requirements == RQ_CREATECHAR && modify_mysql(tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ }
}
break;
}
@@ -995,10 +1154,10 @@
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
- ast_mutex_unlock(&dbwrite.lock);
} else {
table_altered = 1;
}
+ ast_mutex_unlock(&dbwrite.lock);
ast_free(sql);
ast_free(fieldtype);
@@ -1050,7 +1209,6 @@
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime driver loaded.\n");
ast_cli_register_multiple(cli_realtime_mysql_status, sizeof(cli_realtime_mysql_status) / sizeof(struct ast_cli_entry));
-
return 0;
}
More information about the asterisk-addons-commits
mailing list