[libgda] make gda_sql_builder_select_add_target_id() return an already existing ID



commit 4797dc40c3452e4debd6ae3d989955a138b0830d
Author: Vivien Malerba <malerba gnome-db org>
Date:   Mon May 24 17:14:16 2010 +0200

    make gda_sql_builder_select_add_target_id() return an already existing ID
    
    
    in case a target with the same characteristics as the one to add is
    already present

 libgda/gda-sql-builder.c |   38 +++++++++++++++++++++++++++++--
 tests/test-sql-builder.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 3 deletions(-)
---
diff --git a/libgda/gda-sql-builder.c b/libgda/gda-sql-builder.c
index d44345c..6e21885 100644
--- a/libgda/gda-sql-builder.c
+++ b/libgda/gda-sql-builder.c
@@ -1035,9 +1035,11 @@ typedef struct {
  * @table_id: the ID of the expression holding a table reference (not %0)
  * @alias: the alias to give to the target, or %NULL
  *
- * Adds a new target to a SELECT statement
+ * Adds a new target to a SELECT statement. If there already exists a target representing
+ * the same table and the same alias (or with the same absence of alias) then the same target
+ * ID is returned instead of the ID of a new target.
  *
- * Returns: the ID of the new target, or 0 if there was an error
+ * Returns: the ID of the new (or existing) target, or 0 if there was an error
  *
  * Since: 4.2
  */
@@ -1057,9 +1059,39 @@ gda_sql_builder_select_add_target_id (GdaSqlBuilder *builder, guint table_id, co
 	if (!p)
 		return 0;
 
+	/* check for an already existing target with the same characteristics */
+	GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+	if (sel->from) {
+		gchar *ser;
+		GSList *list;
+
+		g_assert (p->part->type == GDA_SQL_ANY_EXPR);
+		ser = gda_sql_expr_serialize ((GdaSqlExpr*) p->part);
+		for (list = sel->from->targets; list; list = list->next) {
+			BuildTarget *bt = (BuildTarget*) list->data;
+			GdaSqlSelectTarget *t = (GdaSqlSelectTarget*) list->data;
+			gboolean idalias = FALSE;
+			if (alias && t->as && !strcmp (t->as, alias))
+				idalias = TRUE;
+			else if (!alias && ! t->as)
+				idalias = TRUE;
+			
+			gchar *tmp;
+			tmp = gda_sql_expr_serialize (t->expr);
+			if (! strcmp (ser, tmp)) {
+				if (idalias) {
+					g_free (tmp);
+					g_free (ser);
+					return bt->part_id;
+				}
+			}
+			g_free (tmp);
+		}
+		g_free (ser);
+	}
+
 	BuildTarget *btarget;
 	GdaSqlSelectTarget *target;
-	GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
 	btarget = g_new0 (BuildTarget, 1);
         GDA_SQL_ANY_PART (btarget)->type = GDA_SQL_ANY_SQL_SELECT_TARGET;
         GDA_SQL_ANY_PART (btarget)->parent = GDA_SQL_ANY_PART (sel->from);
diff --git a/tests/test-sql-builder.c b/tests/test-sql-builder.c
index 163c0fd..3c849e3 100644
--- a/tests/test-sql-builder.c
+++ b/tests/test-sql-builder.c
@@ -44,6 +44,8 @@ static GdaSqlStatement *build10 (void);
 static GdaSqlStatement *build11 (void);
 static GdaSqlStatement *build12 (void);
 
+static gboolean builder_test_target_id (void);
+
 ATest tests[] = {
 	{"build0", build0, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"false\",\"fields\":[{\"expr\":{\"value\":\"*\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]}}}"},
 	{"build1", build1, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"false\",\"fields\":[{\"expr\":{\"value\":\"contents\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"descr\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"name\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]},\"where\":{\"operation\":{\"operator\":\"AND\",\"operand0\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"session\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"session\",\"descr\":null,\"type\":\"string\",\"is_param\":true,\"nullok\":false}}}},\"operand1\":{\"operation\":{\"operator\":\"AND\",\"operand0\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"type\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":\"'TABLE'\"}}},\"operand1\":{\"operation\":{\"operator\":\"=\",\"operand0\":{
 \"value\":\"name\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":\"'alf'\"}}}}}}}}}"},
@@ -116,6 +118,9 @@ main (int argc, char** argv)
 			nfailed++;
 	}
 
+	if (! builder_test_target_id ())
+		nfailed++;
+
 	g_print ("%d tests executed, ", i);
 	if (nfailed > 0)
 		g_print ("%d failed\n", nfailed);
@@ -546,3 +551,52 @@ build12 (void)
 	g_object_unref (b);
 	return stmt;
 }
+
+/*
+ * 
+ */
+static gboolean
+builder_test_target_id (void)
+{
+	GdaSqlBuilder *builder;
+	guint id1, id2;
+	gboolean allok = TRUE;
+
+	builder = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+	gda_sql_builder_add_field_id (builder,
+				      gda_sql_builder_add_id (builder, "*"), 0);
+	/* same target with aliases */
+	id1 = gda_sql_builder_select_add_target_id (builder,
+						    gda_sql_builder_add_id (builder, "mytable"), "alias");
+	id2 = gda_sql_builder_select_add_target_id (builder,
+						    gda_sql_builder_add_id (builder, "mytable"), "alias");
+	if (id1 != id2) {
+		g_print ("identical targets with an alias not recognized as same target.\n");
+		allok = FALSE;
+	}
+
+	id2 = gda_sql_builder_select_add_target_id (builder,
+						    gda_sql_builder_add_id (builder, "mytable"), "alias2");
+	if (id1 == id2) {
+		g_print ("identical tables with different alias recognized as same target.\n");
+		allok = FALSE;
+	}
+
+	id2 = gda_sql_builder_select_add_target_id (builder,
+						    gda_sql_builder_add_id (builder, "mytable"), NULL);
+	if (id1 == id2) {
+		g_print ("identical tables with no alias recognized as same target.\n");
+		allok = FALSE;
+	}
+
+	id1 = gda_sql_builder_select_add_target_id (builder,
+						    gda_sql_builder_add_id (builder, "mytable"), NULL);
+	if (id1 != id2) {
+		g_print ("identical tables with different alias not recognized as same target.\n");
+		allok = FALSE;
+	}
+
+	g_object_unref (builder);
+	
+	return allok;
+}



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