258 lines
6.8 KiB
C
258 lines
6.8 KiB
C
/*
|
|
* Copyright (C) 2012 - Juan Ferrer Toribio
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "sql-join.h"
|
|
#include "sql-field.h"
|
|
#include "sql-holder.h"
|
|
|
|
/**
|
|
* SECTION: sql-join
|
|
* @Short_description: the equivalent of the SQL JOIN.
|
|
* @Title: SqlJoin
|
|
*
|
|
* The #SqlJoin represents a joins between any targets.
|
|
**/
|
|
G_DEFINE_TYPE (SqlJoin, sql_join, SQL_TYPE_TARGET);
|
|
|
|
SqlObject * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type)
|
|
{
|
|
return g_object_new (SQL_TYPE_JOIN
|
|
,"target-left" ,left
|
|
,"target-right" ,right
|
|
,"join-type" ,type
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
|
|
|
|
static const gchar * SQL_JOIN_TYPE[] =
|
|
{
|
|
"INNER"
|
|
,"LEFT"
|
|
,"RIGHT"
|
|
};
|
|
|
|
static void sql_join_render (SqlJoin * obj, SqlRender * render)
|
|
{
|
|
sql_render_add_item (render, TRUE, NULL, obj->target_left);
|
|
sql_render_add_token (render, SQL_JOIN_TYPE[obj->type]);
|
|
sql_render_add_token (render, "JOIN");
|
|
sql_render_add_item (render, TRUE, NULL, obj->target_right);
|
|
|
|
if (obj->has_using)
|
|
{
|
|
sql_render_add_token (render, "USING");
|
|
sql_render_append (render, "(");
|
|
sql_render_add_list (render, TRUE, NULL, obj->using_fields, ",");
|
|
sql_render_append (render, ")");
|
|
}
|
|
else
|
|
sql_render_add_item (render, FALSE, "ON", obj->condition);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
|
|
|
|
void sql_join_set_target_left (SqlJoin * obj, SqlTarget * target)
|
|
{
|
|
g_return_if_fail (SQL_IS_JOIN (obj));
|
|
g_return_if_fail (SQL_IS_TARGET (target) || SQL_IS_HOLDER (target) || !target);
|
|
|
|
sql_object_remove (obj, obj->target_left);
|
|
obj->target_left = sql_object_add (obj, target);
|
|
}
|
|
|
|
void sql_join_set_target_right (SqlJoin * obj, SqlTarget * target)
|
|
{
|
|
g_return_if_fail (SQL_IS_JOIN (obj));
|
|
g_return_if_fail (SQL_IS_TARGET (target) || SQL_IS_HOLDER (target) || !target);
|
|
|
|
sql_object_remove (obj, obj->target_right);
|
|
obj->target_right = sql_object_add (obj, target);
|
|
}
|
|
|
|
void sql_join_set_condition (SqlJoin * obj, SqlExpr * condition)
|
|
{
|
|
g_return_if_fail (SQL_IS_JOIN (obj));
|
|
g_return_if_fail (SQL_IS_EXPR (condition) || SQL_IS_HOLDER (condition) || !condition);
|
|
|
|
sql_object_remove (obj, obj->condition);
|
|
obj->condition = sql_object_add (obj, condition);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
|
|
|
|
enum
|
|
{
|
|
PROP_TARGET_LEFT = 1
|
|
,PROP_TARGET_RIGHT
|
|
,PROP_TYPE
|
|
,PROP_CONDITION
|
|
,PROP_HAS_USING
|
|
,PROP_USING_FIELDS
|
|
};
|
|
|
|
static void sql_join_set_property (SqlJoin * obj, guint id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
switch (id)
|
|
{
|
|
case PROP_TARGET_LEFT:
|
|
sql_join_set_target_left (obj, g_value_get_object (value));
|
|
break;
|
|
case PROP_TARGET_RIGHT:
|
|
sql_join_set_target_right (obj, g_value_get_object (value));
|
|
break;
|
|
case PROP_TYPE:
|
|
obj->type = g_value_get_enum (value);
|
|
break;
|
|
case PROP_CONDITION:
|
|
sql_join_set_condition (obj, g_value_get_object (value));
|
|
break;
|
|
case PROP_HAS_USING:
|
|
obj->has_using = g_value_get_boolean (value);
|
|
break;
|
|
case PROP_USING_FIELDS:
|
|
sql_object_remove (obj, obj->using_fields);
|
|
obj->using_fields = sql_object_add (obj, g_value_get_object (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
|
|
}
|
|
}
|
|
|
|
static void sql_join_get_property (SqlJoin * obj, guint id,
|
|
GValue * value, GParamSpec * pspec)
|
|
{
|
|
switch (id)
|
|
{
|
|
case PROP_TARGET_LEFT:
|
|
g_value_set_object (value, obj->target_left);
|
|
break;
|
|
case PROP_TARGET_RIGHT:
|
|
g_value_set_object (value, obj->target_right);
|
|
break;
|
|
case PROP_TYPE:
|
|
g_value_set_enum (value, obj->type);
|
|
break;
|
|
case PROP_CONDITION:
|
|
g_value_set_object (value, obj->condition);
|
|
break;
|
|
case PROP_HAS_USING:
|
|
g_value_set_boolean (value, obj->has_using);
|
|
break;
|
|
case PROP_USING_FIELDS:
|
|
g_value_set_object (value, obj->using_fields);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
|
|
}
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
|
|
|
|
static void sql_join_init (SqlJoin * obj)
|
|
{
|
|
obj->target_left = NULL;
|
|
obj->target_right = NULL;
|
|
obj->condition = NULL;
|
|
obj->using_fields = NULL;
|
|
}
|
|
|
|
static void sql_join_finalize (SqlJoin * obj)
|
|
{
|
|
sql_object_remove (obj, obj->target_left);
|
|
sql_object_remove (obj, obj->target_right);
|
|
sql_object_remove (obj, obj->condition);
|
|
sql_object_remove (obj, obj->using_fields);
|
|
G_OBJECT_CLASS (sql_join_parent_class)->finalize (G_OBJECT (obj));
|
|
}
|
|
|
|
static void sql_join_class_init (SqlJoinClass * klass)
|
|
{
|
|
GObjectClass * k = G_OBJECT_CLASS (klass);
|
|
k->finalize = (GObjectFinalizeFunc) sql_join_finalize;
|
|
k->set_property = (GObjectSetPropertyFunc) sql_join_set_property;
|
|
k->get_property = (GObjectGetPropertyFunc) sql_join_get_property;
|
|
SQL_OBJECT_CLASS (klass)->render = (SqlRenderFunc) sql_join_render;
|
|
|
|
g_object_class_install_property (k, PROP_TARGET_LEFT,
|
|
sql_param_list ("target-left"
|
|
,("Left target")
|
|
,("The left target in the join")
|
|
,SQL_TYPE_TARGET
|
|
,G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_TARGET_RIGHT,
|
|
sql_param_list ("target-right"
|
|
,("Right target")
|
|
,("The right target in the join")
|
|
,SQL_TYPE_TARGET
|
|
,G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_TYPE,
|
|
g_param_spec_enum ("join-type"
|
|
,("Type")
|
|
,("The type of join")
|
|
,SQL_TYPE_JOIN_TYPE
|
|
,SQL_JOIN_TYPE_INNER
|
|
,G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_CONDITION,
|
|
sql_param_list ("condition"
|
|
,("Condition")
|
|
,("The condition used for the join")
|
|
,SQL_TYPE_EXPR
|
|
,G_PARAM_READWRITE
|
|
));
|
|
g_object_class_install_property (k, PROP_HAS_USING,
|
|
g_param_spec_boolean ("has-using"
|
|
,("Has using")
|
|
,("Wether the condition is a USING")
|
|
,FALSE
|
|
,G_PARAM_READWRITE | G_PARAM_CONSTRUCT
|
|
));
|
|
g_object_class_install_property (k, PROP_CONDITION,
|
|
sql_param_list ("using-fields"
|
|
,("Using fields")
|
|
,("The list of fields of the USING")
|
|
,SQL_TYPE_FIELD
|
|
,G_PARAM_READWRITE | G_PARAM_CONSTRUCT
|
|
));
|
|
}
|
|
|
|
GType sql_join_type_get_type ()
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (type == 0)
|
|
{
|
|
static const GEnumValue values[] =
|
|
{
|
|
{SQL_JOIN_TYPE_INNER ,"SQL_JOIN_TYPE_INNER" ,"inner"
|
|
},{SQL_JOIN_TYPE_LEFT ,"SQL_JOIN_TYPE_LEFT" ,"left"
|
|
},{SQL_JOIN_TYPE_RIGHT ,"SQL_JOIN_TYPE_RIGHT" ,"right"
|
|
},{0, NULL, NULL}
|
|
};
|
|
|
|
type = g_enum_register_static
|
|
(g_intern_static_string ("SqlJoinType"), values);
|
|
}
|
|
|
|
return type;
|
|
}
|