Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
MidgardQueryOrder *midgard_core_query_order_new(
		MidgardQueryBuilder *builder, const gchar *name, const gchar *dir)
{
	g_assert(builder != NULL);
	g_assert(name != NULL);

	const gchar *user_dir = dir;

	if(user_dir == NULL)
		user_dir = "ASC";

	guint i = 0;
	while(valid_dirs[i] != NULL) {
		
		if (g_str_equal(user_dir, valid_dirs[i])) 
			break;

		i++;
	}

	if(valid_dirs[i] == NULL) {
		
		 g_warning("Invalid order direction: %s", dir);
		 return NULL;
	}

        MidgardQueryOrder *order = g_new(MidgardQueryOrder, 1);

	order->constraint = midgard_core_query_constraint_new();
	order->constraint->priv->order_dir = g_strdup(dir);

	/* Explicitly set builder. It's required for proper constraint's property "parser".
	 * Without builder, implicit joins (for example) are not added */
	midgard_core_query_constraint_set_builder(order->constraint, builder);

	MidgardDBObjectClass *klass = MIDGARD_DBOBJECT_CLASS(g_type_class_peek(builder->priv->type));

	if(!midgard_core_query_constraint_parse_property(&(order->constraint), klass, name)) {

		midgard_core_query_order_free(order);
		return FALSE;
	}

	midgard_core_qb_add_table(builder, order->constraint->priv->prop_left->table);

        return order;
}
Ejemplo n.º 3
0
/**
 * 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;
}
Ejemplo n.º 4
0
static void __get_view_constraints(xmlNode *node, MgdSchemaTypeAttr *type)
{
	xmlNode *cur;

	for (cur = node->children; cur; cur = cur->next) {
	
		if (cur->type == XML_ELEMENT_NODE 
				&& g_str_equal(cur->name, "constraint")) { /* FIXME, add constraint to reserved words constants */
			
			xmlChar *property = xmlGetProp(cur, (const xmlChar *)"property");

			if (!property || (property && *property == '\0'))
				__view_error(cur, "Can not add constraint with empty property", NULL);

			gchar **classprop = g_strsplit((gchar *)property, ":", 2);
			if (!classprop || classprop[0] == NULL || classprop[1] == NULL) {
				__view_error(cur, "Constraint property misconfigured", NULL);
				return;
			}

			MidgardDBObjectClass *klass = 
				MIDGARD_DBOBJECT_CLASS(MIDGARD_OBJECT_GET_CLASS_BY_NAME((const gchar *)classprop[0]));
			if (!klass)
				__view_error(cur, "Class %s not registered", classprop[0]);

			MidgardCoreQueryConstraint *constraint = midgard_core_query_constraint_new();
			if (!midgard_core_query_constraint_parse_property(&constraint, klass, classprop[1]))
				__view_error(cur, "Can not parse %s constraint property", classprop[1]);

			g_strfreev(classprop);
			xmlFree(property);
			
			/* Add operator */
			xmlChar *operator = xmlGetProp(cur, (const xmlChar *)"operator");
			if (!operator || (operator && *operator == '\0'))
				__view_error(cur, "Can not add constraint with empty operator", NULL);
			if (!midgard_core_query_constraint_add_operator(constraint, (const gchar *)operator))
				__view_error(cur, "Invalid operator", NULL);
			xmlFree(operator);

			/* Add value */
			xmlChar *valtype = xmlGetProp(cur, (const xmlChar *)"value_type");
			if (!valtype || (valtype && *valtype == '\0'))
				__view_error(cur, "Can not add constraint with empty value_type", NULL);

			GType vtype = midgard_core_schema_gtype_from_string((const gchar *)valtype);
			if (!vtype)
				__view_error(cur, "Invalid %s value_type", valtype);

			xmlFree(valtype);

			xmlChar *value = xmlGetProp(cur, (const xmlChar *)"value");
			if (!value || (value && *value == '\0'))
				__view_error(cur, "Can not add constraint with empty value", NULL);

			/* Get value as string and convert to declared type */
			GValue strval = {0, };
			g_value_init(&strval, G_TYPE_STRING);
			g_value_set_string(&strval, (const gchar *)value);

			GValue val = {0, };
			g_value_init(&val, vtype);
			g_value_transform((const GValue *) &strval, &val);
		
			midgard_core_query_constraint_add_value(constraint, &val);
			midgard_core_query_constraint_build_condition(constraint);

			type->constraints = g_slist_append(type->constraints, (gpointer) constraint);
			
			g_value_unset(&val);
			g_value_unset(&strval);
			xmlFree(value);
		}
	}
}