[libgda] Added gda_data_select_compute_modification_statements_ext()



commit 1ad31aa16f0714e976967ce7dd23f8c89e93172b
Author: Vivien Malerba <malerba gnome-db org>
Date:   Fri Aug 5 16:33:34 2011 +0200

    Added gda_data_select_compute_modification_statements_ext()

 doc/C/libgda-sections.txt |    2 +
 libgda/gda-data-proxy.c   |    1 +
 libgda/gda-data-select.c  |   35 ++++++++++++++++-
 libgda/gda-data-select.h  |   16 ++++++++
 libgda/gda-util.c         |   90 ++++++++++++++++++++++++++++++++++++++------
 libgda/libgda.symbols     |    1 +
 6 files changed, 130 insertions(+), 15 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index b4bd955..95fe56c 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -1473,6 +1473,8 @@ gda_data_select_compute_row_selection_condition
 gda_data_select_set_modification_statement
 gda_data_select_set_modification_statement_sql
 gda_data_select_compute_modification_statements
+GdaDataSelectConditionType
+gda_data_select_compute_modification_statements_ext
 gda_data_select_compute_columns_attributes
 gda_data_select_rerun
 gda_data_select_add_exception
diff --git a/libgda/gda-data-proxy.c b/libgda/gda-data-proxy.c
index dca54c4..960a0a9 100644
--- a/libgda/gda-data-proxy.c
+++ b/libgda/gda-data-proxy.c
@@ -1456,6 +1456,7 @@ gda_data_proxy_get_value_attributes (GdaDataProxy *proxy, gint proxy_row, gint c
 
 	gda_mutex_unlock (proxy->priv->mutex);
 
+	/*g_print ("%s (%p, %d, %d) => %d\n", __FUNCTION__, proxy, col, proxy_row, flags);*/
 	return flags;
 }
 
diff --git a/libgda/gda-data-select.c b/libgda/gda-data-select.c
index 6061081..5ac6e7f 100644
--- a/libgda/gda-data-select.c
+++ b/libgda/gda-data-select.c
@@ -1286,6 +1286,9 @@ gda_data_select_set_modification_statement (GdaDataSelect *model, GdaStatement *
 					gda_column_set_g_type (gdacol, gda_holder_get_g_type (holder));
 					coltypeschanged = TRUE;
 				}
+				if (model->prep_stmt && model->prep_stmt->types &&
+				    (model->prep_stmt->types [num] == GDA_TYPE_NULL))
+					model->prep_stmt->types [num] = gda_holder_get_g_type (holder);
 			}
 		}
 
@@ -1357,11 +1360,36 @@ gda_data_select_set_modification_statement (GdaDataSelect *model, GdaStatement *
  * Makes @model try to compute INSERT, UPDATE and DELETE statements to be used when modifying @model's contents.
  * Note: any modification statement set using gda_data_select_set_modification_statement() will first be unset
  *
+ * This function is similar to calling gda_data_select_compute_modification_statements_ext with
+ * @cond_type set to %GDA_DATA_SELECT_COND_PK
+ *
  * Returns: %TRUE if no error occurred. If %FALSE is returned, then some modification statement may still have been computed
  */
 gboolean
 gda_data_select_compute_modification_statements (GdaDataSelect *model, GError **error)
 {
+	return gda_data_select_compute_modification_statements_ext (model, GDA_DATA_SELECT_COND_PK,
+								    error);
+}
+
+/**
+ * gda_data_select_compute_modification_statements_ext:
+ * @model: a #GdaDataSelect data model
+ * @cond_type: the type of condition for the modifications where one row only should be identified
+ * @error: a place to store errors, or %NULL
+ *
+ * Makes @model try to compute INSERT, UPDATE and DELETE statements to be used when modifying @model's contents.
+ * Note: any modification statement set using gda_data_select_set_modification_statement() will first be unset
+ *
+ * Returns: %TRUE if no error occurred. If %FALSE is returned, then some modification statement may still have been computed
+ *
+ * Since: 4.2.9
+ */
+gboolean
+gda_data_select_compute_modification_statements_ext (GdaDataSelect *model,
+						     GdaDataSelectConditionType cond_type,
+						     GError **error)
+{
 	GdaStatement *stmt;
 	ModType mtype;
 	gboolean retval = TRUE;
@@ -1384,10 +1412,12 @@ gda_data_select_compute_modification_statements (GdaDataSelect *model, GError **
 			model->priv->sh->modif_internals->modif_stmts[mtype] = NULL;
 		}
 
-	retval = gda_compute_dml_statements (model->priv->cnc, stmt, TRUE,
+	retval = gda_compute_dml_statements (model->priv->cnc, stmt,
+					     cond_type == GDA_DATA_SELECT_COND_PK ? TRUE : FALSE,
 					     &(modif_stmts[INS_QUERY]),
 					     NULL, NULL, error);
-	retval = gda_compute_dml_statements (model->priv->cnc, stmt, TRUE,
+	retval = gda_compute_dml_statements (model->priv->cnc, stmt,
+					     cond_type == GDA_DATA_SELECT_COND_PK ? TRUE : FALSE,
 					     NULL,
 					     &(modif_stmts[UPD_QUERY]),
 					     &(modif_stmts[DEL_QUERY]), error) && retval;
@@ -1414,6 +1444,7 @@ gda_data_select_compute_modification_statements (GdaDataSelect *model, GError **
 	return retval;
 }
 
+
 static gboolean
 row_selection_condition_foreach_func (GdaSqlAnyPart *part, G_GNUC_UNUSED gpointer data, GError **error)
 {
diff --git a/libgda/gda-data-select.h b/libgda/gda-data-select.h
index 0913e58..e4865b9 100644
--- a/libgda/gda-data-select.h
+++ b/libgda/gda-data-select.h
@@ -50,6 +50,19 @@ typedef enum {
 	GDA_DATA_SELECT_SAFETY_LOCKED_ERROR
 } GdaDataSelectError;
 
+/**
+ * GdaDataSelectConditionType:
+ * @GDA_DATA_SELECT_COND_PK: only primary key fields are used
+ * @GDA_DATA_SELECT_COND_ALL_COLUMNS: all the columns of the tables are used
+ *
+ * Defines what criteria gda_data_select_compute_modification_statements_ext() uses
+ * to uniquely identify a single row in a table when creating modification statements.
+ */
+typedef enum {
+	GDA_DATA_SELECT_COND_PK,
+	GDA_DATA_SELECT_COND_ALL_COLUMNS
+} GdaDataSelectConditionType;
+
 struct _GdaDataSelect {
 	GObject           object;
 	GdaDataSelectPrivate *priv;
@@ -142,6 +155,9 @@ gboolean       gda_data_select_compute_row_selection_condition (GdaDataSelect *m
 gboolean       gda_data_select_set_modification_statement      (GdaDataSelect *model, GdaStatement *mod_stmt, GError **error);
 gboolean       gda_data_select_set_modification_statement_sql  (GdaDataSelect *model, const gchar *sql, GError **error);
 gboolean       gda_data_select_compute_modification_statements (GdaDataSelect *model, GError **error);
+gboolean       gda_data_select_compute_modification_statements_ext (GdaDataSelect *model,
+								    GdaDataSelectConditionType cond_type,
+								    GError **error);
 
 gboolean       gda_data_select_compute_columns_attributes      (GdaDataSelect *model, GError **error);
 GdaConnection *gda_data_select_get_connection                  (GdaDataSelect *model);
diff --git a/libgda/gda-util.c b/libgda/gda-util.c
index 3a36630..92dd59a 100644
--- a/libgda/gda-util.c
+++ b/libgda/gda-util.c
@@ -913,17 +913,16 @@ gda_compute_unique_table_row_condition_with_cnc (GdaConnection *cnc, GdaSqlState
 	GdaSqlOperation *and_cond = NULL;
 
 	g_return_val_if_fail (!cnc || GDA_IS_CONNECTION (cnc), NULL);
-
-	if (mtable->pk_cols_nb == 0) {
-		g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
-			     "%s", _("Table does not have any primary key"));
-		return NULL;
-	}
 	
 	expr = gda_sql_expr_new (NULL); /* no parent */
 	if (require_pk) {
 		if (mtable->pk_cols_nb == 0) {
 			g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+				     "%s", _("Table does not have any primary key"));
+			goto onerror;
+		}
+		if (mtable->pk_cols_nb == 0) {
+			g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
 					     "%s", _("Table does not have any primary key"));
 			goto onerror;
 		}
@@ -937,10 +936,10 @@ gda_compute_unique_table_row_condition_with_cnc (GdaConnection *cnc, GdaSqlState
 			GdaMetaTableColumn *tcol;
 			GSList *list;
 			gint index;
-			
+
 			tcol = (GdaMetaTableColumn *) g_slist_nth_data (mtable->columns, mtable->pk_cols_array[i]);
-			for (index = 0, list = stsel->expr_list; 
-			     list; 
+			for (index = 0, list = stsel->expr_list;
+			     list;
 			     index++, list = list->next) {
 				sfield = (GdaSqlSelectField *) list->data;
 				if (sfield->validity_meta_table_column == tcol)
@@ -950,7 +949,7 @@ gda_compute_unique_table_row_condition_with_cnc (GdaConnection *cnc, GdaSqlState
 			}
 			if (!sfield) {
 				g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
-					     "%s", _("Table's primary key is not selected"));
+					     "%s", _("Table's primary key is not part of SELECT"));
 				goto onerror;
 			}
 			else {
@@ -990,9 +989,74 @@ gda_compute_unique_table_row_condition_with_cnc (GdaConnection *cnc, GdaSqlState
 		}
 	}
 	else {
-		TO_IMPLEMENT;
-		gda_sql_expr_free (expr);
-		expr = NULL;
+		GSList *columns;
+		if (! mtable->columns) {
+			g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+					     "%s", _("Table does not have any column"));
+			goto onerror;
+		}
+		else if (mtable->columns->next) {
+			and_cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+			and_cond->operator_type = GDA_SQL_OPERATOR_TYPE_AND;
+			expr->cond = and_cond;
+		}
+		for (columns = mtable->columns; columns; columns = columns->next) {
+			GdaSqlSelectField *sfield = NULL;
+			GdaMetaTableColumn *tcol;
+			GSList *list;
+			gint index;
+
+			tcol = (GdaMetaTableColumn *) columns->data;
+			for (index = 0, list = stsel->expr_list;
+			     list;
+			     index++, list = list->next) {
+				sfield = (GdaSqlSelectField *) list->data;
+				if (sfield->validity_meta_table_column == tcol)
+					break;
+				else
+					sfield = NULL;
+			}
+			if (!sfield) {
+				g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+					     _("Table's column '%s' is not part of SELECT"),
+					     tcol->column_name);
+				goto onerror;
+			}
+			else {
+				GdaSqlOperation *op;
+				GdaSqlExpr *opexpr;
+				GdaSqlParamSpec *pspec;
+
+				/* equal condition */
+				if (and_cond) {
+					opexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (and_cond));
+					op = gda_sql_operation_new (GDA_SQL_ANY_PART (opexpr));
+					opexpr->cond = op;
+					and_cond->operands = g_slist_append (and_cond->operands, opexpr);
+				}
+				else {
+					op = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+					expr->cond = op;
+				}
+				op->operator_type = GDA_SQL_OPERATOR_TYPE_EQ;
+				/* left operand */
+				gchar *str;
+				opexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (op));
+				str = gda_sql_identifier_quote (tcol->column_name, cnc, NULL, FALSE, FALSE);
+				g_value_take_string (opexpr->value = gda_value_new (G_TYPE_STRING), str);
+
+				op->operands = g_slist_append (op->operands, opexpr);
+
+				/* right operand */
+				opexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (op));
+				pspec = g_new0 (GdaSqlParamSpec, 1);
+				pspec->name = g_strdup_printf ("-%d", index);
+				pspec->g_type = (tcol->gtype != GDA_TYPE_NULL) ? tcol->gtype: G_TYPE_STRING;
+				pspec->nullok = tcol->nullok;
+				opexpr->param_spec = pspec;
+				op->operands = g_slist_append (op->operands, opexpr);
+			}
+		}
 	}
 	return expr;
 	
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index ac34218..0fa9cb1 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -319,6 +319,7 @@
 	gda_data_select_add_exception
 	gda_data_select_compute_columns_attributes
 	gda_data_select_compute_modification_statements
+	gda_data_select_compute_modification_statements_ext
 	gda_data_select_compute_row_selection_condition
 	gda_data_select_error_quark
 	gda_data_select_get_connection



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