[libgda: 7/17] DB: GdaDbIndex and GdaDbIndexField objects added



commit f41e7a199f2d294b5181967ccecee49ca82c5ca1
Author: Pavlo Solntsev <p sun fun gmail com>
Date:   Thu Mar 21 07:19:07 2019 -0500

    DB: GdaDbIndex and GdaDbIndexField objects added
    
    New Objects added to simplify DDL operations with indexes.

 libgda/gda-db-index-field.c | 214 +++++++++++++++++++++++++++++++++++
 libgda/gda-db-index-field.h |  91 +++++++++++++++
 libgda/gda-db-index.c       | 265 ++++++++++++++++++++++++++++++++++++++++++++
 libgda/gda-db-index.h       |  73 ++++++++++++
 4 files changed, 643 insertions(+)
---
diff --git a/libgda/gda-db-index-field.c b/libgda/gda-db-index-field.c
new file mode 100644
index 000000000..8c7314acd
--- /dev/null
+++ b/libgda/gda-db-index-field.c
@@ -0,0 +1,214 @@
+/* gda-db-index-index.c
+ *
+ * Copyright (C) 2019 Pavlo Solntsev <p sun fun gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "gda-db-index-field.h"
+
+typedef struct
+{
+  GdaDbColumn *mColumn;
+  GdaDbIndexCollate mCollate;
+  GdaDbIndexSortOrder mSortOrder;
+} GdaDbIndexFieldPrivate;
+
+
+/**
+ * SECTION:gda-db-index-field
+ * @short_description: Object to represent table index
+ * @see_also: #GdaDbTable, #GdaDbCatalog
+ * @stability: Stable
+ * @include: libgda/libgda.h
+ *
+ * This object is a container for information needed to create an index for a table. After
+ * population with information, it should be passed to the #GdaDbIndex instance.
+ *
+ */
+
+G_DEFINE_TYPE_WITH_PRIVATE(GdaDbIndexField, gda_db_index_field, G_TYPE_OBJECT)
+
+/**
+ * gda_db_index_field_new:
+ *
+ * Create a new instance of #GdaDbIndexField
+ *
+ * Returns: (transfer full): A new instance of #GdaDbIndexField
+ *
+ * Since: 6.0
+ */
+GdaDbIndexField *
+gda_db_index_field_new (void)
+{
+  return g_object_new (GDA_TYPE_DB_INDEX_FIELD, NULL);
+}
+static void
+gda_db_index_field_dispose (GObject *object)
+{
+  GdaDbIndexField *self = GDA_DB_INDEX_FIELD (object);
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+
+  g_object_unref (priv->mColumn);
+
+  G_OBJECT_CLASS (gda_db_index_field_parent_class)->dispose (object);
+}
+
+static void
+gda_db_index_field_class_init (GdaDbIndexFieldClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gda_db_index_field_dispose;
+}
+
+static void
+gda_db_index_field_init (GdaDbIndexField *self)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+
+  priv->mColumn = NULL;
+  priv->mCollate = GDA_DB_INDEX_COLLATE_BINARY;
+  priv->mSortOrder = GDA_DB_INDEX_SORT_ORDER_ASC;
+}
+
+/**
+ * gda_db_index_field_set_column:
+ * @self: an instance of #GdaDbIndexField
+ * @column: column to add index to
+ *
+ * Only full name will be extracted from @column.
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_field_set_column (GdaDbIndexField *self,
+                               GdaDbColumn *column)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+
+  if (priv->mColumn)
+    g_object_unref (priv->mColumn);
+
+  priv->mColumn = g_object_ref (column);
+}
+
+/**
+ * gda_db_index_field_get_column:
+ * @self: a #GdaDbIndexField instance
+ *
+ * Returns an active column that was asigned to #GdaDbIndexField instance
+ *
+ * Returns: (transfer none): A #GdaDbColumn where index should be added
+ *
+ * Since: 6.0
+ */
+GdaDbColumn *
+gda_db_index_field_get_column (GdaDbIndexField *self)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+  return priv->mColumn;
+}
+
+/**
+ * gda_db_index_field_set_collate:
+ * @self: instance of #GdaDbIndexField
+ * @collate: collate to set
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_field_set_collate (GdaDbIndexField *self,
+                                GdaDbIndexCollate collate)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+  priv->mCollate = collate;
+}
+
+/**
+ * gda_db_index_field_get_collate:
+ * @self: instance of #GdaDbIndexField
+ *
+ * Returns: Collate value
+ *
+ * Since: 6.0
+ */
+GdaDbIndexCollate
+gda_db_index_field_get_collate (GdaDbIndexField *self)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+  return priv->mCollate;
+}
+
+/**
+ * gda_db_index_field_set_sort_order:
+ * @self: object to use
+ * @sorder: sort order to set
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_field_set_sort_order (GdaDbIndexField *self,
+                                   GdaDbIndexSortOrder sorder)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+  priv->mSortOrder = sorder;
+}
+
+/**
+ * gda_db_index_field_get_sort_order:
+ * @self: object to use
+ *
+ * Returns: sort order as a #GdaDbIndexSortOrder object
+ *
+ * Since: 6.0
+ */
+GdaDbIndexSortOrder
+gda_db_index_field_get_sort_order (GdaDbIndexField *self)
+{
+  GdaDbIndexFieldPrivate *priv = gda_db_index_field_get_instance_private (self);
+  return priv->mSortOrder;
+}
+
+const gchar *
+gda_db_index_field_get_collate_str (GdaDbIndexField *field)
+{
+  g_return_val_if_fail (GDA_IS_DB_INDEX_FIELD(field), NULL);
+
+  GdaDbIndexCollate collate = gda_db_index_field_get_collate(field);
+
+  if (collate == GDA_DB_INDEX_COLLATE_BINARY)
+    return "BINARY";
+  else if (collate == GDA_DB_INDEX_COLLATE_NOCASE)
+    return "NOCASE";
+  else
+    return NULL;
+}
+
+const gchar *
+gda_db_index_field_get_sort_order_str (GdaDbIndexField *field)
+{
+  g_return_val_if_fail (GDA_IS_DB_INDEX_FIELD(field), NULL);
+
+  GdaDbIndexSortOrder sorder = gda_db_index_field_get_sort_order (field);
+
+  if (sorder == GDA_DB_INDEX_SORT_ORDER_ASC)
+    return "ASC";
+  else if (sorder == GDA_DB_INDEX_SORT_ORDER_DESC)
+    return "DESC";
+  else
+    return NULL;
+}
diff --git a/libgda/gda-db-index-field.h b/libgda/gda-db-index-field.h
new file mode 100644
index 000000000..59ffeb75c
--- /dev/null
+++ b/libgda/gda-db-index-field.h
@@ -0,0 +1,91 @@
+/*
+ * gda-db-index-field.h
+ * Copyright (C) 2019 Pavlo Solntsev <p sun fun gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GDA_DB_INDEX_FIELD_H
+#define GDA_DB_INDEX_FIELD_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gda-db-base.h"
+#include "gda-db-column.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DB_INDEX_FIELD (gda_db_index_field_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GdaDbIndexField, gda_db_index_field, GDA, DB_INDEX_FIELD, GObject)
+
+struct _GdaDbIndexFieldClass
+{
+  GObjectClass parent_class;
+};
+
+/**
+ * GdaDbIndexCollate:
+ * @GDA_DB_INDEX_COLLATE_BINARY: BINARY collate
+ * @GDA_DB_INDEX_COLLATE_NOCASE: NOCASE collate
+ *
+ * Enum values to specify the collate value for the column
+ */
+typedef enum
+{
+  GDA_DB_INDEX_COLLATE_BINARY = 0,
+  GDA_DB_INDEX_COLLATE_NOCASE
+} GdaDbIndexCollate;
+
+/**
+ * GdaDbIndexSortOrder:
+ * @GDA_DB_INDEX_SORT_ORDER_ASC: ascending sorting
+ * @GDA_DB_INDEX_SORT_ORDER_DESC: descending sorting
+ *
+ * Enum values to specify the sorting
+ */
+typedef enum
+{
+  GDA_DB_INDEX_SORT_ORDER_ASC = 0,
+  GDA_DB_INDEX_SORT_ORDER_DESC
+} GdaDbIndexSortOrder;
+
+GdaDbIndexField     *gda_db_index_field_new            (void);
+
+void                 gda_db_index_field_set_column     (GdaDbIndexField *self,
+                                                        GdaDbColumn *column);
+
+GdaDbColumn         *gda_db_index_field_get_column     (GdaDbIndexField *self);
+
+void                 gda_db_index_field_set_collate    (GdaDbIndexField *self,
+                                                        GdaDbIndexCollate collate);
+
+GdaDbIndexCollate    gda_db_index_field_get_collate    (GdaDbIndexField *self);
+
+void                 gda_db_index_field_set_sort_order (GdaDbIndexField *self,
+                                                        GdaDbIndexSortOrder sorder);
+
+GdaDbIndexSortOrder  gda_db_index_field_get_sort_order (GdaDbIndexField *self);
+
+const gchar *        gda_db_index_field_get_collate_str (GdaDbIndexField *field);
+const gchar *        gda_db_index_field_get_sort_order_str (GdaDbIndexField *field);
+
+G_END_DECLS
+
+#endif /* end of include guard: GDA-DB-INDEX_H */
+
+
+
+
diff --git a/libgda/gda-db-index.c b/libgda/gda-db-index.c
new file mode 100644
index 000000000..1b827fff5
--- /dev/null
+++ b/libgda/gda-db-index.c
@@ -0,0 +1,265 @@
+/* gda-db-index.c
+ *
+ * Copyright (C) 2019 Pavlo Solntsev <p sun fun gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "gda-db-index.h"
+#include "gda-connection.h"
+#include "gda-server-operation.h"
+#include "gda-server-provider.h"
+#include "gda-lockable.h"
+#include <glib/gi18n-lib.h>
+
+G_DEFINE_QUARK (gda_db_index_error, gda_db_index_error)
+
+typedef struct
+{
+  gboolean mUnique;
+  GSList *mFieldList; /* A list of GdaDbIndexField */
+} GdaDbIndexPrivate;
+
+/**
+ * SECTION:gda-db-index
+ * @short_description: Object to represent table index
+ * @see_also: #GdaDbTable, #GdaDbCatalog
+ * @stability: Stable
+ * @include: libgda/libgda.h
+ *
+ */
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdaDbIndex, gda_db_index, GDA_TYPE_DB_BASE)
+
+GdaDbIndex *
+gda_db_index_new (void)
+{
+  return g_object_new (GDA_TYPE_DB_INDEX, NULL);
+}
+
+static void
+gda_db_index_init (GdaDbIndex *self)
+{
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+
+  priv->mFieldList = NULL;
+  priv->mUnique = TRUE;
+}
+
+static void
+gda_db_index_finalize (GObject *object)
+{
+  GdaDbIndex *self = GDA_DB_INDEX (object);
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+
+  g_slist_free_full (priv->mFieldList, g_object_unref);
+
+  G_OBJECT_CLASS (gda_db_index_parent_class)->finalize (object);
+}
+
+static void
+gda_db_index_class_init (GdaDbIndexClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gda_db_index_finalize;
+}
+
+/**
+ * gda_db_index_set_unique:
+ * @self: #GdaDbIndex instance
+ * @val: if set to %TRUE UNIQUE index type will be used.
+ *
+ * If @val is %TRUE a "UNIQUE" will be added to the INDEX CREATE command, e.g.
+ * CREATE UNIQUE INDEX ...
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_set_unique (GdaDbIndex *self,
+                         gboolean val)
+{
+  G_DEBUG_HERE();
+  g_return_if_fail (self);
+
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+  priv->mUnique = val;
+}
+
+/**
+ * gda_db_index_get_unique:
+ * @self: instance os #GdaDbIndex to use
+ *
+ * Returns: state for UNIQUE. This method will abort if @self is %NULL
+ *
+ * Since: 6.0
+ */
+gboolean
+gda_db_index_get_unique (GdaDbIndex *self)
+{
+  G_DEBUG_HERE();
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+  return priv->mUnique;
+}
+
+/**
+ * gda_db_index_append_field:
+ * @self: an instance of #GdaDbIndex
+ * @field: a field to set
+ *
+ * Append to index filed to the current index instance, The @self object will recieve full
+ * ownership of the field. After this call, the reference to the @field from the caller can be
+ * destoyed by calling g_object_unref()
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_append_field  (GdaDbIndex *self,
+                            GdaDbIndexField *field)
+{
+  G_DEBUG_HERE();
+  g_return_if_fail (self);
+  g_return_if_fail (field);
+
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+// Check if field name already exists, then update values, otherwise append
+
+  if (!priv->mFieldList)
+    priv->mFieldList = g_slist_append (priv->mFieldList, g_object_ref (field));
+  else
+    {
+      GSList *it = priv->mFieldList;
+      for (; it != NULL; it = it->next)
+        {
+          GdaDbColumn *current_col = gda_db_index_field_get_column (GDA_DB_INDEX_FIELD (it->data));
+          GdaDbColumn *new_col = gda_db_index_field_get_column (field);
+
+          if (gda_db_base_compare (GDA_DB_BASE (current_col), GDA_DB_BASE (new_col)))
+            priv->mFieldList = g_slist_append (priv->mFieldList, g_object_ref (field));
+          else
+            {
+              gda_db_index_field_set_collate (GDA_DB_INDEX_FIELD (it->data),
+                                              gda_db_index_field_get_collate (field));
+              gda_db_index_field_set_sort_order(GDA_DB_INDEX_FIELD (it->data),
+                                                gda_db_index_field_get_sort_order (field));
+            }
+        }
+    }
+}
+
+/**
+ * gda_db_index_remove_field:
+ * @self: instance of #GdaDbIndex
+ * @name: Name of the column where field should be removed.
+ *
+ * Since: 6.0
+ */
+void
+gda_db_index_remove_field (GdaDbIndex *self,
+                           const gchar *name)
+{
+  G_DEBUG_HERE();
+  g_return_if_fail (self);
+  g_return_if_fail (name);
+
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+
+  GSList *it = priv->mFieldList;
+  for (; it != NULL; it = it->next)
+    {
+      const gchar *full_name = gda_db_base_get_full_name (GDA_DB_BASE (it->data));
+
+      if (!g_strcmp0 (full_name, name))
+        priv->mFieldList = g_slist_remove (priv->mFieldList, it->data);
+    }
+}
+
+/**
+ * gda_db_index_get_fields:
+ * @self: an instance of #GdaDbIndex
+ *
+ * This function is thread safe, that is, @cnc will be locked.
+ *
+ * Returns: (transfer none): A list of #GdaDbIndexField
+ */
+GSList *
+gda_db_index_get_fields (GdaDbIndex *self)
+{
+  G_DEBUG_HERE();
+  GdaDbIndexPrivate *priv = gda_db_index_get_instance_private (self);
+
+  return priv->mFieldList;
+}
+
+gboolean
+gda_db_index_drop (GdaDbIndex *self,
+                   GdaConnection *cnc,
+                   gboolean ifexists,
+                   GError **error)
+{
+  G_DEBUG_HERE();
+  g_return_val_if_fail (GDA_IS_DB_INDEX (self), FALSE);
+  g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (!gda_connection_is_opened(cnc))
+    {
+      g_set_error (error, GDA_DB_INDEX_ERROR, GDA_DB_INDEX_CONNECTION_NOT_OPENED,
+                   _("Connection is not opened"));
+      return FALSE;
+    }
+
+  GdaServerProvider *provider = NULL;
+  GdaServerOperation *op = NULL;
+
+  gda_lockable_lock (GDA_LOCKABLE (cnc));
+
+  provider = gda_connection_get_provider (cnc);
+
+  op = gda_server_provider_create_operation (provider,
+                                             cnc,
+                                             GDA_SERVER_OPERATION_DROP_INDEX,
+                                             NULL,
+                                             error);
+  if (!op)
+    {
+      g_set_error (error, GDA_DB_INDEX_ERROR, GDA_DB_INDEX_CONNECTION_NOT_OPENED,
+                   _("Connection is not opened"));
+      goto on_error;
+    }
+
+  if (!gda_server_operation_set_value_at (op, gda_db_base_get_full_name (GDA_DB_BASE (self)),
+                                          error, "/INDEX_DESC_P/INDEX_NAME"))
+    goto on_error;
+
+  if (!gda_server_operation_set_value_at (op, GDA_BOOL_TO_STR (ifexists), error,
+                                          "/INDEX_DESC_P/INDEX_IFEXISTS"))
+    goto on_error;
+
+  if (!gda_server_provider_perform_operation (provider, cnc, op, error))
+    goto on_error;
+
+  gda_lockable_unlock (GDA_LOCKABLE (cnc));
+
+  return TRUE;
+
+on_error:
+  if (op) g_object_unref (op);
+
+  gda_lockable_unlock (GDA_LOCKABLE (cnc));
+
+  return FALSE;
+}
diff --git a/libgda/gda-db-index.h b/libgda/gda-db-index.h
new file mode 100644
index 000000000..fc1938a2a
--- /dev/null
+++ b/libgda/gda-db-index.h
@@ -0,0 +1,73 @@
+/*
+ * gda-db-index.h
+ * Copyright (C) 2019 Pavlo Solntsev <p sun fun gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GDA_DB_INDEX_H
+#define GDA_DB_INDEX_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gda-db-base.h"
+#include "gda-db-index-field.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DB_INDEX (gda_db_index_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GdaDbIndex, gda_db_index, GDA, DB_INDEX, GdaDbBase)
+
+struct _GdaDbIndexClass
+{
+  GdaDbBaseClass parent_class;
+};
+
+/**
+ * GdaDbIndexError:
+ *
+ */
+typedef enum {
+    GDA_DB_INDEX_CONNECTION_NOT_OPENED,
+    GDA_DB_INDEX_SERVER_OPERATION
+} GdaDbIndexError;
+
+#define GDA_DB_INDEX_ERROR gda_db_index_error_quark()
+
+GQuark gda_db_index_error_quark(void);
+
+GdaDbIndex       *gda_db_index_new (void);
+
+void              gda_db_index_set_unique (GdaDbIndex *self, gboolean val);
+gboolean          gda_db_index_get_unique (GdaDbIndex *self);
+
+void              gda_db_index_append_field (GdaDbIndex *self, GdaDbIndexField *field);
+
+void              gda_db_index_remove_field (GdaDbIndex *self, const gchar *name);
+
+GSList           *gda_db_index_get_fields   (GdaDbIndex *self);
+
+gboolean          gda_db_index_drop (GdaDbIndex *self,
+                                     GdaConnection *cnc,
+                                     gboolean ifexists,
+                                     GError **error);
+
+G_END_DECLS
+
+#endif /* end of include guard: GDA-DB-INDEX_H */
+
+
+


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