[libgda: 1/5] DB: Convenient API to get GdaDbTable and GdaDbView




commit da078d70740231db4df409bf8b612396d2c9fbcf
Author: Pavlo Solntsev <p sun fun gmail com>
Date:   Mon Aug 3 22:42:36 2020 -0500

    DB: Convenient API to get GdaDbTable and GdaDbView
    
    See https://gitlab.gnome.org/GNOME/libgda/-/issues/223

 libgda/gda-db-base.c               |  46 ++++++++---
 libgda/gda-db-catalog.c            | 159 ++++++++++++++++++++++++++++++-------
 libgda/gda-db-catalog.h            |   9 +++
 tests/db/check-db-base.c           |  41 ++++++++++
 tests/db/check-db-catalog.c        |  63 +++++++++++++++
 tests/test-ddl-modifiable-sqlite.c |   2 +
 6 files changed, 280 insertions(+), 40 deletions(-)
---
diff --git a/libgda/gda-db-base.c b/libgda/gda-db-base.c
index 6c1344b20..45d768c1b 100644
--- a/libgda/gda-db-base.c
+++ b/libgda/gda-db-base.c
@@ -319,9 +319,11 @@ gda_db_base_set_name (GdaDbBase  *self,
  * @a: first #GdaDbBase object
  * @b: second #GdaDbBase object
  *
- * Compares two objects similar to g_strcmp().
+ * Compares two objects similar to g_strcmp(). In general, catalog and schema can be %NULL. In this case
+ * those pairs are ignored. If we represent a full name as catalog.schema.name then two objects
+ * null.null.customer and main.main.customer are identical.
  *
- * Returns: 0 if catalog, schema and name are the same
+ * Returns: 0 if two objects are identical or -1 or 1 otherwise.
  *
  * Since: 6.0
  */
@@ -336,17 +338,41 @@ gda_db_base_compare (GdaDbBase *a,
   else if (a && !b)
     return 1;
 
-  gint res = g_strcmp0 (gda_db_base_get_name(a), gda_db_base_get_name(b));
+  const gchar *a_catalog = gda_db_base_get_catalog (a);
+  const gchar *b_catalog = gda_db_base_get_catalog (b);
 
-  if (!res)
-    {
-      res = g_strcmp0 (gda_db_base_get_catalog(a), gda_db_base_get_catalog(b));
+  const gchar *a_schema = gda_db_base_get_schema (a);
+  const gchar *b_schema = gda_db_base_get_schema (b);
+
+  const gchar *a_name = gda_db_base_get_name (a);
+  const gchar *b_name = gda_db_base_get_name (b);
 
-      if (!res)
-        return g_strcmp0(gda_db_base_get_schema(a), gda_db_base_get_schema(b));
+  gint res;
+
+  res = g_strcmp0 (a_name, b_name);
+  if (a_name && b_name)
+    {
+      if (a_schema && b_schema)
+        {
+          res = g_strcmp0 (a_schema, b_schema);
+          if (a_catalog && b_catalog)
+            {
+              return g_strcmp0 (a_catalog, b_catalog);
+            }
+          else
+            {
+              return res;
+            }
+        }
       else
-        return res;
+        {
+          return res;
+        }
     }
   else
-    return res;
+    {
+      return res;
+    }
+
+  return -1;
 }
diff --git a/libgda/gda-db-catalog.c b/libgda/gda-db-catalog.c
index 04d590aa6..a5b4324c4 100644
--- a/libgda/gda-db-catalog.c
+++ b/libgda/gda-db-catalog.c
@@ -552,14 +552,20 @@ gda_db_catalog_get_views (GdaDbCatalog *self)
 /**
  * gda_db_catalog_get_table:
  * @self: a #GdaDbCatalog object
+ * @catalog (nullable): catalog name or %NULL
+ * @schema (nullable): schema name or %NULL
  * @name: table name
  *
- * Convenient function to return a table based on name
+ * Convenient function to get a table based on @name. The coller is responsible
+ * for calling gda_db_catalog_parse_cnc() before calling this function.
  *
- * Returns: table as #GdaDbTable or %NULL
+ * Returns: (transfer none): table as #GdaDbTable or %NULL if the table is not found. The
+ * returned pointer should not be freed and belongs to the @self.
+ *
+ * Since: 6.2
  *
  */
-const GdaDbTable*
+GdaDbTable *
 gda_db_catalog_get_table (GdaDbCatalog *self,
                           const gchar *catalog,
                           const gchar *schema,
@@ -568,55 +574,132 @@ gda_db_catalog_get_table (GdaDbCatalog *self,
   g_return_val_if_fail (self, NULL);
   g_return_val_if_fail (name, NULL);
 
+  GdaDbBase *iobj;
+  GList *it;
+
   GdaDbCatalogPrivate *priv = gda_db_catalog_get_instance_private (self);
 
-  GdaDbBase *iobj = gda_db_base_new ();
+  iobj = gda_db_base_new ();
   gda_db_base_set_names (iobj, catalog, schema, name);
 
-  GList *it = NULL;
-
   for (it = priv->mp_tables; it; it = it->next)
-      if (!gda_db_base_compare (iobj,GDA_DB_BASE(it->data)))
-        {
-          g_object_unref (iobj);
-          return GDA_DB_TABLE(it->data);
-        }
+    {
+         if (!gda_db_base_compare (GDA_DB_BASE (it->data), iobj)) {
+                 if (iobj)
+                         g_object_unref (iobj);
+
+                 return GDA_DB_TABLE (it->data);
+         }
+    }
+
+  if (iobj)
+    g_object_unref (iobj);
 
-  g_object_unref (iobj);
   return NULL;
 }
 
 /**
  * gda_db_catalog_get_view:
  * @self: a #GdaDbCatalog object
- * @name: view name
+ * @catalog: a catalog name or %NULL
+ * @schema: a schema name or %NULL
+ * @name: view name. Can't be %NULL
+ *
+ * Convenient function to get a view based on name. The coller is responsible
+ * for calling gda_db_catalog_parse_cnc() before calling this function. This
+ * code is equivalent to the following code:
  *
- * Convenient function to return a view based on name.
+ * |[<!-- language="C" -->
+ *  GdaDbBase *iobj;
+ *  GList *it;
  *
- * Returns: table as #GdaDbView or %NULL if the view is not found.
+ *  GdaDbCatalogPrivate *priv = gda_db_catalog_get_instance_private (self);
+ *
+ *  if (gda_db_catalog_parse_cnc (self, error))
+ *    return NULL;
+ *
+ *  iobj = gda_db_base_new ();
+ *  gda_db_base_set_names (iobj, catalog, schema, name);
+ *
+ *  for (it = priv->mp_views; it; it = it->next)
+ *    {
+ *      if (!gda_db_base_compare (iobj, GDA_DB_BASE (it->data)))
+ *        {
+ *          if (iobj)
+ *            g_object_unref (iobj);
+ *
+ *          return GDA_DB_VIEW (it->data);
+ *        }
+ *    }
+ *
+ *  if (iobj)
+ *    g_object_unref (iobj);
+ *
+ *  return NULL;
+ * ]|
+ * Returns: (transfer none): View as #GdaDbView or %NULL if the view is not found. The returned
+ * pointer should not be freed and belongs to @self
+ *
+ * Since: 6.0
  *
  */
-const GdaDbView*
+GdaDbView*
 gda_db_catalog_get_view (GdaDbCatalog *self,
                          const gchar *catalog,
                          const gchar *schema,
                          const gchar *name)
 {
-  GdaDbCatalogPrivate *priv = gda_db_catalog_get_instance_private (self);
+  g_return_val_if_fail (self, NULL);
+  g_return_val_if_fail (name, NULL);
 
-  GList *it = NULL;
+  GdaDbBase *iobj;
+  GList *it;
+
+  GdaDbCatalogPrivate *priv = gda_db_catalog_get_instance_private (self);
 
-  GdaDbBase *iobj = gda_db_base_new ();
-  gda_db_base_set_names (iobj,catalog,schema,name);
+  iobj = gda_db_base_new ();
+  gda_db_base_set_names (iobj, catalog, schema, name);
 
   for (it = priv->mp_views; it; it = it->next)
-    if (!gda_db_base_compare (iobj, GDA_DB_BASE(it)))
-      {
-        g_object_unref (iobj);
-        return GDA_DB_VIEW(it);
-      }
+    {
+      if (schema && catalog)
+        {
+          if (!gda_db_base_compare (iobj, GDA_DB_BASE (it->data)))
+            {
+              if (iobj)
+                g_object_unref (iobj);
+
+              return GDA_DB_VIEW (it->data);
+            }
+        }
+      else if (schema && !catalog)
+        {
+          if (!g_strcmp0 (schema,
+                          gda_db_base_get_schema (GDA_DB_BASE (it->data)))
+              && !g_strcmp0 (name,
+                             gda_db_base_get_name (GDA_DB_BASE (it->data))))
+            {
+              if (iobj)
+                g_object_unref (iobj);
+
+              return GDA_DB_VIEW (it->data);
+            }
+        }
+      else if (!schema && !catalog)
+        {
+          if (!g_strcmp0 (name, gda_db_base_get_name (GDA_DB_BASE (it->data))))
+            {
+              if (iobj)
+                g_object_unref (iobj);
+
+              return GDA_DB_VIEW (it->data);
+            }
+        }
+    }
+
+  if (iobj)
+    g_object_unref (iobj);
 
-  g_object_unref (iobj);
   return NULL;
 }
 
@@ -683,15 +766,18 @@ _gda_db_table_new_from_meta (GdaMetaDbObject *obj)
  * Returns: New instance of #GdaDbView
  */
 static GdaDbView*
-_gda_db_view_new_from_meta (GdaMetaView *view)
+_gda_db_view_new_from_meta (GdaMetaDbObject *obj)
 {
-  if (!view)
+  if (!obj)
     return gda_db_view_new ();
 
   GdaDbView *dbview = gda_db_view_new ();
 
-  gda_db_view_set_defstring (dbview,view->view_def);
-  gda_db_view_set_replace (dbview,view->is_updatable);
+  gda_db_base_set_names (GDA_DB_BASE (dbview), obj->obj_catalog,
+                         obj->obj_schema, obj->obj_name);
+
+  gda_db_view_set_defstring (dbview, obj->extra.meta_view.view_def);
+  gda_db_view_set_replace (dbview, obj->extra.meta_view.is_updatable);
 
   return dbview;
 }
@@ -744,6 +830,9 @@ gda_db_catalog_parse_cnc (GdaDbCatalog *self,
 
   GSList *it = NULL;
 
+  gint ntables = 0;
+  gint nviews = 0;
+
   for (it=dblist; it; it = it->next)
     {
       if(GDA_META_DB_OBJECT(it->data)->obj_type == GDA_META_DB_TABLE)
@@ -753,17 +842,27 @@ gda_db_catalog_parse_cnc (GdaDbCatalog *self,
             continue;
 
           priv->mp_tables = g_list_append (priv->mp_tables,table);
+         ntables++;
           continue;
         }
 
       if(GDA_META_DB_OBJECT(it->data)->obj_type == GDA_META_DB_VIEW)
         {
           GdaDbView *view = _gda_db_view_new_from_meta (it->data);
+
+          if (!view)
+            continue;
+
+         g_print ("%s:%d Found %s view\n", __FILE__, __LINE__, gda_db_base_get_full_name(GDA_DB_BASE 
(view)));
           priv->mp_views = g_list_append (priv->mp_views, view);
+         nviews++;
           continue;
         }
     }
 
+#ifdef GDA_DEBUG
+  g_print ("Tables: %d total, Views: %d total\n", ntables, nviews);
+#endif
   g_slist_free (dblist);
   g_object_unref (mstruct);
   return TRUE;
diff --git a/libgda/gda-db-catalog.h b/libgda/gda-db-catalog.h
index 239777b6a..312e3a2b1 100644
--- a/libgda/gda-db-catalog.h
+++ b/libgda/gda-db-catalog.h
@@ -106,6 +106,15 @@ gboolean         gda_db_catalog_write_to_path (GdaDbCatalog *self,
 
 gboolean         gda_db_catalog_validate_file_from_path (const gchar *xmlfile,
                                                          GError **error);
+GdaDbTable *gda_db_catalog_get_table (GdaDbCatalog *self,
+                                      const gchar *catalog,
+                                      const gchar *schema,
+                                      const gchar *name);
+
+GdaDbView *gda_db_catalog_get_view (GdaDbCatalog *self,
+                                    const gchar *catalog,
+                                    const gchar *schema,
+                                    const gchar *name);
 G_END_DECLS
 
 #endif /* GDA_DB_CATALOG_H */
diff --git a/tests/db/check-db-base.c b/tests/db/check-db-base.c
index 38315c57c..c59260cb1 100644
--- a/tests/db/check-db-base.c
+++ b/tests/db/check-db-base.c
@@ -30,6 +30,11 @@ typedef struct {
        GdaDbBase *obj;
 }BaseFixture;
 
+typedef struct {
+       GdaDbBase *obja;
+       GdaDbBase *objb;
+} TestBaseCompare;
+
 static void
 test_db_base_start (BaseFixture *self,
                     G_GNUC_UNUSED gconstpointer user_data)
@@ -38,6 +43,25 @@ test_db_base_start (BaseFixture *self,
 
 }
 
+static void
+test_db_base_compare_start (TestBaseCompare *self,
+                    G_GNUC_UNUSED gconstpointer user_data)
+{
+       self->obja = gda_db_base_new ();
+       self->objb = gda_db_base_new();
+}
+
+static void
+test_db_base_compare_finish (TestBaseCompare *self,
+                     G_GNUC_UNUSED gconstpointer user_data)
+{
+       if (self->obja)
+               g_object_unref (self->obja);
+
+       if (self->objb)
+               g_object_unref (self->objb);
+}
+
 static void
 test_db_base_finish (BaseFixture *self,
                      G_GNUC_UNUSED gconstpointer user_data)
@@ -46,6 +70,16 @@ test_db_base_finish (BaseFixture *self,
                g_object_unref (self->obj);
 }
 
+static void
+test_db_base_compare_run1 (TestBaseCompare *self,
+                  G_GNUC_UNUSED gconstpointer user_data)
+{
+    gda_db_base_set_name (self->obja, "name_a");
+    gda_db_base_set_name (self->objb, "name_b");
+
+    g_assert_cmpint (gda_db_base_compare (self->obja, self->objb), ==, 0);
+}
+
 static void
 test_db_base_run1 (BaseFixture *self,
                   G_GNUC_UNUSED gconstpointer user_data)
@@ -225,5 +259,12 @@ main (gint   argc,
                    test_db_base_run5,
                    test_db_base_finish);
 
+       g_test_add ("/test-db/base-compare",
+                   TestBaseCompare,
+                   NULL,
+                   test_db_base_compare_start,
+                   test_db_base_compare_run1,
+                   test_db_base_compare_finish);
+
        return g_test_run();
 }
diff --git a/tests/db/check-db-catalog.c b/tests/db/check-db-catalog.c
index dba5b5715..f2ff229eb 100644
--- a/tests/db/check-db-catalog.c
+++ b/tests/db/check-db-catalog.c
@@ -54,6 +54,7 @@ typedef struct {
     GdaDbColumn *column_ts;
     GdaDbColumn *column_state;
     GdaDbTable *table;
+    GdaDbView  *view;
 } DbCatalogCnc;
 
 typedef struct {
@@ -119,6 +120,8 @@ test_db_catalog_start_db (DbCatalogCnc *self,
 
   gchar* dbname = g_strdup_printf ("DB_DIR=.;DB_NAME=db_types_%d", g_random_int ());
 
+  g_print ("Will use DB: %s\n", dbname);
+
   self->cnc = gda_connection_new_from_string ("SQLite",
                                               dbname,
                                               NULL,
@@ -177,6 +180,17 @@ test_db_catalog_start_db (DbCatalogCnc *self,
   open_res = gda_db_catalog_perform_operation (self->catalog,NULL);
 
   g_assert_true (open_res);
+
+  self->view = gda_db_view_new ();
+
+  gda_db_base_set_name (GDA_DB_BASE (self->view), "myview");
+  gda_db_view_set_defstring (self->view, "SELECT name FROM dntypes");
+  gda_db_view_set_istemp (self->view, FALSE);
+
+  open_res = gda_ddl_modifiable_create (GDA_DDL_MODIFIABLE (self->view),
+                                        self->cnc, NULL, NULL);
+
+  g_assert_true (open_res);
 }
 
 static void
@@ -202,6 +216,7 @@ test_db_catalog_finish_db (DbCatalogCnc *self,
   g_object_unref (self->column_ctime);
   g_object_unref (self->column_ts);
   g_object_unref (self->table);
+  g_object_unref (self->view);
 }
 
 static void
@@ -531,6 +546,47 @@ test_db_catalog_constraint_finish (DbCheckCatallog *self,
   gda_connection_close (self->cnc, NULL);
 }
 
+static void
+test_db_catalog_get_objects (DbCatalogCnc *self,
+                             G_GNUC_UNUSED gconstpointer user_data)
+{
+  GdaDbTable *copy_table;
+  GdaDbView *copy_view;
+  GError *error = NULL;
+  gboolean res;
+  const gchar *name1;
+  const gchar *name2;
+  /* Creating a view to work with */
+
+  /* view has been created */
+
+  res = gda_db_catalog_parse_cnc (self->catalog, &error);
+
+  g_assert_true (res);
+  g_assert_null (error);
+
+  copy_table = gda_db_catalog_get_table (self->catalog, NULL, NULL,
+         gda_db_base_get_name (GDA_DB_BASE (self->table)));
+
+  g_assert_nonnull (copy_table);
+
+  name1 = gda_db_base_get_name (GDA_DB_BASE (copy_table));
+  name2 = gda_db_base_get_name (GDA_DB_BASE (self->table));
+
+  g_assert_cmpstr (name1, ==, name2);
+
+  const gchar *view_name = gda_db_base_get_name (GDA_DB_BASE (self->view));
+
+  copy_view = gda_db_catalog_get_view (self->catalog, NULL, NULL, view_name);
+
+  g_assert_nonnull (copy_view);
+
+  name1 = gda_db_base_get_name (GDA_DB_BASE (copy_view));
+  name2 = gda_db_base_get_name (GDA_DB_BASE (self->view));
+
+  g_assert_cmpstr (name1, ==, name2);
+}
+
 gint
 main (gint   argc,
       gchar *argv[])
@@ -580,5 +636,12 @@ main (gint   argc,
               test_db_catalog_constraint_run,
               test_db_catalog_constraint_finish);
 
+  g_test_add ("/test-db/catalog-get-objects",
+              DbCatalogCnc,
+              NULL,
+              test_db_catalog_start_db,
+              test_db_catalog_get_objects,
+              test_db_catalog_finish_db);
+
   return g_test_run();
 }
diff --git a/tests/test-ddl-modifiable-sqlite.c b/tests/test-ddl-modifiable-sqlite.c
index 3b59f7d45..60ec5458a 100644
--- a/tests/test-ddl-modifiable-sqlite.c
+++ b/tests/test-ddl-modifiable-sqlite.c
@@ -51,6 +51,8 @@ test_ddl_modifiable_start (TestObjectFixture *fixture,
 
   gchar *dbname = g_strdup_printf("DB_DIR=.;DB_NAME=%s_%d", DB_TEST_BASE, g_random_int ());
 
+  g_print ("Will use DB: %s\n", dbname);
+
   fixture->cnc = gda_connection_open_from_string (PROVIDER_NAME,
                                                   dbname,
                                                   NULL,


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