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;
}
Beispiel #2
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, &params, 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;
}