static void __join_reference(MidgardQueryBuilder *builder, const gchar *src_table, const gchar *ref_table) { /* Join guid and parent_guid */ MidgardCoreQueryConstraint *jc = midgard_core_query_constraint_new(); GString *jstr = g_string_new(""); g_string_append_printf(jstr,"%s.parent_guid = %s.guid", ref_table, src_table); jc->priv->condition = g_strdup(jstr->str); g_string_free(jstr, TRUE); midgard_core_qb_add_constraint(builder,jc); /* limit to records which are not deleted */ MidgardCoreQueryConstraint *dc = midgard_core_query_constraint_new(); GString *dstr = g_string_new(""); g_string_append_printf(dstr,"%s.metadata_deleted = 0", ref_table); dc->priv->condition = g_string_free(dstr, FALSE); midgard_core_qb_add_constraint(builder,dc); return; }
/** * midgard_query_builder_add_constraint_with_property: * @builder: #MidgardQueryBuilder instance * @property_a: property name * @op: comparison operator * @property_b: property name * * Adds named property constraint to the given query builder. * Unlike add_constraint method, this one accepts property name * instead of scalar value. The difference is that with add_constraint * method you can compare property with particular value, while using * add_constraint_with_property method you can compare two different * properties without any need to know their values. * For example, you should use this method if you want to select only * those objects which has been revised after publication time, and particular * date doesn't matter. * * <example> * <programlisting> * * midgard_query_builder_add_constraint_with_property(builder, "metadata.revised", ">", "metadata.published"); * * </programlisting> * </example> * * @See: midgard_query_builder_add_constraint() * * Returns: %TRUE if properties' names are valid, %FALSE otherwise */ gboolean midgard_query_builder_add_constraint_with_property( MidgardQueryBuilder *builder, const gchar *property_a, const gchar *op, const gchar *property_b) { g_assert(builder != NULL); g_assert(property_a != NULL); g_assert(op != NULL); g_assert(property_b != NULL); MidgardDBObjectClass *klass = MIDGARD_DBOBJECT_CLASS(g_type_class_peek(builder->priv->type)); MidgardCoreQueryConstraint *constraint = midgard_core_query_constraint_new(); midgard_core_query_constraint_set_builder(constraint, builder); midgard_core_query_constraint_set_class(constraint, klass); if(!midgard_core_query_constraint_parse_property(&constraint, klass, property_a)) return FALSE; constraint->priv->current = constraint->priv->prop_right; if(!midgard_core_query_constraint_parse_property(&constraint, klass, property_b)) return FALSE; constraint->priv->condition_operator = g_strdup(op); midgard_core_query_constraint_build_condition(constraint); midgard_core_qb_add_table(builder, constraint->priv->prop_left->table); midgard_core_qb_add_table(builder, constraint->priv->prop_right->table); if(builder->priv->grouping_ref > 0) { MidgardGroupConstraint *group = builder->priv->group_constraint; midgard_group_constraint_add_constraint(group, constraint); return TRUE; } else { midgard_core_qb_add_constraint(builder, constraint); } return TRUE; }
/** * midgard_query_builder_add_constraint(): * @builder: #MidgardQueryBuilder instance * @name: property name used for this constraint * @op: comparison operator * @value: value used in comparison * * Adds a constraint to the given query builder. The constraint is * expressed as a triple of a field name, a comparison operator, and * a comparison value. * * <para> * @name referes to a property of the queried Midgard object class. * For example: #MidgardQueryBuilder has been initialized for person * class which has lastname property registered. * <example> * <programlisting> * * GValue value = {0, }; * g_value_init(&value, G_TYPE_STRING); * g_value_set_string(&value, "smith"); * * midgard_query_builder_add_constraint(builder, "lastname", "=", &value); * * </programlisting> * </example> * </para> * <para> * It also can be name of the linked class property or reserved one. * A dot '.' is used to separate properties for special constraints. * If such special constraint property is used, #MidgardQueryBuilder * performs right join. * <itemizedlist> * <listitem><para> * First property is the one registered for given class which is a link * to property of different class. Second is a property of target class. * For example: person object has property 'friend' which holds some identifier * (id or guid) to friend class property, and friend class has property 'nick'. * In such case we can use constraint and comparison using friend property, * even if #MidgardQueryBuilder has been initialized for person class. * <example> * <programlisting> * * GValue value = {0, }; * g_value_init(&value, G_TYPE_STRING); * g_value_set_string(&value, "Lancelot"); * * midgard_query_builder_add_constraint(builder, "friend.nick", "=", &value); * * </programlisting> * </example> * </para></listitem> * <listitem><para> * There are three reserved words which have special meaning for query builder. * 'metadata', 'parameter' and 'attachment'. If one of them is used, query builder * will make (if necessary) right join and query objects against dependent class table. * <example> * <programlisting> * * GValue value = {0, }; * g_value_init(&value, G_TYPE_STRING); * g_value_set_string(&value, "avatar"); * * midgard_query_builder_add_constraint(builder, "attachment.name", "=", &value); * * </programlisting> * </example> * </para></listitem> * </itemizedlist> * </para> * * <para> * The comparison operator is a string representation of the requested comparison. * Available operators are =, <>, <, >, <=, >=, LIKE, NOT LIKE, IN, INTREE. * </para> * * <para> * The given @value is copied and converted into the property type before comparison. * </para> * * Returns: %TRUE if constraint is valid, %FALSE otherwise */ gboolean midgard_query_builder_add_constraint( MidgardQueryBuilder *builder, const gchar *name, const gchar *op, const GValue *value) { g_assert(builder); g_assert(name); g_assert(op); g_assert(value); MidgardCoreQueryConstraint *constraint = midgard_core_query_constraint_new(); midgard_core_query_constraint_set_builder(constraint, builder); midgard_core_query_constraint_set_class(constraint, MIDGARD_DBOBJECT_CLASS(g_type_class_peek(builder->priv->type))); if(!midgard_core_query_constraint_add_operator(constraint, op)) return FALSE; if(!midgard_core_query_constraint_parse_property(&constraint, MIDGARD_DBOBJECT_CLASS(g_type_class_peek(builder->priv->type)), name)) return FALSE; if(!midgard_core_query_constraint_add_value(constraint, value)) return FALSE; midgard_core_query_constraint_build_condition(constraint); /* FIXME, table should be stored per every constraint, order, whatever */ midgard_core_qb_add_table(builder, constraint->priv->prop_left->table); if(builder->priv->grouping_ref > 0) { MidgardGroupConstraint *group = (MidgardGroupConstraint *)builder->priv->group_constraint; midgard_group_constraint_add_constraint(group, constraint); return TRUE; } midgard_core_qb_add_constraint(builder, constraint); return TRUE; }