static void _midgard_query_select_execute (MidgardExecutable *iface, gboolean async, GError **error) { g_return_if_fail (iface != NULL); MidgardQuerySelect *self = MIDGARD_QUERY_SELECT (iface); MidgardQueryExecutor *executor = MIDGARD_QUERY_EXECUTOR (self); GError *err = NULL; midgard_validable_validate (MIDGARD_VALIDABLE (self), &err); if (err) { g_propagate_error (error, err); return; } MidgardDBObjectClass *klass = executor->priv->storage->priv->klass; MidgardConnection *mgd = executor->priv->mgd; GdaConnection *cnc = mgd->priv->connection; GdaSqlStatement *sql_stm; GdaSqlStatementSelect *sss; sql_stm = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT); sss = (GdaSqlStatementSelect*) sql_stm->contents; g_assert (GDA_SQL_ANY_PART (sss)->type == GDA_SQL_ANY_STMT_SELECT); MIDGARD_QUERY_EXECUTOR (self)->priv->stmt = sql_stm; sss->from = gda_sql_select_from_new (GDA_SQL_ANY_PART (sss)); /* Initialize top base expresion and operation with default AND operator type */ GdaSqlExpr *base_where = gda_sql_expr_new (GDA_SQL_ANY_PART (sss)); GdaSqlOperation *base_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (base_where)); base_operation->operator_type = GDA_SQL_OPERATOR_TYPE_AND; base_where->cond = base_operation; gda_sql_statement_select_take_where_cond (sql_stm, base_where); /* Create targets (FROM) */ GdaSqlSelectTarget *s_target = gda_sql_select_target_new (GDA_SQL_ANY_PART (sss->from)); s_target->table_name = g_strdup (midgard_core_class_get_table (klass)); s_target->as = g_strdup_printf ("t%d", ++MIDGARD_QUERY_EXECUTOR (self)->priv->tableid); MIDGARD_QUERY_EXECUTOR (self)->priv->table_alias = g_strdup (s_target->as); gda_sql_select_from_take_new_target (sss->from, s_target); /* Set target expression */ GdaSqlExpr *texpr = gda_sql_expr_new (GDA_SQL_ANY_PART (s_target)); GValue *tval = g_new0 (GValue, 1); g_value_init (tval, G_TYPE_STRING); g_value_set_string (tval, s_target->table_name); texpr->value = tval; s_target->expr = texpr; /* Add fields for all properties registered per class (SELECT a,b,c...) */ klass->dbpriv->add_fields_to_select_statement (klass, mgd, sss, s_target->as); GdaSqlExpr *where = sss->where_cond; GdaSqlOperation *operation = where->cond; /* Add joins, LEFT JOIN tbl2 ON... */ __query_select_add_joins (MIDGARD_QUERY_SELECT (self), operation, &err); if (err) { g_propagate_error (error, err); goto return_false; } /* Add constraints' conditions (WHERE a=1, b=2...) */ if (MIDGARD_QUERY_EXECUTOR (self)->priv->constraint) { MIDGARD_QUERY_CONSTRAINT_SIMPLE_GET_INTERFACE (MIDGARD_QUERY_EXECUTOR (self)->priv->constraint)->priv->add_conditions_to_statement (MIDGARD_QUERY_EXECUTOR (self), MIDGARD_QUERY_EXECUTOR (self)->priv->constraint, sql_stm, base_where, &err); if (err) { g_propagate_error (error, err); goto return_false; } if (MIDGARD_QUERY_EXECUTOR (self)->priv->n_constraints == 1) __add_second_dummy_constraint (sss, operation); /* Add dummy constraint if operation has only one operand */ if (operation->operands && (g_slist_length (operation->operands) == 1)) __add_dummy_constraint (sss, operation); } else { /* no constraints, add dummy '1=1 AND 0<1' to satisfy top constraint group */ __add_dummy_constraint (sss, operation); __add_second_dummy_constraint (sss, operation); } /* Add orders , ORDER BY t1.field... */ if (!__query_select_add_orders (executor, &err)) { if (err) g_propagate_error (error, err); goto return_false; } /* Exclude deleted */ if (MGD_DBCLASS_METADATA_CLASS (klass) && !executor->priv->include_deleted) __add_exclude_deleted_constraints (executor, sss, operation, klass); /* Add limit, LIMIT x */ if (executor->priv->limit > 0) { GdaSqlExpr *limit_expr = gda_sql_expr_new (GDA_SQL_ANY_PART (sss)); GValue *limit_val = g_new0 (GValue, 1); g_value_init (limit_val, G_TYPE_STRING); g_value_take_string (limit_val, g_strdup_printf ("%d", executor->priv->limit)); limit_expr->value = limit_val; sss->limit_count = limit_expr; } /* Add offset, OFFSET x */ if (executor->priv->offset >= 0) { GdaSqlExpr *offset_expr = gda_sql_expr_new (GDA_SQL_ANY_PART (sss)); GValue *offset_val = g_new0 (GValue, 1); g_value_init (offset_val, G_TYPE_STRING); g_value_take_string (offset_val, g_strdup_printf ("%d", executor->priv->offset)); offset_expr->value = offset_val; sss->limit_offset = offset_expr; } /* Check structure */ if (!gda_sql_statement_check_structure (sql_stm, &err)) { g_set_error (error, MIDGARD_EXECUTION_ERROR, MIDGARD_EXECUTION_ERROR_INTERNAL, "Can't build SELECT statement: %s)", err && err->message ? err->message : _("Unknown reason")); if (err) g_clear_error (&err); goto return_false; } /* Create statement */ GdaStatement *stmt = gda_statement_new (); g_object_set (G_OBJECT (stmt), "structure", sql_stm, NULL); gda_sql_statement_free (sql_stm); sql_stm = NULL; if (MGD_CNC_DEBUG (mgd)) { gchar *debug_sql = gda_connection_statement_to_sql (cnc, stmt, NULL, GDA_STATEMENT_SQL_PRETTY, NULL, NULL); g_debug ("QuerySelect: %s", debug_sql); g_free (debug_sql); } /* execute statement */ GdaDataModel *model = NULL; midgard_executable_execution_start (MIDGARD_EXECUTABLE(self)); model = gda_connection_statement_execute_select (cnc, stmt, NULL, &err); g_object_unref (stmt); if (!model && !err) { g_set_error (error, MIDGARD_EXECUTION_ERROR, MIDGARD_EXECUTION_ERROR_INTERNAL, "Execute error - Unknown reason, underlying error is NULL"); goto return_false; } if (err) { g_set_error (error, MIDGARD_EXECUTION_ERROR, MIDGARD_EXECUTION_ERROR_INTERNAL, "Execute error - %s", err->message); g_error_free (err); goto return_false; } executor->priv->results_count = gda_data_model_get_n_rows (model); if (executor->priv->resultset && G_IS_OBJECT (executor->priv->resultset)) g_object_unref (G_OBJECT (executor->priv->resultset)); executor->priv->resultset = (gpointer) model; return; return_false: if (sql_stm) gda_sql_statement_free (sql_stm); return; }
/* * 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; }