[libgda] SQlite: handle meta data of views using non native SQLite functions



commit b360b08cb4319e4a78a91a2feadcbc88f06a1ca9
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Sep 3 22:06:04 2011 +0200

    SQlite: handle meta data of views using non native SQLite functions

 libgda/gda-meta-struct.c        |   10 +++++++-
 libgda/gda-meta-struct.h        |    4 +++
 libgda/sqlite/gda-sqlite-meta.c |   47 +++++++++++++++++++++++++++++----------
 3 files changed, 48 insertions(+), 13 deletions(-)
---
diff --git a/libgda/gda-meta-struct.c b/libgda/gda-meta-struct.c
index 22d85ef..d22fda0 100644
--- a/libgda/gda-meta-struct.c
+++ b/libgda/gda-meta-struct.c
@@ -933,7 +933,7 @@ _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 	}
 	case GDA_META_DB_TABLE: {
 		/* columns */
-		gchar *sql = "SELECT c.column_name, c.data_type, c.gtype, c.is_nullable, t.table_short_name, t.table_full_name, c.column_default, t.table_owner, c.array_spec, c.extra, c.column_comments FROM _columns as c NATURAL JOIN _tables as t WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string ORDER BY ordinal_position";
+		gchar *sql = "SELECT c.column_name, c.data_type, c.gtype, c.is_nullable, t.table_short_name, t.table_full_name, c.column_default, t.table_owner, c.array_spec, c.extra, c.column_comments FROM _tables as t LEFT NATURAL JOIN _columns as c WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string ORDER BY ordinal_position";
 		GdaMetaTable *mt;
 		GdaDataModel *model;
 		gint i, nrows;
@@ -969,6 +969,14 @@ _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 				dbo->obj_owner = g_value_dup_string (cvalue);
 		}
 
+		cvalue = gda_data_model_get_value_at (model, 0, 0, error);
+		if (cvalue && (G_VALUE_TYPE (cvalue) == GDA_TYPE_NULL)) {
+			if (type == GDA_META_DB_VIEW) {
+				/* we don't have the list of columns for the view.
+				 * This can sometimes happen in SQLite */
+				nrows = 0;
+			}
+		}
 		mt = GDA_META_TABLE (dbo);
 		for (i = 0; i < nrows; i++) {
 			GdaMetaTableColumn *tcol;
diff --git a/libgda/gda-meta-struct.h b/libgda/gda-meta-struct.h
index e449136..66feed5 100644
--- a/libgda/gda-meta-struct.h
+++ b/libgda/gda-meta-struct.h
@@ -122,6 +122,10 @@ typedef enum {
  *
  * This structure specifies a #GdaMetaDbObject to represent a table's specific attributes,
  * its contents must not be modified.
+ *
+ * Note that in some cases, the columns cannot be determined for views, and in this case the
+ * @columns will be %NULL (this can be the case for example with SQLite where a view
+ * uses a function which is not natively provided by SQLite.
  */
 typedef struct {
 	/*< public >*/
diff --git a/libgda/sqlite/gda-sqlite-meta.c b/libgda/sqlite/gda-sqlite-meta.c
index e2d2058..a888de9 100644
--- a/libgda/sqlite/gda-sqlite-meta.c
+++ b/libgda/sqlite/gda-sqlite-meta.c
@@ -55,6 +55,8 @@ static gchar *internal_sql[] = {
 	"PRAGMA database_list",
 
 	/* I_PRAGMA_TABLE_INFO */
+	/* warning: this can return an error as "no such function XXX" if a view has been
+	 * defined using a function not native of SQLite (and thus not available in Libgda) */
 	"PRAGMA table_info (##tblname::string)",
 
 	/* I_PRAGMA_INDEX_LIST */
@@ -959,15 +961,22 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
 	GType col_types[] = {G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, 
 			     G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE};
 	GdaStatement *stmt;
+	GError *lerror = NULL;
 	
 	schema_name = g_value_get_string (p_table_schema);
-	stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), error);
+	stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), NULL);
 	tmpmodel = gda_connection_statement_execute_select_full (cnc, stmt, pragma_set, 
 								 GDA_STATEMENT_MODEL_RANDOM_ACCESS, 
-								 col_types, error);
+								 col_types, &lerror);
 	g_object_unref (stmt);
-	if (!tmpmodel)
-		return FALSE;
+	if (!tmpmodel) {
+		if (lerror && lerror->message && !strstr (lerror->message, "no such function")) {
+			g_propagate_error (error, lerror);
+			return FALSE;
+		}
+		else
+			return TRUE;
+	}
 		
 	nrows = gda_data_model_get_n_rows (tmpmodel);
 	for (i = 0; i < nrows; i++) {
@@ -1237,6 +1246,7 @@ fill_constraints_tab_model (GdaConnection *cnc, SqliteConnectionData *cdata, Gda
 	const gchar *schema_name;
 	gint i;
 	GdaStatement *stmt;
+	GError *lerror = NULL;
 
 	schema_name = g_value_get_string (p_table_schema);
 
@@ -1249,13 +1259,19 @@ fill_constraints_tab_model (GdaConnection *cnc, SqliteConnectionData *cdata, Gda
 				G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE};
 	gboolean has_pk = FALSE;
 
-	stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), error);
+	stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), NULL);
 	tmpmodel = gda_connection_statement_execute_select_full (cnc, stmt, pragma_set, 
 								 GDA_STATEMENT_MODEL_RANDOM_ACCESS, 
-								 pk_col_types, error);
+								 pk_col_types, &lerror);
 	g_object_unref (stmt);
-	if (!tmpmodel)
-		return FALSE;
+	if (!tmpmodel) {
+		if (lerror && lerror->message && !strstr (lerror->message, "no such function")) {
+			g_propagate_error (error, lerror);
+			return FALSE;
+		}
+		else
+			return TRUE;
+	}
 		
 	nrows = gda_data_model_get_n_rows (tmpmodel);
 	for (i = 0; i < nrows; i++) {
@@ -1799,13 +1815,20 @@ fill_key_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata, GdaData
 		GType pk_col_types[] = {G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, 
 					G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE};
 		gint ord_pos = 1;
-		stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), error);
+		GError *lerror = NULL;
+		stmt = get_statement (I_PRAGMA_TABLE_INFO, schema_name, g_value_get_string (p_table_name), NULL);
 		tmpmodel = gda_connection_statement_execute_select_full (cnc, stmt, pragma_set, 
 									 GDA_STATEMENT_MODEL_RANDOM_ACCESS, 
-									 pk_col_types, error);
+									 pk_col_types, &lerror);
 		g_object_unref (stmt);
-		if (!tmpmodel)
-			return FALSE;
+		if (!tmpmodel) {
+			if (lerror && lerror->message && !strstr (lerror->message, "no such function")) {
+				g_propagate_error (error, lerror);
+				return FALSE;
+			}
+			else
+				return TRUE;
+		}
 		
 		nrows = gda_data_model_get_n_rows (tmpmodel);
 		for (i = 0; i < nrows; i++) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]