From 8747921d63975ed0b3da0a3e42d4c9bd3bf6f8d4 Mon Sep 17 00:00:00 2001
From: Andrea Zagli <azagli@libero.it>
Date: Sun, 26 Apr 2020 11:16:32 +0200
Subject: [PATCH] Added function GdaEx::data_model_copy_insert.

---
 .gitignore           |   1 +
 src/gdaex.c          | 120 +++++++++++++++++++++++++++++++++++++++++++
 src/gdaex.h          |   9 ++++
 tests/Makefile.am    |   1 +
 tests/copydminsert.c | 104 +++++++++++++++++++++++++++++++++++++
 5 files changed, 235 insertions(+)
 create mode 100644 tests/copydminsert.c

diff --git a/.gitignore b/.gitignore
index ba749cc..0a148f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@ po/libgdaex.pot
 *.bak
 intltool*
 libgdaex*tar*
+tests/copydminsert
 tests/doubletosql
 tests/test_prefix*
 tests/query_editor
diff --git a/src/gdaex.c b/src/gdaex.c
index 26cbf7a..8d44e9a 100644
--- a/src/gdaex.c
+++ b/src/gdaex.c
@@ -39,6 +39,7 @@
 #include <libgda/gda-blob-op.h>
 
 #include "gdaex.h"
+#include "sqlbuilder.h"
 
 static guint debug;
 static gchar *log_file;
@@ -2719,6 +2720,125 @@ GtkTreeStore
 	return ret;
 }
 
+/**
+ * gdaex_data_model_copy_insert:
+ * @src_gdaex:
+ * @src_table:
+ * @src_ht_key
+ * @src_ht_exclude:
+ * @dst_gdaex:
+ * @dst_table:
+ *
+ * Insert a copy of a datamodel row into another datamodel.
+ */
+void
+gdaex_data_model_copy_insert (GdaEx *src_gdaex,
+                              const gchar *src_table,
+                              GHashTable *src_ht_key,
+                              GHashTable *src_ht_exclude,
+                              GdaEx *dst_gdaex,
+                              const gchar *dst_table)
+{
+	GdaDataModel *src_dm;
+	GdaExSqlBuilder *sqlb;
+
+	gchar *_src_table;
+	gchar *_dst_table;
+
+	GHashTableIter iter;
+	gpointer key;
+	gpointer value;
+
+	guint cols;
+	guint col;
+
+	const gchar *field_name;
+	GValue *gval;
+
+	g_return_if_fail (IS_GDAEX (src_gdaex));
+	g_return_if_fail (IS_GDAEX (dst_gdaex));
+	g_return_if_fail (src_table != NULL);
+	g_return_if_fail (src_ht_key != NULL);
+
+	_src_table = g_strstrip (g_strdup (src_table));
+
+	g_return_if_fail (g_strcmp0 (_src_table, "") != 0);
+
+	g_return_if_fail (g_hash_table_size (src_ht_key) > 0);
+
+	sqlb = gdaex_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+
+	gdaex_sql_builder_from (sqlb, _src_table, "");
+
+	gdaex_sql_builder_field (sqlb, _src_table, "*", NULL, NULL);
+
+	g_hash_table_iter_init (&iter, src_ht_key);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		{
+			gdaex_sql_builder_where (sqlb, 0,
+			                         _src_table, (gchar *)key, "",
+			                         GDA_SQL_OPERATOR_TYPE_EQ,
+			                         (GValue *)value,
+			                         NULL);
+		}
+
+	src_dm = gdaex_sql_builder_query (sqlb, src_gdaex, NULL);
+	if (gdaex_data_model_is_empty (src_dm))
+		{
+			g_warning ("Nothing to copy.");
+			return;
+		}
+
+	/* if dst_table is null or empty, we use the same name as source table */
+	if (dst_table == NULL)
+		{
+			_dst_table = g_strdup (_src_table);
+		}
+	else
+		{
+			_dst_table = g_strstrip (g_strdup (dst_table));
+			if (g_strcmp0 (_dst_table, "") == 0)
+				{
+					g_free (_dst_table);
+					_dst_table = g_strdup (_src_table);
+				}
+		}
+
+	sqlb = gdaex_sql_builder_new (GDA_SQL_STATEMENT_INSERT);
+
+	gdaex_sql_builder_from (sqlb, _dst_table, "");
+
+	cols = gda_data_model_get_n_columns (src_dm);
+	for (col = 0; col < cols; col++)
+		{
+			gval = NULL;
+
+			field_name = gda_data_model_get_column_name (src_dm, col);
+			if (src_ht_exclude != NULL)
+				{
+					if (g_hash_table_lookup_extended (src_ht_exclude,
+					                                  (gconstpointer)field_name,
+					                                  NULL,
+					                                  &gval))
+						{
+							if (gval == NULL)
+								{
+									continue;
+								}
+						}
+				}
+
+			if (gval == NULL)
+				{
+					gval = gda_data_model_get_value_at (src_dm, col, 0, NULL);
+				}
+
+			gdaex_sql_builder_field (sqlb, _dst_table, field_name, "", gval);
+		}
+
+	gdaex_sql_builder_execute (sqlb, dst_gdaex, NULL);
+}
+
 /**
  * gdaex_begin:
  * @gdaex: a #GdaEx object.
diff --git a/src/gdaex.h b/src/gdaex.h
index 373de42..dc92271 100644
--- a/src/gdaex.h
+++ b/src/gdaex.h
@@ -207,6 +207,15 @@ GtkListStore *gdaex_data_model_to_gtkliststore (GdaDataModel *dm,
 GtkTreeStore *gdaex_data_model_to_gtktreestore (GdaDataModel *dm,
                                                 gboolean only_schema);
 
+
+void gdaex_data_model_copy_insert (GdaEx *src_gdaex,
+                                   const gchar *src_table,
+                                   GHashTable *src_ht_key,
+                                   GHashTable *src_ht_exclude,
+                                   GdaEx *dst_gdaex,
+                                   const gchar *dst_table);
+
+
 gboolean gdaex_begin (GdaEx *gdaex);
 
 gint gdaex_execute (GdaEx *gdaex, const gchar *sql);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 28f2b22..589b1c1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = $(GDAEX_CFLAGS) \
               -DTESTSDIR="\"@abs_builddir@\""
 
 noinst_PROGRAMS = \
+                  copydminsert \
                   doubletosql \
                   fill_liststore \
                   getsqlfromhashtable \
diff --git a/tests/copydminsert.c b/tests/copydminsert.c
new file mode 100644
index 0000000..cd2d987
--- /dev/null
+++ b/tests/copydminsert.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 Andrea Zagli <azagli@libero.it>
+ *
+ *  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 2 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+#include <libzakutils/libzakutils.h>
+
+#include <libgdaex.h>
+
+static gchar *src_cnc = NULL;
+static gchar *src_table = NULL;
+static gchar *key_name = NULL;
+static guint key_value = 0;
+static gchar *dst_cnc = NULL;
+static gchar *dst_table = NULL;
+static gchar *exclude_name = NULL;
+static gchar *exclude_value = NULL;
+
+static GOptionEntry entries[] =
+{
+	{ "src-cnc-string", 0, 0, G_OPTION_ARG_STRING, &src_cnc, "Connection string for source db", NULL },
+	{ "src-table", 0, 0, G_OPTION_ARG_STRING, &src_table, "Source table", NULL },
+	{ "key-name", 0, 0, G_OPTION_ARG_STRING, &key_name, "Key field name", NULL },
+	{ "key-value", 0, 0, G_OPTION_ARG_INT, &key_value, "Key field value", NULL },
+	{ "dst-cnc-string", 0, 0, G_OPTION_ARG_STRING, &dst_cnc, "Connection string for destination db", NULL },
+	{ "dst-table", 0, 0, G_OPTION_ARG_STRING, &dst_table, "Destination table", NULL },
+	{ "exclude-name", 0, 0, G_OPTION_ARG_STRING, &exclude_name, "Field name to exclude", NULL },
+	{ "exclude-value", 0, 0, G_OPTION_ARG_STRING, &exclude_value, "Field value to replace", NULL },
+	{ NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+	GError *error;
+	GOptionContext *context;
+
+	GdaEx *src_gdaex;
+	GdaEx *dst_gdaex;
+
+	GHashTable *ht_key;
+	GHashTable *ht_exclude;
+
+	context = g_option_context_new ("- test copy_insert");
+	g_option_context_add_main_entries (context, entries, NULL);
+
+	error = NULL;
+	if (!g_option_context_parse (context, &argc, &argv, &error)
+	    || error != NULL)
+		{
+			g_error ("Option parsing failed: %s.", error != NULL && error->message != NULL ? error->message : "no details");
+			return 0;
+		}
+
+	src_gdaex = gdaex_new_from_string (src_cnc);
+	if (src_gdaex == NULL)
+		{
+			g_error ("Unable to connect to the source db.");
+		}
+
+	dst_gdaex = gdaex_new_from_string (dst_cnc);
+	if (dst_gdaex == NULL)
+		{
+			g_error ("Unable to connect to the destination db.");
+		}
+
+	ht_key = g_hash_table_new (g_str_hash, g_str_equal);
+
+	g_hash_table_insert (ht_key,
+	                     g_strdup (key_name),
+	                     zak_utils_gvalue_new_int (key_value));
+
+	ht_exclude = NULL;
+	if (exclude_name != NULL)
+		{
+			ht_exclude = g_hash_table_new (g_str_hash, g_str_equal);
+
+			g_hash_table_insert (ht_exclude, exclude_name, zak_utils_gvalue_new_string (exclude_value));
+		}
+
+	gdaex_data_model_copy_insert (src_gdaex,
+	                              src_table,
+	                              ht_key,
+	                              ht_exclude,
+	                              dst_gdaex,
+	                              dst_table);
+
+	return 0;
+}
-- 
2.49.0