2014-05-29 14:32:28 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 - Juan Ferrer Toribio
|
|
|
|
*
|
|
|
|
* This file is part of Hedera.
|
|
|
|
*
|
|
|
|
* Hedera 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DbUpdatedField:
|
|
|
|
* @column: the position of the field in the row
|
|
|
|
* @value: the old value of the updated field
|
|
|
|
*
|
|
|
|
* Previous value of an updated field.
|
|
|
|
**/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gint column;
|
|
|
|
GValue * value;
|
|
|
|
}
|
|
|
|
DbUpdatedField;
|
|
|
|
|
|
|
|
static void db_updated_field_free (DbUpdatedField * u)
|
|
|
|
{
|
|
|
|
if (u && u->value)
|
|
|
|
{
|
|
|
|
g_value_unset (u->value);
|
|
|
|
g_free (u->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (u);
|
|
|
|
u = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DbOperation:
|
|
|
|
* @type: #DbModelRowOp flags
|
|
|
|
* @locked: %TRUE while the operation is being performed
|
|
|
|
* @row: the #DbRow over which the operation has been performed
|
|
|
|
* @updated: (element-type Db.UpdatedField): old values for the updated fields
|
|
|
|
* in @row
|
|
|
|
* @request: #DbRequest associated to the operation, once performed
|
|
|
|
*
|
|
|
|
* A structure explaining the operations performed over each #DbRow.
|
|
|
|
**/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
DbModelRowOp type;
|
|
|
|
gboolean locked;
|
|
|
|
DbRow * row;
|
|
|
|
GSList * updated;
|
|
|
|
}
|
|
|
|
DbOperation;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DbModelRequest:
|
|
|
|
* @request: a DbRequest being performed
|
|
|
|
* @operations: a GQueue of operations being performed
|
|
|
|
* @model: the DbModel over which the operations are being performed
|
|
|
|
*
|
|
|
|
* This struct holds the information of a request performed but not yet
|
|
|
|
* finalized.
|
|
|
|
**/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
DbModel * obj;
|
|
|
|
GQueue * operations;
|
|
|
|
SqlList * stmts;
|
|
|
|
}
|
|
|
|
DbModelRequest;
|
|
|
|
|
|
|
|
//----------------------------------------------- Field
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar * name;
|
|
|
|
gchar * target;
|
|
|
|
gchar * schema;
|
|
|
|
}
|
|
|
|
Field;
|
|
|
|
|
2014-05-30 09:19:53 +00:00
|
|
|
#define remove_delimiters(str) (g_strdup (g_strstrip (g_strdelimit (str, "`\"", ' '))))
|
2014-05-29 14:32:28 +00:00
|
|
|
|
|
|
|
static void field_parse (Field * field, const gchar * string)
|
|
|
|
{
|
|
|
|
gchar ** split = g_strsplit (string, ".", 0);
|
|
|
|
guint len = g_strv_length (split);
|
|
|
|
|
|
|
|
field->name = len > 0 ? remove_delimiters (split[--len]) : NULL;
|
|
|
|
field->target = len > 0 ? remove_delimiters (split[--len]) : NULL;
|
|
|
|
field->schema = len > 0 ? remove_delimiters (split[--len]) : NULL;
|
|
|
|
|
|
|
|
g_strfreev (split);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Field * field_new_from_string (const gchar * string)
|
|
|
|
{
|
|
|
|
Field * field = g_new (Field, 1);
|
|
|
|
field_parse (field, string);
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void field_clear (Field * field)
|
|
|
|
{
|
|
|
|
g_free (field->name);
|
|
|
|
g_free (field->target);
|
|
|
|
g_free (field->schema);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void field_free (Field * field)
|
|
|
|
{
|
|
|
|
field_clear (field);
|
|
|
|
g_free (field);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean field_equal (const Field * a, const Field * b)
|
|
|
|
{
|
|
|
|
return !g_strcmp0 (a->name, b->name)
|
|
|
|
&& !g_strcmp0 (a->target, b->target)
|
|
|
|
&& !g_strcmp0 (a->schema, b->schema);
|
|
|
|
}
|
|
|
|
|
|
|
|
static guint field_hash (const Field * field)
|
|
|
|
{
|
|
|
|
return g_str_hash (field->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------- Table
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar * name;
|
|
|
|
gchar * schema;
|
|
|
|
}
|
|
|
|
Table;
|
|
|
|
|
|
|
|
static void table_parse (Table * table, const gchar * string)
|
|
|
|
{
|
|
|
|
gchar ** split = g_strsplit (string, ".", 0);
|
|
|
|
guint len = g_strv_length (split);
|
|
|
|
|
|
|
|
table->name = len > 0 ? remove_delimiters (split[--len]) : NULL;
|
|
|
|
table->schema = len > 0 ? remove_delimiters (split[--len]) : NULL;
|
|
|
|
|
|
|
|
g_strfreev (split);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Table * table_copy (Table * src)
|
|
|
|
{
|
|
|
|
Table * table = g_new0 (Table, 1);
|
|
|
|
table->name = g_strdup (src->name);
|
|
|
|
table->schema = g_strdup (src->schema);
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void table_free (Table * table)
|
|
|
|
{
|
|
|
|
g_free (table->name);
|
|
|
|
g_free (table->schema);
|
|
|
|
g_free (table);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean table_equal (const Table * a, const Table * b)
|
|
|
|
{
|
|
|
|
return !g_strcmp0 (a->name, b->name)
|
|
|
|
&& !g_strcmp0 (a->schema, b->schema);
|
|
|
|
}
|
|
|
|
|
|
|
|
static guint table_hash (const Table * table)
|
|
|
|
{
|
|
|
|
return g_str_hash (table->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean table_has_column (Table * table, DbColumn * column)
|
|
|
|
{
|
|
|
|
return !g_strcmp0 (column->table, table->name)
|
|
|
|
&& !g_strcmp0 (column->schema, table->schema);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------- TableData
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GSList * pkeys;
|
|
|
|
}
|
|
|
|
TableData;
|
|
|
|
|
|
|
|
static void table_data_free (TableData * table_data)
|
|
|
|
{
|
|
|
|
g_slist_free (table_data->pkeys);
|
|
|
|
g_free (table_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------- ParamDef
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GvnParam * param;
|
|
|
|
SqlObject * equal_op;
|
|
|
|
SqlObject * link_op;
|
|
|
|
}
|
|
|
|
ParamDef;
|
|
|
|
|
|
|
|
static void param_def_free (ParamDef * def)
|
|
|
|
{
|
|
|
|
g_object_unref (def->param);
|
|
|
|
|
|
|
|
if (def->equal_op)
|
|
|
|
{
|
|
|
|
SqlObject * operators = sql_object_get (def->link_op, "operators");
|
|
|
|
sql_list_remove_item (SQL_LIST (operators), def->equal_op);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (def);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------- ColumnDef
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
PARAM_DEF,
|
|
|
|
FIELD_DEF
|
|
|
|
}
|
|
|
|
DefType;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
Field * field;
|
|
|
|
gpointer def;
|
|
|
|
DefType type;
|
|
|
|
}
|
|
|
|
ColumnDef;
|
|
|
|
|
|
|
|
static ColumnDef * column_def_new (DefType type, gpointer def)
|
|
|
|
{
|
|
|
|
ColumnDef * column_def = g_new (ColumnDef, 1);
|
|
|
|
column_def->type = type;
|
|
|
|
column_def->def = def;
|
|
|
|
return column_def;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void column_def_free (ColumnDef * def)
|
|
|
|
{
|
|
|
|
field_free (def->field);
|
|
|
|
|
|
|
|
switch (def->type)
|
|
|
|
{
|
|
|
|
case PARAM_DEF:
|
|
|
|
param_def_free (def->def);
|
|
|
|
break;
|
|
|
|
case FIELD_DEF:
|
|
|
|
field_free (def->def);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (def);
|
|
|
|
}
|