[libgda/gtk3] GdaMetaStruct now reports foreign keys policy



commit 46f4b41702b5e2d54f0c8caea4ae7a6f6a0327f1
Author: Vivien Malerba <malerba gnome-db org>
Date:   Tue Jan 25 21:21:10 2011 +0100

    GdaMetaStruct now reports foreign keys policy
    
    also improved documentation

 doc/C/libgda-sections.txt       |    4 +
 doc/C/tmpl/gda-meta-struct.sgml |   43 ++++++++++++-
 libgda/gda-meta-struct.c        |   59 +++++++++++++++++-
 libgda/gda-meta-struct.h        |  129 ++++++++++++++++++++++++++++++++++++---
 4 files changed, 218 insertions(+), 17 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index 1495dcc..374ed80 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -1374,8 +1374,12 @@ gda_meta_table_column_get_attribute
 gda_meta_table_column_set_attribute
 gda_meta_table_column_set_attribute_static
 gda_meta_table_column_foreach_attribute
+GdaMetaForeignKeyPolicy
 GdaMetaTableForeignKey
 GDA_META_TABLE_FOREIGN_KEY
+GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY
+GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY
+GDA_META_TABLE_FOREIGN_KEY_IN_SCHEMA
 GDA_META_STRUCT_ERROR
 gda_meta_struct_new
 gda_meta_struct_complement
diff --git a/doc/C/tmpl/gda-meta-struct.sgml b/doc/C/tmpl/gda-meta-struct.sgml
index f43e10f..90864c5 100644
--- a/doc/C/tmpl/gda-meta-struct.sgml
+++ b/doc/C/tmpl/gda-meta-struct.sgml
@@ -161,7 +161,7 @@ gda_meta_struct_free (mstruct);
 
 </para>
 
- x: 
+ dbo: 
 
 
 <!-- ##### MACRO GDA_META_TABLE ##### -->
@@ -217,7 +217,7 @@ gda_meta_struct_free (mstruct);
 
 </para>
 
- x: 
+ col: 
 
 
 <!-- ##### FUNCTION gda_meta_table_column_get_attribute ##### -->
@@ -261,6 +261,19 @@ gda_meta_struct_free (mstruct);
 @data: 
 
 
+<!-- ##### ENUM GdaMetaForeignKeyPolicy ##### -->
+<para>
+
+</para>
+
+ GDA_META_FOREIGN_KEY_UNKNOWN: 
+ GDA_META_FOREIGN_KEY_NONE: 
+ GDA_META_FOREIGN_KEY_NO_ACTION: 
+ GDA_META_FOREIGN_KEY_RESTRICT: 
+ GDA_META_FOREIGN_KEY_CASCADE: 
+ GDA_META_FOREIGN_KEY_SET_NULL: 
+ GDA_META_FOREIGN_KEY_SET_DEFAULT: 
+
 <!-- ##### STRUCT GdaMetaTableForeignKey ##### -->
 <para>
 
@@ -279,7 +292,31 @@ gda_meta_struct_free (mstruct);
 
 </para>
 
- x: 
+ fk: 
+
+
+<!-- ##### MACRO GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY ##### -->
+<para>
+
+</para>
+
+ fk: 
+
+
+<!-- ##### MACRO GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY ##### -->
+<para>
+
+</para>
+
+ fk: 
+
+
+<!-- ##### MACRO GDA_META_TABLE_FOREIGN_KEY_IN_SCHEMA ##### -->
+<para>
+
+</para>
+
+ fk: 
 
 
 <!-- ##### MACRO GDA_META_STRUCT_ERROR ##### -->
diff --git a/libgda/gda-meta-struct.c b/libgda/gda-meta-struct.c
index 8587c38..1c50574 100644
--- a/libgda/gda-meta-struct.c
+++ b/libgda/gda-meta-struct.c
@@ -1,6 +1,6 @@
 /* gda-meta-struct.c
  *
- * Copyright (C) 2008 - 2010 Vivien Malerba
+ * Copyright (C) 2008 - 2011 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -70,6 +70,9 @@ static void gda_meta_table_foreign_key_free (GdaMetaTableForeignKey *tfk);
 static GObjectClass  *parent_class = NULL;
 static GdaAttributesManager *att_mgr;
 
+#define ON_UPDATE_POLICY "upd_policy";
+#define ON_DELETE_POLICY "del_policy";
+
 /* properties */
 enum {
         PROP_0,
@@ -551,6 +554,30 @@ gda_meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 	return dbo;
 }
 
+static GdaMetaForeignKeyPolicy
+policy_string_to_value (const gchar *string)
+{
+	if (!string)
+		return GDA_META_FOREIGN_KEY_UNKNOWN;
+	if (*string == 'C')
+		return GDA_META_FOREIGN_KEY_CASCADE;
+	else if (*string == 'R')
+		return GDA_META_FOREIGN_KEY_RESTRICT;
+	else if (*string == 'N') {
+		if (!strcmp (string + 1, "ONE"))
+			return GDA_META_FOREIGN_KEY_NONE;
+		else
+			return GDA_META_FOREIGN_KEY_NO_ACTION;
+	}
+	else if (*string == 'S') {
+		if (!strcmp (string + 1, "ET NULL"))
+			return GDA_META_FOREIGN_KEY_SET_NULL;
+		else
+			return GDA_META_FOREIGN_KEY_SET_DEFAULT;
+	} 
+	return GDA_META_FOREIGN_KEY_UNKNOWN;
+}
+
 static GdaMetaDbObject *
 _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 			 const GValue *icatalog, const GValue *ischema, const GValue *iname, 
@@ -829,7 +856,7 @@ _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 
 		/* foreign keys */
 		if (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS) { 
-			sql = "SELECT ref_table_catalog, ref_table_schema, ref_table_name, constraint_name, ref_constraint_name FROM _referential_constraints WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
+			sql = "SELECT ref_table_catalog, ref_table_schema, ref_table_name, constraint_name, ref_constraint_name, update_rule, delete_rule FROM _referential_constraints WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
 			model = gda_meta_store_extract (mstruct->priv->store, sql, error, 
 							"tc", icatalog, 
 							"ts", ischema, 
@@ -841,13 +868,18 @@ _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 			for (i = 0; i < nrows; i++) {
 				GdaMetaTableForeignKey *tfk;
 				const GValue *fk_catalog, *fk_schema, *fk_name;
-				
+				const GValue *upd_policy, *del_policy;
+
 				fk_catalog = gda_data_model_get_value_at (model, 0, i, error);
 				if (!fk_catalog) goto onfkerror;
 				fk_schema = gda_data_model_get_value_at (model, 1, i, error);
 				if (!fk_schema) goto onfkerror;
 				fk_name = gda_data_model_get_value_at (model, 2, i, error);
 				if (!fk_name) goto onfkerror;
+				upd_policy = gda_data_model_get_value_at (model, 5, i, error);
+				if (!upd_policy) goto onfkerror;
+				del_policy = gda_data_model_get_value_at (model, 6, i, error);
+				if (!del_policy) goto onfkerror;
 
 				tfk = g_new0 (GdaMetaTableForeignKey, 1);
 				tfk->meta_table = dbo;
@@ -870,7 +902,23 @@ _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 					dot->reverse_fk_list = g_slist_prepend (dot->reverse_fk_list, tfk);
 				}
 				dbo->depend_list = g_slist_append (dbo->depend_list, tfk->depend_on);
-				
+
+				tfk->on_update_policy = g_new (GdaMetaForeignKeyPolicy, 1);
+				if (G_VALUE_TYPE (upd_policy) == G_TYPE_STRING)
+					*tfk->on_update_policy = policy_string_to_value (g_value_get_string (upd_policy));
+				else
+					*tfk->on_update_policy = GDA_META_FOREIGN_KEY_UNKNOWN;
+
+				tfk->on_delete_policy = g_new (GdaMetaForeignKeyPolicy, 1);
+				if (G_VALUE_TYPE (upd_policy) == G_TYPE_STRING)
+					*tfk->on_delete_policy = policy_string_to_value (g_value_get_string (del_policy));
+				else
+					*tfk->on_delete_policy = GDA_META_FOREIGN_KEY_UNKNOWN;
+
+				tfk->defined_in_schema = g_new (gboolean, 1);
+				*tfk->defined_in_schema = TRUE;
+					
+
 				/* FIXME: compute @cols_nb, and all the @*_array members (ref_pk_cols_array must be
 				 * initialized with -1 values everywhere */
 				sql = "SELECT k.column_name, c.ordinal_position FROM _key_column_usage k INNER JOIN _columns c ON (c.table_catalog = k.table_catalog AND c.table_schema = k.table_schema AND c.table_name=k.table_name AND c.column_name=k.column_name) WHERE k.table_catalog = ##tc::string AND k.table_schema = ##ts::string AND k.table_name = ##tname::string AND k.constraint_name = ##cname::string ORDER BY k.ordinal_position";
@@ -1843,6 +1891,9 @@ gda_meta_table_foreign_key_free (GdaMetaTableForeignKey *tfk)
 	g_free (tfk->fk_names_array);
 	g_free (tfk->ref_pk_cols_array);
 	g_free (tfk->ref_pk_names_array);
+	g_free (tfk->on_update_policy);
+	g_free (tfk->on_delete_policy);
+	g_free (tfk->defined_in_schema);
 	g_free (tfk);
 }
 
diff --git a/libgda/gda-meta-struct.h b/libgda/gda-meta-struct.h
index a1614bf..21f0dfa 100644
--- a/libgda/gda-meta-struct.h
+++ b/libgda/gda-meta-struct.h
@@ -1,6 +1,6 @@
 /* gda-meta-struct.h
  *
- * Copyright (C) 2008 - 2009 Vivien Malerba
+ * Copyright (C) 2008 - 2011 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -57,6 +57,7 @@ struct _GdaMetaStructClass
 {
 	GObjectClass              parent_class;
 
+	/*< private >*/
 	/* Padding for future expansion */
 	void (*_gda_reserved1) (void);
 	void (*_gda_reserved2) (void);
@@ -64,8 +65,13 @@ struct _GdaMetaStructClass
 	void (*_gda_reserved4) (void);
 };
 
-/*
- * Type of database object which can be handled
+/**
+ * GdaMetaDbObjectType:
+ * @GDA_META_DB_UNKNOWN: unknown type
+ * @GDA_META_DB_TABLE: represents a table
+ * @GDA_META_DB_VIEW: represents a view
+ *
+ * Type of database object which can be handled as a #GdaMetaDbObject
  */
 typedef enum {
 	GDA_META_DB_UNKNOWN,
@@ -85,7 +91,11 @@ typedef enum {
 	                                            GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES
 } GdaMetaStructFeature;
 
-/*
+/**
+ * GdaMetaSortType:
+ * @GDA_META_SORT_ALHAPETICAL: sort alphabetically
+ * @GDA_META_SORT_DEPENDENCIES: sort by dependencies
+ *
  * Types of sorting
  */
 typedef enum {
@@ -193,8 +203,35 @@ typedef struct {
 	gpointer _gda_reserved3;
 	gpointer _gda_reserved4;
 } GdaMetaDbObject;
-#define GDA_META_DB_OBJECT(x) ((GdaMetaDbObject*)(x))
+
+/**
+ * GDA_META_DB_OBJECT:
+ * @dbo: a pointer
+ *
+ * Casts @dbo to a #GdaMetaDbObject, no check is made on the validity of @dbo
+ *
+ * Returns: a pointer to a #GdaMetaDbObject
+ */
+#define GDA_META_DB_OBJECT(dbo) ((GdaMetaDbObject*)(dbo))
+
+/**
+ * GDA_META_TABLE:
+ * @dbo: a pointer
+ *
+ * Casts @dbo to a #GdaMetaTable, no check is made on the validity of @dbo
+ *
+ * Returns: a pointer to a #GdaMetaTable
+ */
 #define GDA_META_TABLE(dbobj) (&((dbobj)->extra.meta_table))
+
+/**
+ * GDA_META_VIEW:
+ * @dbo: a pointer
+ *
+ * Casts @dbo to a #GdaMetaView, no check is made on the validity of @dbo
+ *
+ * Returns: a pointer to a #GdaMetaView
+ */
 #define GDA_META_VIEW(dbobj) (&((dbobj)->extra.meta_view))
 
 /**
@@ -224,7 +261,17 @@ typedef struct {
 	gpointer _gda_reserved3;
 	gpointer _gda_reserved4;
 } GdaMetaTableColumn;
-#define GDA_META_TABLE_COLUMN(x) ((GdaMetaTableColumn*)(x))
+
+/**
+ * GDA_META_TABLE_COLUMN:
+ * @col: a pointer
+ *
+ * Casts @col to a #GdaMetaTableColumn, no check is made
+ *
+ * Returns: @col, casted to a #GdaMetaTableColumn
+ */
+#define GDA_META_TABLE_COLUMN(col) ((GdaMetaTableColumn*)(col))
+
 const GValue *gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol, const gchar *attribute);
 void          gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, const gchar *attribute, const GValue *value,
 						   GDestroyNotify destroy);
@@ -241,6 +288,29 @@ void          gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, con
 void          gda_meta_table_column_foreach_attribute (GdaMetaTableColumn *tcol, GdaAttributesManagerFunc func, gpointer data);
 
 /**
+ * GdaMetaForeignKeyPolicy:
+ * @GDA_META_FOREIGN_KEY_UNKNOWN: unspecified policy
+ * @GDA_META_FOREIGN_KEY_NONE: not enforced policy
+ * @GDA_META_FOREIGN_KEY_NO_ACTION: return an error, no action taken
+ * @GDA_META_FOREIGN_KEY_RESTRICT: same as @GDA_META_FOREIGN_KEY_NO_ACTION, not deferrable
+ * @GDA_META_FOREIGN_KEY_CASCADE: policy is to delete any rows referencing the deleted row, or update the value of the referencing column to the new value of the referenced column, respectively
+ * @GDA_META_FOREIGN_KEY_SET_NULL: policy is to set the referencing column to NULL
+ * @GDA_META_FOREIGN_KEY_SET_DEFAULT: policy is to set the referencing column to its default value
+ *
+ * Defines the filtering policy of a foreign key when invoked on an UPDATE
+ * or DELETE operation.
+ */
+typedef enum {
+	GDA_META_FOREIGN_KEY_UNKNOWN,
+	GDA_META_FOREIGN_KEY_NONE,
+	GDA_META_FOREIGN_KEY_NO_ACTION,
+	GDA_META_FOREIGN_KEY_RESTRICT,
+	GDA_META_FOREIGN_KEY_CASCADE,
+	GDA_META_FOREIGN_KEY_SET_NULL,
+	GDA_META_FOREIGN_KEY_SET_DEFAULT
+} GdaMetaForeignKeyPolicy;
+
+/**
  * GdaMetaTableForeignKey:
  * @meta_table: the #GdaMetaDbObject for which this structure represents a foreign key
  * @depend_on: the #GdaMetaDbObject which is referenced by the foreign key
@@ -266,14 +336,53 @@ typedef struct {
 	gchar           **ref_pk_names_array; /* Ref PK fields names */
 
 	/*< private >*/
+	GdaMetaForeignKeyPolicy *on_update_policy;
+	GdaMetaForeignKeyPolicy *on_delete_policy;
+	gboolean                *defined_in_schema;
+
 	/* Padding for future expansion */
 	gpointer _gda_reserved1;
-	gpointer _gda_reserved2;
-	gpointer _gda_reserved3;
-	gpointer _gda_reserved4;
 } GdaMetaTableForeignKey;
-#define GDA_META_TABLE_FOREIGN_KEY(x) ((GdaMetaTableForeignKey*)(x))
+/**
+ * GDA_META_TABLE_FOREIGN_KEY
+ * @fk: a pointer
+ *
+ * Casts @fk to a #GdaMetaTableForeignKey (no check is actuelly being done on @fk's validity)
+ *
+ * Returns: @col, casted to a #GdaMetaTableForeignKey
+ */
+#define GDA_META_TABLE_FOREIGN_KEY(fk) ((GdaMetaTableForeignKey*)(fk))
 
+/**
+ * GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY:
+ * @fk: a pointer to a #GdaMetaTableForeignKey
+ * 
+ * Tells the actual policy implemented by @fk when used in the context of an UPDATE.
+ *
+ * Returns: the policy as a #GdaMetaForeignKeyPolicy
+ */
+#define GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY(fk) (*(((GdaMetaTableForeignKey*)(fk))->on_update_policy))
+
+/**
+ * GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY:
+ * @fk: a pointer to a #GdaMetaTableForeignKey
+ * 
+ * Tells the actual policy implemented by @fk when used in the context of a DELETE.
+ *
+ * Returns: the policy as a #GdaMetaForeignKeyPolicy
+ */
+#define GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY(fk) (*(((GdaMetaTableForeignKey*)(fk))->on_update_policy))
+
+/**
+ * GDA_META_TABLE_FOREIGN_KEY_IN_SCHEMA
+ * @fk: a pointer to a #GdaMetaTableForeignKey
+ *
+ * Tells if @fk is an actual foreign key defined in the database's schema, or if it is an indication which
+ * has been added to help Libgda understand the database schema.
+ *
+ * Returns: %TRUE if @fk is an actual foreign key defined in the database's schema
+ */
+#define GDA_META_TABLE_FOREIGN_KEY_IN_SCHEMA(fk) (*(((GdaMetaTableForeignKey*)(fk))->defined_in_schema))
 
 GType               gda_meta_struct_get_type           (void) G_GNUC_CONST;
 GdaMetaStruct      *gda_meta_struct_new                (GdaMetaStore *store, GdaMetaStructFeature features);



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