/** * gda_xa_transaction_rollback: * @xa_trans: a #GdaXaTransaction object * @error: (nullable): a place to store errors, or %NULL * * Cancels a distributed transaction (managed by @xa_trans). * * Returns: %TRUE if no error occurred */ gboolean gda_xa_transaction_rollback (GdaXaTransaction *xa_trans, GError **error) { GList *list; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans); for (list = priv->cnc_list; list; list = list->next) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc == priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { GdaBinary *branch; branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); GError *lerror = NULL; _gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), &lerror); if (error && !*error) g_propagate_error (error, lerror); else g_clear_error (&lerror); } } return TRUE; }
/** * gda_xa_transaction_rollback: * @xa_trans: a #GdaXaTransaction object * @error: (allow-none): a place to store errors, or %NULL * * Cancels a distributed transaction (managed by @xa_trans). * * Returns: %TRUE if no error occurred */ gboolean gda_xa_transaction_rollback (GdaXaTransaction *xa_trans, GError **error) { GList *list; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); for (list = xa_trans->priv->cnc_list; list; list = list->next) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc == xa_trans->priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { const GdaBinary *branch; branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (!PROV_CLASS (prov)->xa_funcs->xa_rollback) g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_prepare()", gda_server_provider_get_name (prov)); else PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), error); } } return TRUE; }
/** * midgard_transaction_rollback: * @self: #MidgardTransaction instance * * In case of error, #MidgardConnection error is set to MGD_ERR_INTERNAL * * Returns: %TRUE on success, %FALSE otherwise. * * Since: 9.09 */ gboolean midgard_transaction_rollback (MidgardTransaction *self) { _ASSERT_T_MGD(self); gboolean rv = FALSE; GdaConnection *cnc = _T_CNC(self); MidgardConnection *mgd = self->priv->mgd; GError *error = NULL; g_debug("Rollback named transaction '%s'", self->priv->name); rv = gda_connection_rollback_transaction(cnc, self->priv->name, &error); if (!error && rv) return TRUE; midgard_set_error(mgd, MGD_GENERIC_ERROR, MGD_ERR_INTERNAL, error && error->message ? error->message : " Unknown error."); if (error) g_error_free(error); return FALSE; }
/** * gda_xa_transaction_begin: * @xa_trans: a #GdaXaTransaction object * @error: (nullable): a place to store errors, or %NULL * * Begins a distributed transaction (managed by @xa_trans). Please note that this phase may fail * for some connections if a (normal) transaction is already started (this depends on the database * provider being used), so it's better to avoid starting any (normal) transaction on any of the * connections registered with @xa_trans. * * Returns: TRUE if no error occurred */ gboolean gda_xa_transaction_begin (GdaXaTransaction *xa_trans, GError **error) { GList *list; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans); for (list = priv->cnc_list; list; list = list->next) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc != priv->non_xa_cnc) { GdaBinary *branch; branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); if (! _gda_server_provider_xa_start (prov, cnc, &(priv->xid), error)) break; } else { /* do a simple BEGIN */ if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, error)) break; } } if (list) { /* something went wrong */ for (; list; list = list->prev) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc != priv->non_xa_cnc) { GdaBinary *branch; branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); _gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL); } else { /* do a simple ROLLBACK */ gda_connection_rollback_transaction (cnc, NULL, NULL); } } return FALSE; } return TRUE; }
/** * base_tool_command_result_free: * @res: (allow-none): a #ToolCommandResult, or %NULL * * Frees any resource used by @res */ void base_tool_command_result_free (ToolCommandResult *res) { if (!res) return; switch (res->type) { case BASE_TOOL_COMMAND_RESULT_DATA_MODEL: if (res->u.model) g_object_unref (res->u.model); if (! res->was_in_transaction_before_exec && res->cnc && gda_connection_get_transaction_status (res->cnc)) gda_connection_rollback_transaction (res->cnc, NULL, NULL); break; case BASE_TOOL_COMMAND_RESULT_SET: if (res->u.set) g_object_unref (res->u.set); break; case BASE_TOOL_COMMAND_RESULT_TREE: if (res->u.tree) g_object_unref (res->u.tree); break; case BASE_TOOL_COMMAND_RESULT_TXT: case BASE_TOOL_COMMAND_RESULT_TXT_STDOUT: if (res->u.txt) g_string_free (res->u.txt, TRUE); break; case BASE_TOOL_COMMAND_RESULT_MULTIPLE: { GSList *list; for (list = res->u.multiple_results; list; list = list->next) base_tool_command_result_free ((ToolCommandResult *) list->data); g_slist_free (res->u.multiple_results); break; } case BASE_TOOL_COMMAND_RESULT_HELP: if (res->u.xml_node) xmlFreeNode (res->u.xml_node); break; case BASE_TOOL_COMMAND_RESULT_EXIT: case BASE_TOOL_COMMAND_RESULT_EMPTY: break; default: g_assert_not_reached (); break; } if (res->cnc) g_object_unref (res->cnc); g_free (res); }
void midgard_cr_core_transaction_rollback (MidgardCRCoreTransaction *self, GError **error) { _ASSERT_T_MGD (self); gboolean rv = FALSE; GdaConnection *cnc = _T_CNC (self); MidgardCRSQLStorageManager *manager = self->priv->manager; GError *err = NULL; rv = gda_connection_rollback_transaction (cnc, self->priv->name, &err); if (err) g_propagate_error (error, err); if (!rv && !err) g_warning ("Failed to rollback underlying database transaction and no error has been set"); return; }
/** * gda_xa_transaction_commit: * @xa_trans: a #GdaXaTransaction object * @cnc_to_recover: (allow-none) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the commit phase failed, or %NULL * @error: a place to store errors, or %NULL * * Commits a distributed transaction (managed by @xa_trans). The commit is composed of two phases: * <itemizedlist> * <listitem><para>a PREPARE phase where all the connections are required to store their transaction data to a * permanent place (to be able to complete the commit should a problem occur afterwards)</para></listitem> * <listitem><para>a COMMIT phase where the transaction data is actually written to the database</para></listitem> * </itemizedlist> * * If the PREPARE phase fails for any of the connection registered with @xa_trans, then the distributed commit * fails and FALSE is returned. During the COMMIT phase, some commit may actually fail but the transaction can * still be completed because the PREPARE phase succeeded (through the recover method). * * Returns: TRUE if no error occurred (there may be some connections to recover, though) */ gboolean gda_xa_transaction_commit (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error) { GList *list; if (cnc_to_recover) *cnc_to_recover = NULL; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); /* * PREPARE phase */ for (list = xa_trans->priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; const GdaBinary *branch; if (cnc == xa_trans->priv->non_xa_cnc) continue; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (PROV_CLASS (prov)->xa_funcs->xa_end && !PROV_CLASS (prov)->xa_funcs->xa_end (prov, cnc, &(xa_trans->priv->xid), error)) break; if (!PROV_CLASS (prov)->xa_funcs->xa_prepare) { g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_prepare()", gda_server_provider_get_name (prov)); break; } if (!PROV_CLASS (prov)->xa_funcs->xa_commit) { g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_commit()", gda_server_provider_get_name (prov)); break; } if (!PROV_CLASS (prov)->xa_funcs->xa_prepare (prov, cnc, &(xa_trans->priv->xid), error)) break; } if (list) { /* something went wrong during the PREPARE phase => rollback everything */ for (; list; list = list->prev) { GdaConnection *cnc = NULL; GdaServerProvider *prov; if (cnc == xa_trans->priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { const GdaBinary *branch; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (PROV_CLASS (prov)->xa_funcs->xa_rollback) PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL); else g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_rollback()", gda_server_provider_get_name (prov)); } } return FALSE; } /* * COMMIT phase */ if (xa_trans->priv->non_xa_cnc && ! gda_connection_commit_transaction (xa_trans->priv->non_xa_cnc, NULL, error)) { /* something went wrong => rollback everything */ for (list = xa_trans->priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; if (cnc == xa_trans->priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { const GdaBinary *branch; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (PROV_CLASS (prov)->xa_funcs->xa_rollback) PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL); else g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_rollback()", gda_server_provider_get_name (prov)); } } return FALSE; } for (list = xa_trans->priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; const GdaBinary *branch; if (cnc == xa_trans->priv->non_xa_cnc) continue; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (!PROV_CLASS (prov)->xa_funcs->xa_commit (prov, cnc, &(xa_trans->priv->xid), error) && cnc_to_recover) *cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc); } return TRUE; }
/** * gda_xa_transaction_begin: * @xa_trans: a #GdaXaTransaction object * @error: (allow-none): a place to store errors, or %NULL * * Begins a distributed transaction (managed by @xa_trans). Please note that this phase may fail * for some connections if a (normal) transaction is already started (this depends on the database * provider being used), so it's better to avoid starting any (normal) transaction on any of the * connections registered with @xa_trans. * * Returns: TRUE if no error occurred */ gboolean gda_xa_transaction_begin (GdaXaTransaction *xa_trans, GError **error) { GList *list; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); for (list = xa_trans->priv->cnc_list; list; list = list->next) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc != xa_trans->priv->non_xa_cnc) { if (!PROV_CLASS (prov)->xa_funcs->xa_start) { g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_start()", gda_server_provider_get_name (prov)); break; } else { const GdaBinary *branch; branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); if (!PROV_CLASS (prov)->xa_funcs->xa_start (prov, cnc, &(xa_trans->priv->xid), error)) break; } } else { /* do a simple BEGIN */ if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, error)) break; } } if (list) { /* something went wrong */ for (; list; list = list->prev) { GdaConnection *cnc; GdaServerProvider *prov; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); if (cnc != xa_trans->priv->non_xa_cnc) { if (!PROV_CLASS (prov)->xa_funcs->xa_rollback) g_warning (_("Provider error: %s method not implemented for provider %s"), "xa_rollback()", gda_server_provider_get_name (prov)); else { const GdaBinary *branch; branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc); memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */ branch->data, branch->binary_length); PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL); } } else { /* do a simple ROLLBACK */ gda_connection_rollback_transaction (cnc, NULL, NULL); } } return FALSE; } return TRUE; }
/** * gda_xa_transaction_commit: * @xa_trans: a #GdaXaTransaction object * @cnc_to_recover: (nullable) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the commit phase failed, or %NULL * @error: a place to store errors, or %NULL * * Commits a distributed transaction (managed by @xa_trans). The commit is composed of two phases: * <itemizedlist> * <listitem><para>a PREPARE phase where all the connections are required to store their transaction data to a * permanent place (to be able to complete the commit should a problem occur afterwards)</para></listitem> * <listitem><para>a COMMIT phase where the transaction data is actually written to the database</para></listitem> * </itemizedlist> * * If the PREPARE phase fails for any of the connection registered with @xa_trans, then the distributed commit * fails and FALSE is returned. During the COMMIT phase, some commit may actually fail but the transaction can * still be completed because the PREPARE phase succeeded (through the recover method). * * Returns: TRUE if no error occurred (there may be some connections to recover, though) */ gboolean gda_xa_transaction_commit (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error) { GList *list; if (cnc_to_recover) *cnc_to_recover = NULL; g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE); GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans); /* * PREPARE phase */ for (list = priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; GdaBinary *branch; if (cnc == priv->non_xa_cnc) continue; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); if (!_gda_server_provider_xa_end (prov, cnc, &(priv->xid), error)) break; if (!_gda_server_provider_xa_prepare (prov, cnc, &(priv->xid), error)) break; } if (list) { /* something went wrong during the PREPARE phase => rollback everything */ for (; list; list = list->prev) { GdaConnection *cnc = NULL; GdaServerProvider *prov; if (cnc == priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { GdaBinary *branch; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); _gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL); } } return FALSE; } /* * COMMIT phase */ if (priv->non_xa_cnc && ! gda_connection_commit_transaction (priv->non_xa_cnc, NULL, error)) { /* something went wrong => rollback everything */ for (list = priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; if (cnc == priv->non_xa_cnc) gda_connection_rollback_transaction (cnc, NULL, NULL); else { GdaBinary *branch; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); _gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL); } } return FALSE; } for (list = priv->cnc_list; list; list = list->next) { GdaConnection *cnc = NULL; GdaServerProvider *prov; GdaBinary *branch; if (cnc == priv->non_xa_cnc) continue; cnc = GDA_CONNECTION (list->data); prov = gda_connection_get_provider (cnc); branch = g_hash_table_lookup (priv->cnc_hash, cnc); memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */ gda_binary_get_data (branch), gda_binary_get_size (branch)); if (! _gda_server_provider_xa_commit (prov, cnc, &(priv->xid), error) && cnc_to_recover) *cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc); } return TRUE; }
GdaBlobOp * _gda_sqlite_blob_op_new (GdaConnection *cnc, const gchar *db_name, const gchar *table_name, const gchar *column_name, sqlite3_int64 rowid) { GdaSqliteBlobOp *bop = NULL; int rc; sqlite3_blob *sblob; gchar *db, *table; gboolean free_strings = TRUE; gboolean transaction_started = FALSE; g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); g_return_val_if_fail (table_name, NULL); g_return_val_if_fail (column_name, NULL); g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (gda_connection_get_provider (cnc)), NULL); GdaSqliteBlobOpPrivate *priv = gda_sqlite_blob_op_get_instance_private (bop); if (db_name) { db = (gchar *) db_name; table = (gchar *) table_name; free_strings = FALSE; } else if (! _split_identifier_string (g_strdup (table_name), &db, &table)) return NULL; SqliteConnectionData *cdata; cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL); if (!cdata || ! _gda_sqlite_check_transaction_started (cnc, &transaction_started, NULL)) return NULL; GdaSqliteProvider *prov = GDA_SQLITE_PROVIDER (gda_connection_get_provider (cnc)); rc = SQLITE3_CALL (prov, sqlite3_blob_open) (cdata->connection, db ? db : "main", table, column_name, rowid, 1, /* Read & Write */ &(sblob)); if (rc != SQLITE_OK) { #ifdef GDA_DEBUG_NO g_print ("ERROR: %s\n", SQLITE3_CALL (prov, sqlite3_errmsg) (cdata->connection)); #endif if (transaction_started) gda_connection_rollback_transaction (cnc, NULL, NULL); goto out; } bop = g_object_new (GDA_TYPE_SQLITE_BLOB_OP, "connection", cnc, NULL); priv->sblob = sblob; g_weak_ref_set (&priv->provider, prov); #ifdef GDA_DEBUG_NO g_print ("OPENED blob %p\n", bop); #endif out: if (free_strings) { g_free (db); g_free (table); } return (GdaBlobOp*) bop; }
int main (int argc, char *argv[]) { gda_init (); GdaConnection *cnc; GError *error = NULL; GdaStatement *stmt; GdaDataModel *model; gchar *str; GValue *name; /* open connection */ cnc = open_connection (); /* begin transaction */ if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, &error)) { g_print ("Could not begin transaction: %s\n", error && error->message ? error->message : "No detail"); exit (1); } /* execute SELECT */ stmt = gda_sql_parser_parse_string (parser, "SELECT id, name FROM customers ORDER BY id", NULL, NULL); g_assert (stmt); model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error); g_object_unref (stmt); if (!model) { g_print ("Could not execute SELECT statement: %s\n", error && error->message ? error->message : "No detail"); exit (1); } g_print ("** Data model is:\n"); gda_data_model_dump (model, stdout); /* * make sure the mete data is up to date */ g_print ("Computing meta data, this may take a while; in real applications, this should be cached to avoid waiting\n"); if (! gda_connection_update_meta_store (cnc, NULL, &error)) { g_print ("Could not fetch meta data: %s\n", error && error->message ? error->message : "No detail"); exit (1); } /* * Make the data model compute the modification statements which * will actually be executed when the data model is modified */ if (! gda_data_select_compute_modification_statements (GDA_DATA_SELECT (model), &error)) { g_print ("Could not compute modification statements: %s\n", error && error->message ? error->message : "No detail"); exit (1); } g_object_get (G_OBJECT (model), "update-stmt", &stmt, NULL); str = gda_statement_to_sql (stmt, NULL, NULL); g_print ("Computed UPDATE: %s\n", str); g_free (str); g_object_unref (stmt); g_object_get (G_OBJECT (model), "delete-stmt", &stmt, NULL); str = gda_statement_to_sql (stmt, NULL, NULL); g_print ("Computed DELETE: %s\n", str); g_free (str); g_object_unref (stmt); g_object_get (G_OBJECT (model), "insert-stmt", &stmt, NULL); str = gda_statement_to_sql (stmt, NULL, NULL); g_print ("Computed INSERT: %s\n", str); g_free (str); g_object_unref (stmt); /* * remove row 0 (1st row) */ g_print ("\n\n** Removing row 0\n"); if (! gda_data_model_remove_row (model, 0, &error)) { g_print ("Could not remove row 0: %s\n", error && error->message ? error->message : "No detail"); exit (1); } g_print ("** Data model is now:\n"); gda_data_model_dump (model, stdout); g_print ("** Table's contents is now:\n"); display_customers (cnc); /* * add a row: the row's values is a list of GValue pointers * (or NULL pointers where the default value should be inserted */ GList *list; g_print ("\n\n** Adding a row\n"); list = g_list_append (NULL, NULL); g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), "Hiro"); list = g_list_append (list, name); if (gda_data_model_append_values (model, list, &error) == -1) { g_print ("Could not add a row: %s\n", error && error->message ? error->message : "No detail"); exit (1); } gda_value_free (name); g_list_free (list); g_print ("** Data model is now:\n"); gda_data_model_dump (model, stdout); g_print ("** Table's contents is now:\n"); display_customers (cnc); /* * alter row 2 */ g_print ("\n\n** Modifying row 2\n"); g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), "Tom"); if (! gda_data_model_set_value_at (model, 1, 2, name, &error)) { g_print ("Could not modify row 2: %s\n", error && error->message ? error->message : "No detail"); exit (1); } gda_value_free (name); g_print ("** Data model is now:\n"); gda_data_model_dump (model, stdout); g_print ("** Table's contents is now:\n"); display_customers (cnc); /* rollback transaction */ gda_connection_rollback_transaction (cnc, NULL, NULL); gda_connection_close (cnc); return 0; }
/* * Load data from file @file into table @table */ gboolean test_cnc_load_data_from_file (GdaConnection *cnc, const gchar *table, const gchar *full_file, GError **error) { GdaStatement *stmt = NULL; GdaSet *params = NULL; GdaDataModel *import; gint nrows, ncols, i; GdaMetaStruct *mstruct = NULL; GSList *list; gboolean retval = TRUE; /* loading XML file */ import = gda_data_model_import_new_file (full_file, TRUE, NULL); if (gda_data_model_import_get_errors (GDA_DATA_MODEL_IMPORT (import))) { g_set_error (error, TEST_ERROR, TEST_ERROR_GENERIC, "Error loading '%s' file", full_file); return FALSE; } /* retrieving meta data info */ GdaMetaDbObject *table_dbo; GValue *name_value; g_value_set_string ((name_value = gda_value_new (G_TYPE_STRING)), table); mstruct = gda_meta_struct_new (gda_connection_get_meta_store (cnc), GDA_META_STRUCT_FEATURE_NONE); table_dbo = gda_meta_struct_complement (mstruct, GDA_META_DB_TABLE, NULL, NULL, name_value, error); gda_value_free (name_value); if (! table_dbo) { retval = FALSE; goto out; } /* creating INSERT statement */ GdaSqlStatement *st; GdaSqlStatementInsert *ist; GSList *insert_values_list = NULL; ist = g_new0 (GdaSqlStatementInsert, 1); GDA_SQL_ANY_PART (ist)->type = GDA_SQL_ANY_STMT_INSERT; ist->table = gda_sql_table_new (GDA_SQL_ANY_PART (ist)); ist->table->table_name = g_strdup (table); GdaMetaTable *mtable = GDA_META_TABLE (table_dbo); for (list = mtable->columns; list; list = list->next) { GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data); GdaSqlField *field; /* field */ field = gda_sql_field_new (GDA_SQL_ANY_PART (ist)); field->field_name = g_strdup (tcol->column_name); ist->fields_list = g_slist_append (ist->fields_list, field); /* value */ GdaSqlParamSpec *pspec = g_new0 (GdaSqlParamSpec, 1); GdaSqlExpr *expr; pspec->name = g_strdup (tcol->column_name); pspec->g_type = tcol->gtype; pspec->nullok = tcol->nullok; expr = gda_sql_expr_new (GDA_SQL_ANY_PART (ist)); expr->param_spec = pspec; insert_values_list = g_slist_append (insert_values_list, expr); } ist->values_list = g_slist_append (NULL, insert_values_list); st = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT); st->contents = ist; stmt = g_object_new (GDA_TYPE_STATEMENT, "structure", st, NULL); gda_sql_statement_free (st); g_object_unref (mstruct); if (! gda_statement_get_parameters (stmt, ¶ms, error)) { retval = FALSE; goto out; } /* executing inserts */ nrows = gda_data_model_get_n_rows (import); ncols = gda_data_model_get_n_columns (import); if (!gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, error)) { retval = FALSE; goto out; } for (i = 0; i < nrows; i++) { gint j; GSList *list; for (list = params->holders, j = 0; list && (j < ncols); list = list->next, j++) { const GValue *cvalue = gda_data_model_get_value_at (import, j, i, error); if (!cvalue) { gda_connection_rollback_transaction (cnc, NULL, NULL); retval = FALSE; goto out; } if (! gda_holder_set_value (GDA_HOLDER (list->data), cvalue, error)) { gda_connection_rollback_transaction (cnc, NULL, NULL); retval = FALSE; goto out; } } if (list || (j < ncols)) { g_set_error (error, TEST_ERROR, TEST_ERROR_GENERIC, "%s", "Incoherent number of columns in table and imported data"); gda_connection_rollback_transaction (cnc, NULL, NULL); retval = FALSE; goto out; } if (gda_connection_statement_execute_non_select (cnc, stmt, params, NULL, error) == -1) { gda_connection_rollback_transaction (cnc, NULL, NULL); retval = FALSE; goto out; } } if (! gda_connection_commit_transaction (cnc, NULL, error)) retval = FALSE; out: if (import) g_object_unref (import); if (stmt) g_object_unref (stmt); if (params) g_object_unref (params); return retval; }