static void
gda_sql_statement_insert_free (gpointer stmt)
{
	GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt;
	GSList *list;
	g_free (insert->on_conflict);
	gda_sql_table_free (insert->table);
	for (list = insert->values_list; list; list = list->next) {
		if (list->data) {
			g_slist_foreach ((GSList *) list->data, (GFunc) gda_sql_expr_free, NULL);
			g_slist_free ((GSList *) list->data);
		}
	}
	g_slist_free (insert->values_list);

	g_slist_foreach (insert->fields_list, (GFunc) gda_sql_field_free, NULL);
	g_slist_free (insert->fields_list);
	if (insert->select) {
		if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT)
			_gda_sql_statement_select_free (insert->select);
		else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
			_gda_sql_statement_compound_free (insert->select);
		else
			g_assert_not_reached ();
	}

	g_free (insert);
}
static void
__add_join (Psh *holder)
{
    MidgardCRCoreQueryExecutor *executor = MIDGARD_CR_CORE_QUERY_EXECUTOR (holder->executor);
    GdaSqlStatement *sql_stm = executor->priv->stmt;
    GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) sql_stm->contents;
    GdaSqlSelectFrom *from = select->from;
    GdaSqlSelectJoin *join = gda_sql_select_join_new (GDA_SQL_ANY_PART (from));
    join->type = GDA_SQL_SELECT_JOIN_LEFT;

    GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (join));
    expr->value = gda_value_new (G_TYPE_STRING);
    g_value_take_string (expr->value, g_strdup_printf ("%s.%s = %s.%s",
                         holder->table_alias, holder->colname, holder->target_table_alias, holder->target_colname));
    join->expr = expr;
    join->position = ++executor->priv->joinid;

    gda_sql_select_from_take_new_join (from , join);

    GdaSqlSelectTarget *s_target = gda_sql_select_target_new (GDA_SQL_ANY_PART (from));
    s_target->table_name = g_strdup (holder->target_table);
    s_target->as = g_strdup (holder->target_table_alias);
    gda_sql_select_from_take_new_target (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;
}
gboolean __query_select_add_orders (MidgardQueryExecutor *self, GError **error)
{
	if (!self->priv->orders)
		return TRUE;

	GSList *l = NULL;

	MidgardQueryExecutor *executor = MIDGARD_QUERY_EXECUTOR (self);
	GdaSqlStatement *sql_stm = executor->priv->stmt;
	GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) sql_stm->contents;	
	GdaSqlSelectOrder *order; 
	
	for (l = MIDGARD_QUERY_EXECUTOR (self)->priv->orders; l != NULL; l = l->next) {

		/* Proper asc type is set during validation phase */
		qso *_so = (qso*) l->data;

		/* Create new order */
		order = gda_sql_select_order_new (GDA_SQL_ANY_PART (select));
		order->asc = _so->asc;
		MidgardQueryProperty *property = _so->property;
		MidgardQueryStorage *storage = NULL;
		
		if (property->priv && property->priv->storage)
			storage = property->priv->storage;

		/* Compute table.colname for given property name */
		GValue rval = {0, };
		midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (property), &rval);
		GError *err = NULL;
		gchar *table_field = midgard_core_query_compute_constraint_property (executor, storage, g_value_get_string (&rval), &err);
		if (err) {
			g_propagate_error (error, err);
			g_free (table_field);
			gda_sql_select_order_free (order);
			return FALSE;
		}

		if (!table_field) {
			g_set_error (error, MIDGARD_VALIDATION_ERROR, MIDGARD_VALIDATION_ERROR_LOCATION_INVALID,
					"Can not find table and column name for given '%s' property name", g_value_get_string (&rval));
			g_value_unset (&rval);
			return FALSE;	
		}

		g_value_unset (&rval);

		GValue *value = g_new0 (GValue, 1);
		g_value_init (value, G_TYPE_STRING);
		g_value_take_string (value, table_field);

		/* Set order's expression and add new one to statement orders list */
		GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (order));
		expr->value = value;
		order->expr = expr;
		select->order_by = g_slist_append (select->order_by, order);
	}

	return TRUE;
}
void 
_midgard_sql_query_constraint_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *constraint_simple, GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node, GError **error)
{	
	MidgardSqlQueryConstraint *self = MIDGARD_SQL_QUERY_CONSTRAINT (constraint_simple);
	MidgardConnection *mgd = executor->priv->mgd;
	GdaConnection *cnc = mgd->priv->connection;

	GdaSqlStatementSelect *select = stmt->contents;
	GdaSqlExpr *top_where, *where, *expr;
	GdaSqlOperation *top_operation, *cond;
	GValue *value;

	/* Create table_alias.field name */
	MidgardSqlQueryColumn *column = midgard_sql_query_constraint_get_column (self);
	gchar *table_alias_field = get_real_table_field (executor, column);
	g_object_unref (column);

	if (!table_alias_field) {
		/* TODO */
		/* Handle error */
	}

	if (where_expr_node) {
		top_where = where_expr_node;
		top_operation = top_where->cond;
	} else {
		top_where = select->where_cond;
		top_operation = top_where->cond;
	}

	where = gda_sql_expr_new (GDA_SQL_ANY_PART (top_operation));
	top_operation->operands = g_slist_append (top_operation->operands, where);

	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (where));
	where->cond = cond;	
	cond->operator_type = self->priv->op_type;

	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
	g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), table_alias_field);
	expr->value = value;
	cond->operands = g_slist_append (cond->operands, expr);
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));	

	/* Create value */
	GValue val = {0, };
	midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (self->priv->holder), &val);
	//FIXME, create parameter name::type */
	expr->value = gda_value_new (G_TYPE_STRING);
	GString *str = g_string_new ("");
	__get_expression_value (cnc, &val, str);
	g_value_take_string (expr->value, g_string_free (str, FALSE));
	g_value_unset (&val);
	cond->operands = g_slist_append (cond->operands, expr);

	/* increase executor's constraints number */
	executor->priv->n_constraints++;
}
/**
 * gda_sql_operation_new
 * @parent: a #GdaSqlAnyPart structure
 *
 * Creates a new #GdaSqlOperation structure and sets its parent to @parent.
 *
 * Returns: a new #GdaSqlOperation structure.
 */
GdaSqlOperation *
gda_sql_operation_new (GdaSqlAnyPart *parent)
{
	GdaSqlOperation *operation;
	operation = g_new0 (GdaSqlOperation, 1);
	GDA_SQL_ANY_PART(operation)->type = GDA_SQL_ANY_SQL_OPERATION;
	GDA_SQL_ANY_PART(operation)->parent = parent;
	return operation;
}
/**
 * gda_sql_function_new
 * @parent: a #GdaSqlAnyPart structure
 *
 * Creates a new #GdaSqlFunction structure initiated.
 *
 * Returns: a new #GdaSqlFunction structure.
 */
GdaSqlFunction *
gda_sql_function_new (GdaSqlAnyPart *parent)
{
	GdaSqlFunction *function;
	function = g_new0 (GdaSqlFunction, 1);
	GDA_SQL_ANY_PART(function)->type = GDA_SQL_ANY_SQL_FUNCTION;
	GDA_SQL_ANY_PART(function)->parent = parent;
	return function;
}
/**
 * gda_sql_select_target_new
 * @parent: a #GdaSqlSelectFrom
 *
 * Creates a new #GdaSqlSelectTarget structure and sets its parent to @parent. A
 * #GdaSqlSelectTarget is the table in a SELECT statement.
 *
 * Returns: a new #GdaSqlSelectTarget structure.
 */
GdaSqlSelectTarget *
gda_sql_select_target_new (GdaSqlAnyPart *parent)
{
	GdaSqlSelectTarget *target;
	target = g_new0 (GdaSqlSelectTarget, 1);
	GDA_SQL_ANY_PART(target)->type = GDA_SQL_ANY_SQL_SELECT_TARGET;
	GDA_SQL_ANY_PART(target)->parent = parent;
	return target;
}
/**
 * gda_sql_select_from_new
 * @parent: a #GdaSqlStatementSelect
 *
 * Creates a new #GdaSqlSelectFrom structure and sets its parent to @parent.
 *
 * Returns: a new #GdaSqlSelectFrom structure
 */
GdaSqlSelectFrom *
gda_sql_select_from_new (GdaSqlAnyPart *parent)
{
	GdaSqlSelectFrom *from;
	from = g_new0 (GdaSqlSelectFrom, 1);
	GDA_SQL_ANY_PART(from)->type = GDA_SQL_ANY_SQL_SELECT_FROM;
	GDA_SQL_ANY_PART(from)->parent = parent;
	return from;
}
/**
 * gda_sql_select_order_new
 * @parent: a #GdaSqlStatementSelect
 *
 * Creates a new #GdaSqlSelectOrder structure and sets its parent to @parent.
 *
 * Returns: a new #GdaSqlSelectOrder structure
 */
GdaSqlSelectOrder *
gda_sql_select_order_new (GdaSqlAnyPart *parent)
{
	GdaSqlSelectOrder *order;
	order = g_new0 (GdaSqlSelectOrder, 1);
	GDA_SQL_ANY_PART(order)->type = GDA_SQL_ANY_SQL_SELECT_ORDER;
	GDA_SQL_ANY_PART(order)->parent = parent;
	return order;
}
/**
 * gda_sql_expr_new
 * @parent: a #GdaSqlStatementInsert, #GdaSqlStatementUpdate, #GdaSqlSelectField, #GdaSqlSelectTarget, #GdaSqlOperation
 *
 * Creates a new #GdaSqlField structure, using @parent as its parent part.
 *
 * Returns: a new #GdaSqlField structure.
 */
GdaSqlExpr *
gda_sql_expr_new (GdaSqlAnyPart *parent)
{
	GdaSqlExpr *expr;
	expr = g_new0 (GdaSqlExpr, 1);
	GDA_SQL_ANY_PART(expr)->type = GDA_SQL_ANY_EXPR;
	GDA_SQL_ANY_PART(expr)->parent = parent;
	return expr;
}
/**
 * gda_sql_case_new
 * @parent: a #GdaSqlAnyPart structure
 *
 * Creates a new #GdaSqlCase structure and sets its parent to @parent.
 *
 * Returns: a new #GdaSqlCase structure.
 */
GdaSqlCase *
gda_sql_case_new (GdaSqlAnyPart *parent)
{
	GdaSqlCase *sc;
	sc = g_new0 (GdaSqlCase, 1);
	GDA_SQL_ANY_PART(sc)->type = GDA_SQL_ANY_SQL_CASE;
	GDA_SQL_ANY_PART(sc)->parent = parent;
	return sc;
}
/**
 * gda_sql_field_new
 * @parent: a #GdaSqlStatementSelect, #GdaSqlStatementInsert, #GdaSqlStatementDelete, #GdaSqlStatementUpdate
 *
 * Creates a new #GdaSqlField structure, using @parent as its parent part.
 *
 * Returns: a new #GdaSqlField structure.
 */
GdaSqlField *
gda_sql_field_new (GdaSqlAnyPart *parent)
{
	GdaSqlField *field;
	field = g_new0 (GdaSqlField, 1);
	GDA_SQL_ANY_PART(field)->type = GDA_SQL_ANY_SQL_FIELD;
	GDA_SQL_ANY_PART(field)->parent = parent;
	return field;
}
/**
 * gda_sql_table_new
 * @parent: a #GdaSqlStatementSelect, #GdaSqlStatementInsert, #GdaSqlStatementDelete, #GdaSqlStatementUpdate
 *
 * Creates a new #GdaSqlTable structure, using @parent as its parent part.
 *
 * Returns: a new #GdaSqlTable structure.
 */
GdaSqlTable *
gda_sql_table_new (GdaSqlAnyPart *parent)
{
	GdaSqlTable *table;
	table = g_new0 (GdaSqlTable, 1);
	GDA_SQL_ANY_PART(table)->type = GDA_SQL_ANY_SQL_TABLE;
	GDA_SQL_ANY_PART(table)->parent = parent;
	return table;
}
/**
 * gda_sql_select_join_new
 * @parent: a #GdaSqlSelectFrom
 *
 * Creates a new #GdaSqlSelectJoin structure and sets its parent to @parent.
 *
 * Returns: a new #GdaSqlSelectJoin structure
 */
GdaSqlSelectJoin *
gda_sql_select_join_new (GdaSqlAnyPart *parent)
{
	GdaSqlSelectJoin *join;
	join = g_new0 (GdaSqlSelectJoin, 1);
	GDA_SQL_ANY_PART(join)->type = GDA_SQL_ANY_SQL_SELECT_JOIN;
	GDA_SQL_ANY_PART(join)->parent = parent;
	return join;
}
/**
 * gda_sql_select_target_take_table_name
 * @target: a #GdaSqlSelectTarget structure
 * @stmt: a #GValue to take from
 *
 * Sets the target to be a SELECT subquery setting target's expression to use
 * @stmt; after call this function the target owns @stmt, then you must not free it.
 */
void
gda_sql_select_target_take_select (GdaSqlSelectTarget *target, GdaSqlStatement *stmt)
{
	if (stmt) {
		target->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (target));
		gda_sql_expr_take_select (target->expr, stmt);
	}
}
static gpointer
gda_sql_statement_delete_new (void)
{
	GdaSqlStatementDelete *stmt;
	stmt = g_new0 (GdaSqlStatementDelete, 1);
	GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_DELETE;
	return (gpointer) stmt;
}
Beispiel #17
0
static VALUE ast(VALUE self)
{
    GdaSqlStatement * sqlst;

    Data_Get_Struct(self, GdaSqlStatement, sqlst);

    return WrapAnyPart(self, GDA_SQL_ANY_PART(sqlst->contents));
}
static gpointer
gda_sql_statement_insert_new (void)
{
	GdaSqlStatementInsert *stmt;
	stmt = g_new0 (GdaSqlStatementInsert, 1);
	GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_INSERT;
	return (gpointer) stmt;
}
static gpointer
gda_sql_statement_select_new (void)
{
	GdaSqlStatementSelect *stmt;
	stmt = g_new0 (GdaSqlStatementSelect, 1);
	GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_SELECT;
	return (gpointer) stmt;
}
/**
 * gda_sql_select_field_take_star_value
 * @field: a #GdaSqlSelectField structure
 * @value: a #GValue to take from
 *
 * Sets the expression field's value in the #GdaSqlSelectField structure to point to @value;
 * after this @field is the owner of @value.
 *
 */
void
gda_sql_select_field_take_star_value (GdaSqlSelectField *field, GValue *value)
{
	if (value) {
		field->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (field));
		field->expr->value = value;
	}
}
static gpointer
gda_sql_statement_unknown_new (void)
{
	GdaSqlStatementUnknown *stmt;
	stmt = g_new0 (GdaSqlStatementUnknown, 1);
	GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_UNKNOWN;
	return (gpointer) stmt;
}
/**
 * gda_sql_statement_update_take_table_name
 * @stmt: a #GdaSqlStatement pointer
 * @value: a table name, as a G_TYPE_STRING #GValue
 *
 * Sets the name of the table to delete from in @stmt.
 *
 * @value's ownership is transferred to
 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
 */
void
gda_sql_statement_update_take_table_name (GdaSqlStatement *stmt, GValue *value)
{
	GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt->contents;
	if (value) {
		update->table = gda_sql_table_new (GDA_SQL_ANY_PART (update));
		gda_sql_table_take_name (update->table, value);
	}
}
/**
 * gda_sql_statement_insert_take_table_name
 * @stmt: a #GdaSqlStatement pointer
 * @value: name of the table to insert into, as a G_TYPE_STRING #GValue
 *
 * Sets the name of the table to insert into in @stmt. @value's ownership is transferred to
 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
 */
void
gda_sql_statement_insert_take_table_name (GdaSqlStatement *stmt, GValue *value)
{
	GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
	if (value) {
		insert->table = gda_sql_table_new (GDA_SQL_ANY_PART (insert));
		gda_sql_table_take_name (insert->table, value);
	}
}
/**
 * gda_sql_select_target_take_table_name
 * @target: a #GdaSqlSelectTarget structure
 * @value: a #GValue to take from
 *
 * Sets the target's name using the string stored in @value and the expression
 * to set its value to point to value; after call this function the target owns
 * @value, then you must not free it.
 */
void
gda_sql_select_target_take_table_name (GdaSqlSelectTarget *target, GValue *value)
{
	if (value) {
		target->table_name = g_value_dup_string (value);
		target->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (target));
		target->expr->value = value;
	}
}
static void
__add_second_dummy_constraint (GdaSqlStatementSelect *select, GdaSqlOperation *top_operation)
{
	GdaSqlExpr *dexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (top_operation));
	dexpr->value = gda_value_new (G_TYPE_STRING);
	g_value_take_string (dexpr->value, g_strdup ("0<1"));
	top_operation->operands = g_slist_append (top_operation->operands, dexpr);

	return;
}
/**
 * gda_select_alter_select_for_empty:
 * @stmt: a SELECT #GdaStatement
 * @error: (allow-none): a place to store errors, or %NULL
 *
 * Creates a new #GdaStatement, selecting the same data as @stmt, but which always returns an
 * empty (no row) data model. This is use dy database providers' implementations.
 *
 * Returns: (transfer full): a new #GdaStatement
 */
GdaStatement *
gda_select_alter_select_for_empty (GdaStatement *stmt, G_GNUC_UNUSED GError **error)
{
	GdaStatement *estmt;
	GdaSqlStatement *sqlst;
	GdaSqlStatementSelect *stsel;

	g_assert (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT);
	g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
	g_assert (sqlst);

	if (sqlst->sql) {
		g_free (sqlst->sql);
		sqlst->sql = NULL;
	}
	stsel = (GdaSqlStatementSelect*) sqlst->contents;

	/* set the WHERE condition to "1 = 0" */
	GdaSqlExpr *expr, *cond = stsel->where_cond;
	GdaSqlOperation *op;
	if (cond)
		gda_sql_expr_free (cond);
	cond = gda_sql_expr_new (GDA_SQL_ANY_PART (stsel));
	stsel->where_cond = cond;
	op = gda_sql_operation_new (GDA_SQL_ANY_PART (cond));
	cond->cond = op;
	op->operator_type = GDA_SQL_OPERATOR_TYPE_EQ;
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (op));
	op->operands = g_slist_prepend (NULL, expr);
	g_value_set_int ((expr->value = gda_value_new (G_TYPE_INT)), 1);
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (op));
	op->operands = g_slist_prepend (op->operands, expr);
	g_value_set_int ((expr->value = gda_value_new (G_TYPE_INT)), 0);

	/* replace any selected field which has a parameter with NULL */
	gda_sql_any_part_foreach (GDA_SQL_ANY_PART (stsel), (GdaSqlForeachFunc) param_to_null_foreach,
				  NULL, NULL);

	/* create new statement */
	estmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
	gda_sql_statement_free (sqlst);
	return estmt;
}
void
_midgard_query_group_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *self, 
		GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node, GError **error)
{	
	guint n_objects;
	guint i;
	MidgardQueryConstraintSimple **constraints = 
		midgard_query_constraint_simple_list_constraints (MIDGARD_QUERY_CONSTRAINT_SIMPLE (self), &n_objects);
	if (!constraints)
		return;

	GdaSqlStatementSelect *select = stmt->contents;
	GdaSqlExpr *top_where = NULL, *where;
	GdaSqlOperation *top_operation, *operation;	
	
	/* Create base top expression and operation */
	if (!select->where_cond) {
		top_where = gda_sql_expr_new (GDA_SQL_ANY_PART (select));
		top_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (top_where));
		top_operation->operator_type = MIDGARD_QUERY_CONSTRAINT_GROUP (self)->priv->op_type;
		top_where->cond = top_operation;
	     	gda_sql_statement_select_take_where_cond (stmt, top_where);	
	} else if (where_expr_node) {
		/* This is nested groups case: '... AND (f2=1 OR f2=2)...' */
		where = where_expr_node;
		operation = where->cond;
		top_where = gda_sql_expr_new (GDA_SQL_ANY_PART (operation));
		top_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (where_expr_node));
		top_operation->operator_type = MIDGARD_QUERY_CONSTRAINT_GROUP (self)->priv->op_type;
		top_where->cond = top_operation;
		operation->operands = g_slist_append (operation->operands, top_where);
	}

	for (i = 0; i < n_objects; i++) {

		GError *err = NULL;
		MIDGARD_QUERY_CONSTRAINT_SIMPLE_GET_INTERFACE (constraints[i])->priv->add_conditions_to_statement (executor, MIDGARD_QUERY_CONSTRAINT_SIMPLE (constraints[i]), stmt, top_where, &err);
		if (err)
			g_propagate_error (error, err);
	}

	g_free (constraints);
}
/**
 * gda_sql_expr_copy
 * @expr: a #GdaSqlExpr
 *
 * Creates a new #GdaSqlExpr structure initiated with the values stored in @expr.
 *
 * Returns: a new #GdaSqlExpr structure.
 */
GdaSqlExpr *
gda_sql_expr_copy (GdaSqlExpr *expr)
{
	GdaSqlExpr *copy;
	if (!expr) return NULL;

	copy = gda_sql_expr_new (NULL);
	if (expr->value) {
		GValue *value;

		value = g_new0 (GValue, 1);
		g_value_init (value, G_VALUE_TYPE (expr->value));
		g_value_copy (expr->value, value);
		copy->value = value;
	}
	copy->param_spec = gda_sql_param_spec_copy (expr->param_spec);

	copy->func = gda_sql_function_copy (expr->func);
	gda_sql_any_part_set_parent (copy->func, copy);

	copy->cond = gda_sql_operation_copy (expr->cond);
	gda_sql_any_part_set_parent (copy->cond, copy);

	if (expr->select) {
		if (GDA_SQL_ANY_PART (expr->select)->type == GDA_SQL_ANY_STMT_SELECT)
			copy->select = _gda_sql_statement_select_copy (expr->select);
		else if (GDA_SQL_ANY_PART (expr->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
			copy->select = _gda_sql_statement_compound_copy (expr->select);
		else
			g_assert_not_reached ();
		gda_sql_any_part_set_parent (copy->select, copy);
	}

	copy->case_s = gda_sql_case_copy (expr->case_s);
	gda_sql_any_part_set_parent (copy->case_s, copy);

	if (expr->cast_as)
		copy->cast_as = g_strdup (expr->cast_as);

	copy->value_is_ident = expr->value_is_ident;
	return copy;
}
static gpointer
gda_sql_statement_insert_copy (gpointer src)
{
	GdaSqlStatementInsert *dest;
	GSList *list;
	GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) src;

	dest = gda_sql_statement_insert_new ();
	if (insert->on_conflict)
		dest->on_conflict = g_strdup (insert->on_conflict);

	dest->table = gda_sql_table_copy (insert->table);
	gda_sql_any_part_set_parent (dest->table, dest);
	
	for (list = insert->fields_list; list; list = list->next) {
		dest->fields_list = g_slist_prepend (dest->fields_list, 
						     gda_sql_field_copy ((GdaSqlField*) list->data));
		gda_sql_any_part_set_parent (dest->fields_list->data, dest);
	}
	dest->fields_list = g_slist_reverse (dest->fields_list);

	for (list = insert->values_list; list; list = list->next) {
		GSList *vlist, *clist = NULL;
		for (vlist = (GSList *) list->data; vlist; vlist = vlist->next) {
			clist = g_slist_prepend (clist,
						 gda_sql_expr_copy ((GdaSqlExpr*) vlist->data));
			gda_sql_any_part_set_parent (clist->data, dest);
		}
		dest->values_list = g_slist_append (dest->values_list, g_slist_reverse (clist));
	}
	if (insert->select) {
		if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT)
			dest->select = _gda_sql_statement_select_copy (insert->select);
		else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
			dest->select = _gda_sql_statement_compound_copy (insert->select);
		else
			g_assert_not_reached ();
		gda_sql_any_part_set_parent (dest->select, dest);
	}

	return dest;
}
/**
 * gda_sql_statement_insert_take_select
 * @stmt: a #GdaSqlStatement pointer
 * @select: a SELECT or COMPOUND #GdaSqlStatement pointer
 *
 * Specifies a SELECT statement, the values inserted will be the result set of @select. @select's 
 * ownership is transferred to
 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
 */
void
gda_sql_statement_insert_take_select (GdaSqlStatement *stmt, GdaSqlStatement *select)
{
	GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
	GdaSqlAnyPart *part;
	part = GDA_SQL_ANY_PART (select->contents);
	select->contents = NULL;
	gda_sql_statement_free (select);
	insert->select = _gda_sql_statement_compound_reduce (part);
	gda_sql_any_part_set_parent (insert->select, insert);	
}