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/>.
|
|
|
|
*/
|
|
|
|
|
2014-06-05 15:59:35 +00:00
|
|
|
#define remove_delimiters(str) (g_strdup (g_strstrip (g_strdelimit (str, "`\"", ' '))))
|
|
|
|
|
2014-05-29 14:32:28 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2014-06-05 15:59:35 +00:00
|
|
|
//----------------------------------------------- Table
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar * name;
|
|
|
|
gchar * schema;
|
|
|
|
}
|
|
|
|
Table;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-05-29 14:32:28 +00:00
|
|
|
//----------------------------------------------- Field
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar * name;
|
|
|
|
gchar * target;
|
|
|
|
gchar * schema;
|
|
|
|
}
|
|
|
|
Field;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-06-05 15:59:35 +00:00
|
|
|
//----------------------------------------------- TableInfo
|
2014-05-29 14:32:28 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar * name;
|
|
|
|
gchar * schema;
|
2014-06-05 15:59:35 +00:00
|
|
|
gchar * alias;
|
2014-05-29 14:32:28 +00:00
|
|
|
GSList * pkeys;
|
2014-06-05 15:59:35 +00:00
|
|
|
GHashTable * columns;
|
|
|
|
GSList * parent_columns;
|
|
|
|
GSList * child_columns;
|
2014-05-29 14:32:28 +00:00
|
|
|
}
|
2014-06-05 15:59:35 +00:00
|
|
|
TableInfo;
|
2014-05-29 14:32:28 +00:00
|
|
|
|
2014-06-05 15:59:35 +00:00
|
|
|
static void table_info_free (TableInfo * table_info)
|
2014-05-29 14:32:28 +00:00
|
|
|
{
|
2014-06-05 15:59:35 +00:00
|
|
|
g_free (table_info->name);
|
|
|
|
g_free (table_info->schema);
|
|
|
|
g_free (table_info->alias);
|
|
|
|
g_slist_free (table_info->pkeys);
|
|
|
|
g_hash_table_unref (table_info->columns);
|
|
|
|
g_slist_free (table_info->parent_columns);
|
|
|
|
g_slist_free (table_info->child_columns);
|
2014-05-29 14:32:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------- ColumnDef
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2014-06-05 15:59:35 +00:00
|
|
|
gulong link;
|
|
|
|
GvnParam * param;
|
|
|
|
Field * src_column;
|
2014-05-29 14:32:28 +00:00
|
|
|
}
|
|
|
|
ColumnDef;
|
|
|
|
|
2014-06-05 15:59:35 +00:00
|
|
|
static ColumnDef * column_def_new ()
|
2014-05-29 14:32:28 +00:00
|
|
|
{
|
|
|
|
ColumnDef * column_def = g_new (ColumnDef, 1);
|
2014-06-05 15:59:35 +00:00
|
|
|
column_def->link = 0;
|
|
|
|
column_def->param = NULL;
|
|
|
|
column_def->src_column = NULL;
|
2014-05-29 14:32:28 +00:00
|
|
|
return column_def;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void column_def_free (ColumnDef * def)
|
|
|
|
{
|
2014-06-05 15:59:35 +00:00
|
|
|
if (def->param)
|
2014-05-29 14:32:28 +00:00
|
|
|
{
|
2014-06-05 15:59:35 +00:00
|
|
|
if (def->link)
|
|
|
|
g_signal_handler_disconnect (def->param, def->link);
|
|
|
|
|
|
|
|
g_object_unref (def->param);
|
2014-05-29 14:32:28 +00:00
|
|
|
}
|
2014-06-05 15:59:35 +00:00
|
|
|
if (def->src_column)
|
|
|
|
field_free (def->src_column);
|
2014-05-29 14:32:28 +00:00
|
|
|
|
|
|
|
g_free (def);
|
|
|
|
}
|