之前困惑于GtkClist中数据类型与MySQL数据类型之间转换的问题,在gtk-app-dvel-list邮件列表上发了一个主题提问:
Arthur1989 says:
Hello, I used clist to display data iI fetch from mysql server,but when writing data back into the table of database, I got this question: the data type of clist is always gchar *, while there are quite a lot of other data types in mysql. What can I do to get this question solved? Any tips will be appreciated.
今天发现居然有人把实现的源码都贴到邮件里了..转到博客记下.
Shawn Bakhtlar(***@hotmail.com)replys:
//Ran into the same problem.
//I use a structure like
_IsiField {
int type,
int pos,
int ....
}
//Then create my own list with
_IsiList {
GList Fields;
GList rows;
}
//Every time retrieve a set of values, I have a routing which sets type to a G_TYPE, which corresponds to the MYSQL_TYPE
//Here is what I do:
GList *
isi_database_fetch_fields(IsiDatabase *self)
{
MYSQL_FIELD *field;
IsiFields *l;
GList *gl = NULL;
guint column = 0;
/* Sanity Check */
g_return_val_if_fail(self != NULL, NULL);
g_return_val_if_fail(self->priv != NULL, NULL);
g_return_val_if_fail(self->priv->dispose_has_run != TRUE, NULL);
g_return_val_if_fail(self->priv->res != NULL, NULL);
/* Rewind the feild set */
mysql_field_seek(self->priv->res,0L);
while((field = mysql_fetch_field(self->priv->res)))
{
/* Initialize a new IsiFields structure */
//l = (IsiFields*) g_new0(IsiFields, 1);
l = g_new0(IsiFields, 1);
/* Set the values */
l->alias = g_strdup(field->name);
l->name = g_strdup(field->org_name);
l->length = field->length;
/* always make fields visable */
l->hidden = FALSE;
l->sortable = FALSE;
l->pos = column++;
switch (field->type){
/* Integer types */
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
/* Check for signage */
if (field->flags & UNSIGNED_FLAG)
l->type = G_TYPE_UINT;
else
l->type = G_TYPE_INT;
break;
/* Long types */
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
/* Check for signage */
if (field->flags & UNSIGNED_FLAG)
l->type = G_TYPE_ULONG;
else
l->type = G_TYPE_LONG;
break;
/* Decimal types */
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
l->type = G_TYPE_DOUBLE;
break;
/* Bit types */
case MYSQL_TYPE_BIT:
l->type = G_TYPE_BOOLEAN;
break;
/* ENUM types */
case MYSQL_TYPE_ENUM:
l->type = G_TYPE_ENUM;
break;
/* All other types */
default:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_NULL:
if(l->length <= 1){
l->type = G_TYPE_CHAR;
}else{
l->type = G_TYPE_STRING;
}
break;
}
/*DEBUG*/
//g_print("%s %d %d \n", l->alias,l->type,l->length);
/* Save pointer to list */
gl = g_list_append(gl,(gpointer)l);
}
return gl;
}
//now convert the row data to a GList and you have two GLists in your one lists, one with the field header info, the other with the data.
//and create the liststore like this:
GtkTreeModel *
isi_display_liststore_create(IsiDisplay *self, GList *fields)
{
guint num_fields, i;
IsiFields *l;
GtkTreeModel *model;
GType *types;
guint search_col_adj = 0;
/* Sanity Check */
g_return_val_if_fail(self != NULL, NULL);
g_return_val_if_fail(self->priv != NULL, NULL);
g_return_val_if_fail(self->priv->dispose_has_run != TRUE, NULL);
/* Get the number of fields */
if(fields != NULL){
num_fields = g_list_length(fields);
/* Initialize values based on number of columns */
types = (GType*) g_new0( GType, num_fields);
for(i=0;i<num_fields;i++){
l = (IsiFields*)g_list_nth_data(fields,i);
types[i] = l->type;
}
/* create the model store for data input */
model = (GtkTreeModel*) gtk_list_store_newv(num_fields,types);
g_free(types);
for(i=0;i<num_fields;i++){
l = (IsiFields*)g_list_nth_data(fields,i);
/* Setup sorting functions for the modle */
switch(l->type){
case G_TYPE_INT:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_int,(gpointer) l->pos, NULL);
break;
case G_TYPE_UINT:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_uint,(gpointer) l->pos, NULL);
break;
case G_TYPE_LONG:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_long,(gpointer) l->pos, NULL);
break;
case G_TYPE_ULONG:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_ulong,(gpointer) l->pos, NULL);
break;
case G_TYPE_DOUBLE:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_double,(gpointer) l->pos, NULL);
break;
case G_TYPE_STRING:
l->sortable=TRUE;
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), l->pos, sort_by_string,(gpointer) l->pos, NULL);
break;
}
}
return model;
}
//Hope this helps,
//Shawn
认真的看了一下,发现原来和自己想的差不多,都是事先记录好MySQL数据表中每列的数据类型,往回写时做个判断进行转换..只不过我是想用类似于map的字符串哈希映射实现的,这里变成了switch case罢了..
PS: 本文在vim下通过vimpress插件编辑发布,不知道浏览器看起来怎样,呵呵..