[libgda/wip/xml-ddl-tool: 1/2] A new object GdaDdlFkey was added
- From: Rodrigo Moya <rodrigo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda/wip/xml-ddl-tool: 1/2] A new object GdaDdlFkey was added
- Date: Tue, 15 May 2018 15:39:31 +0000 (UTC)
commit ca3b4d256304ec608fcb94bb714a0ec61f383e29
Author: Pavlo Solntsev <p sun fun gmail com>
Date: Sun Apr 22 20:04:51 2018 -0500
A new object GdaDdlFkey was added
Object and corresponding test was added.
doc/C/libgda-sections.txt | 26 +++
doc/C/libgda.types.in | 4 +
libgda/Makefile.am | 6 +-
libgda/gda-ddl-fkey.c | 528 +++++++++++++++++++++++++++++++++++++++++++++
libgda/gda-ddl-fkey.h | 100 +++++++++
tests/ddl/Makefile.am | 9 +-
tests/ddl/check-ddl-fkey.c | 219 +++++++++++++++++++
tests/ddl/fkey_test.xml | 7 +
8 files changed, 896 insertions(+), 3 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index 75bd426b0..8dc011d68 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -1,4 +1,30 @@
<SECTION>
+<FILE>gda-ddl-fkey</FILE>
+<TITLE>GdaDdlFkey</TITLE>
+GDA_TYPE_DDL_FKEY
+GdaDdlFkeyClass
+GdaDdlFkeyReferenceAction
+GdaDdlFkeyError
+GDA_DDL_FKEY_ERROR
+gda_ddl_fkey_error_quark
+gda_ddl_fkey_new
+gda_ddl_fkey_get_field_name
+gda_ddl_fkey_get_ref_field
+gda_ddl_fkey_set_field
+gda_ddl_fkey_get_ref_table
+gda_ddl_fkey_set_ref_table
+gda_ddl_fkey_get_ondelete
+gda_ddl_fkey_get_ondelete_id
+gda_ddl_fkey_set_ondelete
+gda_ddl_fkey_get_onupdate
+gda_ddl_fkey_get_onupdate_id
+gda_ddl_fkey_set_onupdate
+gda_ddl_fkey_parse_node
+gda_ddl_fkey_write_xml
+gda_ddl_fkey_free
+GdaDdlFkey
+</SECTION>
+<SECTION>
<FILE>gda-column</FILE>
<TITLE>GdaColumn</TITLE>
GdaColumn
diff --git a/doc/C/libgda.types.in b/doc/C/libgda.types.in
index 42f5faead..92f4604e4 100644
--- a/doc/C/libgda.types.in
+++ b/doc/C/libgda.types.in
@@ -7,6 +7,8 @@
#include <gda-report-document.h>
#include <RML/gda-report-rml-document.h>
#include <DocBook/gda-report-docbook-document.h>
+#include <libgda/gda-ddl-fkey.h>
+#include <libgda/gda-ddl-base.h>
gda_blob_op_get_type
gda_column_get_type
gda_config_get_type
@@ -67,3 +69,5 @@ gda_tree_mgr_select_get_type
gda_tree_mgr_tables_get_type
gda_tree_node_get_type
gda_sql_builder_get_type
+gda_ddl_fkey_get_type
+gda_ddl_base_get_type
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index c0695597d..9b7cf4e4c 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -113,7 +113,8 @@ gda_headers = \
gda-xa-transaction.h \
libgda-global-variables.h \
gda-data-pivot.h \
- gda-ddl-base.h
+ gda-ddl-base.h \
+ gda-ddl-fkey.h
gda_built_sources= \
$(builddir)/libgda.h
@@ -167,7 +168,8 @@ gda_sources= \
gda-value.c \
gda-xa-transaction.c \
gda-data-pivot.c \
- gda-ddl-base.c
+ gda-ddl-base.c \
+ gda-ddl-fkey.c
libgda_sources = \
csv.h \
diff --git a/libgda/gda-ddl-fkey.c b/libgda/gda-ddl-fkey.c
new file mode 100644
index 000000000..be4bed42d
--- /dev/null
+++ b/libgda/gda-ddl-fkey.c
@@ -0,0 +1,528 @@
+/* gda-ddl-fkey.c
+*
+* Copyright (C) 2018 Pavlo Solntsev <p sun fun gmail com>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "gda-ddl-fkey.h"
+#include <glib/gi18n-lib.h>
+#include <glib.h>
+
+G_DEFINE_QUARK (gda-ddl-fkey-error, gda_ddl_fkey_error)
+
+typedef struct
+{
+ /* /FKEY_S/%d/FKEY_REF_TABLE */
+ gchar *mp_ref_table;
+ /* /FKEY_S/%d/FKEY_FIELDS_A/@FK_FIELD */
+
+ GList *mp_field;
+ /* /FKEY_S/FKEY_FIELDS_A/@FK_REF_PK_FIELD */
+ GList *mp_ref_field;
+ /* /FKEY_S/FKEY_ONUPDATE This action is reserved for ONUPDATE */
+ GdaDdlFkeyReferenceAction m_onupdate;
+ /* /FKEY_S/FKEY_ONDELETE This action is reserved for ONDELETE */
+ GdaDdlFkeyReferenceAction m_ondelete;
+}GdaDdlFkeyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdaDdlFkey, gda_ddl_fkey, G_TYPE_OBJECT)
+
+static const gchar *OnAction[] = {"NO ACTION", "SET NULL", "RESTRICT",
+ "SET DEFAULT", "CASCADE"};
+
+GdaDdlFkey *
+gda_ddl_fkey_new (void)
+{
+ return g_object_new (GDA_TYPE_DDL_FKEY, NULL);
+}
+
+static void
+gda_ddl_fkey_finalize (GObject *object)
+{
+ GdaDdlFkey *self = GDA_DDL_FKEY(object);
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ if (priv->mp_field) g_list_free_full (priv->mp_field, g_free);
+ if (priv->mp_ref_field) g_list_free_full (priv->mp_ref_field, g_free);
+
+ g_free(priv->mp_ref_table);
+
+ G_OBJECT_CLASS (gda_ddl_fkey_parent_class)->finalize (object);
+}
+
+static void
+gda_ddl_fkey_class_init (GdaDdlFkeyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gda_ddl_fkey_finalize;
+}
+
+static void
+gda_ddl_fkey_init (GdaDdlFkey *self)
+{
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ priv->mp_field = NULL;
+ priv->mp_ref_field = NULL;
+ priv->mp_ref_table = NULL;
+
+ priv->m_onupdate = GDA_DDL_FKEY_NO_ACTION;
+ priv->m_ondelete = GDA_DDL_FKEY_NO_ACTION;
+}
+
+/**
+ * gda_ddl_fkey_get_ondelete:
+ * @self: An object #GdaDdlFkey
+ *
+ * Return: ON DELETE action as a string
+ *
+ * Since: 6.0
+ */
+const gchar *
+gda_ddl_fkey_get_ondelete (GdaDdlFkey *self)
+{
+ g_return_val_if_fail (self,NULL);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return OnAction[priv->m_ondelete];
+}
+
+/**
+ * gda_ddl_fkey_get_ondelete_id:
+ *
+ * Return: ON DELETE action as a #GdaDdlFkeyReferenceAction
+ *
+ * Since: 6.0
+ */
+GdaDdlFkeyReferenceAction
+gda_ddl_fkey_get_ondelete_id (GdaDdlFkey *self)
+{
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return priv->m_ondelete;
+}
+
+/**
+ * gda_ddl_fkey_set_onupdate:
+ * @sefl: An object #GdaDdlFkey
+ * @id: Action to set
+ *
+ * Set action for ON UPDATE
+ *
+ */
+void
+gda_ddl_fkey_set_onupdate (GdaDdlFkey *self,
+ GdaDdlFkeyReferenceAction id)
+{
+ g_return_if_fail (self);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ priv->m_onupdate = id;
+}
+
+/**
+ * gda_ddl_fkey_set_ondelete:
+ * @sefl: An object #GdaDdlFkey
+ * @id: Action to set
+ *
+ * Set action for ON DELETE
+ *
+ */
+void
+gda_ddl_fkey_set_ondelete (GdaDdlFkey *self,
+ GdaDdlFkeyReferenceAction id)
+{
+ g_return_if_fail (self);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ priv->m_ondelete = id;
+}
+
+
+/**
+ * gda_ddl_fkey_get_onupdate:
+ *
+ * Return: ON UPDATE action as a string
+ *
+ * Since: 6.0
+ */
+const gchar *
+gda_ddl_fkey_get_onupdate (GdaDdlFkey *self)
+{
+ g_return_val_if_fail (self,NULL);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return OnAction[priv->m_onupdate];
+}
+
+/**
+ * gda_ddl_fkey_get_onupdate_id:
+ *
+ * Return: ON UPDATE action as a #GdaDdlFkeyReferenceAction
+ *
+ * Since: 6.0
+ */
+GdaDdlFkeyReferenceAction
+gda_ddl_fkey_get_onupdate_id (GdaDdlFkey *self)
+{
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return priv->m_onupdate;
+}
+
+
+/**
+ * gda_ddl_fkey_get_ref_table:
+ *
+ * Return: Returns reference table name as a string
+ *
+ * Since: 6.0
+ */
+const gchar *
+gda_ddl_fkey_get_ref_table (GdaDdlFkey *self)
+{
+ g_return_val_if_fail (self, NULL);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return priv->mp_ref_table;
+}
+
+/**
+ * gda_ddl_fkey_set_ref_table:
+ * @self: #GdaDdlFkey object
+ * @rtable: reference table name
+ *
+ * Set reference table
+ *
+ * Since: 6.0
+ */
+void
+gda_ddl_fkey_set_ref_table (GdaDdlFkey *self,
+ const gchar *rtable)
+{
+ g_return_if_fail (self);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+ g_free (priv->mp_ref_table);
+
+ priv->mp_ref_table = g_strdup (rtable);
+}
+
+/**
+ * gda_ddl_fkey_get_field_name:
+ *
+ * Returns: A list of strings where each string corresponds to a foregin key field.
+ *
+ * Since: 6.0
+ */
+const GList *
+gda_ddl_fkey_get_field_name (GdaDdlFkey *self)
+{
+ g_return_val_if_fail (self, NULL);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return priv->mp_field;
+}
+
+/**
+ * gda_ddl_fkey_get_ref_field:
+ *
+ * Returns: A list of strings where each string corresponds to a foregin key reference field.
+ *
+ * Since: 6.0
+ */
+const GList *
+gda_ddl_fkey_get_ref_field (GdaDdlFkey *self)
+{
+ g_return_val_if_fail (self,NULL);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ return priv->mp_ref_field;
+}
+
+/**
+ * gda_ddl_fkey_parse_node:
+ *
+ * @self: #GdaDdlFkey object
+ * @node: xml node to parse as #xmlNodePtr
+ * @error: #GError object to store error
+ *
+ * Use this method to populate corresponding #GdaDdlFkey object from xml node. Usually,
+ * this method is called from #GdaDdlCreator suring parsing the imput xml file.
+ *
+ * The corresponding DTD section suitable for parsing by this method should correspond
+ * th the following code:
+ *
+ * |[<!-- language="dtd" -->
+ * <!ELEMENT fkey (fk_field?)>
+ * <!ATTLIST fkey reftable IDREF #IMPLIED>
+ * <!ATTLIST fkey onupdate (RESTRICT|CASCADE|SET_NULL|NO_ACTION|SET_DEFAULT) #IMPLIED>
+ * <!ATTLIST fkey ondelete (RESTRICT|CASCADE|SET_NULL|NO_ACTION|SET_DEFAULT) #IMPLIED>
+ *
+ * <!ELEMENT fk_field (#PCDATA)>
+ * <!ATTLIST fk_field name IDREF #REQUIRED>
+ * <!ATTLIST fk_field reffield IDREF #REQUIRED>
+ * ]|
+ *
+ * Returns: %FALSE if an error occures, %TRUE otherwise
+ *
+ * Since: 6.0
+ */
+gboolean
+gda_ddl_fkey_parse_node (GdaDdlFkey *self,
+ xmlNodePtr node,
+ GError **error)
+{
+ g_return_val_if_fail (self, FALSE);
+ g_return_val_if_fail (node, FALSE);
+// g_return_val_if_fail(!*error, FALSE);
+ /*
+ * <fkey reftable="products" onupdate="NO_ACTION" ondelete="NO_ACTION">
+ * <fk_field name="column_name" reffield="column_name"/>
+ * <fk_field name="column_id" reffield="column_"/>
+ * </fkey>
+ * */
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+ xmlChar *prop = NULL;
+
+ prop = xmlGetProp (node,(xmlChar *)"reftable");
+
+ g_assert (prop); /* Bug with xml valdation */
+
+ priv->mp_ref_table = g_strdup ((gchar *)prop);
+ xmlFree (prop);
+ prop = NULL;
+
+ prop = xmlGetProp (node,(xmlChar *)"onupdate");
+
+ g_assert(prop);
+
+ priv->m_onupdate = GDA_DDL_FKEY_NO_ACTION;
+
+ for (guint i = 0; i < G_N_ELEMENTS(OnAction);i++) {
+ if (!g_strcmp0 (prop,OnAction[i]))
+ priv->m_onupdate = (GdaDdlFkeyReferenceAction)i;
+ }
+
+ xmlFree (prop);
+ prop = NULL;
+
+ prop = xmlGetProp (node,(xmlChar *)"ondelete");
+
+ g_assert(prop);
+
+ for (guint i = 0; i < G_N_ELEMENTS(OnAction);i++) {
+ if (!g_strcmp0 (prop,OnAction[i]))
+ priv->m_ondelete = (GdaDdlFkeyReferenceAction)i;
+ }
+
+ xmlFree (prop);
+ prop = NULL;
+
+ xmlChar *name = NULL;
+ xmlChar *reffield = NULL;
+
+ for (xmlNodePtr it = node->children; it; it = it->next) {
+ if (!g_strcmp0 ((gchar *)it->name, "fk_field")) {
+ name = xmlGetProp (it,(xmlChar *)"name");
+
+ g_assert(name);
+ priv->mp_field = g_list_append (priv->mp_field,
+ g_strdup ((const gchar *)name));
+ xmlFree (name);
+
+ reffield = xmlGetProp (it, (xmlChar *)"reffield");
+ g_assert(reffield);
+ priv->mp_ref_field = g_list_append (priv->mp_ref_field,
+ g_strdup ((const gchar *)reffield));
+ xmlFree (reffield);
+ } /* end of if */
+ } /* end of for loop */
+ return TRUE;
+}
+
+/**
+ * gda_ddl_fkey_free:
+ *
+ * Convenient method to free the object. It is a wrap around g_clear_object()
+ *
+ * Since: 6.0
+ */
+void
+gda_ddl_fkey_free (GdaDdlFkey *self)
+{
+ g_clear_object (&self);
+}
+
+
+/**
+ * gda_ddl_fkey_set_field:
+ *
+ * @self: An object #GdaDdlFkey
+ * @field: Field name as a string
+ * @reffield: A reference field name as a string
+ *
+ * Returns:
+ */
+void
+gda_ddl_fkey_set_field (GdaDdlFkey *self,
+ const gchar *field,
+ const gchar *reffield)
+{
+ g_return_if_fail (self);
+ g_return_if_fail (field);
+ g_return_if_fail (reffield);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ priv->mp_field = g_list_append (priv->mp_field,(gpointer)field);
+ priv->mp_ref_field = g_list_append(priv->mp_ref_field,(gpointer)reffield);
+}
+
+/**
+ * gda_ddl_fkey_write_xml:
+ * @self: An object #GdaDdlFkey
+ * @writer: An object to #xmlTextWriterPtr instance
+ * @error: A place to store error
+ *
+ * An appropriate encoding and version should be placed to the writer before
+ * it is used. This method will not add any header, just populate appropriate
+ * fields in the xml tree. The new xml block should be something like:
+ *
+ * |[<!-- language="xml" -->
+ * <fkey reftable="products" onupdate="NO_ACTION" ondelete="NO_ACTION">
+ * <fk_field name="column_namefk1" reffield="column_name1"/>
+ * <fk_field name="column_namefk2" reffield="column_name2"/>
+ * <fk_field name="column_namefk3" reffield="column_name3"/>
+ * </fkey>
+ *]|
+ * Returns: TRUE if no error, FALSE otherwise
+ */
+gboolean
+gda_ddl_fkey_write_xml (GdaDdlFkey *self,
+ xmlTextWriterPtr writer,
+ GError **error)
+{
+ g_return_val_if_fail (self, FALSE);
+ g_return_val_if_fail (writer, FALSE);
+
+ GdaDdlFkeyPrivate *priv = gda_ddl_fkey_get_instance_private (self);
+
+ int res = 0;
+
+ res = xmlTextWriterStartElement(writer, BAD_CAST "fkey");
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_START_ELEMENT,
+ _("Can't set start element <fkey> in xml tree\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterWriteAttribute (writer,"reftable",(xmlChar*)priv->mp_ref_table);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ _("Can't set reftable attribute to element <fkey>\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterWriteAttribute (writer,"onupdate",(xmlChar*)OnAction[priv->m_onupdate]);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ _("Can't set onupdate attribute to element <fkey>\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterWriteAttribute (writer,"ondelete",(xmlChar*)OnAction[priv->m_ondelete]);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ _("Can't set ondelete attribute to element <fkey>\n"));
+ return FALSE;
+ }
+
+ GList *it = priv->mp_field;
+ GList *jt = priv->mp_ref_field;
+
+ for (; it && jt; it = it->next, jt=jt->next ) {
+ res = xmlTextWriterStartElement(writer, BAD_CAST "fk_field");
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_START_ELEMENT,
+ _("Can't set start element <fk_field> in xml tree\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterWriteAttribute (writer,"name",(xmlChar*)it->data);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ _("Can't set ondelete attribute to element <fk_field>\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterWriteAttribute (writer,"reffield",(xmlChar*)jt->data);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ _("Can't set ondelete attribute to element <fk_field>\n"));
+ return FALSE;
+ }
+
+ res = xmlTextWriterEndElement (writer);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_END_ELEMENT,
+ _("Can't close element <fk_field>\n"));
+ return FALSE;
+ }
+ }
+
+ res = xmlTextWriterEndElement (writer);
+
+ if (res < 0) {
+ g_set_error (error,
+ GDA_DDL_FKEY_ERROR,
+ GDA_DDL_FKEY_ERROR_END_ELEMENT,
+ _("Can't close element <fkey>\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
diff --git a/libgda/gda-ddl-fkey.h b/libgda/gda-ddl-fkey.h
new file mode 100644
index 000000000..71d1258c9
--- /dev/null
+++ b/libgda/gda-ddl-fkey.h
@@ -0,0 +1,100 @@
+/* gda-ddl-fkey.h
+ *
+ * Copyright © 2018 Pavlo Solntsev <pavlo solntsev gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GDA_DDL_FKEY_H
+#define GDA_DDL_FKEY_H
+
+#include <glib-object.h>
+#include <gmodule.h>
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/xmlwriter.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DDL_FKEY (gda_ddl_fkey_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GdaDdlFkey, gda_ddl_fkey, GDA, DDL_FKEY, GObject)
+
+struct _GdaDdlFkeyClass {
+ GObjectClass parent_class;
+};
+
+typedef enum {
+ GDA_DDL_FKEY_NO_ACTION,
+ GDA_DDL_FKEY_SET_NULL,
+ GDA_DDL_FKEY_RESTRICT,
+ GDA_DDL_FKEY_SET_DEFAULT,
+ GDA_DDL_FKEY_CASCADE
+} GdaDdlFkeyReferenceAction;
+
+typedef enum {
+ GDA_DDL_FKEY_ERROR_START_ELEMENT,
+ GDA_DDL_FKEY_ERROR_ATTRIBUTE,
+ GDA_DDL_FKEY_ERROR_END_ELEMENT
+}GdaDdlFkeyError;
+
+#define GDA_DDL_FKEY_ERROR gda_ddl_fkey_error_quark()
+GQuark gda_ddl_fkey_error_quark (void);
+
+/**
+ * SECTION:gda-ddl-fkey
+ * @short_description: Object to hold information for foregn key.
+ * @stability: Stable
+ * @include: libgda.h
+ *
+ * For generating database from xml file or for mapping
+ * database to an xml file #GdaDdlFkey holds information about
+ * foregn keys with a convenient set of methods to manipulate them.
+ */
+
+GdaDdlFkey* gda_ddl_fkey_new (void);
+
+const GList* gda_ddl_fkey_get_field_name (GdaDdlFkey *self);
+const GList* gda_ddl_fkey_get_ref_field (GdaDdlFkey *self);
+
+void gda_ddl_fkey_set_field (GdaDdlFkey *self,
+ const gchar
*field,
+ const gchar
*reffield);
+
+const gchar* gda_ddl_fkey_get_ref_table (GdaDdlFkey *self);
+void gda_ddl_fkey_set_ref_table (GdaDdlFkey *self,
+ const gchar
*rtable);
+
+const gchar* gda_ddl_fkey_get_ondelete (GdaDdlFkey *self);
+GdaDdlFkeyReferenceAction gda_ddl_fkey_get_ondelete_id (GdaDdlFkey *self);
+void gda_ddl_fkey_set_ondelete (GdaDdlFkey *self,
+
GdaDdlFkeyReferenceAction id);
+
+const gchar* gda_ddl_fkey_get_onupdate (GdaDdlFkey *self);
+GdaDdlFkeyReferenceAction gda_ddl_fkey_get_onupdate_id (GdaDdlFkey *self);
+void gda_ddl_fkey_set_onupdate (GdaDdlFkey *self,
+
GdaDdlFkeyReferenceAction id);
+gboolean gda_ddl_fkey_parse_node (GdaDdlFkey *self,
+ xmlNodePtr
node,
+ GError
**error);
+
+gboolean gda_ddl_fkey_write_xml (GdaDdlFkey *self,
+
xmlTextWriterPtr writer,
+ GError
**error);
+
+void gda_ddl_fkey_free (GdaDdlFkey *self);
+
+G_END_DECLS
+
+#endif /* GDA_DDL_FKEY_H */
+
diff --git a/tests/ddl/Makefile.am b/tests/ddl/Makefile.am
index d80b69b9d..8233e0e11 100644
--- a/tests/ddl/Makefile.am
+++ b/tests/ddl/Makefile.am
@@ -9,9 +9,16 @@ AM_CPPFLAGS = \
-DROOT_DIR=\""$(top_srcdir)"\"
test_programs = \
- check_ddl_base
+ check_ddl_base \
+ check_ddl_fkey
check_ddl_base_SOURCES = check-ddl-base.c
check_ddl_base_LDADD = \
$(top_builddir)/libgda/libgda-6.0.la \
$(COREDEPS_LIBS)
+
+check_ddl_fkey_SOURCES = check-ddl-fkey.c
+check_ddl_fkey_LDADD = \
+ $(top_builddir)/libgda/libgda-6.0.la \
+ $(COREDEPS_LIBS)
+
diff --git a/tests/ddl/check-ddl-fkey.c b/tests/ddl/check-ddl-fkey.c
new file mode 100644
index 000000000..56efdd6c0
--- /dev/null
+++ b/tests/ddl/check-ddl-fkey.c
@@ -0,0 +1,219 @@
+/* check-ddl-creator.c
+ *
+ * Copyright 2018 Pavlo Solntsev <p sun fun gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <locale.h>
+#include <libgda/libgda.h>
+#include <libgda/gda-ddl-fkey.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlwriter.h>
+
+typedef struct {
+ GdaDdlFkey *fkey;
+
+ GList *fkfield;
+ GList *reffield;
+
+ gchar *xmlfile;
+ gchar *reftable;
+ gchar *onupdate;
+ gchar *ondelete;
+
+ xmlDocPtr doc;
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buffer;
+} CheckDdlObject;
+
+static void
+test_ddl_fkey_run2 (CheckDdlObject *self,
+ gconstpointer user_data)
+{
+ const gchar *reftable = NULL;
+
+ reftable = gda_ddl_fkey_get_ref_table (self->fkey);
+
+ g_assert_cmpstr (reftable, ==, self->reftable);
+
+ const GList *fkfield = NULL;
+
+ fkfield = gda_ddl_fkey_get_field_name (self->fkey);
+
+ g_assert_nonnull (fkfield);
+
+ const GList *it = NULL;
+ GList *jt = NULL;
+
+ for (it = fkfield, jt = self->fkfield; it && jt; it = it->next, jt = jt->next)
+ g_assert_cmpstr (it->data, ==, jt->data);
+
+ const GList *reffield = NULL;
+
+ reffield = gda_ddl_fkey_get_ref_field(self->fkey);
+
+ g_assert_nonnull (reffield);
+
+ for (it = reffield, jt = self->reffield; it && jt; it = it->next, jt = jt->next)
+ g_assert_cmpstr(it->data, ==, jt->data);
+
+ const gchar *onupdate = gda_ddl_fkey_get_onupdate (self->fkey);
+
+ g_assert_cmpstr(onupdate, ==, self->onupdate);
+
+ const gchar *ondelete = gda_ddl_fkey_get_ondelete (self->fkey);
+
+ g_assert_cmpstr(ondelete, ==, self->ondelete);
+}
+
+static void
+test_ddl_fkey_run1 (void)
+{
+ GdaDdlFkey *self = gda_ddl_fkey_new ();
+
+ gda_ddl_fkey_free (self);
+}
+
+static void
+test_ddl_fkey_run3 (CheckDdlObject *self,
+ gconstpointer user_data)
+{
+ int res = gda_ddl_fkey_write_xml (self->fkey,self->writer,NULL);
+
+ g_assert_true (res >= 0);
+
+// res = xmlTextWriterEndDocument (self->writer);
+
+// g_assert_true (res >= 0);
+ xmlFreeTextWriter (self->writer);
+
+ g_print ("%s\n",(gchar*)self->buffer->content);
+}
+
+static void
+test_ddl_fkey_start (CheckDdlObject *self,
+ gconstpointer user_data)
+{
+ self->doc = NULL;
+ self->xmlfile = NULL;
+ self->fkey = NULL;
+ self->reffield = NULL;
+ self->fkfield = NULL;
+ self->reftable = NULL;
+ self->onupdate = NULL;
+ self->ondelete = NULL;
+
+ self->reffield = g_list_append (self->reffield,"column_name1");
+ self->reffield = g_list_append (self->reffield,"column_name2");
+ self->reffield = g_list_append (self->reffield,"column_name3");
+
+ self->fkfield = g_list_append(self->fkfield,"column_namefk1");
+ self->fkfield = g_list_append(self->fkfield,"column_namefk2");
+ self->fkfield = g_list_append(self->fkfield,"column_namefk3");
+
+ self->reftable = g_strdup ("products");
+ self->onupdate = g_strdup("NO ACTION");
+ self->ondelete = g_strdup("NO ACTION");
+
+ const gchar *topsrcdir = g_getenv ("GDA_TOP_SRC_DIR");
+
+ g_print ("ENV: %s\n",topsrcdir);
+ g_assert_nonnull (topsrcdir);
+
+ self->xmlfile = g_build_filename(topsrcdir,
+ "tests",
+ "ddl",
+ "fkey_test.xml",NULL);
+
+ g_assert_nonnull (self->xmlfile);
+
+ self->doc = xmlParseFile(self->xmlfile);
+ g_assert_nonnull (self->doc);
+
+ xmlNodePtr node = xmlDocGetRootElement (self->doc);
+ g_assert_nonnull (node);
+
+ self->fkey = gda_ddl_fkey_new ();
+
+ g_assert_nonnull(self->fkey);
+
+ gboolean res = gda_ddl_fkey_parse_node (self->fkey,
+ node,
+ NULL);
+ g_assert_true (res);
+
+ self->buffer = xmlBufferCreate ();
+
+ g_assert_nonnull (self->buffer);
+
+ self->writer = xmlNewTextWriterMemory (self->buffer,0);
+
+ g_assert_nonnull (self->writer);
+
+ res = xmlTextWriterStartDocument (self->writer, NULL, NULL, NULL);
+
+ g_assert_true (res >= 0);
+}
+
+static void
+test_ddl_fkey_finish (CheckDdlObject *self,
+ gconstpointer user_data)
+{
+ g_free (self->xmlfile);
+ gda_ddl_fkey_free (self->fkey);
+ xmlFreeDoc (self->doc);
+ g_list_free (self->reffield);
+ g_list_free (self->fkfield);
+ g_free (self->reftable);
+ g_free (self->ondelete);
+ g_free (self->onupdate);
+
+
+ xmlBufferFree (self->buffer);
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ setlocale (LC_ALL,"");
+
+ g_test_init (&argc,&argv,NULL);
+
+ g_test_add_func ("/test-ddl/fkey-basic",
+ test_ddl_fkey_run1);
+
+ g_test_add ("/test-ddl/fkey-parse",
+ CheckDdlObject,
+ NULL,
+ test_ddl_fkey_start,
+ test_ddl_fkey_run2,
+ test_ddl_fkey_finish);
+
+ g_test_add ("/test-ddl/fkey-write",
+ CheckDdlObject,
+ NULL,
+ test_ddl_fkey_start,
+ test_ddl_fkey_run3,
+ test_ddl_fkey_finish);
+
+ return g_test_run();
+}
diff --git a/tests/ddl/fkey_test.xml b/tests/ddl/fkey_test.xml
new file mode 100644
index 000000000..2c1b8d5fb
--- /dev/null
+++ b/tests/ddl/fkey_test.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fkey reftable="products" onupdate="NO_ACTION" ondelete="NO_ACTION">
+ <fk_field name="column_namefk1" reffield="column_name1"/>
+ <fk_field name="column_namefk2" reffield="column_name2"/>
+ <fk_field name="column_namefk3" reffield="column_name3"/>
+</fkey>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]