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++; }
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_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; }
/** * gda_sql_operation_copy * @operation: a #GdaSqlOperation structure to be copied * * Creates a new #GdaSqlOperation structure initiated with the values stored in @operation. * * Returns: a new #GdaSqlOperation structure. */ GdaSqlOperation * gda_sql_operation_copy (GdaSqlOperation *operation) { GdaSqlOperation *copy; GSList *list; if (!operation) return NULL; copy = gda_sql_operation_new (NULL); copy->operator_type = operation->operator_type; for (list = operation->operands; list; list = list->next) { copy->operands = g_slist_prepend (copy->operands, gda_sql_expr_copy ((GdaSqlExpr*) list->data)); gda_sql_any_part_set_parent (copy->operands->data, copy); } copy->operands = g_slist_reverse (copy->operands); return copy; }
static void __add_exclude_deleted_constraints (MidgardQueryExecutor *self, GdaSqlStatementSelect *select, GdaSqlOperation *operation, MidgardDBObjectClass *dbklass) { GSList *l = select->from->targets; const gchar *deleted_field = midgard_core_object_get_deleted_field (dbklass); gboolean bool_is_int = MIDGARD_QUERY_EXECUTOR (self)->priv->bool_is_int; /* We have only one target table, so create one expression and add to top operation */ if (g_slist_length (l) == 1) { if (!deleted_field) return; GdaSqlSelectTarget *target = (GdaSqlSelectTarget *) l->data; GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (operation)); expr->value = gda_value_new (G_TYPE_STRING); g_value_take_string (expr->value, g_strdup_printf ("%s.%s = %s", target->as, deleted_field, __BOOL_VALUE (bool_is_int))); operation->operands = g_slist_append (operation->operands, expr); return; } /* Create new constraint group, (t1.deleted AND t2.deleted AND ...) */ GdaSqlExpr *deleted_expr = gda_sql_expr_new (GDA_SQL_ANY_PART (operation)); GdaSqlOperation *deleted_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (deleted_expr)); deleted_operation->operator_type = GDA_SQL_OPERATOR_TYPE_AND; deleted_expr->cond = deleted_operation; operation->operands = g_slist_append (operation->operands, deleted_expr); /* FIXME, we do not have own klass list involved in query */ /* Add metadata_deleted constraint for each statement's table */ for (l = select->from->targets; l != NULL; l = l->next) { GdaSqlSelectTarget *target = (GdaSqlSelectTarget *) l->data; GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (operation)); expr->value = gda_value_new (G_TYPE_STRING); g_value_take_string (expr->value, g_strdup_printf ("%s.metadata_deleted = %s", target->as, __BOOL_VALUE (bool_is_int))); deleted_operation->operands = g_slist_append (deleted_operation->operands, expr); } }
void _midgard_query_constraint_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *constraint_simple, GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node) { MidgardQueryConstraint *self = MIDGARD_QUERY_CONSTRAINT (constraint_simple); //GdaConnection *cnc = executor->priv->mgd->priv->connection; MidgardDBObjectClass *dbklass = NULL; if (self->priv->storage && (self->priv->storage != MIDGARD_QUERY_EXECUTOR (executor)->priv->storage)) { dbklass = self->priv->storage->priv->klass; MQE_SET_TABLE_ALIAS (executor, self->priv->storage); } if (!dbklass) dbklass = executor->priv->storage->priv->klass; g_return_if_fail (dbklass != NULL); /* Get table */ //const gchar *table = midgard_core_class_get_table (dbklass); /* Get field name */ GValue field_value = {0, }; midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (MIDGARD_QUERY_CONSTRAINT (constraint_simple)->priv->property_value), &field_value); GdaSqlStatementSelect *select = stmt->contents; GdaSqlExpr *top_where, *where, *expr; GdaSqlOperation *top_operation, *cond; GValue *value; 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; /* Create table_alias.field name */ gchar *table_alias_field; expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond)); table_alias_field = midgard_core_query_compute_constraint_property (executor, MIDGARD_QUERY_CONSTRAINT (constraint_simple)->priv->storage, g_value_get_string (&field_value)); if (!table_alias_field) g_warning ("Null table.field alias for given '%s'", g_value_get_string (&field_value)); /* TODO, handle error case when table_alias_field is NULL */ 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_CONSTRAINT (constraint_simple)->priv->holder, &val); /*GType v_type = G_VALUE_TYPE (&val); //FIXME, create parameter name::type */ //GValue *dval = gda_value_new (G_TYPE_STRING); //g_value_transform (&val, dval); //expr->param_spec = gda_sql_param_spec_new (dval); //expr->param_spec->g_type = v_type; expr->value = gda_value_new (G_TYPE_STRING); __set_expression_value (expr->value, &val); g_value_unset (&val); cond->operands = g_slist_append (cond->operands, expr); /* increase executor's constraints number */ executor->priv->n_constraints++; }
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; }