From beeb26a19ea14114c2d5cdde3f8cd5292eb592c8 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Mon, 14 Oct 2013 13:53:53 +0200 Subject: [PATCH 01/10] Actualizado con los ultimos cambio locales del proyecto subversion --- sql/sql-batch.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ sql/sql-batch.h | 51 ++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 sql/sql-batch.c create mode 100644 sql/sql-batch.h diff --git a/sql/sql-batch.c b/sql/sql-batch.c new file mode 100644 index 0000000..cbbe885 --- /dev/null +++ b/sql/sql-batch.c @@ -0,0 +1,209 @@ +/* + * 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 . + */ + +#include "sql-batch.h" +#include "sql-value.h" + +/** + * SECTION: sql_batch + * @Short_description: represents an SQL statement or a part of it + * @Title: SqlBatch + * + * The #SqlBatch is the base class for all objects in SqlLib. + **/ +G_DEFINE_ABSTRACT_TYPE (SqlBatch, sql_batch, G_TYPE_INITIALLY_UNOWNED); + +enum { + CHANGED + ,LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private + +static void sql_batch_child_changed (SqlBatch * child, SqlBatch * obj) +{ + sql_batch_changed (obj); +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public + +/** + * sql_batch_is_ready: + * @obj: a #SqlBatch + * + * Checks if @obj and all of its elemens are ready to be rendered. + * + * Return value: %TRUE if ready, %FALSE otherwise. + **/ +gboolean sql_batch_is_ready (SqlBatch * obj) +{ + SqlBatchClass * klass = SQL_BATCH_GET_CLASS (obj); + + g_return_val_if_fail (SQL_IS_BATCH (obj), FALSE); + + if (obj->items) + { + GList * i; + GList * items = g_hash_table_get_values (obj->items); + gboolean is_ready = TRUE; + + for (i = items; i; i = i->next) + if (!sql_object_is_ready (i->data)) + { + is_ready = FALSE; + break; + } + + g_list_free (items); + + if (!is_ready) + return FALSE; + } + + return TRUE; +} + +/** + * sql_batch_add: + * @obj: a #SqlBatch + * @id: the id of the #SqlHolder + * @held_object: the held object + * + * Adds a held object. + **/ +void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * held_object) +{ + g_return_if_fail (SQL_IS_BATCH (obj)); + g_return_if_fail (id); + + if (!obj->held_objects) + obj->held_objects = g_hash_table_new_full ( + g_str_hash + ,g_str_equal + ,g_free + ,g_object_unref + ); + + g_signal_connect (held_object, "changed", + G_CALLBACK (sql_batch_child_changed), obj + ); + g_hash_table_replace (obj->held_objects, + g_strdup (id), g_object_ref_sink (held_object)); +} + +/** + * sql_batch_get: + * @obj: a #SqlBatch + * @id: the id of the #SqlHolder + * + * Gets a held object by its id. + * + * Return value: the #SqlObject if an object with that id exists, %NULL otherwise + **/ +SqlObject * sql_batch_get (SqlBatch * obj, const gchar * id) +{ + g_return_val_if_fail (SQL_IS_BATCH (obj), NULL); + g_return_val_if_fail (id, NULL); + + if (obj->held_objects) + return g_hash_table_lookup (obj->held_objects, id); + + return NULL; +} + +/** + * sql_batch_add_from_param: + * @obj: the #SqlString + * @id: the id assigned to the item + **/ +void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * param) +{ + g_return_if_fail (SQL_IS_BATCH (obj)); + g_return_if_fail (id); + g_return_if_fail (GVN_IS_PARAM (param)); + + SqlObject * value = sql_value_new (); + sql_value_set_param (SQL_VALUE (value), param); + sql_batch_add (obj, id, value); + g_object_unref (value); +} + +/** + * sql_batch_add_from_value: + * @obj: the #SqlString + * @id: the id assigned to the item + **/ +void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpointer content) +{ + g_return_if_fail (SQL_IS_BATCH (obj)); + g_return_if_fail (id); + + GValue gvalue = {0}; + SqlObject * value; + + gvn_value_new_with_content (&gvalue, type, content); + value = sql_value_new (); + sql_value_set_value (SQL_VALUE (value), &gvalue); + sql_batch_add (obj, id, value); + g_object_unref (value); + g_value_unset (&gvalue); +} + +/** + * sql_batch_changed: + * @obj: a #SqlBatch + * + * Emits the changed signal on #SqlBatch. + **/ +void sql_batch_changed (SqlBatch * obj) +{ + g_signal_emit (obj, signals[CHANGED], 0); +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class + +static void sql_batch_init (SqlBatch * obj) +{ + obj->items = NULL; +} + +static void sql_batch_finalize (SqlBatch * obj) +{ + if (obj->items) + g_hash_table_destroy (obj->items); + + G_OBJECT_CLASS (sql_batch_parent_class)->finalize (G_OBJECT (obj)); +} + +static void sql_batch_class_init (SqlBatchClass * klass) +{ + G_OBJECT_CLASS (klass)->finalize = (GObjectFinalizeFunc) sql_batch_finalize; + + /** + * SqlBatch::changed: + * @obj: the object which emit the signal. + * + * This signal is emitted every time the batch or one of its attributes + * is modified. + */ + signals[CHANGED] = g_signal_new ("changed", SQL_TYPE_BATCH, + G_SIGNAL_RUN_FIRST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 + ); +} diff --git a/sql/sql-batch.h b/sql/sql-batch.h new file mode 100644 index 0000000..f7bcadf --- /dev/null +++ b/sql/sql-batch.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 - 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 . + */ + +#ifndef SQL_BATCH_H +#define SQL_BATCH_H + +#include "sql-object.h" + +#define SQL_TYPE_BATCH (sql_batch_get_type ()) +#define SQL_BATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_BATCH, SqlBatch)) +#define SQL_IS_BATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_BATCH)) +#define SQL_BATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, SQL_TYPE_BATCH, SqlBatchClass)) +#define SQL_BATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS (obj, SQL_TYPE_BATCH, SqlBatchClass)) + +typedef struct _SqlBatch SqlBatch; +typedef struct _SqlBatchClass SqlBatchClass; + +struct _SqlBatch +{ + GInitiallyUnowned parent; + GHashTable * items; +}; + +struct _SqlBatchClass +{ + /* */ + GInitiallyUnownedClass parent; +}; + +GType sql_batch_get_type (); +gboolean sql_batch_is_ready (SqlBatch * obj); +void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * held_object); +SqlObject * sql_batch_get (SqlBatch * obj, const gchar * id); +void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * param); +void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpointer content); + +#endif From 67bd1ad79c2767455da0457db379bf9ccc656474 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Mon, 14 Oct 2013 13:59:07 +0200 Subject: [PATCH 02/10] Actualizado con los ultimos cambios locales del proyecto subversion --- module/data/users.glade | 5 ++-- module/src/vn-users.c | 16 ++++++----- sql/Makefile.am | 2 ++ sql/parser/gram.y | 53 +++++++----------------------------- sql/sql-delete.h | 4 +-- sql/sql-dml.c | 2 +- sql/sql-dml.h | 6 ++--- sql/sql-function.c | 12 +++------ sql/sql-function.h | 2 +- sql/sql-holder.c | 6 ++--- sql/sql-holder.h | 2 +- sql/sql-join.c | 2 +- sql/sql-join.h | 2 +- sql/sql-multi-stmt.c | 2 +- sql/sql-multi-stmt.h | 2 +- sql/sql-object.c | 60 ++--------------------------------------- sql/sql-object.h | 5 ---- sql/sql-operation.c | 2 +- sql/sql-render.c | 34 +++++++++-------------- sql/sql-select-field.c | 2 +- sql/sql-select-field.h | 4 +-- sql/sql-select-order.c | 2 +- sql/sql-select-order.h | 6 ++--- sql/sql-select.c | 9 ++++--- sql/sql-select.h | 9 +++---- sql/sql-set.c | 4 +-- sql/sql-set.h | 2 +- sql/sql-string.c | 50 ++++++---------------------------- sql/sql-string.h | 5 +--- sql/sql-subquery.c | 2 +- sql/sql-subquery.h | 2 +- sql/sql-update-set.c | 2 +- sql/sql-update-set.h | 2 +- sql/sql-update.c | 2 +- sql/sql-value.c | 8 +++--- sql/sql.h | 1 + 36 files changed, 95 insertions(+), 236 deletions(-) diff --git a/module/data/users.glade b/module/data/users.glade index 400bf00..95af7fe 100644 --- a/module/data/users.glade +++ b/module/data/users.glade @@ -3,8 +3,8 @@ - SELECT user_id, group_id, uid, last_change, expire FROM account WHERE #p on-iter + SELECT user_id, group_id, uid, last_change, expire FROM account WHERE #p SELECT mail_alias_id, user_id FROM mail_alias_account WHERE #p @@ -707,6 +707,7 @@ 6 end sip + True False @@ -899,8 +900,8 @@ - SELECT user_id, extension, secret, callerid, callgroup FROM account_sip WHERE #p on-iter + SELECT user_id, extension, secret, callerid, callgroup FROM account_sip WHERE #p SELECT u.id, u.name, u.mysql_user_id, m.user, u.active FROM `user` u JOIN mysql_user m ON u.mysql_user_id = m.id diff --git a/module/src/vn-users.c b/module/src/vn-users.c index 8c008ae..9eb2618 100644 --- a/module/src/vn-users.c +++ b/module/src/vn-users.c @@ -77,20 +77,22 @@ void vn_users_on_dialog_response (GtkDialog * dialog, gint response_id, VnUsers vn_users_reset_dialog (obj, _("Passwords do not match.")); else { - SqlString * query; + SqlObject * query; + SqlBatch * batch; - query = sql_string_new ("SELECT user_set_password (#user, #password)" - ,"user", GVN_TYPE_PARAM, obj->user_id - ,"password", G_TYPE_STRING, password - ,NULL - ); + query = sql_string_new ("SELECT user_set_password (#user, #password)"); + + batch = sql_batch_new (); + sql_batch_add_from_param ("user", obj->user_id); + sql_batch_add_from_value ("password", G_TYPE_STRING, password); db_conn_query_with_stmt_async (VN_FORM (obj)->conn ,SQL_STMT (query) + ,batch ,(DbRequestDoneCallback) vn_users_on_password_changed ,g_object_ref (obj) ,g_object_unref - ); + ); } } else diff --git a/sql/Makefile.am b/sql/Makefile.am index 66d2c13..996a978 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -10,6 +10,7 @@ sql_include_HEADERS = \ sql-param-list.h \ sql-holder.h \ sql-list.h \ + sql-batch.h \ sql-set.h \ sql-multi-stmt.h \ sql-string.h \ @@ -47,6 +48,7 @@ libsql_la_SOURCES = \ sql-param-list.c \ sql-holder.c \ sql-list.c \ + sql-batch.c \ sql-set.c \ sql-expr.c \ sql-insert.c \ diff --git a/sql/parser/gram.y b/sql/parser/gram.y index 07fac6e..980b284 100644 --- a/sql/parser/gram.y +++ b/sql/parser/gram.y @@ -44,6 +44,7 @@ } } +%default_type {SqlObject *} %token_type {gchar *} %token_destructor {g_free ($$);} %token_prefix SQL_PARSER_ @@ -94,7 +95,6 @@ // Start symbol: %start_symbol start -%type start {SqlObject *} start ::= multi_stmt (A). { state->object = SQL_OBJECT (A); @@ -102,7 +102,6 @@ start ::= multi_stmt (A). //+++++++++++++++++++++++++++++++++++++++++++++++++++ Multi statement -%type multi_stmt {SqlStmt *} multi_stmt(A) ::= stmt_list(stmts). { guint len = sql_list_length (stmts); @@ -123,7 +122,6 @@ stmt_list(A) ::= stmt(X) SC stmt_list(B). { A = list_add (X, B); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Statemet -%type stmt {SqlStmt *} stmt(A) ::= select_stmt(X). { A = X; } stmt(A) ::= delete_stmt(X). { A = X; } stmt(A) ::= update_stmt(X). { A = X; } @@ -131,7 +129,6 @@ stmt(A) ::= insert_stmt(X). { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Select -%type select_stmt {SqlStmt *} select_stmt(A) ::= select_stmt(B) set_op(type) simple_select(X). { g_object_set (B, "type", type, "next", X, NULL); @@ -146,7 +143,6 @@ set_op(A) ::= UNION. { A = SQL_SELECT_UNION_ALL; } set_op(A) ::= INTERSECT. { A = SQL_SELECT_INTERSECT; } set_op(A) ::= EXCEPT. { A = SQL_SELECT_EXCEPT; } -%type simple_select {SqlStmt *} simple_select(A) ::= LP simple_select(X) RP. { A = X; } simple_select(A) ::= SELECT distinct(distinct) @@ -182,7 +178,6 @@ distinct(A) ::= DISTINCT. { A = TRUE; } distinct(A) ::= ALL. { A = FALSE; } distinct(A) ::= . { A = FALSE; } -%type select_field {SqlSelectField *} select_field(A) ::= expr(X). { A = g_object_new (SQL_TYPE_SELECT_FIELD, "expr", X, NULL); } select_field(A) ::= expr(X) alias(Y). @@ -200,7 +195,6 @@ from(A) ::= . { A = NULL; } group(A) ::= GROUP expr_list(X). { A = X; } group(A) ::= . { A = NULL; } -%type having {SqlExpr *} having(A) ::= HAVING expr(X). { A = X; } having(A) ::= . { A = NULL; } @@ -212,7 +206,6 @@ order(A) ::= . { A = NULL; } order_list(A) ::= order_expr(X). { A = list_new (X, SQL_TYPE_SELECT_ORDER); } order_list(A) ::= order_list(B) CM order_expr(X). { A = list_add (X, B); } -%type order_expr {SqlSelectOrder *} order_expr(A) ::= expr(X) order_way(Y). { A = g_object_new (SQL_TYPE_SELECT_ORDER, "expr", X, "way", Y, NULL); } %type order_way {SqlSelectOrderWay} @@ -247,7 +240,6 @@ limit(A) ::= . { A = NULL; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Delete -%type delete_stmt {SqlStmt *} delete_stmt(A) ::= DELETE table_list(targets) del_using(tables) where(where). { A = g_object_new (SQL_TYPE_DELETE @@ -268,7 +260,6 @@ del_using(A) ::= . { A = NULL; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Update -%type update_stmt {SqlStmt *} update_stmt(A) ::= UPDATE table(table) SET update_list(sets) where(where). { A = g_object_new (SQL_TYPE_UPDATE @@ -283,7 +274,6 @@ update_stmt(A) ::= UPDATE table(table) SET update_list(sets) where(where). update_list(A) ::= update_set(X). { A = list_new (X, SQL_TYPE_UPDATE_SET); } update_list(A) ::= update_list(B) CM update_set(X). { A = list_add (X, B); } -%type update_set {SqlUpdateSet *} update_set(A) ::= field(X) EQ def_expr(Y). { A = g_object_new (SQL_TYPE_UPDATE_SET @@ -295,7 +285,6 @@ update_set(A) ::= field(X) EQ def_expr(Y). //+++++++++++++++++++++++++++++++++++++++++++++++++++ Insert -%type insert_stmt {SqlStmt *} insert_stmt(A) ::= INSERT table(table) insert_fields(fields) insert_values(values). { A = g_object_new (SQL_TYPE_INSERT @@ -323,7 +312,6 @@ insert_values(A) ::= VALUES set_list(X). { A = X; } set_list(A) ::= set(X). { A = list_new (X, SQL_TYPE_SET); } set_list(A) ::= set_list(B) CM set(X). { A = list_add (X, B); } -%type set {SqlSet *} set(A) ::= LP def_expr_list(X) RP. { A = g_object_new (SQL_TYPE_SET, "exprs", X, NULL); } %type def_expr_list {SqlList *} @@ -332,17 +320,14 @@ def_expr_list(A) ::= def_expr_list(B) CM def_expr(X). { A = list_add (X, B); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Common to statements -%type where {SqlExpr *} -where(A) ::= WHERE expr(X). { A = SQL_EXPR (X); } +where(A) ::= WHERE expr(X). { A = X; } where(A) ::= . { A = NULL; } -%type def_expr {SqlExpr *} def_expr(A) ::= expr(X). { A = X; } def_expr(A) ::= DEFAULT. { A = NULL; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Target -%type target {SqlTarget *} target(A) ::= unaliased_target(X). { A = X; } target(A) ::= unaliased_target(X) alias(Y). { @@ -355,14 +340,12 @@ target(A) ::= unaliased_target(X) alias(Y). target_list(A) ::= target(X). { A = list_new (X, SQL_TYPE_TARGET); } target_list(A) ::= target_list(B) CM target(X). { A = list_add (X, B); } -%type unaliased_target {SqlTarget *} unaliased_target(A) ::= join(X). { A = X; } unaliased_target(A) ::= subquery(X). { A = X; } unaliased_target(A) ::= table(X). { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Join -%type join {SqlTarget *} join(A) ::= target(left) join_type(type) target(right) join_cond(condition). { A = g_object_new (SQL_TYPE_JOIN @@ -391,15 +374,14 @@ join(A) ::= target(left) join_type(type) target(right) join_cond(condition). ,NULL ); - gchar * target = left->alias ? - left->alias : SQL_TABLE (left)->name; + gchar * target = SQL_TARGET (left)->alias ? SQL_TARGET (left)->alias : SQL_TABLE (left)->name; gchar * schema = SQL_IS_TABLE(left) && SQL_TABLE (left)->schema ? SQL_TABLE (left)->schema : NULL; g_object_set (n->data, "target", target, "schema", schema, NULL); sql_list_add (equal, n->data); - target = right->alias ? right->alias : SQL_TABLE (right)->name; + target = SQL_TARGET (right)->alias ? SQL_TARGET (right)->alias : SQL_TABLE (right)->name; schema = SQL_IS_TABLE (right) && SQL_TABLE (right)->schema ? SQL_TABLE (right)->schema : NULL; @@ -428,7 +410,6 @@ join_cond(A) ::= USING LP field_list(X) RP. { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Subquery -%type subquery {SqlTarget *} subquery(A) ::= LP select_stmt(stmts) RP. { A = g_object_new (SQL_TYPE_SUBQUERY, "stms", stmts, NULL); @@ -436,19 +417,17 @@ subquery(A) ::= LP select_stmt(stmts) RP. //+++++++++++++++++++++++++++++++++++++++++++++++++++ Table -%type table {SqlTarget *} table(A) ::= identifier(X). { - A = g_object_new (SQL_TYPE_TABLE, "table", X, NULL); + A = g_object_new (SQL_TYPE_TABLE, "name", X, NULL); } table(A) ::= identifier(Y) DOT identifier(X). { - A = g_object_new (SQL_TYPE_TABLE, "table", X, "schema", Y, NULL); + A = g_object_new (SQL_TYPE_TABLE, "name", X, "schema", Y, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Expr -%type expr {SqlExpr *} expr(A) ::= LP expr(X) RP. { A = X; } %type expr_list {SqlList *} @@ -462,7 +441,6 @@ expr(A) ::= value(X). { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Field -%type field {SqlExpr *} field(A) ::= unqualified_field(X). { A = X; } field(A) ::= identifier(Y) DOT unqualified_field(X). { @@ -475,7 +453,6 @@ field(A) ::= identifier(Z) DOT identifier(Y) DOT unqualified_field(X). A = X; } -%type unqualified_field {SqlExpr *} unqualified_field(A) ::= identifier(X). { A = g_object_new (SQL_TYPE_FIELD, "name", X, NULL); @@ -491,7 +468,6 @@ field_list(A) ::= field_list(B) CM field(X). { A = list_add (X, B); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Function -%type function {SqlExpr *} function(A) ::= unqualified_function(X). { A = X; } function(A) ::= identifier(Z) DOT unqualified_function(X). { @@ -499,7 +475,6 @@ function(A) ::= identifier(Z) DOT unqualified_function(X). A = X; } -%type unqualified_function {SqlExpr *} unqualified_function(A) ::= identifier(X) LP function_expr_list(Y) RP. { A = g_object_new (SQL_TYPE_FUNCTION, "name", X, "params", Y, NULL); @@ -511,10 +486,9 @@ function_expr_list(A) ::= expr_list(X). { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Operation -%type operation {SqlExpr *} %include { - static inline SqlExpr * create_operation + static inline SqlObject * create_operation (const gpointer X, const gpointer Y, const SqlOperationType type) { SqlList * exprs = sql_list_new (SQL_TYPE_EXPR); @@ -529,7 +503,7 @@ function_expr_list(A) ::= expr_list(X). { A = X; } operation(A) ::= MINUS expr(X). [SIGN] { GValue value = {0}; - SqlExpr * minus = sql_value_new (); + SqlObject * minus = sql_value_new (); g_value_init (&value, G_TYPE_INT); g_value_set_int (&value, -1); sql_value_set_value (SQL_VALUE (minus), &value); @@ -594,8 +568,6 @@ operation(A) ::= expr(X) MOD expr(Y). //+++++++++++++++++++++++++++++++++++++++++++++++++++ Value -%type value {SqlExpr *} - value(A) ::= INTEGER(X). { GValue value = {0}; @@ -603,7 +575,6 @@ value(A) ::= INTEGER(X). A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL); g_value_unset (&value); } - value(A) ::= FLOAT(X). { GValue value = {0}; @@ -612,7 +583,6 @@ value(A) ::= FLOAT(X). A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL); g_value_unset (&value); } - value(A) ::= STRING(X). { GValue value = {0}; @@ -620,7 +590,6 @@ value(A) ::= STRING(X). A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL); g_value_unset (&value); } - value(A) ::= BOOLEAN(X). { GValue value = {0}; @@ -633,17 +602,15 @@ value(A) ::= BOOLEAN(X). //+++++++++++++++++++++++++++++++++++++++++++++++++++ Alias %type alias {gchar *} -%destructor alias {g_free ($$);} alias(A) ::= AS identifier(X). { A = X; } alias(A) ::= identifier(X). { A = X; } +%type identifier {gchar *} identifier(A) ::= IDENTIFIER(X). { A = X; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Placeholder -%type placeholder {gchar *} -%destructor expr {g_free ($$);} -placeholder(A) ::= PLACEHOLDER(X). { A = X; } +placeholder(A) ::= PLACEHOLDER(X). { A = g_object_new (SQL_TYPE_HOLDER, "id", X, NULL); } stmt ::= placeholder. target ::= placeholder. diff --git a/sql/sql-delete.h b/sql/sql-delete.h index fcb0783..c2ecc72 100644 --- a/sql/sql-delete.h +++ b/sql/sql-delete.h @@ -30,12 +30,12 @@ typedef struct _SqlDeleteClass SqlDeleteClass; /** * SqlDelete: - * @table: (element-type Sql.Table): list of targeted tables + * @table: list of targeted tables **/ struct _SqlDelete { SqlDml parent; - SqlList * tables; + SqlList * tables; // List of SqlTable }; struct _SqlDeleteClass diff --git a/sql/sql-dml.c b/sql/sql-dml.c index 7d61719..bd9055e 100644 --- a/sql/sql-dml.c +++ b/sql/sql-dml.c @@ -28,7 +28,7 @@ G_DEFINE_ABSTRACT_TYPE (SqlDml, sql_dml, SQL_TYPE_STMT); //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public -void sql_dml_set_where (SqlDml * obj, SqlExpr * where) +void sql_dml_set_where (SqlDml * obj, SqlObject * where) { g_return_if_fail (SQL_IS_DML (obj)); g_return_if_fail (SQL_IS_EXPR (where) || SQL_IS_HOLDER (where) || !where); diff --git a/sql/sql-dml.h b/sql/sql-dml.h index d7c528f..f125877 100644 --- a/sql/sql-dml.h +++ b/sql/sql-dml.h @@ -31,13 +31,13 @@ typedef struct _SqlDmlClass SqlDmlClass; /** * SqlDml: - * @target: (element-type Sql.Target): list of targets for the DML query + * @target: list of targets for the DML query * @where: an #SqlExpr **/ struct _SqlDml { SqlStmt parent; - SqlList * targets; + SqlList * targets; // List of SqlTarget SqlExpr * where; }; @@ -48,6 +48,6 @@ struct _SqlDmlClass }; GType sql_dml_get_type (); -void sql_dml_set_where (SqlDml * obj, SqlExpr * expr); +void sql_dml_set_where (SqlDml * obj, SqlObject * expr); #endif diff --git a/sql/sql-function.c b/sql/sql-function.c index d5c7249..d02a67c 100644 --- a/sql/sql-function.c +++ b/sql/sql-function.c @@ -26,7 +26,7 @@ **/ G_DEFINE_TYPE (SqlFunction, sql_function, SQL_TYPE_EXPR); -SqlFunction * sql_function_new (const gchar * name, const gchar * schema) +SqlObject * sql_function_new (const gchar * name, const gchar * schema) { return g_object_new (SQL_TYPE_FUNCTION, "name", name, "schema", schema, NULL); } @@ -42,13 +42,9 @@ static void sql_function_render (SqlFunction * obj, SqlRender * render) } sql_render_add_identifier (render, obj->name); - - if (obj->name) - { - sql_render_append (render, "("); - sql_render_add_list (render, FALSE, NULL, obj->params, ","); - sql_render_append (render, ")"); - } + sql_render_append (render, "("); + sql_render_add_list (render, FALSE, NULL, obj->params, ","); + sql_render_append (render, ")"); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties diff --git a/sql/sql-function.h b/sql/sql-function.h index ac4190c..b8262df 100644 --- a/sql/sql-function.h +++ b/sql/sql-function.h @@ -47,6 +47,6 @@ struct _SqlFunctionClass }; GType sql_function_get_type (); -SqlFunction * sql_function_new (const gchar * name, const gchar * schema); +SqlObject * sql_function_new (const gchar * name, const gchar * schema); #endif diff --git a/sql/sql-holder.c b/sql/sql-holder.c index b3c3fe2..13c3f33 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -24,7 +24,7 @@ **/ G_DEFINE_TYPE (SqlHolder, sql_holder, SQL_TYPE_OBJECT); -SqlHolder * sql_holder_new (const gchar * id) +SqlObject * sql_holder_new (const gchar * id) { return g_object_new (SQL_TYPE_HOLDER, "id", id, NULL); } @@ -37,7 +37,7 @@ static void sql_holder_render (SqlHolder * obj, SqlRender * render) GSList * i = sql_render_get_ancestors (render); for (; i && !held_object; i = i->next) - held_object = sql_object_get_held_object (held_object, obj->id); + held_object = sql_object_get_held (held_object, obj->id); if (held_object) sql_render_add_object (render, held_object); @@ -78,7 +78,7 @@ static void sql_holder_set_property (SqlHolder * obj, guint id, g_free (obj->id); obj->id = g_value_dup_string (value); break; - default: + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); } } diff --git a/sql/sql-holder.h b/sql/sql-holder.h index ab18735..c06d849 100644 --- a/sql/sql-holder.h +++ b/sql/sql-holder.h @@ -40,7 +40,7 @@ struct _SqlHolderClass }; GType sql_holder_get_type (); -SqlHolder * sql_holder_new (const gchar * id); +SqlObject * sql_holder_new (const gchar * id); const gchar * sql_holder_get_id (SqlHolder * obj); #endif \ No newline at end of file diff --git a/sql/sql-join.c b/sql/sql-join.c index 4836962..69815a2 100644 --- a/sql/sql-join.c +++ b/sql/sql-join.c @@ -27,7 +27,7 @@ **/ G_DEFINE_TYPE (SqlJoin, sql_join, SQL_TYPE_TARGET); -SqlTarget * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type) +SqlObject * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type) { return g_object_new (SQL_TYPE_JOIN ,"target-left" ,left diff --git a/sql/sql-join.h b/sql/sql-join.h index 91a929c..7e342c4 100644 --- a/sql/sql-join.h +++ b/sql/sql-join.h @@ -59,7 +59,7 @@ struct _SqlJoinClass GType sql_join_get_type (); GType sql_join_type_get_type (); -SqlTarget * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type); +SqlObject * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type); void sql_join_set_condition (SqlJoin * obj, SqlExpr * condition); void sql_join_set_target_right (SqlJoin * obj, SqlTarget * target); void sql_join_set_target_left (SqlJoin * obj, SqlTarget * target); diff --git a/sql/sql-multi-stmt.c b/sql/sql-multi-stmt.c index 2f7047e..ffcfcf6 100644 --- a/sql/sql-multi-stmt.c +++ b/sql/sql-multi-stmt.c @@ -26,7 +26,7 @@ **/ G_DEFINE_TYPE (SqlMultiStmt, sql_multi_stmt, SQL_TYPE_STMT); -SqlMultiStmt * sql_multi_stmt_new () +SqlObject * sql_multi_stmt_new () { return g_object_new (SQL_TYPE_MULTI_STMT, NULL); } diff --git a/sql/sql-multi-stmt.h b/sql/sql-multi-stmt.h index 2b544be..1b587c9 100644 --- a/sql/sql-multi-stmt.h +++ b/sql/sql-multi-stmt.h @@ -44,6 +44,6 @@ struct _SqlMultiStmtClass }; GType sql_multi_stmt_get_type (); -SqlMultiStmt * sql_multi_stmt_new (); +SqlObject * sql_multi_stmt_new (); #endif diff --git a/sql/sql-object.c b/sql/sql-object.c index d3363b0..8715a88 100644 --- a/sql/sql-object.c +++ b/sql/sql-object.c @@ -16,6 +16,7 @@ */ #include "sql-object.h" +#include "sql-value.h" /** * SECTION: sql-object @@ -176,54 +177,6 @@ void sql_object_remove_child (SqlObject * obj, const gchar * property, guint n) sql_list_remove (list, n); } -/** - * sql_object_add_held_object: - * @obj: a #SqlObject - * @id: the id of the #SqlHolder - * @held_object: the held object - * - * Adds a held object. - **/ -void sql_object_add_held_object (SqlObject * obj, const gchar * id, SqlObject * held_object) -{ - g_return_if_fail (SQL_IS_OBJECT (obj)); - g_return_if_fail (id); - - if (!obj->held_objects) - obj->held_objects = g_hash_table_new_full ( - g_str_hash - ,g_str_equal - ,g_free - ,g_object_unref - ); - - g_signal_connect (held_object, "changed", - G_CALLBACK (sql_object_child_changed), obj - ); - g_hash_table_replace (obj->held_objects, - g_strdup (id), g_object_ref_sink (held_object)); -} - -/** - * sql_object_get_held_object: - * @obj: a #SqlObject - * @id: the id of the #SqlHolder - * - * Gets a held object by its id. - * - * Return value: the #SqlObject if an object with that id exists, %NULL otherwise - **/ -SqlObject * sql_object_get_held_object (SqlObject * obj, const gchar * id) -{ - g_return_val_if_fail (SQL_IS_OBJECT (obj), NULL); - g_return_val_if_fail (id, NULL); - - if (obj->held_objects) - return g_hash_table_lookup (obj->held_objects, id); - - return NULL; -} - /** * sql_object_changed: * @obj: a #SqlObject @@ -237,19 +190,10 @@ void sql_object_changed (SqlObject * obj) //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_object_init (SqlObject * obj) -{ - obj->child_groups = NULL; - obj->held_objects = NULL; -} +static void sql_object_init (SqlObject * obj) {} static void sql_object_finalize (SqlObject * obj) { - if (obj->child_groups) - g_hash_table_destroy (obj->child_groups); - if (obj->held_objects) - g_hash_table_destroy (obj->held_objects); - G_OBJECT_CLASS (sql_object_parent_class)->finalize (G_OBJECT (obj)); } diff --git a/sql/sql-object.h b/sql/sql-object.h index fc81513..fa4694a 100644 --- a/sql/sql-object.h +++ b/sql/sql-object.h @@ -36,8 +36,6 @@ typedef gboolean (* SqlObjectIsReadyFunc) (SqlObject * obj); struct _SqlObject { GInitiallyUnowned parent; - GHashTable * child_groups; - GHashTable * held_objects; }; struct _SqlObjectClass @@ -60,9 +58,6 @@ void sql_object_set (SqlObject * obj, const gchar * property, SqlObject * se SqlObject * sql_object_get (SqlObject * obj, const gchar * property); void sql_object_add_child (SqlObject * obj, const gchar * property, SqlObject * child); void sql_object_remove_child (SqlObject * obj, const gchar * property, guint n); - -void sql_object_add_held_object (SqlObject * obj, const gchar * id, SqlObject * held_object); -SqlObject * sql_object_get_held_object (SqlObject * obj, const gchar * id); void sql_object_changed (SqlObject * obj); gpointer sql_object_add (gpointer obj, gpointer child); diff --git a/sql/sql-operation.c b/sql/sql-operation.c index b0fa96f..5d735e0 100644 --- a/sql/sql-operation.c +++ b/sql/sql-operation.c @@ -145,7 +145,7 @@ static void sql_operation_class_init (SqlOperationClass * klass) ,"Operators" ,"The list of operators" ,SQL_TYPE_EXPR - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); } diff --git a/sql/sql-render.c b/sql/sql-render.c index ce7dfa9..754e485 100644 --- a/sql/sql-render.c +++ b/sql/sql-render.c @@ -296,32 +296,18 @@ void sql_render_add_item (SqlRender * obj, gboolean required, const gchar * toke * @obj: a #SqlRender * @required: * @token: - * @list: (element-type GObject.Object): a list of objects to add + * @list: a list of objects to add * @separator: * * **/ void sql_render_add_list (SqlRender * obj, gboolean required, const gchar * token, SqlList * list, const gchar * separator) -{ +{ g_return_if_fail (SQL_IS_RENDER (obj)); g_return_if_fail (SQL_IS_LIST (list)); - - if (list) - { - GList * n; - sql_render_add_token (obj, token); - for (n = sql_list_get_items (list); n; n = n->next) - { - sql_render_add_object (obj, n->data); - - if (n->next) - g_string_append_printf (obj->buffer, " %s", separator); - } - } - else if (required) - sql_render_set_error (obj); + sql_render_add_list_with_func (obj, required, token, list, separator, NULL); } /** @@ -329,7 +315,7 @@ void sql_render_add_list (SqlRender * obj, gboolean required, const gchar * toke * @obj: a #SqlRender * @required: * @token: - * @list: (element-type GObject.Object): + * @list: * @separator: * @function: (scope call): * @@ -338,17 +324,21 @@ void sql_render_add_list (SqlRender * obj, gboolean required, const gchar * toke void sql_render_add_list_with_func (SqlRender * obj, gboolean required, const gchar * token, SqlList * list, const gchar * separator, SqlRenderFunc function) { + GList * n; + g_return_if_fail (SQL_IS_RENDER (obj)); g_return_if_fail (SQL_IS_LIST (list)); - if (list) + if (list && (n = sql_list_get_items (list))) { - GList * n; sql_render_add_token (obj, token); - for (n = sql_list_get_items (list); n; n = n->next) + for (; n; n = n->next) { - function (n->data, obj); + if (function) + function (n->data, obj); + else + sql_render_add_object (obj, n->data); if (n->next) g_string_append_printf (obj->buffer, " %s", separator); diff --git a/sql/sql-select-field.c b/sql/sql-select-field.c index f6915d9..14c4b5f 100644 --- a/sql/sql-select-field.c +++ b/sql/sql-select-field.c @@ -24,7 +24,7 @@ **/ G_DEFINE_TYPE (SqlSelectField, sql_select_field, SQL_TYPE_OBJECT); -SqlSelectField * sql_select_field_new () +SqlObject * sql_select_field_new () { return g_object_new (SQL_TYPE_SELECT_FIELD, NULL); } diff --git a/sql/sql-select-field.h b/sql/sql-select-field.h index 61ffd7d..465ed64 100644 --- a/sql/sql-select-field.h +++ b/sql/sql-select-field.h @@ -41,7 +41,7 @@ struct _SqlSelectFieldClass SqlObjectClass parent; }; -GType sql_select_field_get_type (); -SqlSelectField * sql_select_field_new (); +GType sql_select_field_get_type (); +SqlObject * sql_select_field_new (); #endif diff --git a/sql/sql-select-order.c b/sql/sql-select-order.c index 8735789..027530b 100644 --- a/sql/sql-select-order.c +++ b/sql/sql-select-order.c @@ -24,7 +24,7 @@ **/ G_DEFINE_TYPE (SqlSelectOrder, sql_select_order, SQL_TYPE_OBJECT); -SqlSelectOrder * sql_select_order_new () +SqlObject * sql_select_order_new () { return g_object_new (SQL_TYPE_SELECT_ORDER, NULL); } diff --git a/sql/sql-select-order.h b/sql/sql-select-order.h index 6454c79..c7bd38f 100644 --- a/sql/sql-select-order.h +++ b/sql/sql-select-order.h @@ -55,9 +55,9 @@ struct _SqlSelectOrderClass SqlObjectClass parent; }; -GType sql_select_order_get_type (); -GType sql_select_order_way_get_type (); +GType sql_select_order_get_type (); +GType sql_select_order_way_get_type (); -SqlSelectOrder * sql_select_order_new (); +SqlObject * sql_select_order_new (); #endif diff --git a/sql/sql-select.c b/sql/sql-select.c index dfc4179..096c068 100644 --- a/sql/sql-select.c +++ b/sql/sql-select.c @@ -254,14 +254,14 @@ static void sql_select_class_init (SqlSelectClass * klass) ,"Fields" ,"The list of fields" ,SQL_TYPE_EXPR - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_GROUP, - sql_param_object ("group" + sql_param_list ("group" ,"Group" ,"The GROUP BY section" ,SQL_TYPE_EXPR - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_HAVING, sql_param_object ("having" @@ -275,11 +275,12 @@ static void sql_select_class_init (SqlSelectClass * klass) ,"Order" ,"The ORDER BY section" ,SQL_TYPE_SELECT_ORDER - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_LIMIT_COUNT, g_param_spec_uint ("limit-count" ,"Limit count" + ,"The COUNT field of the LIMIT clause" ,0, G_MAXUINT, 0 ,G_PARAM_READWRITE diff --git a/sql/sql-select.h b/sql/sql-select.h index 420deb3..c9f5e28 100644 --- a/sql/sql-select.h +++ b/sql/sql-select.h @@ -42,18 +42,15 @@ SqlSelectType; /** * SqlSelect: - * @expr: (element-type Sql.Expr): - * @group: (element-type Sql.Expr): - * @order: (element-type Sql.Expr): **/ struct _SqlSelect { SqlDml parent; gboolean distinct; - SqlList * fields; - SqlList * group; + SqlList * fields; // List of SqlSelectField + SqlList * group; // List of SqlExpr SqlExpr * having; - SqlList * order; + SqlList * order; // List of SqlSelectOrder guint limit_offset; guint limit_count; diff --git a/sql/sql-set.c b/sql/sql-set.c index 521b6fc..e096246 100644 --- a/sql/sql-set.c +++ b/sql/sql-set.c @@ -24,7 +24,7 @@ **/ G_DEFINE_TYPE (SqlSet, sql_set, SQL_TYPE_EXPR); -SqlSet * sql_set_new () +SqlObject * sql_set_new () { return g_object_new (SQL_TYPE_SET, NULL); } @@ -103,6 +103,6 @@ static void sql_set_class_init (SqlSetClass * klass) ,"Expressions" ,"The list of expressions" ,SQL_TYPE_EXPR - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); } diff --git a/sql/sql-set.h b/sql/sql-set.h index 14419e6..55ca012 100644 --- a/sql/sql-set.h +++ b/sql/sql-set.h @@ -40,6 +40,6 @@ struct _SqlSetClass }; GType sql_set_get_type (); -SqlSet * sql_set_new (); +SqlObject * sql_set_new (); #endif diff --git a/sql/sql-string.c b/sql/sql-string.c index 8d119b1..8dad5fb 100644 --- a/sql/sql-string.c +++ b/sql/sql-string.c @@ -22,7 +22,7 @@ typedef struct { gchar * start; gchar * end; - SqlHolder * holder; + SqlObject * holder; } HolderData; @@ -35,7 +35,7 @@ HolderData; **/ G_DEFINE_TYPE (SqlString, sql_string, SQL_TYPE_STMT); -SqlString * sql_string_new (const gchar * sql) +SqlObject * sql_string_new (const gchar * sql) { return g_object_new (SQL_TYPE_STRING, "sql", sql, NULL); } @@ -65,44 +65,6 @@ static void sql_string_free_holder_data (HolderData * holder_data) g_free (holder_data); } -//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public - -/** - * sql_string_add_param: - * @obj: the #SqlString - * @id: the id assigned to the item - **/ -void sql_string_add_param (SqlString * obj, const gchar * id, GvnParam * param) -{ - g_return_if_fail (SQL_IS_STRING (obj)); - g_return_if_fail (GVN_IS_PARAM (param)); - - SqlExpr * value = sql_value_new (); - sql_value_set_param (SQL_VALUE (value), param); - sql_object_add_held_object (SQL_OBJECT (obj), id, SQL_OBJECT (value)); - g_object_unref (value); -} - -/** - * sql_string_add_value: - * @obj: the #SqlString - * @id: the id assigned to the item - **/ -void sql_string_add_value (SqlString * obj, const gchar * id, GType type, gpointer content) -{ - g_return_if_fail (SQL_IS_STRING (obj)); - - GValue gvalue = {0}; - SqlExpr * value; - - gvn_value_new_with_content (&gvalue, type, content); - value = sql_value_new (); - sql_value_set_value (SQL_VALUE (value), &gvalue); - sql_object_add_held_object (SQL_OBJECT (obj), id, SQL_OBJECT (value)); - g_object_unref (value); - g_value_unset (&gvalue); -} - //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties enum @@ -122,7 +84,7 @@ static void sql_string_set_property (SqlString * obj, guint id, obj->sql = g_value_dup_string (value); if (obj->sql) - for (i = obj->sql; ; i++) + for (i = obj->sql; TRUE; i++) { switch (*i) { @@ -141,7 +103,7 @@ static void sql_string_set_property (SqlString * obj, guint id, obj->holders = g_slist_prepend (obj->holders, holder_data); holder_id = g_strndup (ptr, i - ptr); - holder_data->holder = sql_holder_new (holder_id); + holder_data->holder = g_object_ref_sink (sql_holder_new (holder_id)); g_free (holder_id); break; @@ -153,8 +115,12 @@ static void sql_string_set_property (SqlString * obj, guint id, gchar delimiter = *i; while (*(++i) != delimiter) + { if (*i == '\\') i++; + if (*i == '\0') + break; + } break; } diff --git a/sql/sql-string.h b/sql/sql-string.h index 75193d5..b18a564 100644 --- a/sql/sql-string.h +++ b/sql/sql-string.h @@ -21,7 +21,6 @@ #include #include #include "sql-stmt.h" -#include "sql-value.h" #define SQL_TYPE_STRING (sql_string_get_type ()) #define SQL_IS_STRING(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_STRING)) @@ -48,8 +47,6 @@ struct _SqlStringClass }; GType sql_string_get_type (); -SqlString * sql_string_new (const gchar * sql); -void sql_string_add_param (SqlString * obj, const gchar * id, GvnParam * param); -void sql_string_add_value (SqlString * obj, const gchar * id, GType type, gpointer content); +SqlObject * sql_string_new (const gchar * sql); #endif diff --git a/sql/sql-subquery.c b/sql/sql-subquery.c index c7cdbf0..a12d1ce 100644 --- a/sql/sql-subquery.c +++ b/sql/sql-subquery.c @@ -27,7 +27,7 @@ **/ G_DEFINE_TYPE (SqlSubquery, sql_subquery, SQL_TYPE_TARGET); -SqlSubquery * sql_subquery_new (SqlSelect * select) +SqlObject * sql_subquery_new (SqlSelect * select) { return g_object_new (SQL_TYPE_SUBQUERY, "select", select, NULL); } diff --git a/sql/sql-subquery.h b/sql/sql-subquery.h index 24581fc..cbb8c85 100644 --- a/sql/sql-subquery.h +++ b/sql/sql-subquery.h @@ -41,7 +41,7 @@ struct _SqlSubqueryClass }; GType sql_subquery_get_type (); -SqlSubquery * sql_subquery_new (SqlSelect * select); +SqlObject * sql_subquery_new (SqlSelect * select); void sql_subquery_set_select (SqlSubquery * obj, SqlSelect * select); #endif diff --git a/sql/sql-update-set.c b/sql/sql-update-set.c index 2b204e1..5b00e38 100644 --- a/sql/sql-update-set.c +++ b/sql/sql-update-set.c @@ -24,7 +24,7 @@ **/ G_DEFINE_TYPE (SqlUpdateSet, sql_update_set, SQL_TYPE_OBJECT); -SqlUpdateSet * sql_update_set_new () +SqlObject * sql_update_set_new () { return g_object_new (SQL_TYPE_UPDATE_SET, NULL); } diff --git a/sql/sql-update-set.h b/sql/sql-update-set.h index ffa1037..c7fc381 100644 --- a/sql/sql-update-set.h +++ b/sql/sql-update-set.h @@ -43,6 +43,6 @@ struct _SqlUpdateSetClass }; GType sql_update_set_get_type (); -SqlUpdateSet * sql_update_set_new (); +SqlObject * sql_update_set_new (); #endif diff --git a/sql/sql-update.c b/sql/sql-update.c index b582722..b3af9aa 100644 --- a/sql/sql-update.c +++ b/sql/sql-update.c @@ -112,6 +112,6 @@ static void sql_update_class_init (SqlUpdateClass * klass) ,"Sets" ,"A list of sets" ,SQL_TYPE_UPDATE_SET - ,G_PARAM_READWRITE + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); } diff --git a/sql/sql-value.c b/sql/sql-value.c index 7940aa5..42267bc 100644 --- a/sql/sql-value.c +++ b/sql/sql-value.c @@ -111,7 +111,7 @@ static gboolean sql_value_is_ready (SqlValue * obj) return !gvn_value_is_null (obj->value); } -static void sql_value_set_real_value (SqlValue * obj, const GValue * value) +static void sql_value_put_value (SqlValue * obj, const GValue * value) { if (gvn_value_ccopy (value, obj->value)) g_signal_emit_by_name (obj, "changed"); @@ -119,7 +119,7 @@ static void sql_value_set_real_value (SqlValue * obj, const GValue * value) static void sql_value_cb_value_changed (GvnParam * param, const GValue * value, SqlValue * obj) { - sql_value_set_real_value (obj, value); + sql_value_put_value (obj, value); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public @@ -136,7 +136,7 @@ void sql_value_set_value (SqlValue * obj, const GValue * value) g_return_if_fail (SQL_IS_VALUE (obj)); g_return_if_fail (!obj->param); - sql_value_set_real_value (obj, value); + sql_value_put_value (obj, value); } void sql_value_set_param (SqlValue * obj, GvnParam * param) @@ -155,7 +155,7 @@ void sql_value_set_param (SqlValue * obj, GvnParam * param) obj->param = g_object_ref_sink (param); g_signal_connect (param, "value-changed", G_CALLBACK (sql_value_cb_value_changed), obj); - sql_value_set_real_value (obj, gvn_param_get_value (param)); + sql_value_put_value (obj, gvn_param_get_value (param)); } } diff --git a/sql/sql.h b/sql/sql.h index 91c5d28..2899b14 100644 --- a/sql/sql.h +++ b/sql/sql.h @@ -22,6 +22,7 @@ #include "sql-object.h" #include "sql-holder.h" #include "sql-list.h" +#include "sql-batch.h" #include "sql-set.h" #include "sql-string.h" #include "sql-stmt.h" From 7a61f30bad66e662ce4433c13d7c9c3ecae11992 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Mon, 16 Dec 2013 12:11:47 +0100 Subject: [PATCH 03/10] Copia de las ultimas modificaciones --- autogen.sh | 18 ++++++++++++++---- configure.ac | 3 --- module/data/example.ui | 1 + module/data/example.xml | 8 ++++++++ module/src/Makefile.am | 4 +++- sql/sql-batch.c | 2 +- sql/sql-holder.c | 6 ++++++ sql/sql-list.c | 19 ++++++++++++++----- sql/sql-object.c | 36 ++++++++++++++++++++++++++++++++++++ sql/sql-object.h | 7 +++++-- sql/sql-param-list.h | 4 ++-- sql/sql-param-object.h | 5 +++-- sql/sql-string.c | 9 +++++++++ 13 files changed, 102 insertions(+), 20 deletions(-) diff --git a/autogen.sh b/autogen.sh index 5d770a0..be57f3c 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,5 +1,15 @@ -gtkdocize --copy -autoreconf -fi -glib-gettextize --force --copy +#!/bin/sh + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +builddir=`pwd` +mkdir -p $builddir/m4 + +cd $srcdir +gtkdocize --copy && +autoreconf -fi && +glib-gettextize --copy --force && intltoolize --copy --force --automake -automake --add-missing --copy + +exit $? diff --git a/configure.ac b/configure.ac index d3454e2..e757bc8 100644 --- a/configure.ac +++ b/configure.ac @@ -87,8 +87,6 @@ AM_CONDITIONAL(ENABLE_INSTALL, [test x"$ENABLE_INSTALL" = x"yes"]) if test x"$ENABLE_INSTALL" = x"yes"; then CFLAGS+=" -O3" -else - CFLAGS+=" -O0" fi AC_SUBST([CPPFLAGS]) @@ -117,7 +115,6 @@ AC_CONFIG_FILES([ module/Makefile module/src/Makefile module/data/Makefile - module/sql/Makefile main/Makefile main/vn-hedera.desktop vapi/Makefile diff --git a/module/data/example.ui b/module/data/example.ui index b290204..8b8fc78 100644 --- a/module/data/example.ui +++ b/module/data/example.ui @@ -5,6 +5,7 @@ + diff --git a/module/data/example.xml b/module/data/example.xml index 9729d1e..92190cd 100644 --- a/module/data/example.xml +++ b/module/data/example.xml @@ -33,5 +33,13 @@ accel="F5"> Customer +
+ Allocator +
diff --git a/module/src/Makefile.am b/module/src/Makefile.am index aed27ca..7230329 100644 --- a/module/src/Makefile.am +++ b/module/src/Makefile.am @@ -14,7 +14,9 @@ libexample_la_SOURCES = \ vn-users.h \ vn-users.c \ vn-customer.h \ - vn-customer.c + vn-customer.c \ + vn-allocator.h \ + vn-allocator.c install-data-hook: rm -f $(DESTDIR)$(module_libdir)/libexample.la diff --git a/sql/sql-batch.c b/sql/sql-batch.c index cbbe885..202961f 100644 --- a/sql/sql-batch.c +++ b/sql/sql-batch.c @@ -47,7 +47,7 @@ static void sql_batch_child_changed (SqlBatch * child, SqlBatch * obj) * sql_batch_is_ready: * @obj: a #SqlBatch * - * Checks if @obj and all of its elemens are ready to be rendered. + * Checks if @obj and all of its elements are ready to be rendered. * * Return value: %TRUE if ready, %FALSE otherwise. **/ diff --git a/sql/sql-holder.c b/sql/sql-holder.c index 13c3f33..12cae6b 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -45,6 +45,11 @@ static void sql_holder_render (SqlHolder * obj, SqlRender * render) sql_render_printf (render, "#%s", obj->id); } +static void sql_holder_find_holders (SqlHolder * obj, GQueue * holders) +{ + g_queue_push_tail (holders, obj->id); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** @@ -116,6 +121,7 @@ static void sql_holder_class_init (SqlHolderClass * k) klass->set_property = (GObjectSetPropertyFunc) sql_holder_set_property; klass->get_property = (GObjectGetPropertyFunc) sql_holder_get_property; SQL_OBJECT_CLASS (klass)->render = (SqlRenderFunc) sql_holder_render; + SQL_OBJECT_CLASS (klass)->find_holders = (SqlObjectFindHoldersFunc) sql_holder_find_holders; g_object_class_install_property (klass, PROP_ID, g_param_spec_string ("id" diff --git a/sql/sql-list.c b/sql/sql-list.c index 0b52408..12d9011 100644 --- a/sql/sql-list.c +++ b/sql/sql-list.c @@ -35,7 +35,7 @@ static void sql_list_render (SqlList * obj, SqlRender * render) { GList * i; - for (i = obj->items.tail; i; i = i->next) + for (i = obj->items.head; i; i = i->next) { sql_render_add_object (render, i->data); @@ -48,13 +48,21 @@ static gboolean sql_list_is_ready (SqlList * obj) { GList * i; - for (i = obj->items.tail; i; i = i->next) + for (i = obj->items.head; i; i = i->next) if (!sql_object_is_ready (i->data)) return FALSE; return TRUE; } +static void sql_list_find_holders (SqlList * obj, GQueue * holders) +{ + GList * i; + + for (i = obj->items.head; i; i = i->next) + sql_object_get_holders (i->data, holders); +} + static void sql_list_item_changed (SqlObject * item, SqlObject * obj) { sql_object_changed (obj); @@ -93,7 +101,7 @@ void sql_list_insert (SqlList * obj, gpointer item, guint n) if (n > 0) g_queue_push_nth (&obj->items, g_object_ref_sink (item), n); else - g_queue_push_head (&obj->items, g_object_ref_sink (item)); + g_queue_push_tail (&obj->items, g_object_ref_sink (item)); g_signal_connect (item, "changed", G_CALLBACK (sql_list_item_changed), obj @@ -148,7 +156,7 @@ GList * sql_list_get_items (SqlList * obj) { g_return_val_if_fail (SQL_IS_LIST (obj), NULL); - return obj->items.tail; + return obj->items.head; } /** @@ -229,7 +237,7 @@ static void sql_list_finalize (SqlList * obj) { GList * i; - for (i = obj->items.tail; i; i = i->next) + for (i = obj->items.head; i; i = i->next) { g_signal_handlers_disconnect_by_func (i->data, sql_list_item_changed, obj); @@ -248,6 +256,7 @@ static void sql_list_class_init (SqlListClass * k) klass->get_property = (GObjectGetPropertyFunc) sql_list_get_property; SQL_OBJECT_CLASS (klass)->render = (SqlRenderFunc) sql_list_render; SQL_OBJECT_CLASS (klass)->is_ready = (SqlObjectIsReadyFunc) sql_list_is_ready; + SQL_OBJECT_CLASS (klass)->find_holders = (SqlObjectFindHoldersFunc) sql_list_find_holders; g_object_class_install_property (klass, PROP_LENGTH, g_param_spec_uint ("length" diff --git a/sql/sql-object.c b/sql/sql-object.c index 8715a88..6274227 100644 --- a/sql/sql-object.c +++ b/sql/sql-object.c @@ -41,6 +41,24 @@ static void sql_object_child_changed (SqlObject * child, SqlObject * obj) sql_object_changed (obj); } +static void sql_object_find_holders (SqlObject * obj, GQueue * holders) +{ + guint i; + guint nparams; + GParamSpec ** params; + + params = g_object_class_list_properties (G_OBJECT_GET_CLASS (obj), &nparams); + + for (i = 0; i < nparams; i++) + if (SQL_IS_PARAM_OBJECT (params[i]) || SQL_IS_PARAM_LIST (params[i])) + { + SqlObject * child = sql_object_get (obj, params[i]->name); + sql_object_get_holders (child, holders); + } + + g_free (params); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Protected /** @@ -177,6 +195,23 @@ void sql_object_remove_child (SqlObject * obj, const gchar * property, guint n) sql_list_remove (list, n); } +/** + * sql_object_get_holders: + * @obj: a #SqlObject + * @holders: a #GQueue + * + * Gets all identifiers of the contained holders. + **/ +void sql_object_get_holders (SqlObject * obj, GQueue * holders) +{ + if (!obj) + return; + + g_return_if_fail (SQL_IS_OBJECT (obj)); + + SQL_OBJECT_GET_CLASS (obj)->find_holders (obj, holders); +} + /** * sql_object_changed: * @obj: a #SqlObject @@ -200,6 +235,7 @@ static void sql_object_finalize (SqlObject * obj) static void sql_object_class_init (SqlObjectClass * klass) { G_OBJECT_CLASS (klass)->finalize = (GObjectFinalizeFunc) sql_object_finalize; + klass->find_holders = sql_object_find_holders; klass->is_ready = NULL; klass->render = NULL; diff --git a/sql/sql-object.h b/sql/sql-object.h index fa4694a..52f8911 100644 --- a/sql/sql-object.h +++ b/sql/sql-object.h @@ -31,7 +31,8 @@ typedef struct _SqlObject SqlObject; typedef struct _SqlObjectClass SqlObjectClass; -typedef gboolean (* SqlObjectIsReadyFunc) (SqlObject * obj); +typedef gboolean (* SqlObjectIsReadyFunc) (SqlObject * obj); +typedef void (* SqlObjectFindHoldersFunc) (SqlObject * obj, GQueue * holders); struct _SqlObject { @@ -44,6 +45,7 @@ struct _SqlObjectClass GInitiallyUnownedClass parent; gpointer /* SqlRenderFunc */ render; SqlObjectIsReadyFunc is_ready; + SqlObjectFindHoldersFunc find_holders; }; #include "sql-holder.h" @@ -53,6 +55,7 @@ struct _SqlObjectClass GType sql_object_get_type (); void sql_object_render (SqlObject * obj, SqlRender * render); gboolean sql_object_is_ready (SqlObject * obj); +void sql_object_get_holders (SqlObject * obj, GQueue * holders); void sql_object_set (SqlObject * obj, const gchar * property, SqlObject * set); SqlObject * sql_object_get (SqlObject * obj, const gchar * property); @@ -63,4 +66,4 @@ void sql_object_changed (SqlObject * obj); gpointer sql_object_add (gpointer obj, gpointer child); void sql_object_remove (gpointer obj, gpointer child); -#endif +#endif \ No newline at end of file diff --git a/sql/sql-param-list.h b/sql/sql-param-list.h index 0067b6f..3f6e210 100644 --- a/sql/sql-param-list.h +++ b/sql/sql-param-list.h @@ -21,8 +21,8 @@ #include "sql-object.h" #define SQL_TYPE_PARAM_LIST (sql_param_list_get_type ()) -#define SQL_PARAM_LIST(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), SQL_TYPE_PARAM_LIST, SqlParamList)) - +#define SQL_PARAM_LIST(pspec) (G_TYPE_CHECK_INSTANCE_CAST (pspec, SQL_TYPE_PARAM_LIST, SqlParamList)) +#define SQL_IS_PARAM_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_PARAM_LIST)) typedef struct { diff --git a/sql/sql-param-object.h b/sql/sql-param-object.h index 72a5f07..a92e582 100644 --- a/sql/sql-param-object.h +++ b/sql/sql-param-object.h @@ -20,8 +20,9 @@ #include "sql-object.h" -#define SQL_TYPE_PARAM_OBJECT (sql_param_object_get_type ()) -#define SQL_PARAM_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), SQL_TYPE_PARAM_OBJECT, SqlParamObject)) +#define SQL_TYPE_PARAM_OBJECT (sql_param_object_get_type ()) +#define SQL_PARAM_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST (pspec, SQL_TYPE_PARAM_OBJECT, SqlParamObject)) +#define SQL_IS_PARAM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_PARAM_OBJECT)) typedef struct { diff --git a/sql/sql-string.c b/sql/sql-string.c index 8dad5fb..4ecb697 100644 --- a/sql/sql-string.c +++ b/sql/sql-string.c @@ -59,6 +59,14 @@ static void sql_string_render (SqlString * obj, SqlRender * render) sql_render_append (render, ptr); } +static void sql_string_find_holders (SqlString * obj, GQueue * holders) +{ + GSList * i; + + for (i = obj->holders; i; i = i->next) + sql_object_get_holders (((HolderData *) i->data)->holder); +} + static void sql_string_free_holder_data (HolderData * holder_data) { g_object_unref (holder_data->holder); @@ -173,6 +181,7 @@ static void sql_string_class_init (SqlStringClass * k) klass->set_property = (GObjectSetPropertyFunc) sql_string_set_property; klass->get_property = (GObjectGetPropertyFunc) sql_string_get_property; SQL_OBJECT_CLASS (klass)->render = (SqlRenderFunc) sql_string_render; + SQL_OBJECT_CLASS (klass)->find_holders = (SqlObjectFindHoldersFunc) sql_string_find_holders; g_object_class_install_property (klass, PROP_SQL, g_param_spec_string ("sql" From 030ccc8335cd1aae35af9eb8f38a417339eff7f1 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Fri, 9 May 2014 13:40:32 +0200 Subject: [PATCH 04/10] =?UTF-8?q?Adaptacion=20al=20nuevo=20sistema=20de=20?= =?UTF-8?q?SqlLib.=20Versi=C3=B3n=20Alpha.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- INSTALL | 4 +- configure.ac | 2 +- db/db-conn.c | 35 +- db/db-conn.h | 12 +- db/db-iterator.c | 2 +- db/db-model.c | 1064 ++++++++++++++++-------------------- db/db-model.h | 15 +- db/db-plugin.c | 5 +- db/db-plugin.h | 2 +- db/db-request.c | 18 +- db/db-request.h | 3 +- main/Makefile.am | 1 + module/Makefile.am | 3 +- module/src/vn-users.c | 11 +- plugin/mysql/db-mysql.c | 6 +- plugin/pg/db-pg.c | 46 +- sql/sql-batch.c | 107 ++-- sql/sql-batch.h | 11 +- sql/sql-delete.c | 4 +- sql/sql-dml.c | 9 +- sql/sql-field.c | 12 +- sql/sql-function.c | 12 +- sql/sql-holder.c | 12 +- sql/sql-holder.h | 4 +- sql/sql-insert.c | 12 +- sql/sql-join.c | 25 +- sql/sql-list.c | 59 +- sql/sql-list.h | 7 +- sql/sql-multi-stmt.c | 4 +- sql/sql-object.c | 45 +- sql/sql-object.h | 8 +- sql/sql-operation.c | 8 +- sql/sql-operation.h | 2 +- sql/sql-param-list.c | 2 +- sql/sql-render.c | 21 +- sql/sql-render.h | 10 +- sql/sql-select-field.c | 8 +- sql/sql-select-order.c | 8 +- sql/sql-select.c | 37 +- sql/sql-set.c | 4 +- sql/sql-string.c | 2 +- sql/sql-subquery.c | 4 +- sql/sql-table.c | 10 +- sql/sql-target.c | 4 +- sql/sql-update-set.c | 8 +- sql/sql-update.c | 4 +- vn/field/vn-completion.c | 22 +- vn/field/vn-completion.h | 2 +- vn/field/vn-date-chooser.c | 2 +- vn/vn-login.c | 21 +- 50 files changed, 866 insertions(+), 873 deletions(-) diff --git a/INSTALL b/INSTALL index 007e939..2099840 100644 --- a/INSTALL +++ b/INSTALL @@ -12,8 +12,8 @@ without warranty of any kind. Basic Installation ================== - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following + Briefly, the shell command `./configure && make && make install' +should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented diff --git a/configure.ac b/configure.ac index e757bc8..6a16ce0 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ AM_XGETTEXT_OPTION([-k_ -kQ_:1g -kN_ -kC_:1c,2 -kNC_:1c,2]) # GSettings configuration GLIB_GSETTINGS -CFLAGS=" -Wall" +CFLAGS=" -Wno-deprecated -Wall" # Check for debug mode AC_MSG_CHECKING([whether to build with debug information...]) diff --git a/db/db-conn.c b/db/db-conn.c index cd9126e..d42147b 100644 --- a/db/db-conn.c +++ b/db/db-conn.c @@ -574,13 +574,16 @@ DbResultSet * db_conn_exec (DbConn * obj, const gchar * sql, GError ** err) * * Return value: (transfer full): the new #DbRequest **/ -DbRequest * db_conn_query (DbConn * obj, const gchar * sql) +DbRequest * db_conn_query (DbConn * obj, const gchar * sql, SqlBatch * batch) { + SqlObject * string; DbRequest * request; g_return_val_if_fail (DB_IS_CONN (obj), NULL); - request = db_request_new (obj, sql); + string = sql_string_new (sql); + + request = db_request_new_with_stmt (obj, SQL_STMT (string), batch); db_request_exec (request, NULL); return request; } @@ -594,13 +597,13 @@ DbRequest * db_conn_query (DbConn * obj, const gchar * sql) * * Return value: (transfer full): the new #DbRequest **/ -DbRequest * db_conn_query_with_stmt (DbConn * obj, SqlStmt * stmt) +DbRequest * db_conn_query_with_stmt (DbConn * obj, SqlStmt * stmt, SqlBatch * batch) { DbRequest * request; g_return_val_if_fail (DB_IS_CONN (obj), NULL); - request = db_request_new_with_stmt (obj, stmt); + request = db_request_new_with_stmt (obj, stmt, batch); db_request_exec (request, NULL); return request; } @@ -615,14 +618,17 @@ DbRequest * db_conn_query_with_stmt (DbConn * obj, SqlStmt * stmt) * * Return value: (transfer full): the new #DbRequest **/ -DbRequest * db_conn_query_async (DbConn * obj, const gchar * sql, +DbRequest * db_conn_query_async (DbConn * obj, const gchar * sql, SqlBatch * batch, DbRequestDoneCallback callback, gpointer user_data, GDestroyNotify notify) { + SqlObject * string; DbRequest * request; g_return_val_if_fail (DB_IS_CONN (obj), NULL); - request = db_request_new (obj, sql); + string = sql_string_new (sql); + + request = db_request_new_with_stmt (obj, SQL_STMT (string), batch); db_request_set_callback (request, callback, user_data, notify); db_conn_add_request (obj, request); return request; @@ -638,14 +644,14 @@ DbRequest * db_conn_query_async (DbConn * obj, const gchar * sql, * * Return value: (transfer full): the new #DbRequest **/ -DbRequest * db_conn_query_with_stmt_async (DbConn * obj, SqlStmt * stmt, +DbRequest * db_conn_query_with_stmt_async (DbConn * obj, SqlStmt * stmt, SqlBatch * batch, DbRequestDoneCallback callback, gpointer user_data, GDestroyNotify notify) { DbRequest * request; g_return_val_if_fail (DB_IS_CONN (obj), NULL); - request = db_request_new_with_stmt (obj, stmt); + request = db_request_new_with_stmt (obj, stmt, batch); db_request_set_callback (request, callback, user_data, notify); db_conn_add_request (obj, request); return request; @@ -662,14 +668,14 @@ DbRequest * db_conn_query_with_stmt_async (DbConn * obj, SqlStmt * stmt, * * Return value: %TRUE on success, %FALSE on failure **/ -gboolean db_conn_query_value (DbConn * obj, const gchar * sql, GValue * value, GError ** err) +gboolean db_conn_query_value (DbConn * obj, const gchar * sql, SqlBatch * batch, GValue * value, GError ** err) { gboolean success; DbRequest * request; g_return_val_if_fail (DB_IS_CONN (obj), FALSE); - request = db_conn_query (obj, sql); + request = db_conn_query (obj, sql, batch); success = db_request_fetch_value (request, value, err); g_object_unref (request); @@ -728,12 +734,13 @@ SqlStmt * db_conn_parse (DbConn * obj, gchar * sql) * * Return value: (transfer full): the rendered string, or %NULL if error. **/ -gchar * db_conn_render (DbConn * obj, gpointer object, GError ** err) +gchar * db_conn_render (DbConn * obj, gpointer object, SqlBatch * batch, GError ** err) { g_return_val_if_fail (DB_IS_CONN (obj), NULL); g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (SQL_IS_BATCH (batch) || !batch, NULL); - return db_plugin_render (obj->plugin, object, err); + return db_plugin_render (obj->plugin, object, batch, err); } /** @@ -884,11 +891,11 @@ gchar * db_conn_get_schema (DbConn * obj) * * Return value: (transfer full): an #SqlString **/ -SqlString * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_file) +SqlObject * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_file) { gint i; gchar * file; - SqlString * stmt = NULL; + SqlObject * stmt = NULL; g_return_val_if_fail (DB_IS_CONN (obj), NULL); g_return_val_if_fail (query_file, NULL); diff --git a/db/db-conn.h b/db/db-conn.h index bf34d4d..528cdf5 100644 --- a/db/db-conn.h +++ b/db/db-conn.h @@ -119,27 +119,29 @@ gboolean db_conn_reconnect (DbConn * obj, GError ** err); DbResultSet * db_conn_exec (DbConn * obj, const gchar * sql, GError ** err); -DbRequest * db_conn_query (DbConn * obj, const gchar * sql); +DbRequest * db_conn_query (DbConn * obj, const gchar * sql, SqlBatch * batch); DbRequest * db_conn_query_async (DbConn * obj ,const gchar * sql + ,SqlBatch * batch ,DbRequestDoneCallback callback ,gpointer user_data ,GDestroyNotify notify); -DbRequest * db_conn_query_with_stmt (DbConn * obj, SqlStmt * stmt); +DbRequest * db_conn_query_with_stmt (DbConn * obj, SqlStmt * stmt, SqlBatch * batch); DbRequest * db_conn_query_with_stmt_async (DbConn * obj ,SqlStmt * stmt + ,SqlBatch * batch ,DbRequestDoneCallback callback ,gpointer user_data ,GDestroyNotify notify); -gboolean db_conn_query_value (DbConn * obj, const gchar * sql, GValue * value, GError ** err); +gboolean db_conn_query_value (DbConn * obj, const gchar * sql, SqlBatch * batch, GValue * value, GError ** err); void db_conn_retry (DbConn * obj); void db_conn_kill_query (DbConn * obj); SqlStmt * db_conn_parse (DbConn * obj, gchar * sql); -gchar * db_conn_render (DbConn * obj, gpointer object, GError ** err); +gchar * db_conn_render (DbConn * obj, gpointer object, SqlBatch * batch, GError ** err); guchar * db_conn_escape_binary (DbConn * obj, const guchar * from, gsize from_size, gsize * to_size); void db_conn_start_transaction (DbConn * obj); @@ -150,6 +152,6 @@ gchar * db_conn_get_user (DbConn * obj); gchar * db_conn_get_host (DbConn * obj); gchar * db_conn_get_schema (DbConn * obj); -SqlString * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_file); +SqlObject * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_file); #endif \ No newline at end of file diff --git a/db/db-iterator.c b/db/db-iterator.c index 8585dbf..1a852de 100644 --- a/db/db-iterator.c +++ b/db/db-iterator.c @@ -838,7 +838,7 @@ void db_iterator_link_with_param (DbIterator * obj, const gchar * field, GvnPara g_return_if_fail (obj->model); g_return_if_fail (field); - db_model_set_default_value_from_param (obj->model, field, param); + db_model_set_default_value_from_param (obj->model, field, param, TRUE); } /** diff --git a/db/db-model.c b/db/db-model.c index 912eb4d..500c208 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -21,6 +21,11 @@ #include "db-model.h" #include "db-row.h" +#define MODEL_NOT_READY(obj) (obj->priv->status != DB_MODEL_STATUS_READY) +#define VALID_ITER(iter, model) (iter->data && iter->stamp == model->priv->stamp) +#define DB_ROW_FIELD(row, field) (&((DbRow *) row)->value[field]) +#define DB_ROW_POSITION(row) (((DbRow *) row)->position) + /** * SECTION: db-model * @Short_description: data vinculed to a SELECT query sent to the database @@ -31,6 +36,7 @@ * database connected by a #DbConn. It is normally used undirectly, using instead * #DbForm. **/ +G_DEFINE_TYPE (DbModel, db_model, G_TYPE_OBJECT) /* * DbModel: @@ -46,6 +52,7 @@ struct _DbModelPrivate gboolean use_file; gchar * main_table; DbModelUpdateFlags update_flags; + SqlBatch * batch; GPtrArray * data; DbColumn * column; @@ -64,8 +71,11 @@ struct _DbModelPrivate GHashTable * column_index; GSList * pending_request; GSList * join; - GSList * column_default; - GSList * param_default; + + SqlObject * link_op; + SqlBatch * internal_batch; + GHashTable * defaults; + GHashTable * column_default; gint stamp; @@ -82,63 +92,6 @@ struct _DbModelPrivate GDestroyNotify sort_destroy; }; -G_DEFINE_TYPE (DbModel, db_model, G_TYPE_OBJECT) - -#define MODEL_NOT_READY(obj) (obj->priv->status != DB_MODEL_STATUS_READY) -#define VALID_ITER(iter, model) (iter->data && iter->stamp == model->priv->stamp) -#define DB_ROW_FIELD(row, field) (&((DbRow *) row)->value[field]) -#define DB_ROW_POSITION(row) (((DbRow *) row)->position) - -// Constructors - -/** - * db_model_new: - * @conn: a #DbConn - * @stmt: an #SqlStmt - * - * Returns the newly created #DbModel, filled with the data retrieved from the - * database with @stmt and through @conn. - * - * Return value: (transfer full): a new #DbModel - **/ -DbModel * db_model_new (DbConn * conn, SqlStmt * stmt) -{ - return g_object_new (DB_TYPE_MODEL, "conn", conn, "stmt", stmt, NULL); -} - -/** - * db_model_new_with_sql: - * @conn: a #DbConn - * @sql: a string containing an SQL statement - * - * Returns the newly created #DbModel, filled with the data retrieved from the - * database with @stmt and through @conn. - * - * Return value: (transfer full): a new #DbModel - **/ -DbModel * db_model_new_with_sql (DbConn * conn, const gchar * sql) -{ - return g_object_new (DB_TYPE_MODEL, - "conn", conn, "use-file", FALSE, "sql", sql, NULL); -} - -/** - * db_model_new_with_file: - * @conn: a #DbConn - * @file: the path to the file containing the SQL query to fill the model - * - * Returns a newly created #DbModel, filled with the data retrieved from @file. - * - * Return value: (transfer full): a new #DbModel - **/ -DbModel * db_model_new_with_file (DbConn * conn, const gchar * file) -{ - return g_object_new (DB_TYPE_MODEL, - "conn", conn, "use-file", TRUE, "sql", file, NULL); -} - -//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private - // Helper structures and methods // Structures @@ -219,17 +172,13 @@ DbJoin; typedef struct { - gchar * dst; - gint col; + gchar * field; + gpointer param; + gboolean link; + SqlObject * equal_op; + DbModel * obj; } -DbColDef; - -typedef struct -{ - gchar * dst; - GvnParam * param; -} -DbParamDef; +ParamDef; typedef struct { @@ -244,6 +193,56 @@ enum DB_MODEL_DEFAULT_SORT_COLUMN_ID }; +// Constructors + +/** + * db_model_new: + * @conn: a #DbConn + * @stmt: an #SqlStmt + * + * Returns the newly created #DbModel, filled with the data retrieved from the + * database with @stmt and through @conn. + * + * Return value: (transfer full): a new #DbModel + **/ +DbModel * db_model_new (DbConn * conn, SqlStmt * stmt) +{ + return g_object_new (DB_TYPE_MODEL, "conn", conn, "stmt", stmt, NULL); +} + +/** + * db_model_new_with_sql: + * @conn: a #DbConn + * @sql: a string containing an SQL statement + * + * Returns the newly created #DbModel, filled with the data retrieved from the + * database with @stmt and through @conn. + * + * Return value: (transfer full): a new #DbModel + **/ +DbModel * db_model_new_with_sql (DbConn * conn, const gchar * sql) +{ + return g_object_new (DB_TYPE_MODEL, + "conn", conn, "use-file", FALSE, "sql", sql, NULL); +} + +/** + * db_model_new_with_file: + * @conn: a #DbConn + * @file: the path to the file containing the SQL query to fill the model + * + * Returns a newly created #DbModel, filled with the data retrieved from @file. + * + * Return value: (transfer full): a new #DbModel + **/ +DbModel * db_model_new_with_file (DbConn * conn, const gchar * file) +{ + return g_object_new (DB_TYPE_MODEL, + "conn", conn, "use-file", TRUE, "sql", file, NULL); +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private + // Prototypes static void db_model_set_status (DbModel * obj @@ -470,9 +469,9 @@ static void db_model_on_join_query_done (DbRequest * request, JoinData * join_da static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) { - if (obj->priv->conn && stmt) + if (obj->priv->conn && obj->priv->stmt) { - if (sql_object_is_ready (SQL_OBJECT (stmt))) + if (sql_object_is_ready (SQL_OBJECT (obj->priv->stmt))) db_model_refresh (obj); else { @@ -482,6 +481,11 @@ static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) } } +static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj) +{ + db_model_on_stmt_changed (NULL, obj); +} + static void db_model_on_operations_done (DbRequest * request, DbModelRequest * data) { DbOperation * op; @@ -860,7 +864,7 @@ static void db_join_free (DbJoin * join) g_free (join); } - +/* static void db_model_calculate_col_def (DbModel * obj, SqlJoin * join, SqlField * l_field, SqlField * r_field) { @@ -936,17 +940,15 @@ static void db_model_set_join_fields (DbModel * obj, SqlJoin * join, g_ptr_array_add (rfield->name, g_strdup (check ? rsql_field->name : lsql_field->name)); } - +*/ static void db_model_post_process_query (DbModel * obj) { +/* // TODO When parser gets fully functional, these 3 lines won't be needed, // because obj->stmt will be a parsed stmt: - gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, NULL); + gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, obj->priv->batch, NULL); SqlObject * stmt = sql_parser_parse (rend); -/*gchar * rend2 = NULL; -if (stmt && (rend2 = db_conn_render (obj->priv->conn, stmt, NULL))) -g_message ("SQL + Parser + Render =\n %s", rend2); -g_free (rend2);*/ + g_free (rend); if (stmt && SQL_IS_SELECT (stmt)) @@ -983,10 +985,10 @@ g_free (rend2);*/ for (l = sql_list_get_items (op->operators); l; l = l->next) { - SqlOperation * subop; + SqlOperation * subop = l->data; operators = sql_list_get_items (subop->operators); - if (SQL_IS_OPERATION (subop = l->data) + if (SQL_IS_OPERATION (subop) && subop->type == SQL_OPERATION_TYPE_EQUAL && operators->data // Left Field && operators->next && operators->next->data) // Right Field @@ -1049,6 +1051,7 @@ g_free (rend2);*/ if (G_IS_OBJECT (stmt)) g_object_unref (stmt); +*/ } static inline gboolean stored (const gint * v, const gint length, const gint target) @@ -1061,39 +1064,6 @@ static inline gboolean stored (const gint * v, const gint length, const gint tar return FALSE; } -static DbModelPKey * db_model_get_primary_key (DbModel *obj, gchar * table) -{ - gint i, j; - DbModelPKey * pkey = g_new (DbModelPKey, 1); - pkey->count = 0; -// Get number of pkeys - for (i = 0; i < obj->priv->result->ncols; i++) - if ((obj->priv->column[i].info & DB_COLUMN_PRI_KEY) - && !g_strcmp0 (obj->priv->column[i].table, table)) - pkey->count++; - - pkey->index = g_new (gint, pkey->count); -// Get pkey/s - for (i = 0; i < pkey->count; i++) - for (j = 0; j < obj->priv->result->ncols; j++) - if (!g_strcmp0 (obj->priv->column[j].table, table) - && (obj->priv->column[j].info & DB_COLUMN_PRI_KEY) - && !stored (pkey->index, i+1, j)) - { - pkey->index[i] = j; - break; - } - - return pkey; -} - -static void db_model_pkey_free (DbModelPKey * pkey) -{ - g_free (pkey->index); - g_free (pkey); -} - - /* * Comparison between values, using case-insensitive and UTF-8 strings */ @@ -1304,6 +1274,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) request = db_conn_query_with_stmt_async (priv->conn ,g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL) + ,NULL ,(DbRequestDoneCallback) db_model_on_join_query_done ,join_data ,(GDestroyNotify) join_data_free @@ -1414,6 +1385,57 @@ static gboolean db_model_table_row_all_null (DbModel * obj, DbRow * row, gint co return TRUE; } +// Memory allocate functions + +static void param_def_free (ParamDef * def) +{ + g_object_unref (def->param); + + if (def->equal_op) + { + SqlObject * operators = + sql_object_get (def->obj->priv->link_op, "operators"); + sql_list_remove_item (SQL_LIST (operators), def->equal_op); + } + + g_free (def); +} + +static void db_model_alloc_updatable_data (DbModel * obj) +{ + DbModelPrivate * priv = obj->priv; + + priv->operation = g_queue_new (); + priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->defaults = g_hash_table_new_full ( + g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) param_def_free + ); + priv->column_default = g_hash_table_new_full ( + g_str_hash, + g_str_equal, + g_free, + g_free + ); +} + +static void db_model_alloc_link_data (DbModel * obj) +{ + DbModelPrivate * priv = obj->priv; + + if (!priv->internal_batch) + { + priv->internal_batch = g_object_ref_sink (sql_batch_new ()); + g_signal_connect (priv->internal_batch, "changed", + G_CALLBACK (db_model_on_batch_changed), obj); + + priv->link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); + sql_batch_add (priv->internal_batch, "link", priv->link_op); + } +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public // Set&Get methods @@ -1685,77 +1707,108 @@ void db_model_add_join_columns (DbModel * obj, const gchar * left, const gchar * obj->priv->join = g_slist_prepend (obj->priv->join, join); } +/** + * db_model_get_batch: + * @obj: a #DbModel + * @return: the #SqlBatch + * + * Gets the batch used by the model. + **/ +SqlBatch * db_model_get_batch (DbModel * obj) +{ + return obj->priv->batch; +} + +/** + * db_model_set_batch: + * @obj: a #DbModel + * @batch: the #SqlBatch + * + * Sets the batch used by the model. + **/ +void db_model_set_batch (DbModel * obj, SqlBatch * batch) +{ + DbModelPrivate * priv; + + g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (SQL_IS_BATCH (batch) || !batch); + + priv = obj->priv; + + if (priv->batch) + { + g_signal_handlers_disconnect_by_func (priv->batch, + db_model_on_batch_changed, obj); + g_object_unref (priv->batch); + } + if (batch) + { + g_signal_connect (batch, "changed", + G_CALLBACK (db_model_on_batch_changed), obj); + g_object_ref_sink (batch); + } + + priv->batch = batch; +} + /** * db_model_set_default_value_from_column: * @obj: a #DbModel - * @dst_field: the field to be set - * @src_column: field from wich the value is picked - * - * TODO: cambiar src_column a string y almacenarlo, cuando se vaya a usar, cambiarlo - por el entero correspondiente + * @field: the field to be set + * @column: field from wich the value is picked **/ void db_model_set_default_value_from_column (DbModel * obj, - const gchar * dst_field, gint src_column) + const gchar * field, const gchar * column) { g_return_if_fail (DB_IS_MODEL (obj)); - if (!obj->priv->result || 0 > src_column || src_column >= obj->priv->result->ncols) - return; + g_return_if_fail (field); + g_return_if_fail (column); - DbColDef * def = g_new (DbColDef, 1); - def->dst = g_strdup (dst_field); - def->col = src_column; - - obj->priv->column_default = g_slist_prepend (obj->priv->column_default, def); + g_hash_table_insert (obj->priv->column_default, g_strdup (field), g_strdup (column)); + g_hash_table_remove (obj->priv->defaults, field); } /** * db_model_set_default_value_from_param: * @obj: a #DbModel - * @dst_field: the field to be set + * @field: the field to be set * @param: a #GvnParam - * @id: an identifier string for @param + * @link: * * Get the default value for @dst_field from @param. **/ void db_model_set_default_value_from_param (DbModel * obj, - const gchar * dst_field, GvnParam * param, const gchar * id) + const gchar * field, GvnParam * param, gboolean link) { - SqlObject * op, * value; + SqlObject * equal_op = NULL; g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (field); g_return_if_fail (GVN_IS_PARAM (param)); - g_return_if_fail (dst_field); + + if (link) + { + SqlObject * value; + + db_model_alloc_link_data (obj); - op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - sql_object_add_child (op, "operators", sql_field_new (dst_field, NULL, NULL)); + equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); + sql_object_add_child (obj->priv->link_op, "operators", equal_op); - value = sql_value_new (); - sql_value_set_param (SQL_VALUE (value), param); - sql_object_add_child (op, "operators", value); + sql_object_add_child (equal_op, "operators", sql_field_new (field, NULL, NULL)); - sql_object_add_held_object (SQL_OBJECT (obj->priv->stmt), id, op); + value = sql_value_new (); + sql_value_set_param (SQL_VALUE (value), param); + sql_object_add_child (equal_op, "operators", value); + } - DbParamDef * def = g_new (DbParamDef, 1); - def->dst = g_strdup (dst_field); - def->param = g_object_ref_sink (param); - - obj->priv->param_default = g_slist_prepend (obj->priv->param_default, def); -} - -/** - * db_model_add_param: - * @obj: a #DbModel - * @id: an identifier string for @param - * @param: the #GvnParam to add - * - * Links the statement in the model to @param. - **/ -void db_model_add_param (DbModel * obj, const gchar * id, GvnParam * param) -{ - g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (GVN_IS_PARAM (param)); - - sql_string_add_param (SQL_STRING (obj->priv->stmt), id, param); + ParamDef * def = g_new (ParamDef, 1); + def->param = g_object_ref (param); + def->link = link; + def->equal_op = equal_op; + def->obj = obj; + g_hash_table_insert (obj->priv->defaults, g_strdup (field), def); + g_hash_table_remove (obj->priv->column_default, field); } /** @@ -1839,7 +1892,7 @@ void db_model_set_stmt (DbModel * obj, SqlStmt * stmt) **/ void db_model_set_sql (DbModel * obj, const gchar * sql) { - SqlString * string; + SqlObject * string; if (!sql) return; @@ -2123,22 +2176,33 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter) for (i = 0; i < row->len; i++) { - GSList * p; - const GValue * def = NULL; - - for (p = priv->param_default; p; p = p->next) + gchar * column = priv->column[i].name; + const GValue * def_value = NULL; + ParamDef * def = g_hash_table_lookup (priv->defaults, column); + + if (def) + def_value = gvn_param_get_value (def->param); + + if (!def_value) { - DbParamDef * param_def = p->data; - - if (!g_strcmp0 (param_def->dst, priv->column[i].name)) + gchar * column_def = g_hash_table_lookup (priv->column_default, column); + + if (column_def) { - def = gvn_param_get_value (param_def->param); - g_value_init (&row->value[i], G_VALUE_TYPE (def)); - gvn_value_copy (def, &row->value[i]); + gint col = db_model_get_column_index (obj, column_def); + + if (col != -1 + && !g_strcmp0 (priv->column[col].table, priv->column[i].table)) + def_value = &row->value[col]; } } - - if (!def) + + if (!def_value) + def_value = gvn_param_spec_get_default (priv->column[i].spec); + + if (def_value && G_VALUE_TYPE (def_value) != SQL_TYPE_FUNCTION) + gvn_value_copy (def_value, &row->value[i]); + else g_value_init (&row->value[i], GVN_TYPE_NULL); } @@ -2357,6 +2421,105 @@ gboolean db_model_has_pending_operations (DbModel * obj) return g_hash_table_size (obj->priv->row_ops) > 0; } +static SqlObject * db_model_create_where (DbModel * obj, + const gchar * table, DbOperation * operation, gboolean for_insert) +{ + gint i; + GSList * l; + DbUpdatedField * u; + GValue * g_value; + SqlObject * value; + DbRow * row = operation->row; + DbModelPrivate * priv = obj->priv; + SqlObject * where = sql_operation_new (SQL_OPERATION_TYPE_AND); + + for (i = 0; i < row->len; i++) + if ((priv->column[i].info & DB_COLUMN_PRI_KEY) + && !g_strcmp0 (priv->column[i].table, table)) + { + SqlObject * equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); + sql_object_add_child (where, "operators", equal); + + sql_object_add_child (equal, "operators", + sql_field_new (priv->column[i].name, NULL, NULL)); + + value = NULL; + + g_value = &row->value[i]; + + for (l = operation->updated; l && (u = l->data); l = l->next) + if (u->column == i) + { + g_value = u->value; + break; + } + + if (gvn_value_is_null (g_value) && for_insert) + { + const GValue * def = gvn_param_spec_get_default (priv->column[i].spec); + + if (def && G_IS_VALUE (def) + && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION) + value = g_value_get_object (def); + } + else + value = sql_value_new_with_value (g_value); + + if (!value) + { + g_object_unref (g_object_ref_sink (where)); + return NULL; + } + + sql_object_add_child (equal, "operators", value); + } + + return where; +} + +static SqlObject * db_model_create_insert (DbModel * obj, + const gchar * table, DbOperation * operation) +{ + gint i; + DbModelPrivate * priv = obj->priv; + DbRow * row = operation->row; + SqlObject * target, * insert, * set, * select, * val, * stmts; + SqlObject * where = db_model_create_where (obj, table, operation, TRUE); + + if (!where) + return NULL; + + stmts = sql_multi_stmt_new (); + target = sql_table_new (table); + + insert = g_object_new (SQL_TYPE_INSERT, "table", target, NULL); + set = g_object_new (SQL_TYPE_SET, NULL); + sql_object_add_child (insert, "values", set); + + select = sql_select_new (); + sql_object_add_child (select, "targets", target); + sql_object_set (select, "where", where); + + for (i = 0; i < row->len; i++) + if (!g_strcmp0 (priv->column[i].table, table)) + { + val = sql_value_new_with_value (&row->value[i]); + + sql_object_add_child (insert, "fields", + sql_field_new (priv->column[i].name, NULL, NULL)); + sql_object_add_child (set, "exprs", + gvn_value_is_null (&row->value[i]) ? NULL : val); + + sql_object_add_child (select, "exprs", + sql_field_new (priv->column[i].name, + priv->column[i].table, NULL)); + } + + sql_object_add_child (stmts, "stmts", insert); + sql_object_add_child (stmts, "stmts", select); + return stmts; +} + /** * db_model_perform_operations: * @obj: a #DbModel with a new row, not yet inserted @@ -2372,19 +2535,13 @@ gboolean db_model_has_pending_operations (DbModel * obj) void db_model_perform_operations (DbModel * obj, gboolean retry) { DbModelPrivate * priv; - gboolean render_ops = FALSE, transaction = FALSE; - gint i; + gboolean error = FALSE; DbRow * row; DbOperation * op_elem; - GList * l = NULL; - GSList * sl = NULL; - SqlObject * multi = NULL, - * equal_op, * val = NULL, - * insert, * set, - * select, * where = NULL; + SqlObject * where; SqlList * stmts; DbRequest * request; - GQueue * req_ops = NULL; + GQueue * req_ops; g_return_if_fail (DB_IS_MODEL (obj)); @@ -2399,16 +2556,12 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) if (!priv->operation->length) return; - - if (priv->operation->length > 1) - transaction = TRUE; - + + req_ops = g_queue_new (); stmts = sql_list_new (SQL_TYPE_STMT); - while ((op_elem = g_queue_pop_head (priv->operation))) + while (!error && (op_elem = g_queue_pop_head (priv->operation))) { - const GValue * def; - op_elem->locked = TRUE; row = op_elem->row; @@ -2420,389 +2573,112 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) op_elem = NULL; g_signal_emit (obj, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (row)); - - if (!transaction) - { - g_object_unref (stmts); - stmts = NULL; - } } - else + else if ((where = db_model_create_where (obj, priv->main_table, op_elem, FALSE))) { SqlObject * delete = sql_delete_new (); sql_object_add_child (delete, "targets", - sql_table_new (priv->main_table, NULL)); - - where = sql_operation_new (SQL_OPERATION_TYPE_AND); - - DbModelPKey * pkey = - db_model_get_primary_key (obj, priv->main_table); - - for (i = 0; i < pkey->count; i++) - { - equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - - sql_object_add_child (equal_op, "operators", - sql_field_new (priv->column[pkey->index[i]].name, NULL, NULL)); - sql_object_add_child (equal_op, "operators", - sql_value_new_with_value (&row->value[pkey->index[i]])); - - sql_object_add_child (where, "operators", equal_op); - } - - db_model_pkey_free (pkey); + sql_table_new (priv->main_table)); sql_object_set (delete, "where", where); - sql_list_add (stmts, delete); - render_ops = TRUE; } + else + error = TRUE; } else if (op_elem->type & DB_MODEL_ROW_OP_INSERT) // INSERT { - SqlObject * target = sql_table_new (priv->main_table); - - insert = g_object_new (SQL_TYPE_INSERT, "table", target, NULL); - set = g_object_new (SQL_TYPE_SET, NULL); - sql_object_add_child (insert, "values", set); - - select = sql_select_new (); - sql_object_add_child (select, "targets", target); - where = sql_operation_new (SQL_OPERATION_TYPE_AND); - - for (i = 0; i < row->len; i++) - if (!g_strcmp0 (priv->column[i].table, priv->main_table)) - { - gboolean cont = FALSE; - SqlObject * field = NULL; - - l = sql_list_get_items (SQL_INSERT (insert)->fields); - - for (; l; l = l->next) - if (!g_strcmp0 (((SqlField*) l->data)->name, priv->column[i].name) - && ((!((SqlField*) l->data)->target) - || !g_strcmp0 (((SqlField*) l->data)->target, priv->column[i].table))) - { - cont = TRUE; - break; - } - - if (cont) - continue; - - val = sql_value_new_with_value (&row->value[i]); - - sql_object_add_child (insert, "fields", - sql_field_new (priv->column[i].name, NULL, NULL)); - sql_object_add_child (set, - "exprs", gvn_value_is_null (&row->value[i]) ? NULL : val); - - sql_object_add_child (select, "exprs", - sql_field_new (priv->column[i].name, - priv->column[i].table, NULL)); - - // Set the filter conditions - if (priv->column[i].info & DB_COLUMN_PRI_KEY) - { - gboolean unset = FALSE; - GValue value = {0}; - SqlObject * eq_value; - - equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - sql_object_add_child (equal_op, "operators", field); - - def = gvn_param_spec_get_default (priv->column[i].spec); - - if (!gvn_value_is_null (&row->value[i])) - { - eq_value = val; - } - else if (def && G_IS_VALUE (def)) - { - if (G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION) - eq_value = g_value_get_object (def); - else - eq_value = sql_value_new_with_value (def); - } - else - { - gvn_value_set_null (&value); - eq_value = sql_value_new_with_value (&value); - unset = TRUE; - } - - sql_object_add_child (equal_op, "operators", eq_value); - - if (unset) - g_value_unset (&value); - - sql_object_add_child (where, "operators", equal_op); - } - } - - sql_object_set (select, "where", where); - - for (sl = priv->param_default; sl; sl = sl->next) - { - gboolean cont = FALSE; - DbParamDef * param_def = sl->data; - - l = sql_list_get_items (SQL_INSERT (insert)->fields); - - for (; l; l = l->next) - if (!g_strcmp0 (((SqlField*) l->data)->name, param_def->dst)) - { - cont = TRUE; - break; - } - - if (cont) continue; - - val = sql_value_new_with_value - (gvn_param_get_value (param_def->param)); - - sql_object_add_child (insert, "fields", - sql_field_new (param_def->dst, NULL, NULL)); - sql_object_add_child (set, "exprs", val); - } - - sql_list_add (stmts, insert); - sql_list_add (stmts, select); - render_ops = TRUE; + SqlObject * insert = db_model_create_insert (obj, priv->main_table, op_elem); + + if (insert) + sql_list_add (stmts, insert); + else + error = TRUE; } else if (op_elem->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE { // Depending on the field, generate an UPDATE or INSERT+SELECT - GSList * m; - GValue * new_value; - SqlObject * update = NULL; - GSList * prev_tables = NULL; - GSList * prev_updates = NULL; - gboolean insert_set = FALSE; - select = NULL; - for (m = op_elem->updated; m; m = m->next) + GSList * l; + GHashTableIter iter; + gpointer table; + + GHashTable * tables = g_hash_table_new ( + g_str_hash, g_str_equal); + + for (l = op_elem->updated; l; l = l->next) { - DbUpdatedField * u = m->data; - i = u->column; - - new_value = DB_ROW_FIELD (row, i); - - if (!priv->column_default - || !gvn_value_is_null (u->value) - || !g_strcmp0 (priv->column[i].table, priv->main_table) - || !db_model_table_row_all_null (obj, row, i)) + DbUpdatedField * u = l->data; + g_hash_table_add (tables, priv->column[u->column].table); + } + + g_hash_table_iter_init (&iter, tables); + + while (g_hash_table_iter_next (&iter, &table, NULL)) + { + where = db_model_create_where (obj, priv->main_table, op_elem, FALSE); + + if (where) { - gboolean is_added = NULL != g_slist_find_custom (prev_tables, - priv->column[i].table, (GCompareFunc) g_strcmp0); + DbUpdatedField * u; + SqlObject * update = g_object_new (SQL_TYPE_UPDATE, + "where", where, NULL); - if (!is_added) + sql_object_add_child (update, "targets", + sql_table_new (table)); + + for (l = op_elem->updated; l && (u = l->data); l = l->next) + if (!g_strcmp0 (priv->column[u->column].table, table)) { - where = sql_operation_new (SQL_OPERATION_TYPE_AND); - update = g_object_new (SQL_TYPE_UPDATE, - "where", where, NULL); - } - else - { - GSList * l; - SqlTable * t; + GValue * new_value = DB_ROW_FIELD (row, u->column); - for (l = prev_updates; l; l = l->next) - if (SQL_IS_UPDATE (l->data) - && SQL_IS_TABLE (t = sql_list_get_items (SQL_DML (l->data)->targets)->data) - && !g_strcmp0 (SQL_TABLE (t)->name, priv->column[i].table)) - { - update = l->data; - break; - } + sql_object_add_child (update, "sets", + g_object_new (SQL_TYPE_UPDATE_SET, + "field", sql_field_new (priv->column[u->column].name, NULL, NULL), + "expr", sql_value_new_with_value (new_value), + NULL)); } - sql_object_add_child (update, "sets", - g_object_new (SQL_TYPE_UPDATE_SET, - "field", sql_field_new (priv->column[i].name, NULL, NULL), - "expr", sql_value_new_with_value (new_value), - NULL)); - - if (!is_added) - { - guint j; - DbModelPKey * pkey = - db_model_get_primary_key (obj, priv->column[i].table); - - sql_object_add_child (update, "targets", - sql_table_new (priv->column[i].table)); - - for (j = 0; j < pkey->count; j++) - { - gint key_col = pkey->index[j]; - GValue * primary = NULL; - GSList * n; - - if (key_col == i) - primary = u->value; - else - { - for (n = op_elem->updated; n; n = n->next) - if (((DbUpdatedField *)n->data)->column == key_col) - break; - - if (n) - primary = ((DbUpdatedField *) n->data)->value; - else - primary = DB_ROW_FIELD (row, key_col); - } - - equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - - sql_object_add_child (equal_op, "operators", - sql_field_new (priv->column[key_col].name, - priv->column[key_col].table, NULL)); - - val = sql_value_new_with_value (primary); - sql_object_add_child (equal_op, "operators", val); - - if (where) - sql_object_add_child (where, "operators", equal_op); - } - - sql_object_set (update, "where", where); - - sql_list_add (stmts, update); - db_model_pkey_free (pkey); - } - - prev_tables = g_slist_prepend (prev_tables, priv->column[i].table); - prev_updates = g_slist_prepend (prev_updates, update); + sql_list_add (stmts, update); } else { - GSList * n; - - if (!insert) - { - insert = sql_insert_new (); - select = sql_select_new (); - } - - if (!SQL_INSERT (insert)->table) - { - SqlObject * table = sql_table_new (priv->column[i].table); - sql_object_set (insert, "table", table); - sql_object_add_child (select, "targets", table); - - set = g_object_new (SQL_TYPE_SET, NULL); - sql_object_add_child (insert, "values", set); - - insert_set = TRUE; - - for (n = priv->column_default; n; n = n->next) - { - gchar * dst = ((DbColDef *) n->data)->dst; - gint col_def = ((DbColDef *) n->data)->col; - - if (!g_strcmp0 (priv->column[i].table, - priv->column[col_def].table)) - continue; - - sql_object_add_child (insert, "fields", - sql_field_new (dst, NULL, NULL)); - - sql_object_add_child (set, "exprs" - ,sql_value_new_with_value (DB_ROW_FIELD (row, col_def))); - } - } - - if (insert_set) - { - val = sql_value_new_with_value (new_value); - - sql_object_add_child (insert, "fields", - sql_field_new (priv->column[i].name, NULL, NULL)); - sql_object_add_child (set, "exprs", val); - } + SqlObject * insert = db_model_create_insert (obj, table, op_elem); + + if (insert) + sql_list_add (stmts, insert); } } - - g_slist_free (prev_tables); - g_slist_free (prev_updates); - - if (insert) - { - where = sql_operation_new (SQL_OPERATION_TYPE_AND); - - for (i = 0; i < row->len; i++) - if (!g_strcmp0 (SQL_TABLE (sql_list_get_items (SQL_DML (select)->targets)->data)->name - ,priv->column[i].table)) - { - SqlObject * field = SQL_OBJECT - (sql_field_new (priv->column[i].name, NULL, NULL)); - sql_object_add_child (select, "fields", field); - - if (priv->column[i].info & DB_COLUMN_PRI_KEY) - { - def = gvn_param_spec_get_default (priv->column[i].spec); - - if (!gvn_value_is_null (&row->value[i]) - || (def && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION)) - { - equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - - sql_object_add_child (equal_op, "operators", field); - - if (gvn_value_is_null (&row->value[i])) - { - if (def && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION) - sql_object_add_child (equal_op, "operators", - g_value_get_object (def)); - } - else - sql_object_add_child (equal_op, "operators", val); - - sql_object_add_child (where, "operators", equal_op); - } - } - } - - sql_object_set (select, "where", where); - - sql_list_add (stmts, insert); - sql_list_add (stmts, select); - } - - render_ops = TRUE; + + g_hash_table_destroy (tables); } - if (op_elem) - { - if (!req_ops) - req_ops = g_queue_new (); - - g_queue_push_tail (req_ops, op_elem); - } + g_queue_push_tail (req_ops, op_elem); } - if (render_ops) + if (sql_list_length (stmts) > 0) { - if (multi) - { - DbModelRequest * data = g_new (DbModelRequest, 1); - data->obj = g_object_ref (obj); - data->operations = req_ops; - multi = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); + SqlObject * multi = g_object_new (SQL_TYPE_MULTI_STMT, + "stmts", stmts, NULL); + + DbModelRequest * data = g_new (DbModelRequest, 1); + data->obj = g_object_ref (obj); + data->operations = req_ops; - request = db_conn_query_with_stmt_async (priv->conn - ,SQL_STMT (multi) - ,(DbRequestDoneCallback) db_model_on_operations_done - ,data - ,(GDestroyNotify) db_model_request_free - ); - db_model_add_pending_request (obj, request); - } - else - { - g_queue_free (req_ops); - db_model_clean_operations (obj); - } + request = db_conn_query_with_stmt_async (priv->conn + ,SQL_STMT (multi) + ,NULL + ,(DbRequestDoneCallback) db_model_on_operations_done + ,data + ,(GDestroyNotify) db_model_request_free + ); + db_model_add_pending_request (obj, request); + } + else + { + g_queue_free (req_ops); + g_object_unref (g_object_ref_sink (stmts)); + db_model_clean_operations (obj); } } @@ -2825,6 +2701,7 @@ void db_model_refresh (DbModel * obj) priv->request = db_conn_query_with_stmt_async (priv->conn ,priv->stmt + ,priv->batch ,(DbRequestDoneCallback) db_model_on_data_ready ,g_object_ref (obj) ,(GDestroyNotify) g_object_unref @@ -3157,80 +3034,77 @@ static void db_model_get_property (DbModel * obj, guint property_id, static void db_model_init (DbModel *obj) { - obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, DB_TYPE_MODEL, DbModelPrivate); + DbModelPrivate * priv = obj->priv = + G_TYPE_INSTANCE_GET_PRIVATE (obj, DB_TYPE_MODEL, DbModelPrivate); - obj->priv->conn = NULL; - obj->priv->stmt = NULL; - obj->priv->use_file = FALSE; - obj->priv->sql = NULL; - obj->priv->main_table = NULL; - obj->priv->update_flags = 0; - obj->priv->user_main_table = NULL; - obj->priv->user_update_flags = DB_MODEL_ALL; - obj->priv->request = NULL; - obj->priv->status = DB_MODEL_STATUS_CLEAN; - obj->priv->mode = DB_MODEL_MODE_ON_CHANGE; - obj->priv->result = NULL; - obj->priv->result_pos = 0; - obj->priv->data = NULL; - obj->priv->column = NULL; - obj->priv->operation = g_queue_new (); - obj->priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); - obj->priv->column_index = NULL; - obj->priv->join = NULL; - obj->priv->column_default = NULL; - obj->priv->param_default = NULL; - obj->priv->pending_request = NULL; + priv->conn = NULL; + priv->batch = NULL; + priv->stmt = NULL; + priv->use_file = FALSE; + priv->sql = NULL; + priv->update_flags = 0; + priv->user_update_flags = DB_MODEL_ALL; + priv->request = NULL; + priv->status = DB_MODEL_STATUS_CLEAN; + priv->mode = DB_MODEL_MODE_ON_CHANGE; + priv->result = NULL; + priv->result_pos = 0; + priv->data = NULL; + priv->column = NULL; + priv->column_index = NULL; - obj->priv->stamp = g_random_int (); + priv->link_op = NULL; + priv->internal_batch = NULL; + + priv->main_table = NULL; + priv->user_main_table = NULL; + priv->defaults = NULL; + priv->column_default = NULL; + priv->operation = NULL; + priv->row_ops = NULL; + priv->join = NULL; + priv->pending_request = NULL; - obj->priv->fresh = TRUE; - obj->priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; - obj->priv->default_sort_data = NULL; - obj->priv->default_sort_func = NULL; - obj->priv->default_sort_destroy = NULL; + // TODO: Call this method only when is necessary + db_model_alloc_updatable_data (obj); + + priv->stamp = g_random_int (); + + priv->fresh = TRUE; + priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; + priv->default_sort_data = NULL; + priv->default_sort_func = NULL; + priv->default_sort_destroy = NULL; } static void db_model_finalize (DbModel * obj) { - GSList * n; - GObjectClass * parent; - parent = g_type_class_peek_parent (DB_MODEL_GET_CLASS (obj)); + DbModelPrivate * priv = obj->priv; + GObjectClass * parent = g_type_class_peek_parent (DB_MODEL_GET_CLASS (obj)); db_model_clear (obj); - g_clear_object (&obj->priv->conn); - g_clear_object (&obj->priv->stmt); + g_clear_object (&priv->conn); + g_clear_object (&priv->stmt); - if (obj->priv->join) - g_slist_free_full (obj->priv->join, (GDestroyNotify) db_join_free); + if (priv->join) + g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); - g_hash_table_destroy (obj->priv->row_ops); - g_queue_free (obj->priv->operation); + g_hash_table_destroy (priv->row_ops); + g_queue_free (priv->operation); - g_free (obj->priv->sql); - g_free (obj->priv->main_table); - g_free (obj->priv->user_main_table); + g_free (priv->sql); + g_free (priv->main_table); + g_free (priv->user_main_table); - if (obj->priv->column_index) - g_hash_table_destroy (obj->priv->column_index); + if (priv->column_index) + g_hash_table_destroy (priv->column_index); - for (n = obj->priv->column_default; n; n = n->next) - { - g_free (((DbColDef *) n->data)->dst); - g_free (n->data); - } - - g_slist_free (obj->priv->column_default); - - for (n = obj->priv->param_default; n; n = n->next) - { - g_object_unref (((DbParamDef *) n->data)->param); - g_free (((DbParamDef *) n->data)->dst); - g_free (n->data); - } - - g_slist_free (obj->priv->param_default); + db_model_set_batch (obj, NULL); + g_clear_object (&priv->link_op); + g_clear_object (&priv->internal_batch); + g_hash_table_destroy (priv->defaults); + g_hash_table_destroy (priv->column_default); parent->finalize (G_OBJECT (obj)); } diff --git a/db/db-model.h b/db/db-model.h index 26385ee..831988e 100644 --- a/db/db-model.h +++ b/db/db-model.h @@ -245,16 +245,11 @@ gboolean db_model_iter_is_valid (DbIter * iter void db_model_add_join_columns (DbModel * obj ,const gchar * left ,const gchar * right); -void db_model_set_default_value_from_column (DbModel * obj - ,const gchar * dst_field - ,gint src_column); -void db_model_set_default_value_from_param (DbModel * obj - ,const gchar * dst_field - ,GvnParam * param - ,const gchar * id); -void db_model_add_param (DbModel * obj - ,const gchar * id - ,GvnParam * param); +SqlBatch * db_model_get_batch (DbModel * obj); +void db_model_set_batch (DbModel * obj, SqlBatch * batch); + +void db_model_set_default_value_from_column (DbModel * obj, const gchar * field, const gchar * column); +void db_model_set_default_value_from_param (DbModel * obj, const gchar * field, GvnParam * param, gboolean link); //GtkTreeModel-like methods diff --git a/db/db-plugin.c b/db/db-plugin.c index 1666cb0..922a4b4 100644 --- a/db/db-plugin.c +++ b/db/db-plugin.c @@ -183,12 +183,13 @@ SqlStmt * db_plugin_parse (DbPlugin * obj, gchar * sql) * * Return value: (transfer full): the rendered string, or %NULL if error. **/ -gchar * db_plugin_render (DbPlugin * obj, gpointer object, GError ** err) +gchar * db_plugin_render (DbPlugin * obj, gpointer object, SqlBatch * batch, GError ** err) { g_return_val_if_fail (DB_IS_PLUGIN (obj), NULL); g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (SQL_IS_BATCH (batch) || !batch, NULL); - return sql_render_get_string (obj->render, object, obj, err); + return sql_render_get_string (obj->render, object, batch, obj, err); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class diff --git a/db/db-plugin.h b/db/db-plugin.h index 7d64217..228af06 100644 --- a/db/db-plugin.h +++ b/db/db-plugin.h @@ -78,6 +78,6 @@ void db_plugin_set_ssl (DbPlugin * obj, const gchar * ca); DbResultSet * db_plugin_query (DbPlugin * obj, const gchar * sql, GError ** err); void db_plugin_kill_query (DbPlugin * obj); SqlStmt * db_plugin_parse (DbPlugin * obj, gchar * sql); -gchar * db_plugin_render (DbPlugin * obj, gpointer object, GError ** err); +gchar * db_plugin_render (DbPlugin * obj, gpointer object, SqlBatch * batch, GError ** err); #endif \ No newline at end of file diff --git a/db/db-request.c b/db/db-request.c index 9bf13e6..e9b8bb3 100644 --- a/db/db-request.c +++ b/db/db-request.c @@ -73,12 +73,13 @@ DbRequest * db_request_new (DbConn * conn, const gchar * sql) * * Return value: a new #DbRequest **/ -DbRequest * db_request_new_with_stmt (DbConn * conn, SqlStmt * stmt) +DbRequest * db_request_new_with_stmt (DbConn * conn, SqlStmt * stmt, SqlBatch * batch) { g_return_val_if_fail (DB_IS_CONN (conn), NULL); g_return_val_if_fail (SQL_IS_STMT (stmt), NULL); + g_return_val_if_fail (SQL_IS_BATCH (batch) || !batch, NULL); - return g_object_new (DB_TYPE_REQUEST, "conn", conn, "stmt", stmt, NULL); + return g_object_new (DB_TYPE_REQUEST, "conn", conn, "batch", batch, "stmt", stmt, NULL); } /** @@ -352,6 +353,7 @@ typedef enum PROP_CONN = 1 ,PROP_SQL ,PROP_STMT + ,PROP_BATCH ,PROP_RESULT_SET ,PROP_ERROR } @@ -381,12 +383,15 @@ static void db_request_set_property (DbRequest * obj, guint property_id, SqlStmt * stmt = g_value_get_object (value); if (obj->conn && stmt) - obj->sql = db_conn_render (obj->conn, stmt, NULL); + obj->sql = db_conn_render (obj->conn, stmt, obj->batch, NULL); else if (!obj->conn) g_warning ("DbRequest: Can't render stmt, conn property not set"); break; } + case PROP_BATCH: + obj->batch = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); } @@ -470,6 +475,13 @@ static void db_request_class_init (DbRequestClass * k) ,SQL_TYPE_STMT ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE )); + g_object_class_install_property (klass, PROP_BATCH, + g_param_spec_object ("batch" + ,_("Batch") + ,_("The batch for render the statement") + ,SQL_TYPE_BATCH + ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE + )); g_object_class_install_property (klass, PROP_RESULT_SET, g_param_spec_boxed ("result-set" ,_("Result") diff --git a/db/db-request.h b/db/db-request.h index 4ccbbbc..fcb1dcf 100644 --- a/db/db-request.h +++ b/db/db-request.h @@ -60,6 +60,7 @@ struct _DbRequest /* */ DbConn * conn; + SqlBatch * batch; gchar * sql; DbResultSet * result_set; GError * error; @@ -78,7 +79,7 @@ struct _DbRequestClass GType db_request_get_type (); DbRequest * db_request_new (DbConn * conn, const gchar * sql); -DbRequest * db_request_new_with_stmt (DbConn * conn, SqlStmt * stmt); +DbRequest * db_request_new_with_stmt (DbConn * conn, SqlStmt * stmt, SqlBatch * batch); DbResult * db_request_fetch_result (DbRequest * obj, GError ** err); gint db_request_fetch_non_select (DbRequest * obj, GError ** err); gboolean db_request_fetch_value (DbRequest * obj, GValue * value, GError ** err); diff --git a/main/Makefile.am b/main/Makefile.am index c60c904..83916ad 100644 --- a/main/Makefile.am +++ b/main/Makefile.am @@ -9,6 +9,7 @@ AM_CPPFLAGS = \ hedera_bin_LDFLAGS = -Wl,--export-dynamic hedera_bin_SOURCES = main.c hedera_bin_LDADD = \ + $(gtk_LIBS) \ $(top_builddir)/gvn/libgvn.la \ $(top_builddir)/db/libdb.la \ $(top_builddir)/vn/libvn.la diff --git a/module/Makefile.am b/module/Makefile.am index b2980bc..9240edb 100644 --- a/module/Makefile.am +++ b/module/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ src \ - data \ - sql + data diff --git a/module/src/vn-users.c b/module/src/vn-users.c index 9eb2618..953711e 100644 --- a/module/src/vn-users.c +++ b/module/src/vn-users.c @@ -83,8 +83,8 @@ void vn_users_on_dialog_response (GtkDialog * dialog, gint response_id, VnUsers query = sql_string_new ("SELECT user_set_password (#user, #password)"); batch = sql_batch_new (); - sql_batch_add_from_param ("user", obj->user_id); - sql_batch_add_from_value ("password", G_TYPE_STRING, password); + sql_batch_add_from_param (batch, "user", obj->user_id); + sql_batch_add_from_value (batch, "password", G_TYPE_STRING, password); db_conn_query_with_stmt_async (VN_FORM (obj)->conn ,SQL_STMT (query) @@ -108,8 +108,11 @@ static void vn_users_open (VnUsers * obj, gpointer user_data) obj->repeat_password = vn_form_get (form, "repeat-password"); obj->password_dialog = vn_form_get (form, "password-dialog"); - gtk_dialog_add_button (obj->password_dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (obj->password_dialog, GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT); + gtk_dialog_add_buttons (obj->password_dialog + ,_("Cancel"), GTK_RESPONSE_CANCEL + ,_("Apply"), GTK_RESPONSE_ACCEPT + ,NULL + ); users = vn_form_get (form, "users"); obj->user_id = db_iterator_get_param (users, "id"); diff --git a/plugin/mysql/db-mysql.c b/plugin/mysql/db-mysql.c index 4c200e2..88889f8 100644 --- a/plugin/mysql/db-mysql.c +++ b/plugin/mysql/db-mysql.c @@ -271,7 +271,7 @@ static DbResultSet * db_mysql_query (DbMysql * obj, const gchar * sql, GError ** if (field[i].flags & AUTO_INCREMENT_FLAG) { - SqlFunction * func = sql_function_new ("LAST_INSERT_ID", NULL); + SqlObject * func = sql_function_new ("LAST_INSERT_ID", NULL); g_value_init (&def, SQL_TYPE_FUNCTION); g_value_take_object (&def, g_object_ref_sink (func)); @@ -374,7 +374,7 @@ static void db_mysql_kill_query (DbMysql * obj) } } -static void db_mysql_value_render (SqlValue * obj, SqlRender * render) +static void db_mysql_value_render (SqlValue * obj, SqlRender * render, SqlBatch * batch) { if (G_VALUE_TYPE (obj->value) == G_TYPE_BYTES) { @@ -395,7 +395,7 @@ static void db_mysql_value_render (SqlValue * obj, SqlRender * render) sql_render_append (render, "'"); } else - sql_object_render (SQL_OBJECT (obj), render); + sql_object_render (SQL_OBJECT (obj), render, batch); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class diff --git a/plugin/pg/db-pg.c b/plugin/pg/db-pg.c index ad060e6..660a298 100644 --- a/plugin/pg/db-pg.c +++ b/plugin/pg/db-pg.c @@ -16,8 +16,43 @@ */ #include -#include -#include + +//#include +// Replaces postgres_fe.h until it gets fixed +#ifndef FRONTEND +#define FRONTEND 1 +#endif + +#include +// end of the "fix" + +//#include +// catalog/pg_type.h has been removed from Debian, this fixes its lack +#define BOOLOID 16 +#define INT8OID 20 +#define INT2OID 21 +#define INT4OID 23 +#define TIDOID 27 +#define OIDOID 26 +#define FLOAT4OID 700 +#define FLOAT8OID 701 +#define NUMERICOID 1700 +#define DATEOID 1082 +#define TIMESTAMPOID 1114 +#define TIMESTAMPTZOID 1184 +#define TIMEOID 1083 +#define TIMETZOID 1266 +#define BYTEAOID 17 +#define ABSTIMEOID 702 +#define RELTIMEOID 703 +#define TINTERVALOID 704 +#define CHAROID 18 +#define TEXTOID 25 +#define NAMEOID 19 +#define BPCHAROID 1042 +#define VARCHAROID 1043 +// end of the "fix" + // Macros to avoid redefinition warnings for constants #undef PACKAGE_BUGREPORT #undef PACKAGE_NAME @@ -136,8 +171,6 @@ static GType db_pg_get_g_type (Oid type) case CHAROID: case TEXTOID: case NAMEOID: - case XMLOID: - case CSTRINGOID: case BPCHAROID: case VARCHAROID: default: @@ -332,6 +365,7 @@ static DbResultSet * __db_pg_query switch (PQresultStatus (res)) { case PGRES_COMMAND_OK: + case PGRES_SINGLE_TUPLE: case PGRES_TUPLES_OK: { gchar ** q_t = NULL; @@ -836,7 +870,7 @@ static void db_pg_kill_query (DbPg * obj) } } -static void db_pg_value_render (SqlValue * obj, SqlRender * render) +static void db_pg_value_render (SqlValue * obj, SqlRender * render, SqlBatch * batch) { if (G_VALUE_TYPE (obj->value) == G_TYPE_BYTES) { @@ -853,7 +887,7 @@ static void db_pg_value_render (SqlValue * obj, SqlRender * render) PQfreemem (buffer); } else - sql_object_render (SQL_OBJECT (obj), render); + sql_object_render (SQL_OBJECT (obj), render, batch); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class diff --git a/sql/sql-batch.c b/sql/sql-batch.c index 202961f..21f3c84 100644 --- a/sql/sql-batch.c +++ b/sql/sql-batch.c @@ -25,7 +25,7 @@ * * The #SqlBatch is the base class for all objects in SqlLib. **/ -G_DEFINE_ABSTRACT_TYPE (SqlBatch, sql_batch, G_TYPE_INITIALLY_UNOWNED); +G_DEFINE_TYPE (SqlBatch, sql_batch, G_TYPE_INITIALLY_UNOWNED); enum { CHANGED @@ -34,6 +34,11 @@ enum { static guint signals[LAST_SIGNAL] = {0}; +SqlBatch * sql_batch_new () +{ + return g_object_new (SQL_TYPE_BATCH, NULL); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private static void sql_batch_child_changed (SqlBatch * child, SqlBatch * obj) @@ -53,7 +58,7 @@ static void sql_batch_child_changed (SqlBatch * child, SqlBatch * obj) **/ gboolean sql_batch_is_ready (SqlBatch * obj) { - SqlBatchClass * klass = SQL_BATCH_GET_CLASS (obj); + gboolean is_ready = TRUE; g_return_val_if_fail (SQL_IS_BATCH (obj), FALSE); @@ -61,50 +66,14 @@ gboolean sql_batch_is_ready (SqlBatch * obj) { GList * i; GList * items = g_hash_table_get_values (obj->items); - gboolean is_ready = TRUE; - for (i = items; i; i = i->next) - if (!sql_object_is_ready (i->data)) - { - is_ready = FALSE; - break; - } + for (i = items; i && is_ready; i = i->next) + is_ready = sql_object_is_ready (i->data); g_list_free (items); - - if (!is_ready) - return FALSE; } - return TRUE; -} - -/** - * sql_batch_add: - * @obj: a #SqlBatch - * @id: the id of the #SqlHolder - * @held_object: the held object - * - * Adds a held object. - **/ -void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * held_object) -{ - g_return_if_fail (SQL_IS_BATCH (obj)); - g_return_if_fail (id); - - if (!obj->held_objects) - obj->held_objects = g_hash_table_new_full ( - g_str_hash - ,g_str_equal - ,g_free - ,g_object_unref - ); - - g_signal_connect (held_object, "changed", - G_CALLBACK (sql_batch_child_changed), obj - ); - g_hash_table_replace (obj->held_objects, - g_strdup (id), g_object_ref_sink (held_object)); + return is_ready; } /** @@ -121,12 +90,42 @@ SqlObject * sql_batch_get (SqlBatch * obj, const gchar * id) g_return_val_if_fail (SQL_IS_BATCH (obj), NULL); g_return_val_if_fail (id, NULL); - if (obj->held_objects) - return g_hash_table_lookup (obj->held_objects, id); + if (obj->items) + return g_hash_table_lookup (obj->items, id); return NULL; } +/** + * sql_batch_add: + * @obj: a #SqlBatch + * @id: the id of the #SqlHolder + * @held_object: the held object + * + * Adds a held object. + **/ +void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * object) +{ + g_return_if_fail (SQL_IS_BATCH (obj)); + g_return_if_fail (id); + + sql_batch_remove (obj, id); + + if (!obj->items) + obj->items = g_hash_table_new_full ( + g_str_hash + ,g_str_equal + ,g_free + ,NULL + ); + + g_signal_connect (object, "changed", + G_CALLBACK (sql_batch_child_changed), obj + ); + g_hash_table_replace (obj->items, + g_strdup (id), g_object_ref_sink (object)); +} + /** * sql_batch_add_from_param: * @obj: the #SqlString @@ -165,6 +164,28 @@ void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpo g_value_unset (&gvalue); } +/** + * sql_batch_remove: + * @id: the id of the #SqlHolder + * + * Removes a held object from the batch. + **/ +void sql_batch_remove (SqlBatch * obj, const gchar * id) +{ + g_return_val_if_fail (SQL_IS_BATCH (obj), NULL); + g_return_val_if_fail (id, NULL); + + SqlObject * object = sql_batch_get (obj, id); + + if (object) + { + g_signal_handlers_disconnect_by_func (object, + sql_batch_child_changed, obj); + g_object_unref (object); + g_hash_table_remove (obj->items, id); + } +} + /** * sql_batch_changed: * @obj: a #SqlBatch diff --git a/sql/sql-batch.h b/sql/sql-batch.h index f7bcadf..1a83cb7 100644 --- a/sql/sql-batch.h +++ b/sql/sql-batch.h @@ -18,7 +18,7 @@ #ifndef SQL_BATCH_H #define SQL_BATCH_H -#include "sql-object.h" +#include #define SQL_TYPE_BATCH (sql_batch_get_type ()) #define SQL_BATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_BATCH, SqlBatch)) @@ -41,11 +41,16 @@ struct _SqlBatchClass GInitiallyUnownedClass parent; }; +#include "sql-object.h" + GType sql_batch_get_type (); +SqlBatch * sql_batch_new (); gboolean sql_batch_is_ready (SqlBatch * obj); -void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * held_object); SqlObject * sql_batch_get (SqlBatch * obj, const gchar * id); +void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * object); void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * param); void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpointer content); +void sql_batch_remove (SqlBatch * obj, const gchar * id); +void sql_batch_changed (SqlBatch * obj); -#endif +#endif \ No newline at end of file diff --git a/sql/sql-delete.c b/sql/sql-delete.c index 63dc205..12521c0 100644 --- a/sql/sql-delete.c +++ b/sql/sql-delete.c @@ -102,8 +102,8 @@ static void sql_delete_class_init (SqlDeleteClass * klass) g_object_class_install_property (k, PROP_TABLES, sql_param_list ("tables" - ,"Tables" - ,"A list of tables" + ,_("Tables") + ,_("A list of tables") ,SQL_TYPE_TABLE ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-dml.c b/sql/sql-dml.c index bd9055e..a923b72 100644 --- a/sql/sql-dml.c +++ b/sql/sql-dml.c @@ -16,6 +16,7 @@ */ #include "sql-dml.h" +#include "sql-holder.h" /** * SECTION: sql-dml @@ -102,15 +103,15 @@ static void sql_dml_class_init (SqlDmlClass * klass) g_object_class_install_property (k, PROP_TARGETS, sql_param_list ("targets" - ,"Targets" - ,"A list of targets" + ,_("Targets") + ,_("A list of targets") ,SQL_TYPE_TARGET ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_WHERE, sql_param_object ("where" - ,"Where" - ,"The WHERE section of an statement" + ,_("Where") + ,_("The WHERE section of an statement") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE )); diff --git a/sql/sql-field.c b/sql/sql-field.c index 8511016..33773b2 100644 --- a/sql/sql-field.c +++ b/sql/sql-field.c @@ -158,22 +158,22 @@ static void sql_field_class_init (SqlFieldClass * klass) g_object_class_install_property (k, PROP_NAME, g_param_spec_string ("name" - ,"Name" - ,"The column name" + ,_("Name") + ,_("The column name") ,NULL ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_TARGET, g_param_spec_string ("target" - ,"Target" - ,"The target name" + ,_("Target") + ,_("The target name") ,NULL ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_SCHEMA, g_param_spec_string ("schema" - ,"Schema" - ,"The schema name" + ,_("Schema") + ,_("The schema name") ,NULL ,G_PARAM_READWRITE )); diff --git a/sql/sql-function.c b/sql/sql-function.c index d02a67c..feaffd6 100644 --- a/sql/sql-function.c +++ b/sql/sql-function.c @@ -124,22 +124,22 @@ static void sql_function_class_init (SqlFunctionClass * klass) g_object_class_install_property (k, PROP_NAME, g_param_spec_string ("name" - ,"Name" - ,"The function name" + ,_("Name") + ,_("The function name") ,NULL ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_SCHEMA, g_param_spec_string ("schema" - ,"Schema" - ,"The schema to which the function belongs" + ,_("Schema") + ,_("The schema to which the function belongs") ,NULL ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_PARAMS, sql_param_list ("params" - ,"Parameters" - ,"The function parameters" + ,_("Parameters") + ,_("The function parameters") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-holder.c b/sql/sql-holder.c index 12cae6b..74217e4 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -31,16 +31,12 @@ SqlObject * sql_holder_new (const gchar * id) //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_holder_render (SqlHolder * obj, SqlRender * render) +static void sql_holder_render (SqlHolder * obj, SqlRender * render, SqlBatch * batch) { - SqlObject * held_object = NULL; - GSList * i = sql_render_get_ancestors (render); - - for (; i && !held_object; i = i->next) - held_object = sql_object_get_held (held_object, obj->id); + SqlObject * object = batch ? sql_batch_get (batch, obj->id) : NULL; - if (held_object) - sql_render_add_object (render, held_object); + if (object) + sql_render_add_object (render, object); else sql_render_printf (render, "#%s", obj->id); } diff --git a/sql/sql-holder.h b/sql/sql-holder.h index c06d849..76da647 100644 --- a/sql/sql-holder.h +++ b/sql/sql-holder.h @@ -18,8 +18,6 @@ #ifndef SQL_HOLDER_H #define SQL_HOLDER_H -#include "sql-object.h" - #define SQL_TYPE_HOLDER (sql_holder_get_type ()) #define SQL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_HOLDER, SqlHolder)) #define SQL_IS_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_HOLDER)) @@ -27,6 +25,8 @@ typedef struct _SqlHolder SqlHolder; typedef struct _SqlHolderClass SqlHolderClass; +#include "sql-object.h" + struct _SqlHolder { SqlObject parent; diff --git a/sql/sql-insert.c b/sql/sql-insert.c index 6270dd0..1a6f7be 100644 --- a/sql/sql-insert.c +++ b/sql/sql-insert.c @@ -147,22 +147,22 @@ static void sql_insert_class_init (SqlInsertClass * klass) g_object_class_install_property (k, PROP_TABLE, sql_param_object ("table" - ,"Table" - ,"The table where the row is inserted" + ,_("Table") + ,_("The table where the row is inserted") ,SQL_TYPE_TABLE ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_FIELDS, sql_param_list ("fields" - ,"Fields" - ,"The list of fields" + ,_("Fields") + ,_("The list of fields") ,SQL_TYPE_FIELD ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_VALUES, sql_param_list ("values" - ,"Values" - ,"The list of values" + ,_("Values") + ,_("The list of values") ,SQL_TYPE_SET ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-join.c b/sql/sql-join.c index 69815a2..9c88c23 100644 --- a/sql/sql-join.c +++ b/sql/sql-join.c @@ -17,6 +17,7 @@ #include "sql-join.h" #include "sql-field.h" +#include "sql-holder.h" /** * SECTION: sql-join @@ -191,44 +192,44 @@ static void sql_join_class_init (SqlJoinClass * klass) g_object_class_install_property (k, PROP_TARGET_LEFT, sql_param_list ("target-left" - ,"Left target" - ,"The left target in the join" + ,("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" + ,("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" + ,("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" + ,("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" + ,("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" + ,("Using fields") + ,("The list of fields of the USING") ,SQL_TYPE_FIELD ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-list.c b/sql/sql-list.c index 12d9011..7985e36 100644 --- a/sql/sql-list.c +++ b/sql/sql-list.c @@ -16,6 +16,7 @@ */ #include "sql-list.h" +#include "sql-holder.h" /** * SECTION: sql-list @@ -68,6 +69,13 @@ static void sql_list_item_changed (SqlObject * item, SqlObject * obj) sql_object_changed (obj); } +static void sql_list_item_unref (SqlList * obj, SqlObject * item) +{ + g_signal_handlers_disconnect_by_func (item, + sql_list_item_changed, obj); + g_object_unref (item); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** @@ -88,60 +96,75 @@ void sql_list_add (SqlList * obj, gpointer item) * sql_list_insert: * @obj: the #SqlList * @item: (allow-none): the #SqlObject - * @n: the position in which to place the item + * @index: the position in which to place the item * * Adds an item to the list. If position is a negative number the element will * be added to the end of the list. **/ -void sql_list_insert (SqlList * obj, gpointer item, guint n) +void sql_list_insert (SqlList * obj, gpointer item, guint index) { g_return_if_fail (SQL_IS_LIST (obj)); g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (item, obj->gtype) || SQL_IS_HOLDER (item) || !item); + + if (!g_queue_find (&obj->items, item)) + g_signal_connect (item, "changed", + G_CALLBACK (sql_list_item_changed), obj); - if (n > 0) - g_queue_push_nth (&obj->items, g_object_ref_sink (item), n); + if (index > 0) + g_queue_push_nth (&obj->items, g_object_ref_sink (item), index); else g_queue_push_tail (&obj->items, g_object_ref_sink (item)); - - g_signal_connect (item, "changed", - G_CALLBACK (sql_list_item_changed), obj - ); } /** * sql_list_get: * @obj: the #SqlList + * @index: the index of the item * * Gets an item from the list. * * Return value: (transfer none) (allow-none): the selected #SqlObject **/ -gpointer sql_list_get (SqlList * obj, guint n) +gpointer sql_list_get (SqlList * obj, guint index) { g_return_val_if_fail (SQL_IS_LIST (obj), NULL); - return g_queue_peek_nth (&obj->items, n); + return g_queue_peek_nth (&obj->items, index); } /** * sql_list_remove: * @obj: the #SqlList + * @index: the index of the item to remove * * Removes an item from the list. - * - * Return value: (transfer none) (allow-none): the removed #SqlObject **/ -gpointer sql_list_remove (SqlList * obj, guint n) +void sql_list_remove (SqlList * obj, guint index) { SqlObject * item; g_return_val_if_fail (SQL_IS_LIST (obj), NULL); - item = g_queue_pop_nth (&obj->items, n); - g_signal_handlers_disconnect_by_func (item, - sql_list_item_changed, obj); - - return item; + item = g_queue_pop_nth (&obj->items, index); + + if (!g_queue_find (&obj->items, item)) + sql_list_item_unref (obj, item); +} + +/** + * sql_list_remove_item: + * @obj: the #SqlList + * @item: the item to remove + * + * Removes an item from the list. + **/ +void sql_list_remove_item (SqlList * obj, SqlObject * item) +{ + g_return_if_fail (SQL_IS_LIST (obj)); + g_return_if_fail (SQL_IS_OBJECT (item)); + + g_queue_remove_all (&obj->items, item); + sql_list_item_unref (obj, item); } /** diff --git a/sql/sql-list.h b/sql/sql-list.h index d1db8af..c2313a8 100644 --- a/sql/sql-list.h +++ b/sql/sql-list.h @@ -43,9 +43,10 @@ struct _SqlListClass GType sql_list_get_type (); SqlList * sql_list_new (GType gtype); void sql_list_add (SqlList * obj, gpointer item); -void sql_list_insert (SqlList * obj, gpointer item, guint n); -gpointer sql_list_get (SqlList * obj, guint n); -gpointer sql_list_remove (SqlList * obj, guint n); +void sql_list_insert (SqlList * obj, gpointer item, guint index); +gpointer sql_list_get (SqlList * obj, guint index); +void sql_list_remove (SqlList * obj, guint index); +void sql_list_remove_item (SqlList * obj, SqlObject * item); GList * sql_list_get_items (SqlList * obj); GType sql_list_get_items_type (SqlList * obj); guint sql_list_length (SqlList * obj); diff --git a/sql/sql-multi-stmt.c b/sql/sql-multi-stmt.c index ffcfcf6..4951150 100644 --- a/sql/sql-multi-stmt.c +++ b/sql/sql-multi-stmt.c @@ -95,8 +95,8 @@ static void sql_multi_stmt_class_init (SqlMultiStmtClass * klass) g_object_class_install_property (k, PROP_STMTS, sql_param_list ("stmts" - ,"Statements" - ,"The list of statements" + ,("Statements") + ,("The list of statements") ,SQL_TYPE_STMT ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-object.c b/sql/sql-object.c index 6274227..cb59fc7 100644 --- a/sql/sql-object.c +++ b/sql/sql-object.c @@ -108,12 +108,13 @@ void sql_object_remove (gpointer obj, gpointer child) * * Renders the object into a SQL string and stores it into the renderer. **/ -void sql_object_render (SqlObject * obj, SqlRender * render) +void sql_object_render (SqlObject * obj, SqlRender * render, SqlBatch * batch) { g_return_if_fail (SQL_IS_OBJECT (obj)); g_return_if_fail (SQL_IS_RENDER (render)); + g_return_if_fail (SQL_IS_BATCH (batch) || !batch); -// SQL_OBJECT_GET_CLASS (obj)->render (obj, render); + SQL_OBJECT_GET_CLASS (obj)->render (obj, render, batch); } /** @@ -126,33 +127,29 @@ void sql_object_render (SqlObject * obj, SqlRender * render) **/ gboolean sql_object_is_ready (SqlObject * obj) { + guint i; + guint nparams; + GParamSpec ** params; + gboolean is_ready = TRUE; SqlObjectClass * klass = SQL_OBJECT_GET_CLASS (obj); g_return_val_if_fail (SQL_IS_OBJECT (obj), FALSE); - - if (obj->held_objects) + + params = g_object_class_list_properties (G_OBJECT_GET_CLASS (obj), &nparams); + + for (i = 0; i < nparams && is_ready; i++) + if (SQL_IS_PARAM_OBJECT (params[i]) || SQL_IS_PARAM_LIST (params[i])) { - GList * i; - GList * held_objects = g_hash_table_get_values (obj->held_objects); - gboolean is_ready = TRUE; - - for (i = held_objects; i; i = i->next) - if (!sql_object_is_ready (i->data)) - { - is_ready = FALSE; - break; - } - - g_list_free (held_objects); - - if (!is_ready) - return FALSE; + SqlObject * child = sql_object_get (obj, params[i]->name); + is_ready = sql_object_is_ready (child); } + + g_free (params); if (klass->is_ready) return klass->is_ready (obj); else - return TRUE; + return is_ready; } void sql_object_set (SqlObject * obj, const gchar * property, SqlObject * value) @@ -204,12 +201,10 @@ void sql_object_remove_child (SqlObject * obj, const gchar * property, guint n) **/ void sql_object_get_holders (SqlObject * obj, GQueue * holders) { - if (!obj) - return; - - g_return_if_fail (SQL_IS_OBJECT (obj)); + g_return_if_fail (SQL_IS_OBJECT (obj) || !obj); - SQL_OBJECT_GET_CLASS (obj)->find_holders (obj, holders); + if (obj) + SQL_OBJECT_GET_CLASS (obj)->find_holders (obj, holders); } /** diff --git a/sql/sql-object.h b/sql/sql-object.h index 52f8911..7016168 100644 --- a/sql/sql-object.h +++ b/sql/sql-object.h @@ -33,6 +33,7 @@ typedef struct _SqlObjectClass SqlObjectClass; typedef gboolean (* SqlObjectIsReadyFunc) (SqlObject * obj); typedef void (* SqlObjectFindHoldersFunc) (SqlObject * obj, GQueue * holders); +typedef void (* SqlRenderFunc) (); // (SqlObject * obj, SqlRender * render, SqlBatch * batch); struct _SqlObject { @@ -43,17 +44,16 @@ struct _SqlObjectClass { /* */ GInitiallyUnownedClass parent; - gpointer /* SqlRenderFunc */ render; + SqlRenderFunc render; SqlObjectIsReadyFunc is_ready; SqlObjectFindHoldersFunc find_holders; }; -#include "sql-holder.h" -#include "sql-list.h" #include "sql-render.h" +#include "sql-batch.h" GType sql_object_get_type (); -void sql_object_render (SqlObject * obj, SqlRender * render); +void sql_object_render (SqlObject * obj, SqlRender * render, SqlBatch * batch); gboolean sql_object_is_ready (SqlObject * obj); void sql_object_get_holders (SqlObject * obj, GQueue * holders); diff --git a/sql/sql-operation.c b/sql/sql-operation.c index 5d735e0..27e4a2a 100644 --- a/sql/sql-operation.c +++ b/sql/sql-operation.c @@ -134,16 +134,16 @@ static void sql_operation_class_init (SqlOperationClass * klass) g_object_class_install_property (k, PROP_TYPE, g_param_spec_enum ("type" - ,"Type" - ,"The type of the operation" + ,("Type") + ,("The type of the operation") ,SQL_TYPE_OPERATION_TYPE ,SQL_OPERATION_TYPE_AND ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_OPERATORS, sql_param_list ("operators" - ,"Operators" - ,"The list of operators" + ,("Operators") + ,("The list of operators") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-operation.h b/sql/sql-operation.h index 78da757..5ee436d 100644 --- a/sql/sql-operation.h +++ b/sql/sql-operation.h @@ -79,6 +79,6 @@ struct _SqlOperationClass GType sql_operation_get_type (); GType sql_operation_type_get_type (); -SqlObject * sql_operation_new (SqlOperationType type); +SqlObject * sql_operation_new (SqlOperationType type); #endif diff --git a/sql/sql-param-list.c b/sql/sql-param-list.c index 61b5963..46148d4 100644 --- a/sql/sql-param-list.c +++ b/sql/sql-param-list.c @@ -54,7 +54,7 @@ sql_param_list_validate (GParamSpec * pspec, GValue * value) GType type; gboolean change; gpointer object = g_value_get_object (value); - + if (!object) return TRUE; diff --git a/sql/sql-render.c b/sql/sql-render.c index 754e485..aa73f47 100644 --- a/sql/sql-render.c +++ b/sql/sql-render.c @@ -56,15 +56,17 @@ SqlRender * sql_render_new (gchar delimiter) * * Return value: a string with the rendered statement of %NULL if error. **/ -gchar * sql_render_get_string (SqlRender * obj, gpointer object, gpointer data, GError ** err) +gchar * sql_render_get_string (SqlRender * obj, gpointer object, SqlBatch * batch, gpointer data, GError ** err) { gchar * sql; g_return_val_if_fail (SQL_IS_RENDER (obj), NULL); g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (SQL_IS_BATCH (batch) || !batch, NULL); obj->data = data; obj->object = g_object_ref (object); + obj->batch = batch ? g_object_ref (batch) : NULL; obj->buffer = g_string_sized_new (SQL_BUFFER_SIZE); obj->ancestors = NULL; @@ -84,6 +86,7 @@ gchar * sql_render_get_string (SqlRender * obj, gpointer object, gpointer data, sql = g_string_free (obj->buffer, FALSE); g_clear_object (&obj->object); + g_clear_object (&obj->batch); g_slist_free (obj->ancestors); obj->ancestors = NULL; obj->buffer = NULL; @@ -144,9 +147,9 @@ void sql_render_add_object (SqlRender * obj, gpointer object) obj->ancestors = g_slist_prepend (obj->ancestors, object); if (function) - function (object, obj); + function (object, obj, obj->batch); else - sql_object_render (object, obj); + sql_object_render (object, obj, obj->batch); obj->ancestors = g_slist_delete_link (obj->ancestors, obj->ancestors); } @@ -324,23 +327,23 @@ void sql_render_add_list (SqlRender * obj, gboolean required, const gchar * toke void sql_render_add_list_with_func (SqlRender * obj, gboolean required, const gchar * token, SqlList * list, const gchar * separator, SqlRenderFunc function) { - GList * n; + GList * i; g_return_if_fail (SQL_IS_RENDER (obj)); g_return_if_fail (SQL_IS_LIST (list)); - if (list && (n = sql_list_get_items (list))) + if (list && (i = sql_list_get_items (list))) { sql_render_add_token (obj, token); - for (; n; n = n->next) + for (; i; i = i->next) { if (function) - function (n->data, obj); + function (i->data, obj, obj->batch); else - sql_render_add_object (obj, n->data); + sql_render_add_object (obj, i->data); - if (n->next) + if (i->next) g_string_append_printf (obj->buffer, " %s", separator); } } diff --git a/sql/sql-render.h b/sql/sql-render.h index da29abf..a1c9d77 100644 --- a/sql/sql-render.h +++ b/sql/sql-render.h @@ -31,9 +31,7 @@ typedef struct _SqlRender SqlRender; typedef struct _SqlRenderClass SqlRenderClass; -typedef void (* SqlRenderFunc) (gpointer obj, SqlRender * render); - -#include "sql-object.h" +#include "sql-batch.h" /** * SqlRender: @@ -45,6 +43,7 @@ struct _SqlRender GError * error; GString * buffer; gpointer object; + SqlBatch * batch; GSList * ancestors; gpointer data; GHashTable * custom_renderers; @@ -69,9 +68,12 @@ typedef enum } SqlRenderError; +#include "sql-object.h" +#include "sql-list.h" + GType sql_render_get_type (); SqlRender * sql_render_new (gchar delimiter); -gchar * sql_render_get_string (SqlRender * obj, gpointer object, gpointer data, GError ** err); +gchar * sql_render_get_string (SqlRender * obj, gpointer object, SqlBatch * batch, gpointer data, GError ** err); void sql_render_register_function (SqlRender * obj, GType type, SqlRenderFunc function); GSList * sql_render_get_ancestors (SqlRender * obj); void sql_render_add_espace (SqlRender * obj); diff --git a/sql/sql-select-field.c b/sql/sql-select-field.c index 14c4b5f..56f5f33 100644 --- a/sql/sql-select-field.c +++ b/sql/sql-select-field.c @@ -109,15 +109,15 @@ static void sql_select_field_class_init (SqlSelectFieldClass * klass) g_object_class_install_property (k, PROP_EXPR, sql_param_object ("expr" - ,"Expression" - ,"The expression" + ,("Expression") + ,("The expression") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_ALIAS, g_param_spec_string ("alias" - ,"Alias" - ,"The alias for the expression" + ,("Alias") + ,("The alias for the expression") ,NULL ,G_PARAM_READWRITE )); diff --git a/sql/sql-select-order.c b/sql/sql-select-order.c index 027530b..4ced113 100644 --- a/sql/sql-select-order.c +++ b/sql/sql-select-order.c @@ -103,15 +103,15 @@ static void sql_select_order_class_init (SqlSelectOrderClass * klass) g_object_class_install_property (k, PROP_EXPR, sql_param_object ("expr" - ,"Expression" - ,"The expression" + ,("Expression") + ,("The expression") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_WAY, g_param_spec_enum ("way" - ,"Way" - ,"The order way" + ,("Way") + ,("The order way") ,SQL_TYPE_SELECT_ORDER_WAY ,SQL_SELECT_ORDER_ASC ,G_PARAM_READWRITE diff --git a/sql/sql-select.c b/sql/sql-select.c index 096c068..959808e 100644 --- a/sql/sql-select.c +++ b/sql/sql-select.c @@ -244,65 +244,64 @@ static void sql_select_class_init (SqlSelectClass * klass) g_object_class_install_property (k, PROP_LIMIT_COUNT, g_param_spec_boolean ("distinct" - ,"Distinct" - ,"Determines if the #SqlSelect uses the DISTINCT clause" + ,_("Distinct") + ,_("Determines if the #SqlSelect uses the DISTINCT clause") ,FALSE ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_FIELDS, sql_param_list ("fields" - ,"Fields" - ,"The list of fields" + ,_("Fields") + ,_("The list of fields") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_GROUP, sql_param_list ("group" - ,"Group" - ,"The GROUP BY section" + ,_("Group") + ,_("The GROUP BY section") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_HAVING, sql_param_object ("having" - ,"Having" - ,"The HAVING clause" + ,_("Having") + ,_("The HAVING clause") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_ORDER, sql_param_list ("order" - ,"Order" - ,"The ORDER BY section" + ,_("Order") + ,_("The ORDER BY section") ,SQL_TYPE_SELECT_ORDER ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); g_object_class_install_property (k, PROP_LIMIT_COUNT, g_param_spec_uint ("limit-count" - ,"Limit count" - - ,"The COUNT field of the LIMIT clause" + ,_("Limit count") + ,_("The COUNT field of the LIMIT clause") ,0, G_MAXUINT, 0 ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_LIMIT_OFFSET, g_param_spec_uint ("limit-offset" - ,"Limit offset" - ,"The OFFSET field of the LIMIT clause" + ,_("Limit offset") + ,_("The OFFSET field of the LIMIT clause") ,0, G_MAXUINT, 0 ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_NEXT, sql_param_object ("next" - ,"Next" - ,"The next #SqlSelect in case of a statement with more than one" + ,_("Next") + ,_("The next #SqlSelect in case of a statement with more than one") ,SQL_TYPE_SELECT ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_TYPE, g_param_spec_int ("type" - ,"Type" - ,"One of the possible options of #SqlSelectType" + ,_("Type") + ,_("One of the possible options of #SqlSelectType") ,0, SQL_SELECT_COUNT - 1, 0 ,G_PARAM_READWRITE )); diff --git a/sql/sql-set.c b/sql/sql-set.c index e096246..486da18 100644 --- a/sql/sql-set.c +++ b/sql/sql-set.c @@ -100,8 +100,8 @@ static void sql_set_class_init (SqlSetClass * klass) g_object_class_install_property (k, PROP_EXPRS, sql_param_list ("exprs" - ,"Expressions" - ,"The list of expressions" + ,("Expressions") + ,("The list of expressions") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-string.c b/sql/sql-string.c index 4ecb697..12a2b00 100644 --- a/sql/sql-string.c +++ b/sql/sql-string.c @@ -64,7 +64,7 @@ static void sql_string_find_holders (SqlString * obj, GQueue * holders) GSList * i; for (i = obj->holders; i; i = i->next) - sql_object_get_holders (((HolderData *) i->data)->holder); + sql_object_get_holders (((HolderData *) i->data)->holder, holders); } static void sql_string_free_holder_data (HolderData * holder_data) diff --git a/sql/sql-subquery.c b/sql/sql-subquery.c index a12d1ce..c389cf4 100644 --- a/sql/sql-subquery.c +++ b/sql/sql-subquery.c @@ -111,8 +111,8 @@ static void sql_subquery_class_init (SqlSubqueryClass * klass) g_object_class_install_property (k, PROP_SELECT, sql_param_object ("select" - ,"Select" - ,"The SELECT statement" + ,("Select") + ,("The SELECT statement") ,SQL_TYPE_SELECT ,G_PARAM_READWRITE )); diff --git a/sql/sql-table.c b/sql/sql-table.c index 6ef7056..af81713 100644 --- a/sql/sql-table.c +++ b/sql/sql-table.c @@ -114,15 +114,15 @@ static void sql_table_class_init (SqlTableClass * klass) g_object_class_install_property (k, PROP_NAME, g_param_spec_string ("name" - , "Name" - , "The table name" - , NULL, G_PARAM_READWRITE + ,("Name") + ,("The table name") + ,NULL, G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_SCHEMA, g_param_spec_string ("schema" - ,"Schema" - ,"The schema where the table is" + ,("Schema") + ,("The schema where the table is") ,NULL, G_PARAM_READWRITE )); } diff --git a/sql/sql-target.c b/sql/sql-target.c index 2dd8ace..8213d9a 100644 --- a/sql/sql-target.c +++ b/sql/sql-target.c @@ -92,8 +92,8 @@ static void sql_target_class_init (SqlTargetClass * k) g_object_class_install_property (klass, PROP_ALIAS, g_param_spec_string ("alias" - ,"Alias" - ,"The alias for the target" + ,("Alias") + ,("The alias for the target") ,NULL ,G_PARAM_READWRITE )); diff --git a/sql/sql-update-set.c b/sql/sql-update-set.c index 5b00e38..0f49a03 100644 --- a/sql/sql-update-set.c +++ b/sql/sql-update-set.c @@ -105,15 +105,15 @@ static void sql_update_set_class_init (SqlUpdateSetClass * klass) g_object_class_install_property (k, PROP_FIELD, g_param_spec_object ("field" - ,"Field" - ,"The field" + ,("Field") + ,("The field") ,SQL_TYPE_FIELD ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_EXPR, g_param_spec_object ("expr" - ,"Expression" - ,"The expression" + ,("Expression") + ,("The expression") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE )); diff --git a/sql/sql-update.c b/sql/sql-update.c index b3af9aa..d52d287 100644 --- a/sql/sql-update.c +++ b/sql/sql-update.c @@ -109,8 +109,8 @@ static void sql_update_class_init (SqlUpdateClass * klass) g_object_class_install_property (k, PROP_SETS, sql_param_list ("sets" - ,"Sets" - ,"A list of sets" + ,("Sets") + ,("A list of sets") ,SQL_TYPE_UPDATE_SET ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/vn/field/vn-completion.c b/vn/field/vn-completion.c index 5e00843..0321d1e 100644 --- a/vn/field/vn-completion.c +++ b/vn/field/vn-completion.c @@ -185,24 +185,32 @@ static gboolean vn_completion_match_selected (GtkEntryCompletion * completion, static void vn_completion_create_model (VnCompletion * obj) { - SqlExpr * field; - SqlString * stmt; - SqlOperation * op; + SqlObject * field; + SqlObject * stmt; + SqlObject * op; + SqlBatch * batch; + SqlList * ops; if (!(obj->sql && obj->field)) return; op = sql_operation_new (SQL_OPERATION_TYPE_LIKE); + + ops = sql_list_new (SQL_TYPE_EXPR); + g_object_set (op, "operators", ops, NULL); field = sql_field_new (obj->field, NULL, NULL); - sql_operation_add_expr (op, field); + sql_list_add (ops, field); obj->value = sql_value_new (); - sql_operation_add_expr (op, obj->value); + sql_list_add (ops, obj->value); + + batch = sql_batch_new (); + sql_batch_add (batch, "field", field); + sql_batch_add (batch, "filter", op); + db_model_set_batch (obj->model, batch); stmt = sql_string_new (obj->sql); - sql_string_add_expr (stmt, field); - sql_string_add_expr (stmt, SQL_EXPR (op)); db_model_set_stmt (obj->model, SQL_STMT (stmt)); } diff --git a/vn/field/vn-completion.h b/vn/field/vn-completion.h index 7bbac31..ba200c4 100644 --- a/vn/field/vn-completion.h +++ b/vn/field/vn-completion.h @@ -39,7 +39,7 @@ struct _VnCompletion guint column; gchar * last_match; DbModel * model; - SqlExpr * value; + SqlObject * value; gchar * field; gchar * sql; }; diff --git a/vn/field/vn-date-chooser.c b/vn/field/vn-date-chooser.c index c356f95..6c58653 100644 --- a/vn/field/vn-date-chooser.c +++ b/vn/field/vn-date-chooser.c @@ -283,7 +283,7 @@ static void vn_date_chooser_init (VnDateChooser * obj) gtk_box_pack_start (GTK_BOX (obj->box), GTK_WIDGET (obj->button), FALSE, FALSE, 0); - image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON); + image = gtk_image_new_from_icon_name ("gtk-edit", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (obj->button), image); obj->label = GTK_LABEL (gtk_label_new (NULL)); diff --git a/vn/vn-login.c b/vn/vn-login.c index 520597b..2b6d3bf 100644 --- a/vn/vn-login.c +++ b/vn/vn-login.c @@ -79,9 +79,10 @@ static void vn_login_show (VnLogin * obj) { gchar * user; gchar * pass; + GError * err = NULL; VnBuilder * builder = vn_builder_new (); - if (gtk_builder_add_from_file (GTK_BUILDER (builder), LOGIN_UI, NULL)) + if (gtk_builder_add_from_file (GTK_BUILDER (builder), LOGIN_UI, &err)) { obj->window = vn_builder_get (builder, "window"); obj->user = vn_builder_get (builder, "user"); @@ -116,16 +117,24 @@ static void vn_login_show (VnLogin * obj) g_free (user); g_free (pass); } + else if (err) + { + g_warning ("VnLogin: %s", err->message); + g_clear_error (&err); + } g_object_unref (builder); } - gtk_widget_show_all (GTK_WIDGET (obj->window)); - gtk_widget_grab_focus (GTK_WIDGET (obj->user)); - gtk_widget_hide (obj->spinner); + if (obj->window) + { + gtk_widget_show_all (GTK_WIDGET (obj->window)); + gtk_widget_grab_focus (GTK_WIDGET (obj->user)); + gtk_widget_hide (obj->spinner); - if (autologin) - gtk_button_clicked (obj->connect); + if (autologin) + gtk_button_clicked (obj->connect); + } } /* From 02da9752e1f418afe7b85300284e59024a03e0f6 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 27 May 2014 09:55:01 +0200 Subject: [PATCH 05/10] Primera version funcional --- db/db-model.c | 500 +++++++++++++++++-------------------- db/db-request.c | 44 +--- db/db-request.h | 1 - db/db-result.h | 1 + module/data/customer.glade | 31 +-- module/data/users.glade | 430 +++++++++++-------------------- plugin/mysql/db-mysql.c | 1 + plugin/pg/db-pg.c | 4 +- sql/parser/gram.y | 2 +- sql/sql-batch.c | 61 ++++- sql/sql-batch.h | 1 + sql/sql-field.c | 18 +- sql/sql-field.h | 11 +- sql/sql-holder.c | 2 +- sql/sql-list.c | 18 +- sql/sql-list.h | 1 + sql/sql-object.c | 2 + sql/sql-operation.c | 103 ++++++-- sql/sql-operation.h | 12 +- sql/sql-param-list.c | 3 +- sql/sql-param-object.c | 4 +- sql/sql-render.c | 2 +- sql/sql-value.c | 15 +- sql/sql-value.h | 2 + vn/field/vn-completion.c | 18 +- 25 files changed, 603 insertions(+), 684 deletions(-) diff --git a/db/db-model.c b/db/db-model.c index 500c208..1cf7b78 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -143,6 +143,7 @@ typedef struct { DbModel * obj; GQueue * operations; + SqlList * stmts; } DbModelRequest; @@ -254,13 +255,6 @@ static void db_model_manage_join (DbModel * obj ,DbIter * iter ,gint col); static void db_model_post_process_query (DbModel * obj); -static void db_model_finish_insert (DbModel * obj - ,DbRow * req_row, gint i - ,DbRow * row, gint j - ,DbIter * iter); -static gboolean db_model_table_row_all_null (DbModel * model - ,DbRow * row - ,gint col); // Signal Handlers @@ -469,125 +463,112 @@ static void db_model_on_join_query_done (DbRequest * request, JoinData * join_da static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) { - if (obj->priv->conn && obj->priv->stmt) - { - if (sql_object_is_ready (SQL_OBJECT (obj->priv->stmt))) - db_model_refresh (obj); - else - { - db_model_clear (obj); - db_model_set_status (obj, DB_MODEL_STATUS_CLEAN); - } - } + db_model_refresh (obj); } static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj) { - db_model_on_stmt_changed (NULL, obj); + db_model_refresh (obj); +} + +static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * row, GError * err) +{ + gint i, j; + DbModelPrivate * priv = obj->priv; + DbResult * result; + DbRow * req_row; + DbIter iter; + + result = db_request_fetch_result (request, &err); + + if (result && result->data && result->nrows > 0) + { + iter.stamp = priv->stamp; + iter.data = row; + req_row = g_ptr_array_index (result->data, 0); + + for (i = 0; i < result->ncols; i++) + for (j = 0; j < priv->result->ncols; j++) + if (!g_strcmp0 (priv->column[j].name, result->column[i].name) + && !g_strcmp0 (priv->column[j].table, result->column[i].table)) + { + GValue * v; + gboolean emit = TRUE; + + priv->updated_value = g_new0 (GValue, 1); + + if ((v = &req_row->value[i]) && G_IS_VALUE (v) + && !gvn_value_is_null (DB_ROW_FIELD (req_row, i)) + && gvn_value_is_null (DB_ROW_FIELD (row, j))) + { + g_value_init (priv->updated_value, G_VALUE_TYPE (v)); + gvn_value_copy (v, priv->updated_value); + } + else if (gvn_value_is_null (DB_ROW_FIELD (row, j))) + { + g_value_init (priv->updated_value, GVN_TYPE_NULL); + } + else + { + emit = FALSE; + g_free (priv->updated_value); + } + + if (emit) + { + priv->updated_col = j; + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + } + } + } + + if (result) + db_result_free (result); } static void db_model_on_operations_done (DbRequest * request, DbModelRequest * data) { + guint i = 0; DbOperation * op; GError * err = NULL; DbModel * obj = data->obj; DbModelPrivate * priv = obj->priv; - obj->priv->pending_request = + priv->pending_request = g_slist_remove (priv->pending_request, request); - - while (db_request_fetch_non_select (request, &err) != -1) + + while ((op = g_queue_pop_head (data->operations)) + && db_request_fetch_non_select (request, &err) != -1) { - gint i, j; - DbResult * result; - DbRow * req_row, * row; + DbRow * row = op->row; + db_request_fetch_non_select (request, &err); - op = g_queue_pop_head (data->operations); - row = op->row; - - g_hash_table_remove (priv->row_ops, op->row); + g_hash_table_remove (priv->row_ops, row); if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE { - g_signal_emit - (obj, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (row)); + g_signal_emit (obj, + db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (row)); } - else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT - { // Catch the SELECT associated with each INSERT - - result = db_request_fetch_result (request, &err); - - if (result) - { - if (result->data && result->nrows > 0) - { - req_row = g_ptr_array_index (result->data, 0); - - for (i = 0; i < result->ncols; i++) - for (j = 0; j < priv->result->ncols; j++) - if (!g_strcmp0 (priv->column[j].name, result->column[i].name) - && !g_strcmp0 (priv->column[j].table, priv->main_table)) - { - DbIter iter; - db_model_finish_insert (obj, req_row, i, row, j, &iter); - } - } - - db_result_free (result); - } - } - else if (op->type & DB_MODEL_ROW_OP_UPDATE)// UPDATE - if (priv->join) + else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { - GSList * n; - DbUpdatedField * u; - DbIter iter; - iter.stamp = priv->stamp; - iter.data = row; + db_model_process_insert (obj, request, row, err); + } + else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT + { + guint j; + SqlList * list; + SqlObject * multi = sql_list_get (data->stmts, i); + + g_object_get (multi, "stmts", &list, NULL); - for (n = op->updated; n; n = n->next) - { - u = n->data; - -/* if (r->next && r->next->data - && ((DbResult *) r->next->data)->column)*/ - if (priv->column_default - && gvn_value_is_null (u->value) - && g_strcmp0 (priv->column[u->column].table, priv->main_table) - && db_model_table_row_all_null (obj, row, u->column)) - { // INSERT + SELECT "update" - - result = db_request_fetch_result (request, &err); - - if (result) - { - if (result->data && result->nrows > 0) - { - req_row = g_ptr_array_index (result->data, 0); - - for (i = 0; i < result->ncols; i++) - for (j = 0; j < priv->result->ncols; j++) - if (!g_strcmp0 (priv->column[j].name, result->column[i].name) - && (!g_strcmp0 (priv->column[j].table, result->column[i].table) - || !result->column[i].table)) - db_model_finish_insert (obj, req_row, i, row, j, &iter); - } - - db_result_free (result); - } - } -/* - if (n->next && (u = ((DbUpdatedField *) n->next->data)) - && priv->column_default - && gvn_value_is_null (u->value) - && g_strcmp0 (priv->column[u->column].table, priv->main_table) - && db_model_table_row_all_null (obj, row, u->column)) - r = r->next; -*/ - } + for (j = 0; j < sql_list_length (list); j++) + if (G_OBJECT_TYPE (sql_list_get (list, j)) == SQL_TYPE_MULTI_STMT) + db_model_process_insert (obj, request, row, err); } db_model_free_operation (obj, op); + i++; } //XXX Iterate both the result list and the queue at the same time @@ -654,6 +635,7 @@ static void db_model_request_free (DbModelRequest * req) { g_queue_free (req->operations); g_object_unref (req->obj); + g_object_unref (req->stmts); } g_free (req); @@ -1237,7 +1219,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) if (!g_strcmp0 (priv->column[i].table, other_field->table)) { sql_object_add_child (select, "exprs", - sql_field_new (priv->column[i].name, other_field->table, NULL)); + sql_field_new_with_table (priv->column[i].name, other_field->table, NULL)); } else if (!g_strcmp0 (priv->column[i].table, main_field->table)) { @@ -1248,7 +1230,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) SqlObject * equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); sql_object_add_child (equal, "operators", - sql_field_new (g_ptr_array_index (other_field->name, j) + sql_field_new_with_table (g_ptr_array_index (other_field->name, j) ,other_field->table, NULL)); sql_object_add_child (equal, "operators", @@ -1286,40 +1268,6 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) } } -static void db_model_finish_insert (DbModel * obj, - DbRow * req_row, gint i, DbRow * row, gint j, DbIter * iter) -{ - GValue * v; - gboolean emit = TRUE; - iter->stamp = obj->priv->stamp; - iter->data = row; - - obj->priv->updated_value = g_new0 (GValue, 1); - - if ((v = &req_row->value[i]) && G_IS_VALUE (v) - && !gvn_value_is_null (DB_ROW_FIELD (req_row, i)) - && gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (obj->priv->updated_value, G_VALUE_TYPE (v)); - gvn_value_copy (v, obj->priv->updated_value); - } - else if (gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (obj->priv->updated_value, GVN_TYPE_NULL); - } - else - { - emit = FALSE; - g_free (obj->priv->updated_value); - } - - if (emit) - { - obj->priv->updated_col = j; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, iter); - } -} - static void db_model_clear (DbModel * obj) { DbModelPrivate * priv = obj->priv; @@ -1351,40 +1299,6 @@ static void db_model_clear (DbModel * obj) } } -static gboolean db_model_table_row_all_null (DbModel * obj, DbRow * row, gint col) -{ - DbUpdatedField * u; - GSList * n; - gboolean updated; - gint i; - - for (i = 0; i < row->len; i++) - { - updated = FALSE; - - if (!g_strcmp0 (obj->priv->column[col].table, obj->priv->column[i].table) - && i != col) - { - DbOperation * operation = g_hash_table_lookup (obj->priv->row_ops, row); - - if (operation) - for (n = operation->updated; n; n = n->next) - if ((u = (DbUpdatedField *) n->data) && u->column == i) - { - updated = TRUE; - - if (!gvn_value_is_null (u->value)) - return FALSE; - } - - if (!updated && !gvn_value_is_null (DB_ROW_FIELD (row, i))) - return FALSE; - } - } - - return TRUE; -} - // Memory allocate functions static void param_def_free (ParamDef * def) @@ -1427,12 +1341,17 @@ static void db_model_alloc_link_data (DbModel * obj) if (!priv->internal_batch) { + SqlList * operators; + priv->internal_batch = g_object_ref_sink (sql_batch_new ()); g_signal_connect (priv->internal_batch, "changed", G_CALLBACK (db_model_on_batch_changed), obj); priv->link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); sql_batch_add (priv->internal_batch, "link", priv->link_op); + + operators = sql_list_new (SQL_TYPE_EXPR); + sql_operation_set_operands (SQL_OPERATION (priv->link_op), operators); } } @@ -1780,7 +1699,7 @@ void db_model_set_default_value_from_column (DbModel * obj, void db_model_set_default_value_from_param (DbModel * obj, const gchar * field, GvnParam * param, gboolean link) { - SqlObject * equal_op = NULL; + SqlObject * equal = NULL; g_return_if_fail (DB_IS_MODEL (obj)); g_return_if_fail (field); @@ -1788,24 +1707,25 @@ void db_model_set_default_value_from_param (DbModel * obj, if (link) { - SqlObject * value; + SqlList * operands, * link_operands; db_model_alloc_link_data (obj); + + link_operands = sql_operation_get_operands (SQL_OPERATION (obj->priv->link_op)); - equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - sql_object_add_child (obj->priv->link_op, "operators", equal_op); - - sql_object_add_child (equal_op, "operators", sql_field_new (field, NULL, NULL)); - - value = sql_value_new (); - sql_value_set_param (SQL_VALUE (value), param); - sql_object_add_child (equal_op, "operators", value); + equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); + sql_list_add (link_operands, equal); + + operands = sql_list_new (SQL_TYPE_EXPR); + sql_list_add (operands, sql_field_new (field)); + sql_list_add (operands, sql_value_new_with_param (param)); + sql_operation_set_operands (SQL_OPERATION (equal), operands); } ParamDef * def = g_new (ParamDef, 1); def->param = g_object_ref (param); def->link = link; - def->equal_op = equal_op; + def->equal_op = equal; def->obj = obj; g_hash_table_insert (obj->priv->defaults, g_strdup (field), def); g_hash_table_remove (obj->priv->column_default, field); @@ -2176,27 +2096,12 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter) for (i = 0; i < row->len; i++) { - gchar * column = priv->column[i].name; const GValue * def_value = NULL; - ParamDef * def = g_hash_table_lookup (priv->defaults, column); + ParamDef * def = g_hash_table_lookup (priv->defaults, priv->column[i].display); if (def) def_value = gvn_param_get_value (def->param); - if (!def_value) - { - gchar * column_def = g_hash_table_lookup (priv->column_default, column); - - if (column_def) - { - gint col = db_model_get_column_index (obj, column_def); - - if (col != -1 - && !g_strcmp0 (priv->column[col].table, priv->column[i].table)) - def_value = &row->value[col]; - } - } - if (!def_value) def_value = gvn_param_spec_get_default (priv->column[i].spec); @@ -2431,17 +2336,20 @@ static SqlObject * db_model_create_where (DbModel * obj, SqlObject * value; DbRow * row = operation->row; DbModelPrivate * priv = obj->priv; - SqlObject * where = sql_operation_new (SQL_OPERATION_TYPE_AND); + SqlObject * where; + SqlList * and_operands; + + where = sql_operation_new (SQL_OPERATION_TYPE_AND); + + and_operands = sql_list_new (SQL_TYPE_EXPR); + sql_operation_set_operands (SQL_OPERATION (where), and_operands); for (i = 0; i < row->len; i++) if ((priv->column[i].info & DB_COLUMN_PRI_KEY) && !g_strcmp0 (priv->column[i].table, table)) { - SqlObject * equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - sql_object_add_child (where, "operators", equal); - - sql_object_add_child (equal, "operators", - sql_field_new (priv->column[i].name, NULL, NULL)); + SqlObject * equal; + SqlList * operands; value = NULL; @@ -2464,14 +2372,20 @@ static SqlObject * db_model_create_where (DbModel * obj, } else value = sql_value_new_with_value (g_value); - + if (!value) { g_object_unref (g_object_ref_sink (where)); return NULL; } - sql_object_add_child (equal, "operators", value); + equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); + sql_list_add (and_operands, equal); + + operands = sql_list_new (SQL_TYPE_EXPR); + sql_list_add (operands, sql_field_new (priv->column[i].name)); + sql_list_add (operands, value); + sql_operation_set_operands (SQL_OPERATION (equal), operands); } return where; @@ -2483,41 +2397,75 @@ static SqlObject * db_model_create_insert (DbModel * obj, gint i; DbModelPrivate * priv = obj->priv; DbRow * row = operation->row; - SqlObject * target, * insert, * set, * select, * val, * stmts; + GValue * value; + SqlList * targets, * stmts, * sets, * fields, * values, * exprs; + SqlObject * target, * insert, * set, * select; SqlObject * where = db_model_create_where (obj, table, operation, TRUE); if (!where) return NULL; - - stmts = sql_multi_stmt_new (); + target = sql_table_new (table); + + fields = sql_list_new (SQL_TYPE_FIELD); - insert = g_object_new (SQL_TYPE_INSERT, "table", target, NULL); - set = g_object_new (SQL_TYPE_SET, NULL); - sql_object_add_child (insert, "values", set); + sets = sql_list_new (SQL_TYPE_SET); + values = sql_list_new (SQL_TYPE_EXPR); + set = g_object_new (SQL_TYPE_SET + ,"exprs", values + ,NULL + ); + sql_list_add (sets, set); - select = sql_select_new (); - sql_object_add_child (select, "targets", target); - sql_object_set (select, "where", where); + insert = g_object_new (SQL_TYPE_INSERT + ,"table", target + ,"fields", fields + ,"values", sets + ,NULL + ); + + exprs = sql_list_new (SQL_TYPE_EXPR); + + targets = sql_list_new (SQL_TYPE_TARGET); + sql_list_add (targets, target); + + select = g_object_new (SQL_TYPE_SELECT + ,"exprs", exprs + ,"targets", targets + ,"where", where + ,NULL + ); for (i = 0; i < row->len; i++) if (!g_strcmp0 (priv->column[i].table, table)) { - val = sql_value_new_with_value (&row->value[i]); + if (gvn_value_is_null (&row->value[i])) + { + gchar * column_def = g_hash_table_lookup (priv->column_default, + priv->column[i].display); + gint col = db_model_get_column_index (obj, column_def); + + if (col != -1) + value = &row->value[col]; + else + value = NULL; + } + else + value = &row->value[i]; - sql_object_add_child (insert, "fields", - sql_field_new (priv->column[i].name, NULL, NULL)); - sql_object_add_child (set, "exprs", - gvn_value_is_null (&row->value[i]) ? NULL : val); + if (value) + { + sql_list_add (fields, sql_field_new (priv->column[i].name)); + sql_list_add (values, sql_value_new_with_value (value)); + } - sql_object_add_child (select, "exprs", - sql_field_new (priv->column[i].name, - priv->column[i].table, NULL)); + sql_list_add (exprs, sql_field_new (priv->column[i].name)); } - sql_object_add_child (stmts, "stmts", insert); - sql_object_add_child (stmts, "stmts", select); - return stmts; + stmts = sql_list_new (SQL_TYPE_STMT); + sql_list_add (stmts, insert); + sql_list_add (stmts, select); + return g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); } /** @@ -2562,6 +2510,8 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) while (!error && (op_elem = g_queue_pop_head (priv->operation))) { + SqlObject * stmt = NULL; + op_elem->locked = TRUE; row = op_elem->row; @@ -2576,32 +2526,31 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else if ((where = db_model_create_where (obj, priv->main_table, op_elem, FALSE))) { - SqlObject * delete = sql_delete_new (); - sql_object_add_child (delete, "targets", - sql_table_new (priv->main_table)); + SqlList * targets = sql_list_new (SQL_TYPE_TARGET); + sql_list_add (targets, sql_table_new (priv->main_table)); - sql_object_set (delete, "where", where); - sql_list_add (stmts, delete); + stmt = g_object_new (SQL_TYPE_DELETE + ,"where", where + ,"targets", targets + ,NULL + ); } else error = TRUE; } - else if (op_elem->type & DB_MODEL_ROW_OP_INSERT) // INSERT + else if (op_elem->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { - SqlObject * insert = db_model_create_insert (obj, priv->main_table, op_elem); + stmt = db_model_create_insert (obj, priv->main_table, op_elem); - if (insert) - sql_list_add (stmts, insert); - else + if (!stmt) error = TRUE; } - else if (op_elem->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE + else if (op_elem->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT { - // Depending on the field, generate an UPDATE or INSERT+SELECT - GSList * l; GHashTableIter iter; gpointer table; + SqlList * update_list; GHashTable * tables = g_hash_table_new ( g_str_hash, g_str_equal); @@ -2612,6 +2561,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) g_hash_table_add (tables, priv->column[u->column].table); } + update_list = sql_list_new (SQL_TYPE_STMT); g_hash_table_iter_init (&iter, tables); while (g_hash_table_iter_next (&iter, &table, NULL)) @@ -2621,49 +2571,57 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) if (where) { DbUpdatedField * u; - SqlObject * update = g_object_new (SQL_TYPE_UPDATE, - "where", where, NULL); + SqlList * sets = sql_list_new (SQL_TYPE_UPDATE_SET); + SqlList * targets = sql_list_new (SQL_TYPE_TARGET); - sql_object_add_child (update, "targets", - sql_table_new (table)); + sql_list_add (targets, sql_table_new (table)); for (l = op_elem->updated; l && (u = l->data); l = l->next) if (!g_strcmp0 (priv->column[u->column].table, table)) { GValue * new_value = DB_ROW_FIELD (row, u->column); - sql_object_add_child (update, "sets", - g_object_new (SQL_TYPE_UPDATE_SET, - "field", sql_field_new (priv->column[u->column].name, NULL, NULL), - "expr", sql_value_new_with_value (new_value), - NULL)); + sql_list_add (sets, g_object_new (SQL_TYPE_UPDATE_SET + ,"field", sql_field_new (priv->column[u->column].name) + ,"expr", sql_value_new_with_value (new_value) + ,NULL + )); } - sql_list_add (stmts, update); + sql_list_add (update_list, g_object_new (SQL_TYPE_UPDATE + ,"where", where + ,"targets", targets + ,"sets", sets + ,NULL + )); } else { SqlObject * insert = db_model_create_insert (obj, table, op_elem); if (insert) - sql_list_add (stmts, insert); + sql_list_add (update_list, insert); } } g_hash_table_destroy (tables); + stmt = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", update_list, NULL); } - g_queue_push_tail (req_ops, op_elem); + if (stmt) + sql_list_add (stmts, stmt); + if (op_elem) + g_queue_push_tail (req_ops, op_elem); } if (sql_list_length (stmts) > 0) { - SqlObject * multi = g_object_new (SQL_TYPE_MULTI_STMT, - "stmts", stmts, NULL); + SqlObject * multi = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); DbModelRequest * data = g_new (DbModelRequest, 1); data->obj = g_object_ref (obj); data->operations = req_ops; + data->stmts = g_object_ref_sink (stmts); request = db_conn_query_with_stmt_async (priv->conn ,SQL_STMT (multi) @@ -2693,19 +2651,33 @@ void db_model_refresh (DbModel * obj) DbModelPrivate * priv; g_return_if_fail (DB_IS_MODEL (obj)); + priv = obj->priv; - g_return_if_fail (priv->stmt); - db_model_clear (obj); - db_model_set_status (obj, DB_MODEL_STATUS_LOADING); - - priv->request = db_conn_query_with_stmt_async (priv->conn - ,priv->stmt - ,priv->batch - ,(DbRequestDoneCallback) db_model_on_data_ready - ,g_object_ref (obj) - ,(GDestroyNotify) g_object_unref - ); + + if (priv->conn + && priv->stmt && sql_object_is_ready (SQL_OBJECT (priv->stmt)) + && (!priv->batch || sql_batch_is_ready (priv->batch)) + && (!priv->internal_batch || sql_batch_is_ready (priv->internal_batch))) + { + SqlBatch * tmp_batch = sql_batch_new (); + sql_batch_merge (tmp_batch, priv->batch); + sql_batch_merge (tmp_batch, priv->internal_batch); + + db_model_set_status (obj, DB_MODEL_STATUS_LOADING); + + priv->request = db_conn_query_with_stmt_async (priv->conn + ,priv->stmt + ,tmp_batch + ,(DbRequestDoneCallback) db_model_on_data_ready + ,g_object_ref (obj) + ,(GDestroyNotify) g_object_unref + ); + + g_object_unref (g_object_ref_sink (tmp_batch)); + } + else + db_model_set_status (obj, DB_MODEL_STATUS_CLEAN); } /** diff --git a/db/db-request.c b/db/db-request.c index e9b8bb3..f2136a0 100644 --- a/db/db-request.c +++ b/db/db-request.c @@ -75,11 +75,15 @@ DbRequest * db_request_new (DbConn * conn, const gchar * sql) **/ DbRequest * db_request_new_with_stmt (DbConn * conn, SqlStmt * stmt, SqlBatch * batch) { + DbRequest * obj; + g_return_val_if_fail (DB_IS_CONN (conn), NULL); g_return_val_if_fail (SQL_IS_STMT (stmt), NULL); g_return_val_if_fail (SQL_IS_BATCH (batch) || !batch, NULL); - return g_object_new (DB_TYPE_REQUEST, "conn", conn, "batch", batch, "stmt", stmt, NULL); + obj = g_object_new (DB_TYPE_REQUEST, "conn", conn, NULL); + obj->sql = db_conn_render (conn, stmt, batch, NULL); + return obj; } /** @@ -352,8 +356,6 @@ typedef enum { PROP_CONN = 1 ,PROP_SQL - ,PROP_STMT - ,PROP_BATCH ,PROP_RESULT_SET ,PROP_ERROR } @@ -370,27 +372,7 @@ static void db_request_set_property (DbRequest * obj, guint property_id, obj->conn = g_value_dup_object (value); break; case PROP_SQL: - { - gchar * sql = g_value_dup_string (value); - - if (sql) - obj->sql = sql; - - break; - } - case PROP_STMT: - { - SqlStmt * stmt = g_value_get_object (value); - - if (obj->conn && stmt) - obj->sql = db_conn_render (obj->conn, stmt, obj->batch, NULL); - else if (!obj->conn) - g_warning ("DbRequest: Can't render stmt, conn property not set"); - - break; - } - case PROP_BATCH: - obj->batch = g_value_dup_object (value); + obj->sql = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); @@ -468,20 +450,6 @@ static void db_request_class_init (DbRequestClass * k) ,NULL ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE )); - g_object_class_install_property (klass, PROP_STMT, - g_param_spec_object ("stmt" - ,_("Statement") - ,_("The statement to execute") - ,SQL_TYPE_STMT - ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE - )); - g_object_class_install_property (klass, PROP_BATCH, - g_param_spec_object ("batch" - ,_("Batch") - ,_("The batch for render the statement") - ,SQL_TYPE_BATCH - ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE - )); g_object_class_install_property (klass, PROP_RESULT_SET, g_param_spec_boxed ("result-set" ,_("Result") diff --git a/db/db-request.h b/db/db-request.h index fcb1dcf..630a948 100644 --- a/db/db-request.h +++ b/db/db-request.h @@ -60,7 +60,6 @@ struct _DbRequest /* */ DbConn * conn; - SqlBatch * batch; gchar * sql; DbResultSet * result_set; GError * error; diff --git a/db/db-result.h b/db/db-result.h index 08643d5..1bf95e8 100644 --- a/db/db-result.h +++ b/db/db-result.h @@ -72,6 +72,7 @@ struct _DbColumn DbColumnInfo info; GvnParamSpec * spec; gchar * table; + gchar * table_alias; gchar * name; gchar * display; }; diff --git a/module/data/customer.glade b/module/data/customer.glade index d34db37..27e07b4 100644 --- a/module/data/customer.glade +++ b/module/data/customer.glade @@ -1,10 +1,11 @@ + - - + + - SELECT id, street, pc, city, province, ok FROM user_address WHERE #p ORDER BY id + SELECT id, street, pc, city, province, ok FROM user_address WHERE #link ORDER BY id SELECT id, name, credit, active, born, photo, object_id FROM "user" ORDER BY id @@ -49,8 +50,6 @@ 0 0 - 1 - 1 @@ -63,8 +62,6 @@ 1 0 - 1 - 1 @@ -77,8 +74,6 @@ 0 1 - 1 - 1 @@ -91,8 +86,6 @@ 0 2 - 1 - 1 @@ -105,8 +98,6 @@ 0 3 - 1 - 1 @@ -119,8 +110,6 @@ 0 4 - 1 - 1 @@ -133,8 +122,6 @@ 0 5 - 1 - 1 @@ -147,8 +134,6 @@ 1 1 - 1 - 1 @@ -161,8 +146,6 @@ 1 2 - 1 - 1 @@ -176,8 +159,6 @@ 1 4 - 1 - 1 @@ -190,8 +171,6 @@ 1 5 - 1 - 1 @@ -204,8 +183,6 @@ 1 3 - 1 - 1 diff --git a/module/data/users.glade b/module/data/users.glade index 95af7fe..802bfbe 100644 --- a/module/data/users.glade +++ b/module/data/users.glade @@ -1,42 +1,59 @@ + - - + + on-iter - SELECT user_id, group_id, uid, last_change, expire FROM account WHERE #p + SELECT user_id, group_id, uid, last_change, expire FROM account WHERE #link - SELECT mail_alias_id, user_id FROM mail_alias_account WHERE #p + SELECT mail_alias_id, user_id FROM mail_alias_account WHERE #link - - True + False - 6 - vertical - 6 - - - True + 5 + Change password + False + True + True + dialog + + + + False - 0 - none + vertical + 2 - - True + + True False - 30 - - - True + + False - 6 + 5 + vertical + end - + + + + + False + True + 1 + + + + + False + 8 + 8 + + True False - 1 - User name: False @@ -44,37 +61,117 @@ 0 - - - True - False - search-user - - - False - True - 1 - - + + True + True + 0 + + + False + True + 0 + - - + + True False - <b>Search</b> - True + 6 + 6 + 6 + + + True + False + 1 + Password: + + + 0 + 0 + + + + + True + False + 1 + Repeat password: + + + 0 + 1 + + + + + True + True + False + + + + 1 + 0 + + + + + True + True + False + + + + 1 + 1 + + + + False + True + 1 + + + + + False + end + + + + + + + + + False + True + end + 2 + - - False - True - 0 - + + + + on-iter + SELECT user_id, extension, secret, callerid FROM account_sip WHERE #link + + + SELECT u.id, u.name, u.mysql_user_id, m.user, u.active FROM `user` u JOIN mysql_user m ON u.mysql_user_id = m.id + + + True + False + 6 + vertical + 6 True @@ -168,8 +265,6 @@ 0 1 - 1 - 1 @@ -182,8 +277,6 @@ 0 2 - 1 - 1 @@ -196,8 +289,6 @@ 0 3 - 1 - 1 @@ -210,8 +301,6 @@ 1 4 - 1 - 1 @@ -224,8 +313,6 @@ 0 4 - 1 - 1 @@ -239,8 +326,6 @@ 0 0 - 1 - 1 @@ -255,8 +340,6 @@ 1 0 - 1 - 1 @@ -269,8 +352,6 @@ 1 1 - 1 - 1 @@ -284,8 +365,6 @@ 1 3 - 1 - 1 @@ -295,15 +374,12 @@ True True True - False True 1 2 - 1 - 1 @@ -351,8 +427,6 @@ 1 1 - 1 - 1 @@ -366,8 +440,6 @@ 1 0 - 1 - 1 @@ -381,8 +453,6 @@ 0 0 - 1 - 1 @@ -395,8 +465,6 @@ 0 1 - 1 - 1 @@ -409,8 +477,6 @@ 1 2 - 1 - 1 @@ -423,8 +489,6 @@ 1 3 - 1 - 1 @@ -437,8 +501,6 @@ 0 2 - 1 - 1 @@ -451,8 +513,6 @@ 0 3 - 1 - 1 @@ -590,8 +650,6 @@ 0 0 - 1 - 1 @@ -604,8 +662,6 @@ 0 1 - 1 - 1 @@ -618,22 +674,6 @@ 0 2 - 1 - 1 - - - - - True - False - 1 - Call group: - - - 0 - 3 - 1 - 1 @@ -647,8 +687,6 @@ 1 0 - 1 - 1 @@ -661,8 +699,6 @@ 1 1 - 1 - 1 @@ -675,22 +711,6 @@ 1 2 - 1 - 1 - - - - - True - False - sip - callgroup - - - 1 - 3 - 1 - 1 @@ -740,170 +760,4 @@ - - False - 5 - Change password - False - True - True - dialog - - - - - False - vertical - 2 - - - True - False - - - False - 8 - 8 - - - True - False - - - False - True - 0 - - - - - True - True - 0 - - - - - False - 5 - vertical - end - - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - 6 - 6 - 6 - - - True - False - 1 - Password: - - - 0 - 0 - 1 - 1 - - - - - True - False - 1 - Repeat password: - - - 0 - 1 - 1 - 1 - - - - - True - True - False - - True - - - 1 - 0 - 1 - 1 - - - - - True - True - False - - True - - - 1 - 1 - 1 - 1 - - - - - False - True - 1 - - - - - False - end - - - - - - - - - False - True - end - 2 - - - - - - - - on-iter - SELECT user_id, extension, secret, callerid, callgroup FROM account_sip WHERE #p - - - SELECT u.id, u.name, u.mysql_user_id, m.user, u.active FROM `user` u JOIN mysql_user m ON u.mysql_user_id = m.id - diff --git a/plugin/mysql/db-mysql.c b/plugin/mysql/db-mysql.c index 88889f8..37be7ff 100644 --- a/plugin/mysql/db-mysql.c +++ b/plugin/mysql/db-mysql.c @@ -228,6 +228,7 @@ static DbResultSet * db_mysql_query (DbMysql * obj, const gchar * sql, GError ** column->name = g_strdup (field[i].org_name); column->display = g_strdup (field[i].name); column->table = g_strdup (field[i].org_table); + column->table_alias = g_strdup (field[i].table); switch (field[i].type) { diff --git a/plugin/pg/db-pg.c b/plugin/pg/db-pg.c index 660a298..c704fd0 100644 --- a/plugin/pg/db-pg.c +++ b/plugin/pg/db-pg.c @@ -709,8 +709,10 @@ static DbResultSet * __db_pg_query GValue * v = g_new0 (GValue, 1); gchar ** split = g_strsplit_set (pg_val, "(':)", G_MAXINT8); SqlObject * function = sql_function_new ("currval", NULL); + SqlList * params = sql_list_new (SQL_TYPE_EXPR); g_value_set_string (g_value_init (v, G_TYPE_STRING), split[2]); - sql_object_add_child (function, "params", sql_value_new_with_value (v)); + sql_list_add (params, sql_value_new_with_value (v)); + g_object_set (function, "params", params, NULL); g_value_unset (v); g_free (v); g_value_take_object (g_value_init (&def[j], SQL_TYPE_FUNCTION), diff --git a/sql/parser/gram.y b/sql/parser/gram.y index 980b284..75a367b 100644 --- a/sql/parser/gram.y +++ b/sql/parser/gram.y @@ -386,7 +386,7 @@ join(A) ::= target(left) join_type(type) target(right) join_cond(condition). SQL_TABLE (right)->schema : NULL; sql_list_add (equal, - sql_field_new (SQL_FIELD (n->data)->name, target, schema)); + sql_field_new_with_table (SQL_FIELD (n->data)->name, target, schema)); sql_list_add (exprs, op); } diff --git a/sql/sql-batch.c b/sql/sql-batch.c index 21f3c84..91e2ac1 100644 --- a/sql/sql-batch.c +++ b/sql/sql-batch.c @@ -41,11 +41,18 @@ SqlBatch * sql_batch_new () //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_batch_child_changed (SqlBatch * child, SqlBatch * obj) +static void sql_batch_child_changed (SqlObject * child, SqlBatch * obj) { sql_batch_changed (obj); } +static void sql_batch_free_child (SqlBatch * obj, SqlObject * child) +{ + g_signal_handlers_disconnect_by_func (child, + sql_batch_child_changed, obj); + g_object_unref (child); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** @@ -120,15 +127,14 @@ void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * object) ); g_signal_connect (object, "changed", - G_CALLBACK (sql_batch_child_changed), obj - ); + G_CALLBACK (sql_batch_child_changed), obj); g_hash_table_replace (obj->items, g_strdup (id), g_object_ref_sink (object)); } /** * sql_batch_add_from_param: - * @obj: the #SqlString + * @obj: a #SqlBatch * @id: the id assigned to the item **/ void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * param) @@ -145,7 +151,7 @@ void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * para /** * sql_batch_add_from_value: - * @obj: the #SqlString + * @obj: a #SqlBatch * @id: the id assigned to the item **/ void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpointer content) @@ -166,6 +172,7 @@ void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpo /** * sql_batch_remove: + * @obj: a #SqlBatch * @id: the id of the #SqlHolder * * Removes a held object from the batch. @@ -175,17 +182,39 @@ void sql_batch_remove (SqlBatch * obj, const gchar * id) g_return_val_if_fail (SQL_IS_BATCH (obj), NULL); g_return_val_if_fail (id, NULL); - SqlObject * object = sql_batch_get (obj, id); + SqlObject * child = sql_batch_get (obj, id); - if (object) + if (child) { - g_signal_handlers_disconnect_by_func (object, - sql_batch_child_changed, obj); - g_object_unref (object); + sql_batch_free_child (obj, child); g_hash_table_remove (obj->items, id); } } +/** + * sql_batch_merge: + * @obj: a #SqlBatch + * @batch: a #SqlBatch + * + * Meges the batch with another batch. + **/ +void sql_batch_merge (SqlBatch * obj, SqlBatch * batch) +{ + GHashTableIter iter; + gpointer key, value; + + g_return_if_fail (SQL_IS_BATCH (obj)); + g_return_if_fail (SQL_IS_BATCH (batch) || !batch); + + if (!batch) + return; + + g_hash_table_iter_init (&iter, batch->items); + + while (g_hash_table_iter_next (&iter, &key, &value)) + sql_batch_add (obj, key, value); +} + /** * sql_batch_changed: * @obj: a #SqlBatch @@ -194,6 +223,8 @@ void sql_batch_remove (SqlBatch * obj, const gchar * id) **/ void sql_batch_changed (SqlBatch * obj) { + g_return_if_fail (SQL_IS_BATCH (obj)); + g_signal_emit (obj, signals[CHANGED], 0); } @@ -207,7 +238,17 @@ static void sql_batch_init (SqlBatch * obj) static void sql_batch_finalize (SqlBatch * obj) { if (obj->items) + { + GHashTableIter iter; + gpointer child; + + g_hash_table_iter_init (&iter, obj->items); + + while (g_hash_table_iter_next (&iter, NULL, &child)) + sql_batch_free_child (obj, child); + g_hash_table_destroy (obj->items); + } G_OBJECT_CLASS (sql_batch_parent_class)->finalize (G_OBJECT (obj)); } diff --git a/sql/sql-batch.h b/sql/sql-batch.h index 1a83cb7..edd6d12 100644 --- a/sql/sql-batch.h +++ b/sql/sql-batch.h @@ -51,6 +51,7 @@ void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * object); void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * param); void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpointer content); void sql_batch_remove (SqlBatch * obj, const gchar * id); +void sql_batch_merge (SqlBatch * obj, SqlBatch * batch); void sql_batch_changed (SqlBatch * obj); #endif \ No newline at end of file diff --git a/sql/sql-field.c b/sql/sql-field.c index 33773b2..f07b612 100644 --- a/sql/sql-field.c +++ b/sql/sql-field.c @@ -29,6 +29,22 @@ G_DEFINE_TYPE (SqlField, sql_field, SQL_TYPE_EXPR); /** * sql_field_new: * @name: the name of the field + * + * Creates a new #SqlField. + * + * Return value: an #SqlExpr + */ +SqlObject * sql_field_new (const gchar * name) +{ + return g_object_new (SQL_TYPE_FIELD + ,"name", name + ,NULL + ); +} + +/** + * sql_field_new_with_table: + * @name: the name of the field * @target: (allow-none): the table from which the field is selected * @schema: (allow-none): the schema from which the table and field are selected * @@ -36,7 +52,7 @@ G_DEFINE_TYPE (SqlField, sql_field, SQL_TYPE_EXPR); * * Return value: an #SqlExpr */ -SqlObject * sql_field_new (const gchar * name, const gchar * target, const gchar * schema) +SqlObject * sql_field_new_with_table (const gchar * name, const gchar * target, const gchar * schema) { return g_object_new (SQL_TYPE_FIELD ,"name", name diff --git a/sql/sql-field.h b/sql/sql-field.h index c33efe8..c01723d 100644 --- a/sql/sql-field.h +++ b/sql/sql-field.h @@ -42,10 +42,11 @@ struct _SqlFieldClass SqlExprClass parent; }; -GType sql_field_get_type (); -SqlObject * sql_field_new (const gchar * name - ,const gchar * target - ,const gchar * schema); -void sql_field_set_name (SqlField * obj, const gchar * name); +GType sql_field_get_type (); +SqlObject * sql_field_new (const gchar * name); +SqlObject * sql_field_new_with_table (const gchar * name + ,const gchar * target + ,const gchar * schema); +void sql_field_set_name (SqlField * obj, const gchar * name); #endif diff --git a/sql/sql-holder.c b/sql/sql-holder.c index 74217e4..0fe13d8 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -107,7 +107,7 @@ static void sql_holder_init (SqlHolder * obj) static void sql_holder_finalize (SqlHolder * obj) { g_free (obj->id); - G_OBJECT_CLASS (sql_holder_finalize)->finalize (G_OBJECT (obj)); + G_OBJECT_CLASS (sql_holder_parent_class)->finalize (G_OBJECT (obj)); } static void sql_holder_class_init (SqlHolderClass * k) diff --git a/sql/sql-list.c b/sql/sql-list.c index 7985e36..664e240 100644 --- a/sql/sql-list.c +++ b/sql/sql-list.c @@ -30,6 +30,20 @@ SqlList * sql_list_new (GType gtype) return g_object_new (SQL_TYPE_LIST, "gtype", gtype, NULL); } +SqlList * sql_list_new_with_items (GType gtype, ...) +{ + va_list vl; + SqlObject * item; + SqlList * obj = g_object_new (SQL_TYPE_LIST, "gtype", gtype, NULL); + + va_start (vl, gtype); + + while ((item = va_arg (vl, SqlObject *))) + sql_list_add (obj, item); + + return obj; +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private static void sql_list_render (SqlList * obj, SqlRender * render) @@ -268,7 +282,7 @@ static void sql_list_finalize (SqlList * obj) } g_queue_clear (&obj->items); - G_OBJECT_CLASS (sql_list_finalize)->finalize (G_OBJECT (obj)); + G_OBJECT_CLASS (sql_list_parent_class)->finalize (G_OBJECT (obj)); } static void sql_list_class_init (SqlListClass * k) @@ -293,6 +307,6 @@ static void sql_list_class_init (SqlListClass * k) ,_("GType") ,_("The allowed type for the items") ,SQL_TYPE_OBJECT - ,G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY + ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY )); } diff --git a/sql/sql-list.h b/sql/sql-list.h index c2313a8..0730ebc 100644 --- a/sql/sql-list.h +++ b/sql/sql-list.h @@ -42,6 +42,7 @@ struct _SqlListClass GType sql_list_get_type (); SqlList * sql_list_new (GType gtype); +SqlList * sql_list_new_with_items (GType gtype, ...); void sql_list_add (SqlList * obj, gpointer item); void sql_list_insert (SqlList * obj, gpointer item, guint index); gpointer sql_list_get (SqlList * obj, guint index); diff --git a/sql/sql-object.c b/sql/sql-object.c index cb59fc7..9d8673c 100644 --- a/sql/sql-object.c +++ b/sql/sql-object.c @@ -215,6 +215,8 @@ void sql_object_get_holders (SqlObject * obj, GQueue * holders) **/ void sql_object_changed (SqlObject * obj) { + g_return_if_fail (SQL_IS_OBJECT (obj)); + g_signal_emit (obj, signals[CHANGED], 0); } diff --git a/sql/sql-operation.c b/sql/sql-operation.c index 27e4a2a..c6e2694 100644 --- a/sql/sql-operation.c +++ b/sql/sql-operation.c @@ -31,7 +31,7 @@ G_DEFINE_TYPE (SqlOperation, sql_operation, SQL_TYPE_EXPR); SqlObject * sql_operation_new (SqlOperationType type) { - return g_object_new (SQL_TYPE_OPERATION, "type", type, NULL); + return g_object_new (SQL_TYPE_OPERATION, "operator", type, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private @@ -61,67 +61,120 @@ static const gchar * SQL_OPERATION_TYPE[] = ,"IN" }; -static void sql_operation_render (SqlOperation * obj, SqlRender * render) +static void sql_operation_render (SqlOperation * self, SqlRender * render) { sql_render_add_espace (render); sql_render_append (render, "("); - sql_render_add_list (render, TRUE, NULL, obj->operators, - SQL_OPERATION_TYPE[obj->type]); + sql_render_add_list (render, TRUE, NULL, self->operands, + SQL_OPERATION_TYPE[self->type]); sql_render_append (render, ")"); } +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public + +/** + * sql_operation_get_operator: + * @self: a #SqlOperation + * + * Return value: the operation type + **/ +SqlOperationType sql_operation_get_operator (SqlOperation * self) +{ + g_return_val_if_fail (SQL_IS_OPERATION (self), 0); + + return self->type; +} + +/** + * sql_operation_set_operand: + * @self: a #SqlOperation + * @type: the operation type + **/ +void sql_operation_set_operator (SqlOperation * self, SqlOperationType type) +{ + g_return_if_fail (SQL_IS_OPERATION (self)); + + self->type = type; +} + +/** + * sql_operation_get_operands: + * @self: a #SqlOperation + * + * Return value: (allow-none) (transfer full): a #SqlList + **/ +SqlList * sql_operation_get_operands (SqlOperation * self) +{ + g_return_val_if_fail (SQL_IS_OPERATION (self), NULL); + + return self->operands; +} + +/** + * sql_operation_set_operands: + * @self: a #SqlOperation + * @operators: (allow-none): a #SqlList + **/ +void sql_operation_set_operands (SqlOperation * self, SqlList * operands) +{ + g_return_if_fail (SQL_IS_OPERATION (self)); + g_return_if_fail (SQL_IS_LIST (operands) || !operands); + + sql_object_remove (self, self->operands); + self->operands = sql_object_add (self, operands); +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties enum { PROP_TYPE = 1 - ,PROP_OPERATORS + ,PROP_OPERANDS }; -static void sql_operation_set_property (SqlOperation * obj, guint id, +static void sql_operation_set_property (SqlOperation * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_TYPE: - obj->type = g_value_get_enum (value); + self->type = g_value_get_enum (value); break; - case PROP_OPERATORS: - sql_object_remove (obj, obj->operators); - obj->operators = sql_object_add (obj, g_value_get_object (value)); + case PROP_OPERANDS: + sql_operation_set_operands (self, g_value_get_object (value)); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_operation_get_property (SqlOperation * obj, guint id, +static void sql_operation_get_property (SqlOperation * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_TYPE: - g_value_set_enum (value, obj->type); + g_value_set_enum (value, self->type); break; - case PROP_OPERATORS: - g_value_set_object (value, obj->operators); + case PROP_OPERANDS: + g_value_set_object (value, self->operands); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_operation_init (SqlOperation * obj) +static void sql_operation_init (SqlOperation * self) { - obj->operators = NULL; + self->operands = NULL; } -static void sql_operation_finalize (SqlOperation * obj) +static void sql_operation_finalize (SqlOperation * self) { - sql_object_remove (obj, obj->operators); - G_OBJECT_CLASS (sql_operation_parent_class)->finalize (G_OBJECT (obj)); + sql_object_remove (self, self->operands); + G_OBJECT_CLASS (sql_operation_parent_class)->finalize (G_OBJECT (self)); } static void sql_operation_class_init (SqlOperationClass * klass) @@ -133,17 +186,17 @@ static void sql_operation_class_init (SqlOperationClass * klass) SQL_OBJECT_CLASS (klass)->render = (SqlRenderFunc) sql_operation_render; g_object_class_install_property (k, PROP_TYPE, - g_param_spec_enum ("type" + g_param_spec_enum ("operator" ,("Type") ,("The type of the operation") ,SQL_TYPE_OPERATION_TYPE ,SQL_OPERATION_TYPE_AND ,G_PARAM_READWRITE )); - g_object_class_install_property (k, PROP_OPERATORS, - sql_param_list ("operators" + g_object_class_install_property (k, PROP_OPERANDS, + sql_param_list ("operands" ,("Operators") - ,("The list of operators") + ,("The list of operands") ,SQL_TYPE_EXPR ,G_PARAM_READWRITE | G_PARAM_CONSTRUCT )); diff --git a/sql/sql-operation.h b/sql/sql-operation.h index 5ee436d..df0eca1 100644 --- a/sql/sql-operation.h +++ b/sql/sql-operation.h @@ -66,7 +66,7 @@ SqlOperationType; struct _SqlOperation { SqlExpr parent; - SqlList * operators; // List of SqlExpr + SqlList * operands; // List of SqlExpr SqlOperationType type; }; @@ -76,9 +76,13 @@ struct _SqlOperationClass SqlExprClass parent; }; -GType sql_operation_get_type (); -GType sql_operation_type_get_type (); +GType sql_operation_get_type (); +GType sql_operation_type_get_type (); -SqlObject * sql_operation_new (SqlOperationType type); +SqlObject * sql_operation_new (SqlOperationType type); +SqlList * sql_operation_get_operands (SqlOperation * self); +void sql_operation_set_operands (SqlOperation * self, SqlList * operands); +SqlOperationType sql_operation_get_operator (SqlOperation * self); +void sql_operation_set_operator (SqlOperation * self, SqlOperationType type); #endif diff --git a/sql/sql-param-list.c b/sql/sql-param-list.c index 46148d4..12795c7 100644 --- a/sql/sql-param-list.c +++ b/sql/sql-param-list.c @@ -34,7 +34,6 @@ sql_param_list (const gchar * name, const gchar * nick, ); pspec->items_type = items_type; - G_PARAM_SPEC (pspec)->value_type = SQL_TYPE_LIST; return G_PARAM_SPEC (pspec); } @@ -56,7 +55,7 @@ sql_param_list_validate (GParamSpec * pspec, GValue * value) gpointer object = g_value_get_object (value); if (!object) - return TRUE; + return FALSE; type = G_OBJECT_TYPE (object); diff --git a/sql/sql-param-object.c b/sql/sql-param-object.c index 490956e..4a00e9d 100644 --- a/sql/sql-param-object.c +++ b/sql/sql-param-object.c @@ -32,8 +32,6 @@ sql_param_object (const gchar * name, const gchar * nick, ,blurb ,flags ); - - pspec->value_type = object_type; return pspec; } @@ -54,7 +52,7 @@ sql_param_object_validate (GParamSpec * pspec, GValue * value) GObject * object = g_value_get_object (value); if (!object) - return TRUE; + return FALSE; type = G_OBJECT_TYPE (object); diff --git a/sql/sql-render.c b/sql/sql-render.c index aa73f47..604286e 100644 --- a/sql/sql-render.c +++ b/sql/sql-render.c @@ -145,7 +145,7 @@ void sql_render_add_object (SqlRender * obj, gpointer object) function = g_hash_table_lookup (obj->custom_renderers, GUINT_TO_POINTER (G_OBJECT_TYPE (object))); obj->ancestors = g_slist_prepend (obj->ancestors, object); - + if (function) function (object, obj, obj->batch); else diff --git a/sql/sql-value.c b/sql/sql-value.c index 42267bc..0790196 100644 --- a/sql/sql-value.c +++ b/sql/sql-value.c @@ -33,9 +33,15 @@ SqlObject * sql_value_new () return g_object_new (SQL_TYPE_VALUE, NULL); } +SqlObject * sql_value_new_with_param (GvnParam * param) +{ + g_return_val_if_fail (GVN_IS_PARAM (param), NULL); + + return g_object_new (SQL_TYPE_VALUE, "param", param, NULL); +} + SqlObject * sql_value_new_with_value (const GValue * value) { - g_return_val_if_fail (value, NULL); g_return_val_if_fail (G_IS_VALUE (value), NULL); return g_object_new (SQL_TYPE_VALUE, "value", value, NULL); @@ -159,6 +165,13 @@ void sql_value_set_param (SqlValue * obj, GvnParam * param) } } +GvnParam * sql_value_get_param (SqlValue * self) +{ + g_return_if_fail (SQL_IS_VALUE (self)); + + return self->param; +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties enum diff --git a/sql/sql-value.h b/sql/sql-value.h index 6b75448..9e48b5a 100644 --- a/sql/sql-value.h +++ b/sql/sql-value.h @@ -44,8 +44,10 @@ struct _SqlValueClass GType sql_value_get_type (); SqlObject * sql_value_new (); SqlObject * sql_value_new_with_value (const GValue * value); +SqlObject * sql_value_new_with_param (GvnParam * param); const GValue * sql_value_get_value (SqlValue * obj); void sql_value_set_value (SqlValue * obj, const GValue * value); +GvnParam * sql_value_get_param (SqlValue * self); void sql_value_set_param (SqlValue * obj, GvnParam * param); #endif diff --git a/vn/field/vn-completion.c b/vn/field/vn-completion.c index 0321d1e..6a72b13 100644 --- a/vn/field/vn-completion.c +++ b/vn/field/vn-completion.c @@ -187,27 +187,27 @@ static void vn_completion_create_model (VnCompletion * obj) { SqlObject * field; SqlObject * stmt; - SqlObject * op; + SqlObject * like; SqlBatch * batch; - SqlList * ops; + SqlList * operands; if (!(obj->sql && obj->field)) return; - op = sql_operation_new (SQL_OPERATION_TYPE_LIKE); + like = sql_operation_new (SQL_OPERATION_TYPE_LIKE); - ops = sql_list_new (SQL_TYPE_EXPR); - g_object_set (op, "operators", ops, NULL); + operands = sql_list_new (SQL_TYPE_EXPR); + g_object_set (like, "operands", operands, NULL); - field = sql_field_new (obj->field, NULL, NULL); - sql_list_add (ops, field); + field = sql_field_new (obj->field); + sql_list_add (operands, field); obj->value = sql_value_new (); - sql_list_add (ops, obj->value); + sql_list_add (operands, obj->value); batch = sql_batch_new (); sql_batch_add (batch, "field", field); - sql_batch_add (batch, "filter", op); + sql_batch_add (batch, "filter", like); db_model_set_batch (obj->model, batch); stmt = sql_string_new (obj->sql); From 807c8f6699d5624d99e2b6e50eacb6d8053682dd Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Thu, 29 May 2014 16:30:11 +0200 Subject: [PATCH 06/10] DbModel: - Ahora identifica las columnas y tablas por nombre de tabla y esquema. - Ahora utiliza menos memoria cuando es utilizado en modo solo lectura. - Codigo reorganizado y optimizado. --- db/db-model.c | 1020 ++++++++++++++++++++------------------- db/db-result.c | 4 +- db/db-result.h | 3 +- plugin/mysql/db-mysql.c | 2 +- plugin/pg/db-pg.c | 4 +- sql/parser/gram.y | 2 +- sql/parser/scan.rl | 42 ++ sql/sql-batch.c | 99 ++-- sql/sql-delete.c | 2 +- sql/sql-field.c | 128 +++-- sql/sql-field.h | 18 +- sql/sql-holder.c | 4 +- sql/sql-insert.c | 5 +- sql/sql-list.c | 4 +- sql/sql-object.c | 30 +- sql/sql-object.h | 4 +- sql/sql-parser.h | 5 +- sql/sql-render.c | 4 +- sql/sql-set.c | 5 - sql/sql-string.c | 4 +- sql/sql-table.c | 4 +- sql/sql-table.h | 2 +- 22 files changed, 757 insertions(+), 638 deletions(-) diff --git a/db/db-model.c b/db/db-model.c index 1cf7b78..7ca5c6e 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -20,6 +20,7 @@ #include #include "db-model.h" #include "db-row.h" +#include "db-model-private.c" #define MODEL_NOT_READY(obj) (obj->priv->status != DB_MODEL_STATUS_READY) #define VALID_ITER(iter, model) (iter->data && iter->stamp == model->priv->stamp) @@ -50,7 +51,7 @@ struct _DbModelPrivate SqlStmt * stmt; gchar * sql; gboolean use_file; - gchar * main_table; + Table * main_table; DbModelUpdateFlags update_flags; SqlBatch * batch; @@ -74,8 +75,9 @@ struct _DbModelPrivate SqlObject * link_op; SqlBatch * internal_batch; - GHashTable * defaults; - GHashTable * column_default; + GHashTable * column_defaults; + GHashTable * tables; + gboolean updatable_data_allocated; gint stamp; @@ -96,57 +98,6 @@ struct _DbModelPrivate // Structures -/* - * 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; - -/* - * 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; - typedef struct { DbModel * obj; @@ -171,30 +122,13 @@ typedef struct } DbJoin; -typedef struct -{ - gchar * field; - gpointer param; - gboolean link; - SqlObject * equal_op; - DbModel * obj; -} -ParamDef; - -typedef struct -{ - gint count; - gint * index; -} -DbModelPKey; - enum { DB_MODEL_UNSORTED_SORT_COLUMN_ID = -2, DB_MODEL_DEFAULT_SORT_COLUMN_ID }; -// Constructors +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Constructors /** * db_model_new: @@ -246,6 +180,7 @@ DbModel * db_model_new_with_file (DbConn * conn, const gchar * file) // Prototypes +static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj); static void db_model_set_status (DbModel * obj ,DbModelStatus status); static void db_model_clear (DbModel * obj); @@ -256,7 +191,84 @@ static void db_model_manage_join (DbModel * obj ,gint col); static void db_model_post_process_query (DbModel * obj); -// Signal Handlers +// Memory allocate functions + +static void db_model_alloc_link_data (DbModel * obj) +{ + SqlList * operators; + DbModelPrivate * priv = obj->priv; + + if (priv->link_op) + return; + + priv->internal_batch = g_object_ref_sink (sql_batch_new ()); + g_signal_connect (priv->internal_batch, "changed", + G_CALLBACK (db_model_on_batch_changed), obj); + + priv->link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); + sql_batch_add (priv->internal_batch, "link", priv->link_op); + + operators = sql_list_new (SQL_TYPE_EXPR); + sql_operation_set_operands (SQL_OPERATION (priv->link_op), operators); +} + +static void db_model_free_stmt_data (DbModel * obj) +{ + if (obj->priv->tables) + g_hash_table_destroy (obj->priv->tables); +} + +static void db_model_alloc_stmt_data (DbModel * obj) +{ + gint i; + Table table; + TableData * table_data; + DbModelPrivate * priv = obj->priv; + + if (!priv->updatable_data_allocated) + return; + + db_model_free_stmt_data (obj); + + priv->tables = g_hash_table_new_full ( + (GHashFunc) table_hash, + (GEqualFunc) table_equal, + (GDestroyNotify) table_free, + (GDestroyNotify) table_data_free + ); + + for (i = 0; i < priv->result->ncols; i++) + if ((priv->column[i].info & DB_COLUMN_PRI_KEY)) + { + table.name = priv->column[i].table; + table.schema = priv->column[i].schema; + + table_data = g_hash_table_lookup (priv->tables, &table); + + if (!table_data) + { + table_data = g_new0 (TableData, 1); + table_data->pkeys = NULL; + g_hash_table_insert (priv->tables, table_copy (&table), table_data); + } + + table_data->pkeys = g_slist_prepend (table_data->pkeys, GINT_TO_POINTER (i)); + g_hash_table_insert (priv->tables, table_copy (&table), table_data); + } + + for (i = 0; i < priv->result->ncols; i++) + { + table.name = priv->column[i].table; + table.schema = priv->column[i].schema; + + table_data = g_hash_table_lookup (priv->tables, &table); + + if (table_data && table_data->pkeys) + gvn_param_spec_set_editable (priv->column[i].spec, TRUE); + } +} + +// Signal Handlers enum { @@ -310,34 +322,52 @@ static void db_model_on_line_deleted (DbModel * obj, gint position) static void db_model_calculate_update_flags (DbModel * obj) { gint i; - gchar * main_table = NULL; + Table table; DbModelPrivate * priv = obj->priv; - + + priv->main_table = NULL; + if (priv->result) - for (i = 0; i < priv->result->ncols && !main_table; i++) - if (priv->column[i].info & DB_COLUMN_PRI_KEY) { if (!priv->user_main_table) - main_table = priv->column[i].table; - else if (!g_strcmp0 (priv->user_main_table, priv->column[i].table)) - main_table = priv->user_main_table; + { + for (i = 0; i < priv->result->ncols; i++) + if (priv->column[i].info & DB_COLUMN_PRI_KEY) + { + table.name = priv->column[i].table; + table.schema = priv->column[i].schema; + priv->main_table = g_hash_table_lookup (priv->tables, &table); + break; + } + } + else + { + table_parse (&table, priv->user_main_table); + priv->main_table = g_hash_table_lookup (priv->tables, &table); + + if (!priv->main_table) + g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, + "Can't set '%s' as main table", table.name); + } } - - g_free (priv->main_table); - - if (main_table) - { + + if (priv->main_table) priv->update_flags = DB_MODEL_ALL & priv->user_update_flags; - priv->main_table = g_strdup (main_table); - } else - { - if (priv->user_main_table && priv->result) - g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, - "The requested table can't be set as main table"); - priv->update_flags = 0; - priv->main_table = NULL; + + if (!priv->updatable_data_allocated && priv->update_flags) + { + priv->updatable_data_allocated = TRUE; + priv->operation = g_queue_new (); + priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); + + priv->column_defaults = g_hash_table_new_full ( + (GHashFunc) field_hash, + (GEqualFunc) field_equal, + (GDestroyNotify) field_free, + (GDestroyNotify) column_def_free + ); } } @@ -358,7 +388,7 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) if ((r = db_request_fetch_result (request, NULL))) { - gint i, j; + gint i; priv->column = r->column; priv->data = r->data; @@ -370,40 +400,22 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) } else { - GSList * t = NULL; - priv->result = r; if (priv->fresh) - priv->column_index = g_hash_table_new_full (g_str_hash, - g_str_equal, (GDestroyNotify) g_free, NULL); - - for (i = 0; i < priv->result->ncols; i++) { - // Set fields editable if *all* primary keys are selected FIXME - if (priv->column[i].info & DB_COLUMN_PRI_KEY - && !g_slist_find_custom (t, priv->column[i].table, (GCompareFunc) g_strcmp0)) - for (j = 0; j < priv->result->ncols; j++) - if (!g_strcmp0 (priv->column[i].table, priv->column[j].table)) - { - gvn_param_spec_set_editable (priv->column[j].spec, TRUE); - t = g_slist_prepend (t, priv->column[j].table); - } + db_model_calculate_update_flags (obj); + db_model_alloc_stmt_data (obj); - if (priv->fresh && priv->column_index) + for (i = 0; i < priv->result->ncols; i++) g_hash_table_insert (priv->column_index, - g_strdup (priv->column[i].display), GINT_TO_POINTER (i)); + g_strdup (priv->column[i].alias), GINT_TO_POINTER (i)); + + db_model_post_process_query (obj); } - - g_slist_free (t); - - db_model_calculate_update_flags (obj); - - if (!priv->fresh) + else db_model_set_sort_column_id (obj, priv->old_sort_column_id, priv->old_order); - else - db_model_post_process_query (obj); db_model_set_status (obj, DB_MODEL_STATUS_READY); } @@ -414,6 +426,148 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) g_clear_object (&priv->request); } +static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * row, GError * err) +{ + gint i, j; + DbModelPrivate * priv = obj->priv; + DbResult * result; + DbRow * req_row; + DbIter iter; + + result = db_request_fetch_result (request, &err); + + if (result && result->data && result->nrows > 0 ) + { + iter.stamp = priv->stamp; + iter.data = row; + req_row = g_ptr_array_index (result->data, 0); + + for (i = 0; i < result->ncols; i++) + for (j = 0; j < priv->result->ncols; j++) + if (!g_strcmp0 (priv->column[j].name, result->column[i].name) + && !g_strcmp0 (priv->column[j].table, result->column[i].table)) + { + GValue * v; + gboolean emit = TRUE; + + priv->updated_value = g_new0 (GValue, 1); + + if ((v = &req_row->value[i]) && G_IS_VALUE (v) + && !gvn_value_is_null (DB_ROW_FIELD (req_row, i)) + && gvn_value_is_null (DB_ROW_FIELD (row, j))) + { + g_value_init (priv->updated_value, G_VALUE_TYPE (v)); + gvn_value_copy (v, priv->updated_value); + } + else if (gvn_value_is_null (DB_ROW_FIELD (row, j))) + { + g_value_init (priv->updated_value, GVN_TYPE_NULL); + } + else + { + emit = FALSE; + g_free (priv->updated_value); + } + + if (emit) + { + priv->updated_col = j; + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + } + } + } + + if (result) + db_result_free (result); +} + +static void db_model_on_operations_done (DbRequest * request, DbModelRequest * data) +{ + GList * l; + guint i = 0; + DbOperation * op; + GError * err = NULL; + DbModel * obj = data->obj; + DbModelPrivate * priv = obj->priv; + + priv->pending_request = + g_slist_remove (priv->pending_request, request); + + l = g_queue_peek_head_link (data->operations); + + for (; l; l = l->next) + { + op = l->data; + + if (op->type & DB_MODEL_ROW_OP_DELETE + && op->type & DB_MODEL_ROW_OP_INSERT) // DELETE + INSERT + { + g_signal_emit (obj, + db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); + continue; + } + + if (db_request_fetch_non_select (request, &err) == -1) + break; + + g_hash_table_remove (priv->row_ops, op->row); + + if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE + { + g_signal_emit (obj, + db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); + } + else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT + { + db_model_process_insert (obj, request, op->row, err); + } + else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT + { + guint j; + SqlList * list; + DbIter iter; + SqlObject * multi = sql_list_get (data->stmts, i); + + g_object_get (multi, "stmts", &list, NULL); + + for (j = 0; j < sql_list_length (list); j++) + { + if (j > 0) + db_request_fetch_non_select (request, &err); + + if (G_OBJECT_TYPE (sql_list_get (list, j)) == SQL_TYPE_MULTI_STMT) + db_model_process_insert (obj, request, op->row, err); + } + + iter.stamp = priv->stamp; + iter.data = op->row; + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + } + + i++; + } + + if (!err) + { + while ((op = g_queue_pop_head (data->operations))) + db_model_free_operation (obj, op); + + g_signal_emit (obj, db_model_signal[OPERATIONS_DONE], 0); + } + + g_object_unref (request); +} + +static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) +{ + db_model_refresh (obj); +} + +static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj) +{ + db_model_refresh (obj); +} + static void db_model_on_join_query_done (DbRequest * request, JoinData * join_data) { gint i, j; @@ -461,135 +615,7 @@ static void db_model_on_join_query_done (DbRequest * request, JoinData * join_da g_object_unref (request); } -static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) -{ - db_model_refresh (obj); -} - -static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj) -{ - db_model_refresh (obj); -} - -static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * row, GError * err) -{ - gint i, j; - DbModelPrivate * priv = obj->priv; - DbResult * result; - DbRow * req_row; - DbIter iter; - - result = db_request_fetch_result (request, &err); - - if (result && result->data && result->nrows > 0) - { - iter.stamp = priv->stamp; - iter.data = row; - req_row = g_ptr_array_index (result->data, 0); - - for (i = 0; i < result->ncols; i++) - for (j = 0; j < priv->result->ncols; j++) - if (!g_strcmp0 (priv->column[j].name, result->column[i].name) - && !g_strcmp0 (priv->column[j].table, result->column[i].table)) - { - GValue * v; - gboolean emit = TRUE; - - priv->updated_value = g_new0 (GValue, 1); - - if ((v = &req_row->value[i]) && G_IS_VALUE (v) - && !gvn_value_is_null (DB_ROW_FIELD (req_row, i)) - && gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (priv->updated_value, G_VALUE_TYPE (v)); - gvn_value_copy (v, priv->updated_value); - } - else if (gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (priv->updated_value, GVN_TYPE_NULL); - } - else - { - emit = FALSE; - g_free (priv->updated_value); - } - - if (emit) - { - priv->updated_col = j; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); - } - } - } - - if (result) - db_result_free (result); -} - -static void db_model_on_operations_done (DbRequest * request, DbModelRequest * data) -{ - guint i = 0; - DbOperation * op; - GError * err = NULL; - DbModel * obj = data->obj; - DbModelPrivate * priv = obj->priv; - - priv->pending_request = - g_slist_remove (priv->pending_request, request); - - while ((op = g_queue_pop_head (data->operations)) - && db_request_fetch_non_select (request, &err) != -1) - { - DbRow * row = op->row; - db_request_fetch_non_select (request, &err); - - g_hash_table_remove (priv->row_ops, row); - - if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE - { - g_signal_emit (obj, - db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (row)); - } - else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT - { - db_model_process_insert (obj, request, row, err); - } - else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT - { - guint j; - SqlList * list; - SqlObject * multi = sql_list_get (data->stmts, i); - - g_object_get (multi, "stmts", &list, NULL); - - for (j = 0; j < sql_list_length (list); j++) - if (G_OBJECT_TYPE (sql_list_get (list, j)) == SQL_TYPE_MULTI_STMT) - db_model_process_insert (obj, request, row, err); - } - - db_model_free_operation (obj, op); - i++; - } - - //XXX Iterate both the result list and the queue at the same time - // when the Request has its Results set on errors(future?). - // Currently, if something fails in the plugin's code, it returns NULL - - if (err) - { - while ((op = g_queue_pop_head (data->operations))) - { - op->locked = FALSE; - g_queue_push_tail (priv->operation, op); - } - } - else - g_signal_emit (obj, db_model_signal[OPERATIONS_DONE], 0); - - g_object_unref (request); -} - -// Private helper methods and functions +// Private helper methods and functions static void join_data_free (JoinData * join_data) { @@ -598,18 +624,6 @@ static void join_data_free (JoinData * join_data) g_free (join_data); } -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; -} - static void db_model_free_operation (DbModel * obj, DbOperation * op) { if (op->updated) @@ -633,6 +647,14 @@ static void db_model_request_free (DbModelRequest * req) { if (req) { + DbOperation * op; + + while ((op = g_queue_pop_head (req->operations))) + { + op->locked = FALSE; + g_queue_push_tail (req->obj->priv->operation, op); + } + g_queue_free (req->operations); g_object_unref (req->obj); g_object_unref (req->stmts); @@ -710,6 +732,10 @@ void db_model_reverse_operations (DbModel * obj) while ((op = g_queue_pop_tail (priv->operation))) { + DbIter iter; + iter.data = op->row; + iter.stamp = priv->stamp; + g_hash_table_remove (priv->row_ops, op->row); if (op->type & DB_MODEL_ROW_OP_DELETE) @@ -720,13 +746,7 @@ void db_model_reverse_operations (DbModel * obj) db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); } else - { - DbIter iter; - iter.data = op->row; - iter.stamp = priv->stamp; - g_signal_emit (obj, db_model_signal[LINE_TOGGLED], 0, &iter); - } } else if (op->type & DB_MODEL_ROW_OP_INSERT) { @@ -736,14 +756,10 @@ void db_model_reverse_operations (DbModel * obj) else if (op->type & DB_MODEL_ROW_OP_UPDATE) { GSList * n; - DbUpdatedField * u; for (n = op->updated; n; n = n->next) { - DbIter iter; - iter.stamp = priv->stamp; - iter.data = op->row; - u = n->data; + DbUpdatedField * u = n->data; priv->updated_value = g_new0 (GValue, 1); g_value_init (priv->updated_value, G_VALUE_TYPE (u->value)); @@ -1211,15 +1227,15 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) select = sql_select_new (); - sql_object_add_child (select, "targets", sql_table_new (other_field->table)); + sql_object_add_child (select, "targets", sql_table_new (other_field->table, NULL)); where = sql_operation_new (SQL_OPERATION_TYPE_AND); for (i = 0; i < priv->result->ncols; i++) if (!g_strcmp0 (priv->column[i].table, other_field->table)) { - sql_object_add_child (select, "exprs", - sql_field_new_with_table (priv->column[i].name, other_field->table, NULL)); + sql_object_add_child (select, "fields", + sql_field_new_with_target (priv->column[i].name, other_field->table, NULL)); } else if (!g_strcmp0 (priv->column[i].table, main_field->table)) { @@ -1230,7 +1246,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) SqlObject * equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); sql_object_add_child (equal, "operators", - sql_field_new_with_table (g_ptr_array_index (other_field->name, j) + sql_field_new_with_target (g_ptr_array_index (other_field->name, j) ,other_field->table, NULL)); sql_object_add_child (equal, "operators", @@ -1299,62 +1315,6 @@ static void db_model_clear (DbModel * obj) } } -// Memory allocate functions - -static void param_def_free (ParamDef * def) -{ - g_object_unref (def->param); - - if (def->equal_op) - { - SqlObject * operators = - sql_object_get (def->obj->priv->link_op, "operators"); - sql_list_remove_item (SQL_LIST (operators), def->equal_op); - } - - g_free (def); -} - -static void db_model_alloc_updatable_data (DbModel * obj) -{ - DbModelPrivate * priv = obj->priv; - - priv->operation = g_queue_new (); - priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); - priv->defaults = g_hash_table_new_full ( - g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) param_def_free - ); - priv->column_default = g_hash_table_new_full ( - g_str_hash, - g_str_equal, - g_free, - g_free - ); -} - -static void db_model_alloc_link_data (DbModel * obj) -{ - DbModelPrivate * priv = obj->priv; - - if (!priv->internal_batch) - { - SqlList * operators; - - priv->internal_batch = g_object_ref_sink (sql_batch_new ()); - g_signal_connect (priv->internal_batch, "changed", - G_CALLBACK (db_model_on_batch_changed), obj); - - priv->link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); - sql_batch_add (priv->internal_batch, "link", priv->link_op); - - operators = sql_list_new (SQL_TYPE_EXPR); - sql_operation_set_operands (SQL_OPERATION (priv->link_op), operators); - } -} - //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public // Set&Get methods @@ -1437,7 +1397,7 @@ const gchar * db_model_get_column_name (DbModel * obj, gint col) && 0 <= col && col < obj->priv->result->ncols) && obj->priv->column) - return obj->priv->column[col].display; + return obj->priv->column[col].alias; return NULL; } @@ -1673,38 +1633,48 @@ void db_model_set_batch (DbModel * obj, SqlBatch * batch) /** * db_model_set_default_value_from_column: * @obj: a #DbModel - * @field: the field to be set - * @column: field from wich the value is picked + * @field_str: the field to be set + * @column_str: field from wich the value is picked **/ void db_model_set_default_value_from_column (DbModel * obj, - const gchar * field, const gchar * column) + const gchar * field_str, const gchar * column_str) { - g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (field); - g_return_if_fail (column); + Field * field; + ColumnDef * column_def; - g_hash_table_insert (obj->priv->column_default, g_strdup (field), g_strdup (column)); - g_hash_table_remove (obj->priv->defaults, field); + g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (field_str); + g_return_if_fail (column_str); + + field = field_new_from_string (field_str); + + column_def = column_def_new (FIELD_DEF, field_new_from_string (column_str)); + g_hash_table_insert (obj->priv->column_defaults, field, column_def); } /** * db_model_set_default_value_from_param: * @obj: a #DbModel - * @field: the field to be set + * @field_str: the field to be set * @param: a #GvnParam * @link: * * Get the default value for @dst_field from @param. **/ void db_model_set_default_value_from_param (DbModel * obj, - const gchar * field, GvnParam * param, gboolean link) + const gchar * field_str, GvnParam * param, gboolean link) { + Field * field; + ParamDef * param_def; + ColumnDef * column_def; SqlObject * equal = NULL; g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (field); + g_return_if_fail (field_str); g_return_if_fail (GVN_IS_PARAM (param)); + field = field_new_from_string (field_str); + if (link) { SqlList * operands, * link_operands; @@ -1717,18 +1687,18 @@ void db_model_set_default_value_from_param (DbModel * obj, sql_list_add (link_operands, equal); operands = sql_list_new (SQL_TYPE_EXPR); - sql_list_add (operands, sql_field_new (field)); + sql_list_add (operands, sql_field_new_with_target (field->name, field->target, field->schema)); sql_list_add (operands, sql_value_new_with_param (param)); sql_operation_set_operands (SQL_OPERATION (equal), operands); } - ParamDef * def = g_new (ParamDef, 1); - def->param = g_object_ref (param); - def->link = link; - def->equal_op = equal; - def->obj = obj; - g_hash_table_insert (obj->priv->defaults, g_strdup (field), def); - g_hash_table_remove (obj->priv->column_default, field); + param_def = g_new (ParamDef, 1); + param_def->param = g_object_ref (param); + param_def->equal_op = equal; + param_def->link_op = obj->priv->link_op; + + column_def = column_def_new (PARAM_DEF, param_def); + g_hash_table_insert (obj->priv->column_defaults, field, column_def); } /** @@ -1765,7 +1735,11 @@ void db_model_request_main_table (DbModel * obj, const gchar * table) const gchar * db_model_get_main_table (DbModel * obj) { g_return_val_if_fail (DB_IS_MODEL (obj), NULL); - return obj->priv->main_table; + + if (obj->priv->main_table) + return obj->priv->main_table->name; + + return NULL; } /** @@ -2096,17 +2070,31 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter) for (i = 0; i < row->len; i++) { + Field field; + ColumnDef * column_def; const GValue * def_value = NULL; - ParamDef * def = g_hash_table_lookup (priv->defaults, priv->column[i].display); + DbColumn col = priv->column[i]; - if (def) - def_value = gvn_param_get_value (def->param); + field.name = col.name; + field.target = col.table; + field.schema = col.schema; + + column_def = g_hash_table_lookup (priv->column_defaults, &field); + + if (column_def && column_def->type == PARAM_DEF) + { + ParamDef * param_def = column_def->def; + def_value = gvn_param_get_value (param_def->param); + } if (!def_value) - def_value = gvn_param_spec_get_default (priv->column[i].spec); + def_value = gvn_param_spec_get_default (col.spec); if (def_value && G_VALUE_TYPE (def_value) != SQL_TYPE_FUNCTION) - gvn_value_copy (def_value, &row->value[i]); + { + g_value_init (&row->value[i], G_VALUE_TYPE (def_value)); + g_value_copy (def_value, &row->value[i]); + } else g_value_init (&row->value[i], GVN_TYPE_NULL); } @@ -2327,9 +2315,8 @@ gboolean db_model_has_pending_operations (DbModel * obj) } static SqlObject * db_model_create_where (DbModel * obj, - const gchar * table, DbOperation * operation, gboolean for_insert) + Table * table, DbOperation * operation, gboolean for_insert) { - gint i; GSList * l; DbUpdatedField * u; GValue * g_value; @@ -2344,34 +2331,37 @@ static SqlObject * db_model_create_where (DbModel * obj, and_operands = sql_list_new (SQL_TYPE_EXPR); sql_operation_set_operands (SQL_OPERATION (where), and_operands); - for (i = 0; i < row->len; i++) - if ((priv->column[i].info & DB_COLUMN_PRI_KEY) - && !g_strcmp0 (priv->column[i].table, table)) + TableData * table_data = g_hash_table_lookup (priv->tables, table); + + for (l = table_data->pkeys; l; l = l->next) { SqlObject * equal; SqlList * operands; + gint col = GPOINTER_TO_INT (l->data); value = NULL; - g_value = &row->value[i]; + g_value = &row->value[col]; for (l = operation->updated; l && (u = l->data); l = l->next) - if (u->column == i) + if (u->column == col) { g_value = u->value; break; } - if (gvn_value_is_null (g_value) && for_insert) + if (!gvn_value_is_null (g_value)) { - const GValue * def = gvn_param_spec_get_default (priv->column[i].spec); + value = sql_value_new_with_value (g_value); + } + else if (for_insert) + { + const GValue * def = gvn_param_spec_get_default (priv->column[col].spec); if (def && G_IS_VALUE (def) && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION) value = g_value_get_object (def); } - else - value = sql_value_new_with_value (g_value); if (!value) { @@ -2383,7 +2373,7 @@ static SqlObject * db_model_create_where (DbModel * obj, sql_list_add (and_operands, equal); operands = sql_list_new (SQL_TYPE_EXPR); - sql_list_add (operands, sql_field_new (priv->column[i].name)); + sql_list_add (operands, sql_field_new (priv->column[col].name)); sql_list_add (operands, value); sql_operation_set_operands (SQL_OPERATION (equal), operands); } @@ -2392,20 +2382,20 @@ static SqlObject * db_model_create_where (DbModel * obj, } static SqlObject * db_model_create_insert (DbModel * obj, - const gchar * table, DbOperation * operation) + Table * table, DbOperation * operation) { gint i; DbModelPrivate * priv = obj->priv; DbRow * row = operation->row; - GValue * value; - SqlList * targets, * stmts, * sets, * fields, * values, * exprs; + const GValue * value; + SqlList * targets, * stmts, * sets, * fields, * values, * select_fields; SqlObject * target, * insert, * set, * select; SqlObject * where = db_model_create_where (obj, table, operation, TRUE); if (!where) return NULL; - target = sql_table_new (table); + target = sql_table_new (table->name, table->schema); fields = sql_list_new (SQL_TYPE_FIELD); @@ -2424,42 +2414,60 @@ static SqlObject * db_model_create_insert (DbModel * obj, ,NULL ); - exprs = sql_list_new (SQL_TYPE_EXPR); + select_fields = sql_list_new (SQL_TYPE_EXPR); targets = sql_list_new (SQL_TYPE_TARGET); sql_list_add (targets, target); select = g_object_new (SQL_TYPE_SELECT - ,"exprs", exprs + ,"fields", select_fields ,"targets", targets ,"where", where ,NULL ); + + GHashTableIter iter; + ColumnDef * column_def; + Field * field; + + g_hash_table_iter_init (&iter, priv->column_defaults); + + while (g_hash_table_iter_next (&iter, (gpointer) &field, (gpointer) &column_def)) + if (!g_strcmp0 (field->target, table->name) + && !g_strcmp0 (field->schema, table->schema)) + { + switch (column_def->type) + { + case PARAM_DEF: + { + ParamDef * param_def = column_def->def; + value = gvn_param_get_value (param_def->param); + break; + } + case FIELD_DEF: + value = NULL; // FIXME + break; + } + + if (value) + { + sql_list_add (fields, sql_field_new (field->name)); + sql_list_add (values, sql_value_new_with_value (value)); + } + } for (i = 0; i < row->len; i++) - if (!g_strcmp0 (priv->column[i].table, table)) + if (table_has_column (table, &priv->column[i])) { - if (gvn_value_is_null (&row->value[i])) - { - gchar * column_def = g_hash_table_lookup (priv->column_default, - priv->column[i].display); - gint col = db_model_get_column_index (obj, column_def); - - if (col != -1) - value = &row->value[col]; - else - value = NULL; - } - else - value = &row->value[i]; + value = &row->value[i]; - if (value) + if (!gvn_value_is_null (value)) { sql_list_add (fields, sql_field_new (priv->column[i].name)); sql_list_add (values, sql_value_new_with_value (value)); } - sql_list_add (exprs, sql_field_new (priv->column[i].name)); + sql_list_add (select_fields, sql_field_new (priv->column[i].name)); } stmts = sql_list_new (SQL_TYPE_STMT); @@ -2482,14 +2490,14 @@ static SqlObject * db_model_create_insert (DbModel * obj, **/ void db_model_perform_operations (DbModel * obj, gboolean retry) { + GList * l; + DbOperation * op; DbModelPrivate * priv; - gboolean error = FALSE; DbRow * row; - DbOperation * op_elem; SqlObject * where; SqlList * stmts; DbRequest * request; - GQueue * req_ops; + gboolean error = FALSE; g_return_if_fail (DB_IS_MODEL (obj)); @@ -2504,80 +2512,83 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) if (!priv->operation->length) return; - - req_ops = g_queue_new (); - stmts = sql_list_new (SQL_TYPE_STMT); + + stmts = sql_list_new (SQL_TYPE_STMT); + g_object_ref_sink (stmts); - while (!error && (op_elem = g_queue_pop_head (priv->operation))) + l = g_queue_peek_head_link (priv->operation); + + for (; l && !error; l = l->next) { SqlObject * stmt = NULL; - op_elem->locked = TRUE; - row = op_elem->row; + op = l->data; + op->locked = TRUE; + row = op->row; - if (op_elem->type & DB_MODEL_ROW_OP_DELETE) // DELETE + if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE { - if (op_elem->type & DB_MODEL_ROW_OP_INSERT) + if (!(op->type & DB_MODEL_ROW_OP_INSERT)) { - db_model_free_operation (obj, op_elem); - op_elem = NULL; - g_signal_emit (obj, - db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (row)); - } - else if ((where = db_model_create_where (obj, priv->main_table, op_elem, FALSE))) - { - SqlList * targets = sql_list_new (SQL_TYPE_TARGET); - sql_list_add (targets, sql_table_new (priv->main_table)); + where = db_model_create_where (obj, priv->main_table, op, FALSE); - stmt = g_object_new (SQL_TYPE_DELETE - ,"where", where - ,"targets", targets - ,NULL - ); + if (where) + { + SqlList * targets = sql_list_new (SQL_TYPE_TARGET); + sql_list_add (targets, sql_table_new ( + priv->main_table->name, + priv->main_table->schema + )); + + stmt = g_object_new (SQL_TYPE_DELETE + ,"where", where + ,"targets", targets + ,NULL + ); + } + else + error = TRUE; } - else - error = TRUE; } - else if (op_elem->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT + else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { - stmt = db_model_create_insert (obj, priv->main_table, op_elem); + stmt = db_model_create_insert (obj, priv->main_table, op); if (!stmt) error = TRUE; } - else if (op_elem->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT + else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT { - GSList * l; + Table * table; GHashTableIter iter; - gpointer table; SqlList * update_list; - - GHashTable * tables = g_hash_table_new ( - g_str_hash, g_str_equal); - - for (l = op_elem->updated; l; l = l->next) - { - DbUpdatedField * u = l->data; - g_hash_table_add (tables, priv->column[u->column].table); - } - + update_list = sql_list_new (SQL_TYPE_STMT); - g_hash_table_iter_init (&iter, tables); + g_hash_table_iter_init (&iter, priv->tables); - while (g_hash_table_iter_next (&iter, &table, NULL)) + while (g_hash_table_iter_next (&iter, (gpointer) &table, NULL)) { - where = db_model_create_where (obj, priv->main_table, op_elem, FALSE); + GSList * l; + DbUpdatedField * u; + GSList * fields = NULL; + + for (l = op->updated; l && (u = l->data); l = l->next) + if (table_has_column (table, &priv->column[u->column])) + fields = g_slist_prepend (fields, u); + + if (!fields) + continue; + + where = db_model_create_where (obj, table, op, FALSE); if (where) { - DbUpdatedField * u; SqlList * sets = sql_list_new (SQL_TYPE_UPDATE_SET); SqlList * targets = sql_list_new (SQL_TYPE_TARGET); - sql_list_add (targets, sql_table_new (table)); + sql_list_add (targets, sql_table_new (table->name, table->schema)); - for (l = op_elem->updated; l && (u = l->data); l = l->next) - if (!g_strcmp0 (priv->column[u->column].table, table)) + for (l = fields; l && (u = l->data); l = l->next) { GValue * new_value = DB_ROW_FIELD (row, u->column); @@ -2597,30 +2608,33 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else { - SqlObject * insert = db_model_create_insert (obj, table, op_elem); + SqlObject * insert = db_model_create_insert (obj, table, op); if (insert) sql_list_add (update_list, insert); } + + g_slist_free (fields); } - - g_hash_table_destroy (tables); + stmt = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", update_list, NULL); } if (stmt) sql_list_add (stmts, stmt); - if (op_elem) - g_queue_push_tail (req_ops, op_elem); } - if (sql_list_length (stmts) > 0) + if (sql_list_length (stmts) > 0 && !error) { SqlObject * multi = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); + GQueue * ops = g_queue_new (); + + while ((op = g_queue_pop_head (priv->operation))) + g_queue_push_tail (ops, op); DbModelRequest * data = g_new (DbModelRequest, 1); data->obj = g_object_ref (obj); - data->operations = req_ops; + data->operations = ops; data->stmts = g_object_ref_sink (stmts); request = db_conn_query_with_stmt_async (priv->conn @@ -2633,11 +2647,9 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) db_model_add_pending_request (obj, request); } else - { - g_queue_free (req_ops); - g_object_unref (g_object_ref_sink (stmts)); - db_model_clean_operations (obj); - } + g_warning ("DbModel: Error performing operations"); + + g_object_unref (stmts); } /** @@ -2649,34 +2661,38 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) void db_model_refresh (DbModel * obj) { DbModelPrivate * priv; + gboolean is_ready = FALSE; g_return_if_fail (DB_IS_MODEL (obj)); priv = obj->priv; db_model_clear (obj); - if (priv->conn - && priv->stmt && sql_object_is_ready (SQL_OBJECT (priv->stmt)) - && (!priv->batch || sql_batch_is_ready (priv->batch)) - && (!priv->internal_batch || sql_batch_is_ready (priv->internal_batch))) + if (priv->conn && priv->stmt) { SqlBatch * tmp_batch = sql_batch_new (); + sql_object_get_holders (SQL_OBJECT (priv->stmt), tmp_batch); sql_batch_merge (tmp_batch, priv->batch); - sql_batch_merge (tmp_batch, priv->internal_batch); - - db_model_set_status (obj, DB_MODEL_STATUS_LOADING); + sql_batch_merge (tmp_batch, priv->internal_batch); + + if (sql_batch_is_ready (tmp_batch)) + { + is_ready = TRUE; + db_model_set_status (obj, DB_MODEL_STATUS_LOADING); - priv->request = db_conn_query_with_stmt_async (priv->conn - ,priv->stmt - ,tmp_batch - ,(DbRequestDoneCallback) db_model_on_data_ready - ,g_object_ref (obj) - ,(GDestroyNotify) g_object_unref - ); + priv->request = db_conn_query_with_stmt_async (priv->conn + ,priv->stmt + ,tmp_batch + ,(DbRequestDoneCallback) db_model_on_data_ready + ,g_object_ref (obj) + ,(GDestroyNotify) g_object_unref + ); - g_object_unref (g_object_ref_sink (tmp_batch)); + g_object_unref (g_object_ref_sink (tmp_batch)); + } } - else + + if (!is_ready) db_model_set_status (obj, DB_MODEL_STATUS_CLEAN); } @@ -2991,7 +3007,7 @@ static void db_model_get_property (DbModel * obj, guint property_id, g_value_set_boolean (value, obj->priv->use_file); break; case PROP_MAIN_TABLE: - g_value_set_string (value, obj->priv->main_table); + g_value_set_string (value, db_model_get_main_table (obj)); break; case PROP_UPDATE_FLAGS: g_value_set_flags (value, obj->priv->update_flags); @@ -3014,8 +3030,6 @@ static void db_model_init (DbModel *obj) priv->stmt = NULL; priv->use_file = FALSE; priv->sql = NULL; - priv->update_flags = 0; - priv->user_update_flags = DB_MODEL_ALL; priv->request = NULL; priv->status = DB_MODEL_STATUS_CLEAN; priv->mode = DB_MODEL_MODE_ON_CHANGE; @@ -3023,22 +3037,12 @@ static void db_model_init (DbModel *obj) priv->result_pos = 0; priv->data = NULL; priv->column = NULL; - priv->column_index = NULL; - - priv->link_op = NULL; - priv->internal_batch = NULL; - - priv->main_table = NULL; - priv->user_main_table = NULL; - priv->defaults = NULL; - priv->column_default = NULL; - priv->operation = NULL; - priv->row_ops = NULL; - priv->join = NULL; - priv->pending_request = NULL; - - // TODO: Call this method only when is necessary - db_model_alloc_updatable_data (obj); + priv->column_index = g_hash_table_new_full ( + g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + NULL + ); priv->stamp = g_random_int (); @@ -3047,6 +3051,21 @@ static void db_model_init (DbModel *obj) priv->default_sort_data = NULL; priv->default_sort_func = NULL; priv->default_sort_destroy = NULL; + + priv->link_op = NULL; + priv->internal_batch = NULL; + + priv->updatable_data_allocated = FALSE; + priv->update_flags = 0; + priv->user_update_flags = DB_MODEL_ALL; + priv->main_table = NULL; + priv->user_main_table = NULL; + priv->column_defaults = NULL; + priv->operation = NULL; + priv->row_ops = NULL; + priv->join = NULL; + priv->pending_request = NULL; + priv->tables = NULL; } static void db_model_finalize (DbModel * obj) @@ -3058,25 +3077,22 @@ static void db_model_finalize (DbModel * obj) g_clear_object (&priv->conn); g_clear_object (&priv->stmt); - - if (priv->join) - g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); - - g_hash_table_destroy (priv->row_ops); - g_queue_free (priv->operation); - g_free (priv->sql); - g_free (priv->main_table); - g_free (priv->user_main_table); - - if (priv->column_index) - g_hash_table_destroy (priv->column_index); - + g_hash_table_destroy (priv->column_index); db_model_set_batch (obj, NULL); + g_clear_object (&priv->link_op); g_clear_object (&priv->internal_batch); - g_hash_table_destroy (priv->defaults); - g_hash_table_destroy (priv->column_default); + + if (priv->updatable_data_allocated) + { + g_free (priv->user_main_table); + g_hash_table_destroy (priv->column_defaults); + g_queue_free (priv->operation); + g_hash_table_destroy (priv->row_ops); + g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); + db_model_free_stmt_data (obj); + } parent->finalize (G_OBJECT (obj)); } diff --git a/db/db-result.c b/db/db-result.c index 68ff801..2e89d9d 100644 --- a/db/db-result.c +++ b/db/db-result.c @@ -73,7 +73,7 @@ DbResult * db_result_copy (const DbResult * obj) result->column[n].spec = gvn_param_spec_copy (obj->column[n].spec); result->column[n].table = g_strdup (obj->column[n].table); result->column[n].name = g_strdup (obj->column[n].name); - result->column[n].display = g_strdup (obj->column[n].display); + result->column[n].alias = g_strdup (obj->column[n].alias); } for (n = 0; n < obj->nrows; n++) @@ -105,7 +105,7 @@ void db_result_free (DbResult * obj) DbColumn col = obj->column[i]; gvn_param_spec_free (col.spec); g_free (col.name); - g_free (col.display); + g_free (col.alias); g_free (col.table); } diff --git a/db/db-result.h b/db/db-result.h index 1bf95e8..6c9be48 100644 --- a/db/db-result.h +++ b/db/db-result.h @@ -71,10 +71,11 @@ struct _DbColumn { DbColumnInfo info; GvnParamSpec * spec; + gchar * schema; gchar * table; gchar * table_alias; gchar * name; - gchar * display; + gchar * alias; }; GType db_result_get_type (); diff --git a/plugin/mysql/db-mysql.c b/plugin/mysql/db-mysql.c index 37be7ff..86bed77 100644 --- a/plugin/mysql/db-mysql.c +++ b/plugin/mysql/db-mysql.c @@ -226,7 +226,7 @@ static DbResultSet * db_mysql_query (DbMysql * obj, const gchar * sql, GError ** column = &result->column[i]; column->info = 0; column->name = g_strdup (field[i].org_name); - column->display = g_strdup (field[i].name); + column->alias = g_strdup (field[i].name); column->table = g_strdup (field[i].org_table); column->table_alias = g_strdup (field[i].table); diff --git a/plugin/pg/db-pg.c b/plugin/pg/db-pg.c index c704fd0..c05d82e 100644 --- a/plugin/pg/db-pg.c +++ b/plugin/pg/db-pg.c @@ -647,7 +647,7 @@ static DbResultSet * __db_pg_query else r->column[j].name = fname; - r->column[j].display = g_strdup (r->column[j].name); + r->column[j].alias = g_strdup (r->column[j].name); r->column[j].table = g_strdup (""); r->column[j].spec = gvn_param_spec_new_with_attrs (((GType*) g_ptr_array_index (types, ind))[j] @@ -676,7 +676,7 @@ static DbResultSet * __db_pg_query fdisp = g_ptr_array_index (name_array, j); r->column[j].name = g_strdup (fname); - r->column[j].display = g_strdup (fdisp); + r->column[j].alias = g_strdup (fdisp); // Getting the default value from res_col //FIXME use the parser if (!PQgetisnull (res_col, ctup, 3)) diff --git a/sql/parser/gram.y b/sql/parser/gram.y index 75a367b..c44b0e1 100644 --- a/sql/parser/gram.y +++ b/sql/parser/gram.y @@ -386,7 +386,7 @@ join(A) ::= target(left) join_type(type) target(right) join_cond(condition). SQL_TABLE (right)->schema : NULL; sql_list_add (equal, - sql_field_new_with_table (SQL_FIELD (n->data)->name, target, schema)); + sql_field_new_with_target (SQL_FIELD (n->data)->name, target, schema)); sql_list_add (exprs, op); } diff --git a/sql/parser/scan.rl b/sql/parser/scan.rl index 8b96bc1..6f16392 100644 --- a/sql/parser/scan.rl +++ b/sql/parser/scan.rl @@ -261,3 +261,45 @@ SqlObject * sql_parser_parse (gchar * sql) return object; } + +SqlField * sql_parser_parse_field (const gchar * field_str) +{ + gchar ** split; + SqlObject * field = NULL; + + if (!field_str || !g_strcmp0 (field_str, "")) + return NULL; + + split = g_strsplit (field_str, ".", 0); + + switch (g_strv_length (split)) + { + case 3: + { + field = sql_field_new_with_target + (g_strstrip (g_strdelimit (split[2], "`\"", ' ')) + ,g_strstrip (g_strdelimit (split[1], "`\"", ' ')) + ,g_strstrip (g_strdelimit (split[0], "`\"", ' '))); + break; + } + case 2: + { + field = sql_field_new_with_target + (g_strstrip (g_strdelimit (split[1], "`\"", ' ')) + ,g_strstrip (g_strdelimit (split[0], "`\"", ' ')) + ,NULL); + break; + } + case 1: + { + field = sql_field_new_with_target + (g_strstrip (g_strdelimit (split[0], "`\"", ' ')) + ,NULL + ,NULL); + break; + } + } + + g_strfreev (split); + return SQL_FIELD (field); +} diff --git a/sql/sql-batch.c b/sql/sql-batch.c index 91e2ac1..4436b2c 100644 --- a/sql/sql-batch.c +++ b/sql/sql-batch.c @@ -41,16 +41,16 @@ SqlBatch * sql_batch_new () //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_batch_child_changed (SqlObject * child, SqlBatch * obj) +static void sql_batch_item_changed (SqlObject * item, SqlBatch * obj) { sql_batch_changed (obj); } -static void sql_batch_free_child (SqlBatch * obj, SqlObject * child) +static void sql_batch_free_item (SqlBatch * obj, SqlObject * item) { - g_signal_handlers_disconnect_by_func (child, - sql_batch_child_changed, obj); - g_object_unref (child); + g_signal_handlers_disconnect_by_func (item, + sql_batch_item_changed, obj); + g_object_unref (item); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public @@ -65,22 +65,18 @@ static void sql_batch_free_child (SqlBatch * obj, SqlObject * child) **/ gboolean sql_batch_is_ready (SqlBatch * obj) { - gboolean is_ready = TRUE; + gpointer item; + GHashTableIter iter; g_return_val_if_fail (SQL_IS_BATCH (obj), FALSE); - if (obj->items) - { - GList * i; - GList * items = g_hash_table_get_values (obj->items); - - for (i = items; i && is_ready; i = i->next) - is_ready = sql_object_is_ready (i->data); - - g_list_free (items); - } + g_hash_table_iter_init (&iter, obj->items); - return is_ready; + while (g_hash_table_iter_next (&iter, NULL, &item)) + if (!item || !sql_object_is_ready (item)) + return FALSE; + + return TRUE; } /** @@ -107,29 +103,26 @@ SqlObject * sql_batch_get (SqlBatch * obj, const gchar * id) * sql_batch_add: * @obj: a #SqlBatch * @id: the id of the #SqlHolder - * @held_object: the held object + * @item: the #SqlObject * - * Adds a held object. + * Adds a new item to the batch. **/ -void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * object) +void sql_batch_add (SqlBatch * obj, const gchar * id, SqlObject * item) { g_return_if_fail (SQL_IS_BATCH (obj)); g_return_if_fail (id); + g_return_if_fail (SQL_IS_OBJECT (item) || !item); sql_batch_remove (obj, id); - if (!obj->items) - obj->items = g_hash_table_new_full ( - g_str_hash - ,g_str_equal - ,g_free - ,NULL - ); - - g_signal_connect (object, "changed", - G_CALLBACK (sql_batch_child_changed), obj); - g_hash_table_replace (obj->items, - g_strdup (id), g_object_ref_sink (object)); + if (item) + { + g_object_ref_sink (item); + g_signal_connect (item, "changed", + G_CALLBACK (sql_batch_item_changed), obj); + } + + g_hash_table_replace (obj->items, g_strdup (id), item); } /** @@ -143,10 +136,7 @@ void sql_batch_add_from_param (SqlBatch * obj, const gchar * id, GvnParam * para g_return_if_fail (id); g_return_if_fail (GVN_IS_PARAM (param)); - SqlObject * value = sql_value_new (); - sql_value_set_param (SQL_VALUE (value), param); - sql_batch_add (obj, id, value); - g_object_unref (value); + sql_batch_add (obj, id, sql_value_new_with_param (param)); } /** @@ -160,13 +150,8 @@ void sql_batch_add_from_value (SqlBatch * obj, const gchar * id, GType type, gpo g_return_if_fail (id); GValue gvalue = {0}; - SqlObject * value; - gvn_value_new_with_content (&gvalue, type, content); - value = sql_value_new (); - sql_value_set_value (SQL_VALUE (value), &gvalue); - sql_batch_add (obj, id, value); - g_object_unref (value); + sql_batch_add (obj, id, sql_value_new_with_value (&gvalue)); g_value_unset (&gvalue); } @@ -182,11 +167,11 @@ void sql_batch_remove (SqlBatch * obj, const gchar * id) g_return_val_if_fail (SQL_IS_BATCH (obj), NULL); g_return_val_if_fail (id, NULL); - SqlObject * child = sql_batch_get (obj, id); + SqlObject * item = sql_batch_get (obj, id); - if (child) + if (item) { - sql_batch_free_child (obj, child); + sql_batch_free_item (obj, item); g_hash_table_remove (obj->items, id); } } @@ -232,23 +217,25 @@ void sql_batch_changed (SqlBatch * obj) static void sql_batch_init (SqlBatch * obj) { - obj->items = NULL; + obj->items = g_hash_table_new_full ( + g_str_hash + ,g_str_equal + ,g_free + ,NULL + ); } static void sql_batch_finalize (SqlBatch * obj) { - if (obj->items) - { - GHashTableIter iter; - gpointer child; + gpointer item; + GHashTableIter iter; - g_hash_table_iter_init (&iter, obj->items); + g_hash_table_iter_init (&iter, obj->items); - while (g_hash_table_iter_next (&iter, NULL, &child)) - sql_batch_free_child (obj, child); - - g_hash_table_destroy (obj->items); - } + while (g_hash_table_iter_next (&iter, NULL, &item)) + sql_batch_free_item (obj, item); + + g_hash_table_destroy (obj->items); G_OBJECT_CLASS (sql_batch_parent_class)->finalize (G_OBJECT (obj)); } diff --git a/sql/sql-delete.c b/sql/sql-delete.c index 12521c0..a58e946 100644 --- a/sql/sql-delete.c +++ b/sql/sql-delete.c @@ -36,7 +36,7 @@ SqlObject * sql_delete_new () static void sql_delete_render (SqlDelete * obj, SqlRender * render) { sql_render_add_token (render, "DELETE"); - sql_render_add_list (render, TRUE, NULL, obj->tables, ","); + sql_render_add_list (render, FALSE, NULL, obj->tables, ","); if (SQL_DML (obj)->targets) { diff --git a/sql/sql-field.c b/sql/sql-field.c index f07b612..f7a05d0 100644 --- a/sql/sql-field.c +++ b/sql/sql-field.c @@ -52,7 +52,7 @@ SqlObject * sql_field_new (const gchar * name) * * Return value: an #SqlExpr */ -SqlObject * sql_field_new_with_table (const gchar * name, const gchar * target, const gchar * schema) +SqlObject * sql_field_new_with_target (const gchar * name, const gchar * target, const gchar * schema) { return g_object_new (SQL_TYPE_FIELD ,"name", name @@ -64,38 +64,102 @@ SqlObject * sql_field_new_with_table (const gchar * name, const gchar * target, //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_field_render (SqlField * obj, SqlRender * render) +static void sql_field_render (SqlField * self, SqlRender * render) { - if (obj->target) + if (self->target) { - if (obj->schema) + if (self->schema) { - sql_render_add_identifier (render, obj->schema); + sql_render_add_identifier (render, self->schema); sql_render_append (render, "."); } - sql_render_add_identifier (render, obj->target); + sql_render_add_identifier (render, self->target); sql_render_append (render, "."); } - if (!g_strcmp0 (obj->name, "*")) + if (!g_strcmp0 (self->name, "*")) { sql_render_add_espace (render); sql_render_append (render, "*"); } else - sql_render_add_identifier (render, obj->name); + sql_render_add_identifier (render, self->name); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public -void sql_field_set_name (SqlField * obj, const gchar * name) +/** + * sql_field_get_name: + * @self: the #SqlField + * + * Return value: the field name + **/ +const gchar * sql_field_get_name (SqlField * self) { - g_return_if_fail (SQL_IS_FIELD (obj)); + return self->name; +} + +/** + * sql_field_set_name: + * @self: the #SqlField + * @name: the field name + **/ +void sql_field_set_name (SqlField * self, const gchar * name) +{ + g_return_if_fail (SQL_IS_FIELD (self)); g_return_if_fail (name); - g_free (obj->name); - obj->name = g_strdup (name); + g_free (self->name); + self->name = g_strdup (name); +} + +/** + * sql_field_get_target: + * @self: the #SqlField + * + * Return value: the target name + **/ +const gchar * sql_field_get_target (SqlField * self) +{ + return self->target; +} + +/** + * sql_field_set_target: + * @self: the #SqlField + * @target: the target name + **/ +void sql_field_set_target (SqlField * self, const gchar * target) +{ + g_return_if_fail (SQL_IS_FIELD (self)); + + g_free (self->target); + self->target = g_strdup (target); +} + +/** + * sql_field_get_schema: + * @self: the #SqlField + * + * Return value: the schema name + **/ +const gchar * sql_field_get_schema (SqlField * self) +{ + return self->schema; +} + +/** + * sql_field_set_schema: + * @self: the #SqlField + * @schema: the schema name + **/ +void sql_field_set_schema (SqlField * self, const gchar * schema) +{ + g_return_if_fail (SQL_IS_FIELD (self)); + + g_free (self->schema); + self->schema = g_strdup (schema); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties @@ -107,61 +171,59 @@ enum ,PROP_SCHEMA }; -static void sql_field_set_property (SqlField * obj, guint id, +static void sql_field_set_property (SqlField * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_NAME: - sql_field_set_name (obj, g_value_get_string (value)); + sql_field_set_name (self, g_value_get_string (value)); break; case PROP_TARGET: - g_free (obj->target); - obj->target = g_value_dup_string (value); + sql_field_set_target (self, g_value_get_string (value)); break; case PROP_SCHEMA: - g_free (obj->schema); - obj->schema = g_value_dup_string (value); + sql_field_set_schema (self, g_value_get_string (value)); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_field_get_property (SqlField * obj, guint id, +static void sql_field_get_property (SqlField * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_NAME: - g_value_set_string (value, obj->name); + g_value_set_string (value, self->name); break; case PROP_TARGET: - g_value_set_string (value, obj->target); + g_value_set_string (value, self->target); break; case PROP_SCHEMA: - g_value_set_string (value, obj->schema); + g_value_set_string (value, self->schema); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_field_init (SqlField * obj) +static void sql_field_init (SqlField * self) { - obj->name = NULL; - obj->target = NULL; - obj->schema = NULL; + self->name = NULL; + self->target = NULL; + self->schema = NULL; } -static void sql_field_finalize (SqlField * obj) +static void sql_field_finalize (SqlField * self) { - g_free (obj->name); - g_free (obj->target); - g_free (obj->schema); - G_OBJECT_CLASS (sql_field_parent_class)->finalize (G_OBJECT (obj)); + g_free (self->name); + g_free (self->target); + g_free (self->schema); + G_OBJECT_CLASS (sql_field_parent_class)->finalize (G_OBJECT (self)); } static void sql_field_class_init (SqlFieldClass * klass) diff --git a/sql/sql-field.h b/sql/sql-field.h index c01723d..f21e85b 100644 --- a/sql/sql-field.h +++ b/sql/sql-field.h @@ -42,11 +42,17 @@ struct _SqlFieldClass SqlExprClass parent; }; -GType sql_field_get_type (); -SqlObject * sql_field_new (const gchar * name); -SqlObject * sql_field_new_with_table (const gchar * name - ,const gchar * target - ,const gchar * schema); -void sql_field_set_name (SqlField * obj, const gchar * name); +GType sql_field_get_type (); +SqlObject * sql_field_new (const gchar * name); +SqlObject * sql_field_new_with_target (const gchar * name + ,const gchar * target + ,const gchar * schema); + +const gchar * sql_field_get_name (SqlField * self); +void sql_field_set_name (SqlField * obj, const gchar * name); +const gchar * sql_field_get_target (SqlField * self); +void sql_field_set_target (SqlField * obj, const gchar * target); +const gchar * sql_field_get_schema (SqlField * self); +void sql_field_set_schema (SqlField * obj, const gchar * schema); #endif diff --git a/sql/sql-holder.c b/sql/sql-holder.c index 0fe13d8..36df2a5 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -41,9 +41,9 @@ static void sql_holder_render (SqlHolder * obj, SqlRender * render, SqlBatch * b sql_render_printf (render, "#%s", obj->id); } -static void sql_holder_find_holders (SqlHolder * obj, GQueue * holders) +static void sql_holder_find_holders (SqlHolder * obj, SqlBatch * batch) { - g_queue_push_tail (holders, obj->id); + sql_batch_add (batch, obj->id, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public diff --git a/sql/sql-insert.c b/sql/sql-insert.c index 1a6f7be..9675184 100644 --- a/sql/sql-insert.c +++ b/sql/sql-insert.c @@ -39,13 +39,14 @@ static void sql_insert_render (SqlInsert * obj, SqlRender * render) if (obj->table) { - if (obj->values) + if (obj->fields && sql_list_length (obj->fields) > 0) { sql_render_add_espace (render); sql_render_append (render, "("); sql_render_add_list (render, FALSE, NULL, obj->fields, ","); sql_render_append (render, ")"); sql_render_add_token (render, "VALUES"); + sql_render_add_espace (render); sql_render_add_list (render, FALSE, NULL, obj->values, ","); } else @@ -61,7 +62,7 @@ void sql_insert_set_table_from_name (SqlInsert * obj, const gchar * table) g_return_if_fail (table); sql_object_remove (obj, obj->table); - obj->table = sql_object_add (obj, sql_table_new (table)); + obj->table = sql_object_add (obj, sql_table_new (table, NULL)); } void sql_insert_add_expr (SqlInsert * obj, SqlExpr * expr) diff --git a/sql/sql-list.c b/sql/sql-list.c index 664e240..c935619 100644 --- a/sql/sql-list.c +++ b/sql/sql-list.c @@ -70,12 +70,12 @@ static gboolean sql_list_is_ready (SqlList * obj) return TRUE; } -static void sql_list_find_holders (SqlList * obj, GQueue * holders) +static void sql_list_find_holders (SqlList * obj, SqlBatch * batch) { GList * i; for (i = obj->items.head; i; i = i->next) - sql_object_get_holders (i->data, holders); + sql_object_get_holders (i->data, batch); } static void sql_list_item_changed (SqlObject * item, SqlObject * obj) diff --git a/sql/sql-object.c b/sql/sql-object.c index 9d8673c..9590887 100644 --- a/sql/sql-object.c +++ b/sql/sql-object.c @@ -41,7 +41,7 @@ static void sql_object_child_changed (SqlObject * child, SqlObject * obj) sql_object_changed (obj); } -static void sql_object_find_holders (SqlObject * obj, GQueue * holders) +static void sql_object_find_holders (SqlObject * obj, SqlBatch * batch) { guint i; guint nparams; @@ -52,8 +52,12 @@ static void sql_object_find_holders (SqlObject * obj, GQueue * holders) for (i = 0; i < nparams; i++) if (SQL_IS_PARAM_OBJECT (params[i]) || SQL_IS_PARAM_LIST (params[i])) { - SqlObject * child = sql_object_get (obj, params[i]->name); - sql_object_get_holders (child, holders); + SqlObject * child; + + g_object_get (obj, params[i]->name, &child, NULL); + + if (child) + sql_object_get_holders (child, batch); } g_free (params); @@ -131,17 +135,19 @@ gboolean sql_object_is_ready (SqlObject * obj) guint nparams; GParamSpec ** params; gboolean is_ready = TRUE; - SqlObjectClass * klass = SQL_OBJECT_GET_CLASS (obj); + SqlObjectClass * klass; g_return_val_if_fail (SQL_IS_OBJECT (obj), FALSE); - - params = g_object_class_list_properties (G_OBJECT_GET_CLASS (obj), &nparams); + + klass = SQL_OBJECT_GET_CLASS (obj); + params = g_object_class_list_properties (G_OBJECT_CLASS (klass), &nparams); for (i = 0; i < nparams && is_ready; i++) if (SQL_IS_PARAM_OBJECT (params[i]) || SQL_IS_PARAM_LIST (params[i])) { - SqlObject * child = sql_object_get (obj, params[i]->name); - is_ready = sql_object_is_ready (child); + SqlObject * child; + g_object_get (obj, params[i]->name, &child, NULL); + is_ready = !child || sql_object_is_ready (child); } g_free (params); @@ -199,12 +205,12 @@ void sql_object_remove_child (SqlObject * obj, const gchar * property, guint n) * * Gets all identifiers of the contained holders. **/ -void sql_object_get_holders (SqlObject * obj, GQueue * holders) +void sql_object_get_holders (SqlObject * obj, SqlBatch * batch) { - g_return_if_fail (SQL_IS_OBJECT (obj) || !obj); + g_return_if_fail (SQL_IS_OBJECT (obj)); + g_return_if_fail (SQL_IS_BATCH (batch)); - if (obj) - SQL_OBJECT_GET_CLASS (obj)->find_holders (obj, holders); + SQL_OBJECT_GET_CLASS (obj)->find_holders (obj, batch); } /** diff --git a/sql/sql-object.h b/sql/sql-object.h index 7016168..4d71bd4 100644 --- a/sql/sql-object.h +++ b/sql/sql-object.h @@ -32,7 +32,7 @@ typedef struct _SqlObject SqlObject; typedef struct _SqlObjectClass SqlObjectClass; typedef gboolean (* SqlObjectIsReadyFunc) (SqlObject * obj); -typedef void (* SqlObjectFindHoldersFunc) (SqlObject * obj, GQueue * holders); +typedef void (* SqlObjectFindHoldersFunc) (); // (SqlObject * obj, SqlBatch * holders); typedef void (* SqlRenderFunc) (); // (SqlObject * obj, SqlRender * render, SqlBatch * batch); struct _SqlObject @@ -55,7 +55,7 @@ struct _SqlObjectClass GType sql_object_get_type (); void sql_object_render (SqlObject * obj, SqlRender * render, SqlBatch * batch); gboolean sql_object_is_ready (SqlObject * obj); -void sql_object_get_holders (SqlObject * obj, GQueue * holders); +void sql_object_get_holders (SqlObject * obj, SqlBatch * batch); void sql_object_set (SqlObject * obj, const gchar * property, SqlObject * set); SqlObject * sql_object_get (SqlObject * obj, const gchar * property); diff --git a/sql/sql-parser.h b/sql/sql-parser.h index 9c68dd2..afccf3a 100644 --- a/sql/sql-parser.h +++ b/sql/sql-parser.h @@ -19,6 +19,7 @@ #define SQL_PARSER_H #include "sql-object.h" +#include "sql-field.h" #define SQL_PARSER_LOG_DOMAIN (g_quark_from_string ("SqlParser")) @@ -30,6 +31,8 @@ * * Return value: (transfer full): an #SqlObject. */ -SqlObject * sql_parser_parse (gchar * sql) G_GNUC_WARN_UNUSED_RESULT; +SqlObject * sql_parser_parse (gchar * sql) G_GNUC_WARN_UNUSED_RESULT; + +SqlField * sql_parser_parse_field (const gchar * field_str); #endif \ No newline at end of file diff --git a/sql/sql-render.c b/sql/sql-render.c index 604286e..0bfdedb 100644 --- a/sql/sql-render.c +++ b/sql/sql-render.c @@ -308,7 +308,7 @@ void sql_render_add_list (SqlRender * obj, gboolean required, const gchar * toke SqlList * list, const gchar * separator) { g_return_if_fail (SQL_IS_RENDER (obj)); - g_return_if_fail (SQL_IS_LIST (list)); + g_return_if_fail (SQL_IS_LIST (list) || !list); sql_render_add_list_with_func (obj, required, token, list, separator, NULL); } @@ -330,7 +330,7 @@ void sql_render_add_list_with_func (SqlRender * obj, gboolean required, const gc GList * i; g_return_if_fail (SQL_IS_RENDER (obj)); - g_return_if_fail (SQL_IS_LIST (list)); + g_return_if_fail (SQL_IS_LIST (list) || !list); if (list && (i = sql_list_get_items (list))) { diff --git a/sql/sql-set.c b/sql/sql-set.c index 486da18..3f2a8f7 100644 --- a/sql/sql-set.c +++ b/sql/sql-set.c @@ -33,11 +33,6 @@ SqlObject * sql_set_new () static void sql_set_render (SqlSet * obj, SqlRender * render) { -/* if (obj) - sql_render_add_object (render, obj); - else - sql_render_add_token (render, "DEFAULT"); -*/ sql_render_append (render, "("); sql_render_add_list (render, FALSE, NULL, obj->exprs, ","); sql_render_append (render, ")"); diff --git a/sql/sql-string.c b/sql/sql-string.c index 12a2b00..470f345 100644 --- a/sql/sql-string.c +++ b/sql/sql-string.c @@ -59,12 +59,12 @@ static void sql_string_render (SqlString * obj, SqlRender * render) sql_render_append (render, ptr); } -static void sql_string_find_holders (SqlString * obj, GQueue * holders) +static void sql_string_find_holders (SqlString * obj, SqlBatch * batch) { GSList * i; for (i = obj->holders; i; i = i->next) - sql_object_get_holders (((HolderData *) i->data)->holder, holders); + sql_object_get_holders (((HolderData *) i->data)->holder, batch); } static void sql_string_free_holder_data (HolderData * holder_data) diff --git a/sql/sql-table.c b/sql/sql-table.c index af81713..e03e223 100644 --- a/sql/sql-table.c +++ b/sql/sql-table.c @@ -26,9 +26,9 @@ **/ G_DEFINE_TYPE (SqlTable, sql_table, SQL_TYPE_TARGET); -SqlObject * sql_table_new (const gchar * name) +SqlObject * sql_table_new (const gchar * name, const gchar * schema) { - return g_object_new (SQL_TYPE_TABLE, "name", name, NULL); + return g_object_new (SQL_TYPE_TABLE, "name", name, "schema", schema, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private diff --git a/sql/sql-table.h b/sql/sql-table.h index 9544872..ed7f5b6 100644 --- a/sql/sql-table.h +++ b/sql/sql-table.h @@ -41,6 +41,6 @@ struct _SqlTableClass }; GType sql_table_get_type (); -SqlObject * sql_table_new (const gchar * name); +SqlObject * sql_table_new (const gchar * name, const gchar * schema); #endif From 0d57e4570f5b4f3c1bdc33489bbb4f15d5d6b4ba Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Thu, 29 May 2014 16:32:28 +0200 Subject: [PATCH 07/10] =?UTF-8?q?A=C3=B1adido=20fichero=20db/db-model-priv?= =?UTF-8?q?ate.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/db-model-private.c | 268 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 db/db-model-private.c diff --git a/db/db-model-private.c b/db/db-model-private.c new file mode 100644 index 0000000..c6e33af --- /dev/null +++ b/db/db-model-private.c @@ -0,0 +1,268 @@ +/* + * 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 . + */ + +/* + * 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; + +#define remove_delimiters(str) (g_strstrip (g_strdelimit (str, "`\"", ' '))) + +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); +} From a48f4923f49631d2c43eb88f98fd578ab1c80129 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Fri, 30 May 2014 11:19:53 +0200 Subject: [PATCH 08/10] Algunos bugs en DbModel solucionados. --- db/db-model-private.c | 2 +- db/db-model.c | 323 ++++++++++++++++++--------------------- module/src/vn-customer.c | 2 +- plugin/mysql/db-mysql.c | 1 + plugin/pg/db-pg.c | 1 + sql/parser/scan.rl | 42 ----- sql/sql-parser.h | 2 - 7 files changed, 156 insertions(+), 217 deletions(-) diff --git a/db/db-model-private.c b/db/db-model-private.c index c6e33af..5595d18 100644 --- a/db/db-model-private.c +++ b/db/db-model-private.c @@ -90,7 +90,7 @@ typedef struct } Field; -#define remove_delimiters(str) (g_strstrip (g_strdelimit (str, "`\"", ' '))) +#define remove_delimiters(str) (g_strdup (g_strstrip (g_strdelimit (str, "`\"", ' ')))) static void field_parse (Field * field, const gchar * string) { diff --git a/db/db-model.c b/db/db-model.c index 7ca5c6e..421e3fb 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -51,34 +51,15 @@ struct _DbModelPrivate SqlStmt * stmt; gchar * sql; gboolean use_file; - Table * main_table; - DbModelUpdateFlags update_flags; SqlBatch * batch; - GPtrArray * data; DbColumn * column; + GHashTable * column_index; DbResult * result; + guint result_pos; DbRequest * request; DbModelStatus status; DbModelMode mode; - gchar * user_main_table; - DbModelUpdateFlags user_update_flags; - guint result_pos; - GQueue * operation; - GHashTable * row_ops; - gint updated_col; - GValue * updated_value; - - GHashTable * column_index; - GSList * pending_request; - GSList * join; - - SqlObject * link_op; - SqlBatch * internal_batch; - GHashTable * column_defaults; - GHashTable * tables; - gboolean updatable_data_allocated; - gint stamp; gboolean fresh; @@ -92,6 +73,23 @@ struct _DbModelPrivate DbIterCompareFunc sort_func; gpointer sort_data; GDestroyNotify sort_destroy; + + SqlObject * link_op; + SqlBatch * internal_batch; + GHashTable * column_defaults; + + gboolean updatable_data_allocated; + DbModelUpdateFlags update_flags; + DbModelUpdateFlags user_update_flags; + Table * main_table; + gchar * user_main_table; + GHashTable * tables; + gint updated_col; + GQueue * operation; + GHashTable * row_ops; + GValue * updated_value; + GSList * pending_request; + GSList * join; }; // Helper structures and methods @@ -212,62 +210,6 @@ static void db_model_alloc_link_data (DbModel * obj) sql_operation_set_operands (SQL_OPERATION (priv->link_op), operators); } -static void db_model_free_stmt_data (DbModel * obj) -{ - if (obj->priv->tables) - g_hash_table_destroy (obj->priv->tables); -} - -static void db_model_alloc_stmt_data (DbModel * obj) -{ - gint i; - Table table; - TableData * table_data; - DbModelPrivate * priv = obj->priv; - - if (!priv->updatable_data_allocated) - return; - - db_model_free_stmt_data (obj); - - priv->tables = g_hash_table_new_full ( - (GHashFunc) table_hash, - (GEqualFunc) table_equal, - (GDestroyNotify) table_free, - (GDestroyNotify) table_data_free - ); - - for (i = 0; i < priv->result->ncols; i++) - if ((priv->column[i].info & DB_COLUMN_PRI_KEY)) - { - table.name = priv->column[i].table; - table.schema = priv->column[i].schema; - - table_data = g_hash_table_lookup (priv->tables, &table); - - if (!table_data) - { - table_data = g_new0 (TableData, 1); - table_data->pkeys = NULL; - g_hash_table_insert (priv->tables, table_copy (&table), table_data); - } - - table_data->pkeys = g_slist_prepend (table_data->pkeys, GINT_TO_POINTER (i)); - g_hash_table_insert (priv->tables, table_copy (&table), table_data); - } - - for (i = 0; i < priv->result->ncols; i++) - { - table.name = priv->column[i].table; - table.schema = priv->column[i].schema; - - table_data = g_hash_table_lookup (priv->tables, &table); - - if (table_data && table_data->pkeys) - gvn_param_spec_set_editable (priv->column[i].spec, TRUE); - } -} - // Signal Handlers enum @@ -323,9 +265,64 @@ static void db_model_calculate_update_flags (DbModel * obj) { gint i; Table table; + TableData * table_data; DbModelPrivate * priv = obj->priv; - priv->main_table = NULL; + // Allocates aditional memory when the model is updatable + + if (priv->user_update_flags && !priv->updatable_data_allocated) + { + priv->updatable_data_allocated = TRUE; + priv->operation = g_queue_new (); + priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->tables = g_hash_table_new_full ( + (GHashFunc) table_hash, + (GEqualFunc) table_equal, + (GDestroyNotify) table_free, + (GDestroyNotify) table_data_free + ); + } + + if (priv->user_update_flags && priv->fresh && priv->result) + { + g_hash_table_remove_all (priv->tables); + + for (i = 0; i < priv->result->ncols; i++) + if ((priv->column[i].info & DB_COLUMN_PRI_KEY)) + { + table.name = priv->column[i].table; + table.schema = priv->column[i].schema; + + table_data = g_hash_table_lookup (priv->tables, &table); + + if (!table_data) + { + table_data = g_new0 (TableData, 1); + table_data->pkeys = NULL; + g_hash_table_insert (priv->tables, table_copy (&table), table_data); + } + + table_data->pkeys = g_slist_prepend (table_data->pkeys, GINT_TO_POINTER (i)); + } + } + + if (priv->result) + { + for (i = 0; i < priv->result->ncols; i++) + { + table.name = priv->column[i].table; + table.schema = priv->column[i].schema; + + table_data = g_hash_table_lookup (priv->tables, &table); + + if (table_data && table_data->pkeys) + gvn_param_spec_set_editable (priv->column[i].spec, TRUE); + } + } + + // Searchs for the main table + + table.name = NULL; if (priv->result) { @@ -336,39 +333,29 @@ static void db_model_calculate_update_flags (DbModel * obj) { table.name = priv->column[i].table; table.schema = priv->column[i].schema; - priv->main_table = g_hash_table_lookup (priv->tables, &table); break; } } else - { table_parse (&table, priv->user_main_table); - priv->main_table = g_hash_table_lookup (priv->tables, &table); - - if (!priv->main_table) - g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, - "Can't set '%s' as main table", table.name); - } } + if (!table.name + || !g_hash_table_lookup_extended (priv->tables, &table, (gpointer) &priv->main_table, NULL)) + { + priv->main_table = NULL; + + if (priv->user_main_table) + g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, + "Can't set '%s' as main table", priv->user_main_table); + } + + // Sets the updatable flags + if (priv->main_table) priv->update_flags = DB_MODEL_ALL & priv->user_update_flags; else priv->update_flags = 0; - - if (!priv->updatable_data_allocated && priv->update_flags) - { - priv->updatable_data_allocated = TRUE; - priv->operation = g_queue_new (); - priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); - - priv->column_defaults = g_hash_table_new_full ( - (GHashFunc) field_hash, - (GEqualFunc) field_equal, - (GDestroyNotify) field_free, - (GDestroyNotify) column_def_free - ); - } } static void db_model_on_data_ready (DbRequest * request, DbModel * obj) @@ -388,8 +375,6 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) if ((r = db_request_fetch_result (request, NULL))) { - gint i; - priv->column = r->column; priv->data = r->data; @@ -404,9 +389,6 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) if (priv->fresh) { - db_model_calculate_update_flags (obj); - db_model_alloc_stmt_data (obj); - for (i = 0; i < priv->result->ncols; i++) g_hash_table_insert (priv->column_index, g_strdup (priv->column[i].alias), GINT_TO_POINTER (i)); @@ -417,6 +399,9 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) db_model_set_sort_column_id (obj, priv->old_sort_column_id, priv->old_order); + db_model_calculate_update_flags (obj); + priv->fresh = FALSE; + db_model_set_status (obj, DB_MODEL_STATUS_READY); } } @@ -445,32 +430,17 @@ static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * for (i = 0; i < result->ncols; i++) for (j = 0; j < priv->result->ncols; j++) if (!g_strcmp0 (priv->column[j].name, result->column[i].name) - && !g_strcmp0 (priv->column[j].table, result->column[i].table)) + && !g_strcmp0 (priv->column[j].table, result->column[i].table) + && !g_strcmp0 (priv->column[j].schema, result->column[i].schema)) { - GValue * v; - gboolean emit = TRUE; + GValue * new_value = &req_row->value[i]; - priv->updated_value = g_new0 (GValue, 1); - - if ((v = &req_row->value[i]) && G_IS_VALUE (v) - && !gvn_value_is_null (DB_ROW_FIELD (req_row, i)) - && gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (priv->updated_value, G_VALUE_TYPE (v)); - gvn_value_copy (v, priv->updated_value); - } - else if (gvn_value_is_null (DB_ROW_FIELD (row, j))) - { - g_value_init (priv->updated_value, GVN_TYPE_NULL); - } - else - { - emit = FALSE; - g_free (priv->updated_value); - } - - if (emit) + if (!gvn_value_compare (new_value, DB_ROW_FIELD (row, j))) { + priv->updated_value = g_new0 (GValue, 1); + g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); + g_value_copy (new_value, priv->updated_value); + priv->updated_col = j; g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); } @@ -485,13 +455,11 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d { GList * l; guint i = 0; + DbIter iter; DbOperation * op; GError * err = NULL; DbModel * obj = data->obj; DbModelPrivate * priv = obj->priv; - - priv->pending_request = - g_slist_remove (priv->pending_request, request); l = g_queue_peek_head_link (data->operations); @@ -507,7 +475,7 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d continue; } - if (db_request_fetch_non_select (request, &err) == -1) + if (!request || db_request_fetch_non_select (request, &err) == -1) break; g_hash_table_remove (priv->row_ops, op->row); @@ -525,7 +493,6 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d { guint j; SqlList * list; - DbIter iter; SqlObject * multi = sql_list_get (data->stmts, i); g_object_get (multi, "stmts", &list, NULL); @@ -538,7 +505,7 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d if (G_OBJECT_TYPE (sql_list_get (list, j)) == SQL_TYPE_MULTI_STMT) db_model_process_insert (obj, request, op->row, err); } - + iter.stamp = priv->stamp; iter.data = op->row; g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); @@ -547,6 +514,13 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d i++; } + if (request) + { + priv->pending_request = + g_slist_remove (priv->pending_request, request); + g_object_unref (request); + } + if (!err) { while ((op = g_queue_pop_head (data->operations))) @@ -554,12 +528,11 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d g_signal_emit (obj, db_model_signal[OPERATIONS_DONE], 0); } - - g_object_unref (request); } static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) { + obj->priv->fresh = TRUE; db_model_refresh (obj); } @@ -679,8 +652,6 @@ static void db_operation_add_updated (DbOperation * op, gint col) u->column = col; op->type |= DB_MODEL_ROW_OP_UPDATE; op->updated = g_slist_prepend (op->updated, u); - - return; } static gboolean db_model_set_row_operation (DbModel * obj, @@ -698,12 +669,7 @@ static gboolean db_model_set_row_operation (DbModel * obj, if (type & DB_MODEL_ROW_OP_UPDATE) db_operation_add_updated (new_op, col); -/* if (!db_operation_add_updated (new_op, col)) - { - g_free (new_op); - return FALSE; - } -*/ + g_hash_table_insert (obj->priv->row_ops, row, new_op); g_queue_push_tail (obj->priv->operation, new_op); } @@ -714,8 +680,6 @@ static gboolean db_model_set_row_operation (DbModel * obj, if (type & DB_MODEL_ROW_OP_UPDATE) db_operation_add_updated (op, col); -// if (!db_operation_add_updated (op, col)) -// return FALSE; } else return FALSE; @@ -1302,16 +1266,14 @@ static void db_model_clear (DbModel * obj) priv->result = NULL; priv->column = NULL; priv->data = NULL; - - g_free (priv->main_table); - priv->main_table = NULL; - priv->update_flags = 0; - priv->fresh = FALSE; priv->old_order = priv->order; priv->old_sort_column_id = priv->sort_column_id; priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; priv->stamp = g_random_int (); + + priv->main_table = NULL; + priv->update_flags = 0; } } @@ -1674,7 +1636,7 @@ void db_model_set_default_value_from_param (DbModel * obj, g_return_if_fail (GVN_IS_PARAM (param)); field = field_new_from_string (field_str); - + if (link) { SqlList * operands, * link_operands; @@ -2311,7 +2273,10 @@ gboolean db_model_has_pending_operations (DbModel * obj) { g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - return g_hash_table_size (obj->priv->row_ops) > 0; + if (obj->priv->row_ops) + return g_hash_table_size (obj->priv->row_ops) > 0; + + return FALSE; } static SqlObject * db_model_create_where (DbModel * obj, @@ -2330,11 +2295,12 @@ static SqlObject * db_model_create_where (DbModel * obj, and_operands = sql_list_new (SQL_TYPE_EXPR); sql_operation_set_operands (SQL_OPERATION (where), and_operands); - + TableData * table_data = g_hash_table_lookup (priv->tables, table); - + for (l = table_data->pkeys; l; l = l->next) { + GSList * n; SqlObject * equal; SqlList * operands; gint col = GPOINTER_TO_INT (l->data); @@ -2343,7 +2309,7 @@ static SqlObject * db_model_create_where (DbModel * obj, g_value = &row->value[col]; - for (l = operation->updated; l && (u = l->data); l = l->next) + for (n = operation->updated; n && (u = n->data); n = n->next) if (u->column == col) { g_value = u->value; @@ -2624,9 +2590,8 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) sql_list_add (stmts, stmt); } - if (sql_list_length (stmts) > 0 && !error) + if (!error) { - SqlObject * multi = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); GQueue * ops = g_queue_new (); while ((op = g_queue_pop_head (priv->operation))) @@ -2636,18 +2601,29 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) data->obj = g_object_ref (obj); data->operations = ops; data->stmts = g_object_ref_sink (stmts); - - request = db_conn_query_with_stmt_async (priv->conn - ,SQL_STMT (multi) - ,NULL - ,(DbRequestDoneCallback) db_model_on_operations_done - ,data - ,(GDestroyNotify) db_model_request_free - ); - db_model_add_pending_request (obj, request); + + if (sql_list_length (stmts) > 0) + { + SqlObject * multi = g_object_new ( + SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL); + + request = db_conn_query_with_stmt_async (priv->conn + ,SQL_STMT (multi) + ,NULL + ,(DbRequestDoneCallback) db_model_on_operations_done + ,data + ,(GDestroyNotify) db_model_request_free + ); + db_model_add_pending_request (obj, request); + } + else + { + db_model_on_operations_done (NULL, data); + db_model_request_free (data); + } } else - g_warning ("DbModel: Error performing operations"); + g_warning ("DbModel: Error performing operations."); g_object_unref (stmts); } @@ -3054,13 +3030,18 @@ static void db_model_init (DbModel *obj) priv->link_op = NULL; priv->internal_batch = NULL; + priv->column_defaults = g_hash_table_new_full ( + (GHashFunc) field_hash, + (GEqualFunc) field_equal, + (GDestroyNotify) field_free, + (GDestroyNotify) column_def_free + ); priv->updatable_data_allocated = FALSE; priv->update_flags = 0; priv->user_update_flags = DB_MODEL_ALL; priv->main_table = NULL; priv->user_main_table = NULL; - priv->column_defaults = NULL; priv->operation = NULL; priv->row_ops = NULL; priv->join = NULL; @@ -3083,15 +3064,15 @@ static void db_model_finalize (DbModel * obj) g_clear_object (&priv->link_op); g_clear_object (&priv->internal_batch); + g_hash_table_destroy (priv->column_defaults); if (priv->updatable_data_allocated) { g_free (priv->user_main_table); - g_hash_table_destroy (priv->column_defaults); g_queue_free (priv->operation); g_hash_table_destroy (priv->row_ops); g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); - db_model_free_stmt_data (obj); + g_hash_table_destroy (priv->tables); } parent->finalize (G_OBJECT (obj)); diff --git a/module/src/vn-customer.c b/module/src/vn-customer.c index 70b5a8c..aad83b7 100644 --- a/module/src/vn-customer.c +++ b/module/src/vn-customer.c @@ -26,7 +26,7 @@ static void vn_customer_open (VnForm * obj, gpointer user_data) DbIterator * info = vn_form_get (obj, "info"); DbIterator * homes = vn_form_get (obj, "homes"); - db_iterator_link (homes, "user_id", info, "id"); + db_iterator_link (homes, "user_address.user_id", info, "id"); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class diff --git a/plugin/mysql/db-mysql.c b/plugin/mysql/db-mysql.c index 86bed77..0aeb45d 100644 --- a/plugin/mysql/db-mysql.c +++ b/plugin/mysql/db-mysql.c @@ -229,6 +229,7 @@ static DbResultSet * db_mysql_query (DbMysql * obj, const gchar * sql, GError ** column->alias = g_strdup (field[i].name); column->table = g_strdup (field[i].org_table); column->table_alias = g_strdup (field[i].table); + column->schema = g_strdup (field[i].db); switch (field[i].type) { diff --git a/plugin/pg/db-pg.c b/plugin/pg/db-pg.c index c05d82e..6d5325f 100644 --- a/plugin/pg/db-pg.c +++ b/plugin/pg/db-pg.c @@ -628,6 +628,7 @@ static DbResultSet * __db_pg_query r->column[j].info = 0; r->column[j].name = NULL; r->column[j].table = NULL; + r->column[j].schema = NULL; if (GPOINTER_TO_INT (g_ptr_array_index (col_iter, j)) == 0) { diff --git a/sql/parser/scan.rl b/sql/parser/scan.rl index 6f16392..8b96bc1 100644 --- a/sql/parser/scan.rl +++ b/sql/parser/scan.rl @@ -261,45 +261,3 @@ SqlObject * sql_parser_parse (gchar * sql) return object; } - -SqlField * sql_parser_parse_field (const gchar * field_str) -{ - gchar ** split; - SqlObject * field = NULL; - - if (!field_str || !g_strcmp0 (field_str, "")) - return NULL; - - split = g_strsplit (field_str, ".", 0); - - switch (g_strv_length (split)) - { - case 3: - { - field = sql_field_new_with_target - (g_strstrip (g_strdelimit (split[2], "`\"", ' ')) - ,g_strstrip (g_strdelimit (split[1], "`\"", ' ')) - ,g_strstrip (g_strdelimit (split[0], "`\"", ' '))); - break; - } - case 2: - { - field = sql_field_new_with_target - (g_strstrip (g_strdelimit (split[1], "`\"", ' ')) - ,g_strstrip (g_strdelimit (split[0], "`\"", ' ')) - ,NULL); - break; - } - case 1: - { - field = sql_field_new_with_target - (g_strstrip (g_strdelimit (split[0], "`\"", ' ')) - ,NULL - ,NULL); - break; - } - } - - g_strfreev (split); - return SQL_FIELD (field); -} diff --git a/sql/sql-parser.h b/sql/sql-parser.h index afccf3a..d060221 100644 --- a/sql/sql-parser.h +++ b/sql/sql-parser.h @@ -33,6 +33,4 @@ */ SqlObject * sql_parser_parse (gchar * sql) G_GNUC_WARN_UNUSED_RESULT; -SqlField * sql_parser_parse_field (const gchar * field_str); - #endif \ No newline at end of file From 090b4124dac9d052982ad6fd108f9530e30ead43 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Thu, 5 Jun 2014 17:59:35 +0200 Subject: [PATCH 09/10] DbModel - Version estable pero sin analisis de joins. --- db/db-model-private.c | 167 ++--- db/db-model.c | 1331 +++++++++++++++++++----------------- db/db-model.h | 1 - db/db-result.c | 4 + db/db-result.h | 10 +- module/data/customer.glade | 11 +- plugin/pg/db-pg.c | 6 + sql/sql-batch.c | 9 +- sql/sql-field.h | 10 +- sql/sql-holder.c | 42 +- sql/sql-holder.h | 6 +- sql/sql-join.c | 105 +-- sql/sql-join.h | 11 +- sql/sql-table.c | 96 ++- sql/sql-table.h | 12 +- sql/sql-target.c | 46 +- sql/sql-target.h | 9 +- 17 files changed, 1013 insertions(+), 863 deletions(-) diff --git a/db/db-model-private.c b/db/db-model-private.c index 5595d18..b9bd08a 100644 --- a/db/db-model-private.c +++ b/db/db-model-private.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#define remove_delimiters(str) (g_strdup (g_strstrip (g_strdelimit (str, "`\"", ' ')))) + /* * DbUpdatedField: * @column: the position of the field in the row @@ -80,6 +82,41 @@ typedef struct } DbModelRequest; +//----------------------------------------------- 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); +} + //----------------------------------------------- Field typedef struct @@ -90,8 +127,6 @@ typedef struct } Field; -#define remove_delimiters(str) (g_strdup (g_strstrip (g_strdelimit (str, "`\"", ' ')))) - static void field_parse (Field * field, const gchar * string) { gchar ** split = g_strsplit (string, ".", 0); @@ -136,133 +171,61 @@ static guint field_hash (const Field * field) return g_str_hash (field->name); } -//----------------------------------------------- Table +//----------------------------------------------- TableInfo 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 -{ + gchar * alias; GSList * pkeys; + GHashTable * columns; + GSList * parent_columns; + GSList * child_columns; } -TableData; +TableInfo; -static void table_data_free (TableData * table_data) +static void table_info_free (TableInfo * table_info) { - 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); + 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); } //----------------------------------------------- ColumnDef -typedef enum -{ - PARAM_DEF, - FIELD_DEF -} -DefType; - typedef struct { - Field * field; - gpointer def; - DefType type; + gulong link; + GvnParam * param; + Field * src_column; } ColumnDef; -static ColumnDef * column_def_new (DefType type, gpointer def) +static ColumnDef * column_def_new () { ColumnDef * column_def = g_new (ColumnDef, 1); - column_def->type = type; - column_def->def = def; + column_def->link = 0; + column_def->param = NULL; + column_def->src_column = NULL; return column_def; } static void column_def_free (ColumnDef * def) { - field_free (def->field); - - switch (def->type) + if (def->param) { - case PARAM_DEF: - param_def_free (def->def); - break; - case FIELD_DEF: - field_free (def->def); - break; + if (def->link) + g_signal_handler_disconnect (def->param, def->link); + + g_object_unref (def->param); } + if (def->src_column) + field_free (def->src_column); g_free (def); } diff --git a/db/db-model.c b/db/db-model.c index 421e3fb..c2fdb3c 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -59,9 +59,10 @@ struct _DbModelPrivate guint result_pos; DbRequest * request; DbModelStatus status; - DbModelMode mode; gint stamp; + GHashTable * defaults; + gboolean fresh; gint sort_column_id; gint old_sort_column_id; @@ -73,22 +74,20 @@ struct _DbModelPrivate DbIterCompareFunc sort_func; gpointer sort_data; GDestroyNotify sort_destroy; - - SqlObject * link_op; - SqlBatch * internal_batch; - GHashTable * column_defaults; gboolean updatable_data_allocated; - DbModelUpdateFlags update_flags; DbModelUpdateFlags user_update_flags; - Table * main_table; - gchar * user_main_table; + DbModelUpdateFlags update_flags; + TableInfo * main_table; + DbModelMode mode; GHashTable * tables; gint updated_col; GQueue * operation; GHashTable * row_ops; GValue * updated_value; GSList * pending_request; + TableInfo ** column_table; + gboolean partial_delete; GSList * join; }; @@ -187,28 +186,6 @@ static void db_model_free_operation (DbModel * obj static void db_model_manage_join (DbModel * obj ,DbIter * iter ,gint col); -static void db_model_post_process_query (DbModel * obj); - -// Memory allocate functions - -static void db_model_alloc_link_data (DbModel * obj) -{ - SqlList * operators; - DbModelPrivate * priv = obj->priv; - - if (priv->link_op) - return; - - priv->internal_batch = g_object_ref_sink (sql_batch_new ()); - g_signal_connect (priv->internal_batch, "changed", - G_CALLBACK (db_model_on_batch_changed), obj); - - priv->link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); - sql_batch_add (priv->internal_batch, "link", priv->link_op); - - operators = sql_list_new (SQL_TYPE_EXPR); - sql_operation_set_operands (SQL_OPERATION (priv->link_op), operators); -} // Signal Handlers @@ -265,9 +242,9 @@ static void db_model_calculate_update_flags (DbModel * obj) { gint i; Table table; - TableData * table_data; + TableInfo * tinfo; DbModelPrivate * priv = obj->priv; - + // Allocates aditional memory when the model is updatable if (priv->user_update_flags && !priv->updatable_data_allocated) @@ -276,78 +253,79 @@ static void db_model_calculate_update_flags (DbModel * obj) priv->operation = g_queue_new (); priv->row_ops = g_hash_table_new (g_direct_hash, g_direct_equal); priv->tables = g_hash_table_new_full ( - (GHashFunc) table_hash, - (GEqualFunc) table_equal, - (GDestroyNotify) table_free, - (GDestroyNotify) table_data_free + (GHashFunc) table_hash + ,(GEqualFunc) table_equal + ,(GDestroyNotify) table_free + ,(GDestroyNotify) table_info_free ); } - + if (priv->user_update_flags && priv->fresh && priv->result) { + GArray * cols; + + g_free (priv->column_table); g_hash_table_remove_all (priv->tables); + priv->column_table = g_new (TableInfo *, priv->result->ncols); + for (i = 0; i < priv->result->ncols; i++) - if ((priv->column[i].info & DB_COLUMN_PRI_KEY)) { - table.name = priv->column[i].table; - table.schema = priv->column[i].schema; - - table_data = g_hash_table_lookup (priv->tables, &table); - - if (!table_data) + DbColumn col = priv->column[i]; + + if (!col.table) { - table_data = g_new0 (TableData, 1); - table_data->pkeys = NULL; - g_hash_table_insert (priv->tables, table_copy (&table), table_data); + priv->column_table[i] = NULL; + continue; + } + + table.name = col.table_alias; + table.schema = col.schema; + tinfo = g_hash_table_lookup (priv->tables, &table); + + if (!tinfo) + { + tinfo = g_new (TableInfo, 1); + tinfo->name = g_strdup (col.table); + tinfo->schema = g_strdup (col.schema); + tinfo->alias = g_strdup (col.table_alias); + tinfo->columns = g_hash_table_new_full ( + g_str_hash + ,g_str_equal + ,NULL + ,(GDestroyNotify) g_array_free + ); + tinfo->pkeys = NULL; + tinfo->parent_columns = NULL; + tinfo->child_columns = NULL; + g_hash_table_insert (priv->tables, table_copy (&table), tinfo); } - table_data->pkeys = g_slist_prepend (table_data->pkeys, GINT_TO_POINTER (i)); - } - } - - if (priv->result) - { - for (i = 0; i < priv->result->ncols; i++) - { - table.name = priv->column[i].table; - table.schema = priv->column[i].schema; + priv->column_table[i] = tinfo; - table_data = g_hash_table_lookup (priv->tables, &table); - - if (table_data && table_data->pkeys) - gvn_param_spec_set_editable (priv->column[i].spec, TRUE); + if (col.info & DB_COLUMN_PRI_KEY) + tinfo->pkeys = g_slist_prepend (tinfo->pkeys, GINT_TO_POINTER (i)); + + cols = g_hash_table_lookup (tinfo->columns, col.name); + + if (!cols) + { + cols = g_array_sized_new (TRUE, FALSE, sizeof (gint), 1); + g_hash_table_insert (tinfo->columns, g_strdup (col.name), cols); + } + + g_array_append_val (cols, i); } } // Searchs for the main table - table.name = NULL; - if (priv->result) + for (i = 0; i < priv->result->ncols; i++) + if (priv->column[i].info & DB_COLUMN_PRI_KEY) { - if (!priv->user_main_table) - { - for (i = 0; i < priv->result->ncols; i++) - if (priv->column[i].info & DB_COLUMN_PRI_KEY) - { - table.name = priv->column[i].table; - table.schema = priv->column[i].schema; - break; - } - } - else - table_parse (&table, priv->user_main_table); - } - - if (!table.name - || !g_hash_table_lookup_extended (priv->tables, &table, (gpointer) &priv->main_table, NULL)) - { - priv->main_table = NULL; - - if (priv->user_main_table) - g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, - "Can't set '%s' as main table", priv->user_main_table); + priv->main_table = priv->column_table[i]; + break; } // Sets the updatable flags @@ -356,6 +334,18 @@ static void db_model_calculate_update_flags (DbModel * obj) priv->update_flags = DB_MODEL_ALL & priv->user_update_flags; else priv->update_flags = 0; + + // Sets the params editable + + if (priv->result) + for (i = 0; i < priv->result->ncols; i++) + { + gboolean editable = priv->column_table[i] + && priv->column_table[i]->pkeys + && priv->update_flags & DB_MODEL_UPDATE; + + gvn_param_spec_set_editable (priv->column[i].spec, editable); + } } static void db_model_on_data_ready (DbRequest * request, DbModel * obj) @@ -392,8 +382,6 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) for (i = 0; i < priv->result->ncols; i++) g_hash_table_insert (priv->column_index, g_strdup (priv->column[i].alias), GINT_TO_POINTER (i)); - - db_model_post_process_query (obj); } else db_model_set_sort_column_id (obj, @@ -418,37 +406,44 @@ static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * DbResult * result; DbRow * req_row; DbIter iter; + Table table; + TableInfo * tinfo; result = db_request_fetch_result (request, &err); - if (result && result->data && result->nrows > 0 ) - { - iter.stamp = priv->stamp; - iter.data = row; - req_row = g_ptr_array_index (result->data, 0); + if (!(result && result->data && result->nrows > 0)) + goto exit; - for (i = 0; i < result->ncols; i++) - for (j = 0; j < priv->result->ncols; j++) - if (!g_strcmp0 (priv->column[j].name, result->column[i].name) - && !g_strcmp0 (priv->column[j].table, result->column[i].table) - && !g_strcmp0 (priv->column[j].schema, result->column[i].schema)) + iter.data = row; + iter.stamp = priv->stamp; + req_row = g_ptr_array_index (result->data, 0); + + table.name = result->column[0].table_alias; + table.schema = result->column[0].schema; + + if ((tinfo = g_hash_table_lookup (priv->tables, &table))) + for (i = 0; i < result->ncols; i++) + { + GArray * cols = g_hash_table_lookup (tinfo->columns, result->column[i].name); + + for (j = 0; j < cols->len; j++) { GValue * new_value = &req_row->value[i]; - if (!gvn_value_compare (new_value, DB_ROW_FIELD (row, j))) - { - priv->updated_value = g_new0 (GValue, 1); - g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); - g_value_copy (new_value, priv->updated_value); - - priv->updated_col = j; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); - } + if (gvn_value_compare (new_value, DB_ROW_FIELD (row, i))) + continue; + + priv->updated_value = g_new0 (GValue, 1); + g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); + g_value_copy (new_value, priv->updated_value); + + priv->updated_col = g_array_index (cols, gint, j); + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); } } - if (result) - db_result_free (result); + exit: + db_result_free (result); } static void db_model_on_operations_done (DbRequest * request, DbModelRequest * data) @@ -460,15 +455,15 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d GError * err = NULL; DbModel * obj = data->obj; DbModelPrivate * priv = obj->priv; - - l = g_queue_peek_head_link (data->operations); - for (; l; l = l->next) + for (l = data->operations->head; l; l = l->next) { op = l->data; + iter.stamp = priv->stamp; + iter.data = op->row; - if (op->type & DB_MODEL_ROW_OP_DELETE - && op->type & DB_MODEL_ROW_OP_INSERT) // DELETE + INSERT + if (op->type & DB_MODEL_ROW_OP_INSERT + && op->type & DB_MODEL_ROW_OP_DELETE) // INSERT + DELETE { g_signal_emit (obj, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); @@ -482,8 +477,20 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE { - g_signal_emit (obj, - db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); + if (priv->partial_delete) + { + for (i = 0; i < priv->result->ncols; i++) + if (priv->column_table[i] == priv->main_table) + { + priv->updated_col = i; + priv->updated_value = + g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + } + } + else + g_signal_emit (obj, + db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); } else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { @@ -506,8 +513,6 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d db_model_process_insert (obj, request, op->row, err); } - iter.stamp = priv->stamp; - iter.data = op->row; g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); } @@ -554,25 +559,26 @@ static void db_model_on_join_query_done (DbRequest * request, JoinData * join_da { for (i = 0; i < priv->result->ncols; i++) for (j = 0; j < r->ncols; j++) - if (!g_strcmp0 (r->column[j].table, priv->column[i].table) - && !g_strcmp0 (r->column[j].name, priv->column[i].name)) + if (!g_strcmp0 (r->column[j].name, priv->column[i].name) + && !g_strcmp0 (r->column[j].table, priv->column[i].table) + && !g_strcmp0 (r->column[j].schema, priv->column[i].schema)) + { + if (r->nrows > 0) { - if (r->nrows > 0) - { - GValue * new_value = - DB_ROW_FIELD (g_ptr_array_index (r->data, 0), j); + GValue * new_value = + DB_ROW_FIELD (g_ptr_array_index (r->data, 0), j); - priv->updated_value = g_new0 (GValue, 1); - g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); - gvn_value_copy (new_value, priv->updated_value); - } - else - priv->updated_value = - g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); - - priv->updated_col = i; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, iter); + priv->updated_value = g_new0 (GValue, 1); + g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); + gvn_value_copy (new_value, priv->updated_value); } + else + priv->updated_value = + g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); + + priv->updated_col = i; + g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, iter); + } db_result_free (r); } @@ -738,293 +744,7 @@ void db_model_reverse_operations (DbModel * obj) } } -static DbModelField * db_model_field_new (const gchar * table, const gchar * schema) -{ - DbModelField * field = g_new (DbModelField, 1); - field->schema = g_strdup (schema); - field->table = g_strdup (table); - field->name = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - field->main = FALSE; - return field; -} - -static DbModelField * db_model_field_new_from_string (const gchar * str) -{ - DbModelField * field = NULL; - gchar * new_str = g_strdup (str), ** aux, ** f; - gint i, f_len; - g_strstrip (new_str); - f = g_strsplit (new_str, ".", G_MAXINT); - g_free (new_str); - f_len = g_strv_length (f); - - for (i = 0; i < f_len; i++) - { - aux = g_strsplit (f[i], "\"", G_MAXINT); - - if (g_strcmp0 (aux[0], "")) - { - g_strfreev (aux); - break; - } - - g_free (f[i]); - f[i] = g_strdup (aux[1]); - g_strfreev (aux); - } - - switch (f_len) - { - case 3: - { - field = db_model_field_new (f[1], f[0]); - g_ptr_array_add (field->name, g_strdup (f[2])); - break; - } - case 2: - { - field = db_model_field_new (f[0], NULL); - g_ptr_array_add (field->name, g_strdup (f[1])); - break; - } - case 1: - { - field = db_model_field_new (NULL, NULL); - g_ptr_array_add (field->name, g_strdup (f[0])); - } - } - - g_strfreev (f); - - return field; -} - -static void db_model_field_free (DbModelField * field) -{ - if (field) - { - if (field->schema) - g_free (field->schema); - if (field->table) - g_free (field->table); - if (field->name) - g_ptr_array_free (field->name, TRUE); - } - - g_free (field); -} - -static void db_join_free (DbJoin * join) -{ - if (join) - { - if (join->left) - db_model_field_free (join->left); - if (join->right) - db_model_field_free (join->right); - } - - g_free (join); -} -/* -static void db_model_calculate_col_def (DbModel * obj, SqlJoin * join, - SqlField * l_field, SqlField * r_field) -{ - gint i, col = -1; - gchar * dst = NULL; - DbModelPrivate * priv = obj->priv; - SqlField * f = NULL; - SqlTarget * l_table = join->target_left, * r_table = join->target_right; - - for (i = 0; i < priv->result->ncols; i++) - { - f = NULL; - - if (!g_strcmp0 (priv->column[i].name, l_field->name)) - { - f = l_field; - dst = (join->type == SQL_JOIN_TYPE_RIGHT) ? - l_field->name : r_field->name; - } - else if (!g_strcmp0 (priv->column[i].name, r_field->name)) - { - f = r_field; - dst = (join->type == SQL_JOIN_TYPE_LEFT) ? - l_field->name : r_field->name; - } - - if (f) - {//TODO add schema checks - if (f->target) - { - if (!g_strcmp0 (priv->column[i].table, f->target) - || (!g_strcmp0 (priv->column[i].table, SQL_TABLE (l_table)->name) - && !g_strcmp0 (f->target, l_table->alias))) - { - col = i; - break; - } - else if (!g_strcmp0 (priv->column[i].table, SQL_TABLE (r_table)->name) - && !g_strcmp0 (f->target, r_table->alias)) - { - col = i; - break; - } - } - else - { - col = i; - break; - } - } - } - - if (f) - db_model_set_default_value_from_column (obj, dst, col); -} - -static void db_model_set_join_fields (DbModel * obj, SqlJoin * join, - SqlField * lsql_field, SqlField * rsql_field, - DbModelField * lfield, DbModelField * rfield) -{ - gboolean check; - SqlTarget * ltarget = join->target_left, * rtarget = join->target_right; - - check = !g_strcmp0 (lfield->schema, lsql_field->schema) - || !g_strcmp0 (lfield->table, lsql_field->target) - || !g_strcmp0 (ltarget->alias, lsql_field->target) - || !g_strcmp0 (rfield->schema, rfield->schema) - || !g_strcmp0 (rfield->table, rsql_field->target) - || !g_strcmp0 (rtarget->alias, rsql_field->target); - - g_ptr_array_add (lfield->name, - g_strdup (check ? lsql_field->name : rsql_field->name)); - g_ptr_array_add (rfield->name, - g_strdup (check ? rsql_field->name : lsql_field->name)); -} -*/ -static void db_model_post_process_query (DbModel * obj) -{ -/* -// TODO When parser gets fully functional, these 3 lines won't be needed, -// because obj->stmt will be a parsed stmt: - gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, obj->priv->batch, NULL); - SqlObject * stmt = sql_parser_parse (rend); - - g_free (rend); - - if (stmt && SQL_IS_SELECT (stmt)) - { - DbModelField * lfield, * rfield; - SqlJoin * join; - GList * n; - SqlSelect * select = SQL_SELECT (stmt); - gboolean calculate_join = FALSE; - - for (n = sql_list_get_items (SQL_DML (select)->targets); n; n = n->next) - if ((join = n->data) - && SQL_IS_JOIN (join) - && SQL_IS_TABLE (join->target_left) - && SQL_IS_TABLE (join->target_right) - && SQL_IS_OPERATION (join->condition)) - { -// DbJoin and ColDef creation - GList * operators; - SqlOperation * op = SQL_OPERATION (join->condition); - SqlField * lsql_field = NULL, * rsql_field = NULL; - - lfield = db_model_field_new (SQL_TABLE (join->target_left)->name, NULL); - rfield = db_model_field_new (SQL_TABLE (join->target_right)->name, NULL); - - if (join->type == SQL_JOIN_TYPE_RIGHT) - rfield->main = TRUE; - else - lfield->main = TRUE; - - if (op->type == SQL_OPERATION_TYPE_AND) - { - GList * l; - - for (l = sql_list_get_items (op->operators); l; l = l->next) - { - SqlOperation * subop = l->data; - operators = sql_list_get_items (subop->operators); - - if (SQL_IS_OPERATION (subop) - && subop->type == SQL_OPERATION_TYPE_EQUAL - && operators->data // Left Field - && operators->next && operators->next->data) // Right Field - { - lsql_field = SQL_FIELD (operators->data); - rsql_field = SQL_FIELD (operators->next->data); - - db_model_set_join_fields (obj, join, - lsql_field, rsql_field, lfield, rfield); - - calculate_join = TRUE; - - if (join->type != SQL_JOIN_TYPE_INNER) - db_model_calculate_col_def - (obj, join, lsql_field, rsql_field); - } - else - { - calculate_join = FALSE; - break; - } - } - } - else - { - operators = sql_list_get_items (op->operators); - - if (op->type == SQL_OPERATION_TYPE_EQUAL && operators->data - && operators->next && operators->next->data) - { - lsql_field = SQL_FIELD (operators->data); - rsql_field = SQL_FIELD (operators->next->data); - - db_model_set_join_fields (obj, join, - lsql_field, rsql_field, lfield, rfield); - - calculate_join = TRUE; - - if (join->type != SQL_JOIN_TYPE_INNER) - db_model_calculate_col_def - (obj, join ,lsql_field, rsql_field); - } - } - - if (calculate_join) - { - DbJoin * join_res = g_new (DbJoin, 1); - join_res->left = lfield; - join_res->right = rfield; - - obj->priv->join = g_slist_prepend (obj->priv->join, join_res); - } - else - { - db_model_field_free (lfield); - db_model_field_free (rfield); - } - } - } - - if (G_IS_OBJECT (stmt)) - g_object_unref (stmt); -*/ -} - -static inline gboolean stored (const gint * v, const gint length, const gint target) -{ - gint i; - - for (i = 0; i < length; i++) - if (v[i] == target) - return TRUE; - return FALSE; -} +// Utility functions /* * Comparison between values, using case-insensitive and UTF-8 strings @@ -1133,6 +853,37 @@ static void db_model_add_pending_request (DbModel * obj, DbRequest * request) request); } +static void db_model_clear (DbModel * obj) +{ + DbModelPrivate * priv = obj->priv; + + if (priv->request) + { + db_request_cancel (priv->request); + priv->request = NULL; + } + else if (priv->result) + { + db_model_clean_operations (obj); + db_model_cancel_pending_requests (obj); + + db_result_free (priv->result); + priv->result = NULL; + priv->column = NULL; + priv->data = NULL; + + priv->old_order = priv->order; + priv->old_sort_column_id = priv->sort_column_id; + priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; + priv->stamp = g_random_int (); + + priv->main_table = NULL; + priv->update_flags = 0; + } +} + +// Join related functions + static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) { DbModelPrivate * priv = obj->priv; @@ -1146,18 +897,18 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) gboolean send_request = FALSE, end = FALSE; SqlList * stmts = g_object_ref_sink (sql_list_new (SQL_TYPE_MULTI_STMT)); -/*FIXME - for (i = 0; i < obj->ncols; i++) - // Check for multi-field pkeys to be fully set - // need to know the total number of pkey fields - if (i != col && obj->column[i].info & DB_COLUMN_PRI_KEY - && gvn_value_is_null (DB_ROW_FIELD (iter->data, i)) - && !g_strcmp0 (obj->column[i].table, obj->column[col].table)) - { - end = TRUE; - break; - } -*/ +// FIXME +// for (i = 0; i < obj->ncols; i++) +// // Check for multi-field pkeys to be fully set +// // need to know the total number of pkey fields +// if (i != col && obj->column[i].info & DB_COLUMN_PRI_KEY +// && gvn_value_is_null (DB_ROW_FIELD (iter->data, i)) +// && !g_strcmp0 (obj->column[i].table, obj->column[col].table)) +// { +// end = TRUE; +// break; +// } + if (!end) for (n = priv->join; n; n = n->next) { @@ -1247,39 +998,345 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) g_object_unref (stmts); } } - -static void db_model_clear (DbModel * obj) +/* +static DbModelField * db_model_field_new (const gchar * table, const gchar * schema) { - DbModelPrivate * priv = obj->priv; - - if (priv->request) - { - db_request_cancel (priv->request); - priv->request = NULL; - } - else if (priv->result) - { - db_model_clean_operations (obj); - db_model_cancel_pending_requests (obj); - - db_result_free (priv->result); - priv->result = NULL; - priv->column = NULL; - priv->data = NULL; - - priv->old_order = priv->order; - priv->old_sort_column_id = priv->sort_column_id; - priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; - priv->stamp = g_random_int (); - - priv->main_table = NULL; - priv->update_flags = 0; - } + DbModelField * field = g_new (DbModelField, 1); + field->schema = g_strdup (schema); + field->table = g_strdup (table); + field->name = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + field->main = FALSE; + return field; } +static void db_model_field_free (DbModelField * field) +{ + if (field) + { + if (field->schema) + g_free (field->schema); + if (field->table) + g_free (field->table); + if (field->name) + g_ptr_array_free (field->name, TRUE); + } + + g_free (field); +} + +static void db_join_free (DbJoin * join) +{ + if (join) + { + if (join->left) + db_model_field_free (join->left); + if (join->right) + db_model_field_free (join->right); + } + + g_free (join); +} + +static void db_model_calculate_col_def (DbModel * obj, SqlJoin * join, + SqlField * l_field, SqlField * r_field) +{ + gint i, col = -1; + gchar * dst = NULL; + DbModelPrivate * priv = obj->priv; + SqlField * f = NULL; + SqlTarget * l_table = join->target_left, * r_table = join->target_right; + + for (i = 0; i < priv->result->ncols; i++) + { + f = NULL; + + if (!g_strcmp0 (priv->column[i].name, l_field->name)) + { + f = l_field; + dst = (join->type == SQL_JOIN_TYPE_RIGHT) ? + l_field->name : r_field->name; + } + else if (!g_strcmp0 (priv->column[i].name, r_field->name)) + { + f = r_field; + dst = (join->type == SQL_JOIN_TYPE_LEFT) ? + l_field->name : r_field->name; + } + + if (f) + {//TODO add schema checks + if (f->target) + { + if (!g_strcmp0 (priv->column[i].table, f->target) + || (!g_strcmp0 (priv->column[i].table, SQL_TABLE (l_table)->name) + && !g_strcmp0 (f->target, l_table->alias))) + { + col = i; + break; + } + else if (!g_strcmp0 (priv->column[i].table, SQL_TABLE (r_table)->name) + && !g_strcmp0 (f->target, r_table->alias)) + { + col = i; + break; + } + } + else + { + col = i; + break; + } + } + } + + if (f) + db_model_set_default_value_from_column (obj, dst, col); +} + +static void db_model_set_join_fields (DbModel * obj, SqlJoin * join, + SqlField * lsql_field, SqlField * rsql_field, + DbModelField * lfield, DbModelField * rfield) +{ + gboolean check; + SqlTarget * ltarget = join->target_left, * rtarget = join->target_right; + + check = !g_strcmp0 (lfield->schema, lsql_field->schema) + || !g_strcmp0 (lfield->table, lsql_field->target) + || !g_strcmp0 (ltarget->alias, lsql_field->target) + || !g_strcmp0 (rfield->schema, rfield->schema) + || !g_strcmp0 (rfield->table, rsql_field->target) + || !g_strcmp0 (rtarget->alias, rsql_field->target); + + g_ptr_array_add (lfield->name, + g_strdup (check ? lsql_field->name : rsql_field->name)); + g_ptr_array_add (rfield->name, + g_strdup (check ? rsql_field->name : lsql_field->name)); +} + +static void db_model_post_process_query (DbModel * obj) +{ +// TODO When parser gets fully functional, these 3 lines won't be needed, +// because obj->stmt will be a parsed stmt: + gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, obj->priv->batch, NULL); + SqlObject * stmt = sql_parser_parse (rend); + + g_free (rend); + + if (stmt && SQL_IS_SELECT (stmt)) + { + DbModelField * lfield, * rfield; + SqlJoin * join; + GList * n; + SqlSelect * select = SQL_SELECT (stmt); + gboolean calculate_join = FALSE; + + for (n = sql_list_get_items (SQL_DML (select)->targets); n; n = n->next) + if ((join = n->data) + && SQL_IS_JOIN (join) + && SQL_IS_TABLE (join->target_left) + && SQL_IS_TABLE (join->target_right) + && SQL_IS_OPERATION (join->condition)) + { +// DbJoin and ColDef creation + GList * operators; + SqlOperation * op = SQL_OPERATION (join->condition); + SqlField * lsql_field = NULL, * rsql_field = NULL; + + lfield = db_model_field_new (SQL_TABLE (join->target_left)->name, NULL); + rfield = db_model_field_new (SQL_TABLE (join->target_right)->name, NULL); + + if (join->type == SQL_JOIN_TYPE_RIGHT) + rfield->main = TRUE; + else + lfield->main = TRUE; + + if (op->type == SQL_OPERATION_TYPE_AND) + { + GList * l; + + for (l = sql_list_get_items (op->operators); l; l = l->next) + { + SqlOperation * subop = l->data; + operators = sql_list_get_items (subop->operators); + + if (SQL_IS_OPERATION (subop) + && subop->type == SQL_OPERATION_TYPE_EQUAL + && operators->data // Left Field + && operators->next && operators->next->data) // Right Field + { + lsql_field = SQL_FIELD (operators->data); + rsql_field = SQL_FIELD (operators->next->data); + + db_model_set_join_fields (obj, join, + lsql_field, rsql_field, lfield, rfield); + + calculate_join = TRUE; + + if (join->type != SQL_JOIN_TYPE_INNER) + db_model_calculate_col_def + (obj, join, lsql_field, rsql_field); + } + else + { + calculate_join = FALSE; + break; + } + } + } + else + { + operators = sql_list_get_items (op->operators); + + if (op->type == SQL_OPERATION_TYPE_EQUAL && operators->data + && operators->next && operators->next->data) + { + lsql_field = SQL_FIELD (operators->data); + rsql_field = SQL_FIELD (operators->next->data); + + db_model_set_join_fields (obj, join, + lsql_field, rsql_field, lfield, rfield); + + calculate_join = TRUE; + + if (join->type != SQL_JOIN_TYPE_INNER) + db_model_calculate_col_def + (obj, join ,lsql_field, rsql_field); + } + } + + if (calculate_join) + { + DbJoin * join_res = g_new (DbJoin, 1); + join_res->left = lfield; + join_res->right = rfield; + + obj->priv->join = g_slist_prepend (obj->priv->join, join_res); + } + else + { + db_model_field_free (lfield); + db_model_field_free (rfield); + } + } + } + + if (G_IS_OBJECT (stmt)) + g_object_unref (stmt); + +} + +static gboolean db_model_analyse_join_op (DbModel * obj, SqlOperation * op) +{ + gint i; + gint noperands; + SqlList * operands; + SqlOperationType operator = sql_operation_get_operator (op); + + noperands = sql_list_length (operands); + g_object_get (op, "operands", &operands, NULL); + + if (operator == SQL_OPERATION_TYPE_EQUAL && noperands == 2) + { + gpointer field1 = sql_list_get (operands, 0); + gpointer field2 = sql_list_get (operands, 1); + + if (!SQL_IS_FIELD (field1) || !SQL_IS_FIELD (field2) + || (g_strcmp0 (sql_field_get_target (field1), sql_field_get_target (field2)) + && g_strcmp0 (sql_field_get_schema (field1), sql_field_get_schema (field2)))) + return FALSE; + + + } + else if (operator == SQL_OPERATION_TYPE_AND) + { + for (i = 0; i < noperands; i++) + if (!db_model_analyse_join_op (obj, sql_list_get (operands, i))) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +static void db_model_analyse_join (DbModel * obj, SqlTarget * target) +{ + SqlJoin * join; + SqlTarget * left; + SqlTarget * right; + SqlOperation * on; + + if (!SQL_IS_JOIN (target)) + return; + + join = SQL_JOIN (target); + g_object_get (join + ,"target-left", &left + ,"target-right", &right + ,"condition", &on + ,NULL + ); + + if (SQL_IS_TABLE (left) || SQL_IS_TABLE (right)) + db_model_analyse_join_op (obj, on); + + switch ((gint) sql_join_get_join_type (join)) + { + case SQL_JOIN_TYPE_INNER: + break; + case SQL_JOIN_TYPE_LEFT: + break; + case SQL_JOIN_TYPE_RIGHT: + break; + } + + db_model_analyse_join (obj, left); + db_model_analyse_join (obj, right); +} + +static void db_model_load_join (DbModel * obj) +{ + gchar * sql; + SqlObject * stmt; + SqlObject * select; + DbModelPrivate * priv = obj->priv; + + sql = db_conn_render (obj->priv->conn, obj->priv->stmt, NULL, NULL); + stmt = sql_parser_parse (sql); + g_free (sql); + + if (!stmt) + return; + + g_object_ref_sink (stmt); + + if (SQL_IS_MULTI_STMT (stmt)) + { + SqlList * stmts; + g_object_get (stmt, "stmts", &stmts, NULL); + select = sql_list_get (stmts, priv->result_pos); + } + else + select = stmt; + + if (!SQL_IS_SELECT (select)) + goto exit; + + gint i; + SqlList * targets; + + g_object_get (select, "targets", &targets, NULL); + + for (i = 0; i < sql_list_length (targets); i++) + db_model_analyse_join (obj, sql_list_get (targets, i)); + + exit: + g_object_unref (stmt); +} +*/ //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public -// Set&Get methods +// Setters & getters /** * db_model_set_conn: @@ -1542,8 +1599,8 @@ void db_model_add_join_columns (DbModel * obj, const gchar * left, const gchar * g_return_if_fail (DB_IS_MODEL (obj)); DbJoin * join = g_new (DbJoin, 1); - join->left = db_model_field_new_from_string (left); - join->right = db_model_field_new_from_string (right); +// join->left = db_model_field_new_from_string (left); +// join->right = db_model_field_new_from_string (right); obj->priv->join = g_slist_prepend (obj->priv->join, join); } @@ -1592,6 +1649,30 @@ void db_model_set_batch (DbModel * obj, SqlBatch * batch) priv->batch = batch; } +static ColumnDef * db_model_create_column_def (DbModel * obj, const gchar * field_str) +{ + Field * field = field_new_from_string (field_str); + + if (field->name && field->target && !field->schema) + { + ColumnDef * def = column_def_new (); + g_hash_table_insert (obj->priv->defaults, field, def); + return def; + } + else + { + g_warning ("DbModel: Field string shoud specify name and table alias: %s", field_str); + field_free (field); + } + + return NULL; +} + +static void db_model_on_param_changed (GvnParam * param, GValue * value, DbModel * obj) +{ + db_model_refresh (obj); +} + /** * db_model_set_default_value_from_column: * @obj: a #DbModel @@ -1601,17 +1682,16 @@ void db_model_set_batch (DbModel * obj, SqlBatch * batch) void db_model_set_default_value_from_column (DbModel * obj, const gchar * field_str, const gchar * column_str) { - Field * field; - ColumnDef * column_def; + ColumnDef * def; g_return_if_fail (DB_IS_MODEL (obj)); g_return_if_fail (field_str); g_return_if_fail (column_str); - - field = field_new_from_string (field_str); - column_def = column_def_new (FIELD_DEF, field_new_from_string (column_str)); - g_hash_table_insert (obj->priv->column_defaults, field, column_def); + def = db_model_create_column_def (obj, field_str); + + if (def) + def->src_column = field_new_from_string (column_str); } /** @@ -1626,58 +1706,22 @@ void db_model_set_default_value_from_column (DbModel * obj, void db_model_set_default_value_from_param (DbModel * obj, const gchar * field_str, GvnParam * param, gboolean link) { - Field * field; - ParamDef * param_def; - ColumnDef * column_def; - SqlObject * equal = NULL; + ColumnDef * def; g_return_if_fail (DB_IS_MODEL (obj)); g_return_if_fail (field_str); g_return_if_fail (GVN_IS_PARAM (param)); - field = field_new_from_string (field_str); - - if (link) - { - SqlList * operands, * link_operands; + def = db_model_create_column_def (obj, field_str); - db_model_alloc_link_data (obj); - - link_operands = sql_operation_get_operands (SQL_OPERATION (obj->priv->link_op)); + if (!def) + return; - equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); - sql_list_add (link_operands, equal); - - operands = sql_list_new (SQL_TYPE_EXPR); - sql_list_add (operands, sql_field_new_with_target (field->name, field->target, field->schema)); - sql_list_add (operands, sql_value_new_with_param (param)); - sql_operation_set_operands (SQL_OPERATION (equal), operands); - } - - param_def = g_new (ParamDef, 1); - param_def->param = g_object_ref (param); - param_def->equal_op = equal; - param_def->link_op = obj->priv->link_op; - - column_def = column_def_new (PARAM_DEF, param_def); - g_hash_table_insert (obj->priv->column_defaults, field, column_def); -} - -/** - * db_model_request_main_table: - * @obj: a #DbModel - * @table: the name of the new main table of @model - * - * Requests the main table of @model. The main table is the only table on a - * #DbModel whose rows can be deleted or inserted. - **/ -void db_model_request_main_table (DbModel * obj, const gchar * table) -{ - g_return_if_fail (DB_IS_MODEL (obj)); - - g_free (obj->priv->user_main_table); - obj->priv->user_main_table = g_strdup (table); - db_model_calculate_update_flags (obj); + def->param = g_object_ref_sink (param); + + if (link) + def->link = g_signal_connect (param, "value-changed", + G_CALLBACK (db_model_on_param_changed), obj); } /** @@ -1943,17 +1987,7 @@ gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValu GvnParamSpec * spec = priv->column[col].spec; if (!gvn_param_spec_validate (spec, value, err)) - { return FALSE; - } - - if (!(priv->update_flags & DB_MODEL_UPDATE) - && !(row_op & DB_MODEL_ROW_OP_INSERT)) - { - g_set_error (err, DB_MODEL_LOG_DOMAIN - ,DB_MODEL_ERROR_NOT_UPDATABLE, "Model not updatable"); - return FALSE; - } if (!gvn_value_is_null (value)) { @@ -2033,21 +2067,17 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter) for (i = 0; i < row->len; i++) { Field field; - ColumnDef * column_def; + ColumnDef * def; const GValue * def_value = NULL; DbColumn col = priv->column[i]; field.name = col.name; - field.target = col.table; - field.schema = col.schema; - - column_def = g_hash_table_lookup (priv->column_defaults, &field); - - if (column_def && column_def->type == PARAM_DEF) - { - ParamDef * param_def = column_def->def; - def_value = gvn_param_get_value (param_def->param); - } + field.target = priv->column_table[i]->alias; + field.schema = NULL; + def = g_hash_table_lookup (priv->defaults, &field); + + if (def && def->param) + def_value = gvn_param_get_value (def->param); if (!def_value) def_value = gvn_param_spec_get_default (col.spec); @@ -2280,7 +2310,7 @@ gboolean db_model_has_pending_operations (DbModel * obj) } static SqlObject * db_model_create_where (DbModel * obj, - Table * table, DbOperation * operation, gboolean for_insert) + TableInfo * tinfo, DbOperation * operation, gboolean for_insert) { GSList * l; DbUpdatedField * u; @@ -2296,9 +2326,7 @@ static SqlObject * db_model_create_where (DbModel * obj, and_operands = sql_list_new (SQL_TYPE_EXPR); sql_operation_set_operands (SQL_OPERATION (where), and_operands); - TableData * table_data = g_hash_table_lookup (priv->tables, table); - - for (l = table_data->pkeys; l; l = l->next) + for (l = tinfo->pkeys; l; l = l->next) { GSList * n; SqlObject * equal; @@ -2348,20 +2376,24 @@ static SqlObject * db_model_create_where (DbModel * obj, } static SqlObject * db_model_create_insert (DbModel * obj, - Table * table, DbOperation * operation) + TableInfo * tinfo, DbOperation * operation) { gint i; DbModelPrivate * priv = obj->priv; DbRow * row = operation->row; const GValue * value; SqlList * targets, * stmts, * sets, * fields, * values, * select_fields; - SqlObject * target, * insert, * set, * select; - SqlObject * where = db_model_create_where (obj, table, operation, TRUE); + SqlObject * target, * insert, * set, * select, * where; + GHashTableIter iter; + Field * field; + ColumnDef * def; + GArray * cols; + gchar * colname; + + where = db_model_create_where (obj, tinfo, operation, TRUE); if (!where) return NULL; - - target = sql_table_new (table->name, table->schema); fields = sql_list_new (SQL_TYPE_FIELD); @@ -2373,6 +2405,7 @@ static SqlObject * db_model_create_insert (DbModel * obj, ); sql_list_add (sets, set); + target = sql_table_new (tinfo->name, tinfo->schema); insert = g_object_new (SQL_TYPE_INSERT ,"table", target ,"fields", fields @@ -2383,6 +2416,9 @@ static SqlObject * db_model_create_insert (DbModel * obj, select_fields = sql_list_new (SQL_TYPE_EXPR); targets = sql_list_new (SQL_TYPE_TARGET); + + target = sql_table_new (tinfo->name, tinfo->schema); + sql_target_set_alias (SQL_TARGET (target), tinfo->alias); sql_list_add (targets, target); select = g_object_new (SQL_TYPE_SELECT @@ -2392,28 +2428,16 @@ static SqlObject * db_model_create_insert (DbModel * obj, ,NULL ); - GHashTableIter iter; - ColumnDef * column_def; - Field * field; - - g_hash_table_iter_init (&iter, priv->column_defaults); + g_hash_table_iter_init (&iter, priv->defaults); - while (g_hash_table_iter_next (&iter, (gpointer) &field, (gpointer) &column_def)) - if (!g_strcmp0 (field->target, table->name) - && !g_strcmp0 (field->schema, table->schema)) + while (g_hash_table_iter_next (&iter, (gpointer) &field, (gpointer) &def)) + if (!g_strcmp0 (field->target, tinfo->alias) + && !g_hash_table_lookup (tinfo->columns, field->name)) { - switch (column_def->type) - { - case PARAM_DEF: - { - ParamDef * param_def = column_def->def; - value = gvn_param_get_value (param_def->param); - break; - } - case FIELD_DEF: - value = NULL; // FIXME - break; - } + if (def->param) + value = gvn_param_get_value (def->param); + else + value = NULL; if (value) { @@ -2422,20 +2446,22 @@ static SqlObject * db_model_create_insert (DbModel * obj, } } - for (i = 0; i < row->len; i++) - if (table_has_column (table, &priv->column[i])) + g_hash_table_iter_init (&iter, tinfo->columns); + + while (g_hash_table_iter_next (&iter, (gpointer) &colname, (gpointer) &cols)) { + i = g_array_index (cols, gint, 0); value = &row->value[i]; if (!gvn_value_is_null (value)) { - sql_list_add (fields, sql_field_new (priv->column[i].name)); + sql_list_add (fields, sql_field_new (colname)); sql_list_add (values, sql_value_new_with_value (value)); } - sql_list_add (select_fields, sql_field_new (priv->column[i].name)); + sql_list_add (select_fields, sql_field_new (colname)); } - + stmts = sql_list_new (SQL_TYPE_STMT); sql_list_add (stmts, insert); sql_list_add (stmts, select); @@ -2482,9 +2508,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) stmts = sql_list_new (SQL_TYPE_STMT); g_object_ref_sink (stmts); - l = g_queue_peek_head_link (priv->operation); - - for (; l && !error; l = l->next) + for (l = priv->operation->head; l && !error; l = l->next) { SqlObject * stmt = NULL; @@ -2525,36 +2549,50 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT { - Table * table; + GList * l; + GSList * n; + GQueue * fields; + TableInfo * tinfo; GHashTableIter iter; SqlList * update_list; + DbUpdatedField * u; + + GHashTable * tables = g_hash_table_new_full ( + g_direct_hash + ,g_direct_equal + ,NULL + ,(GDestroyNotify) g_queue_free + ); + + for (n = op->updated; n && (u = n->data); n = n->next) + { + tinfo = priv->column_table[u->column]; + fields = g_hash_table_lookup (tables, tinfo); + + if (!fields) + { + fields = g_queue_new (); + g_hash_table_insert (tables, tinfo, fields); + } + + g_queue_push_tail (fields, u); + } update_list = sql_list_new (SQL_TYPE_STMT); - g_hash_table_iter_init (&iter, priv->tables); + g_hash_table_iter_init (&iter, tables); - while (g_hash_table_iter_next (&iter, (gpointer) &table, NULL)) + while (g_hash_table_iter_next (&iter, (gpointer) &tinfo, (gpointer) &fields)) { - GSList * l; - DbUpdatedField * u; - GSList * fields = NULL; - - for (l = op->updated; l && (u = l->data); l = l->next) - if (table_has_column (table, &priv->column[u->column])) - fields = g_slist_prepend (fields, u); - - if (!fields) - continue; - - where = db_model_create_where (obj, table, op, FALSE); + where = db_model_create_where (obj, tinfo, op, FALSE); if (where) { SqlList * sets = sql_list_new (SQL_TYPE_UPDATE_SET); SqlList * targets = sql_list_new (SQL_TYPE_TARGET); - sql_list_add (targets, sql_table_new (table->name, table->schema)); + sql_list_add (targets, sql_table_new (tinfo->name, tinfo->schema)); - for (l = fields; l && (u = l->data); l = l->next) + for (l = fields->head; l && (u = l->data); l = l->next) { GValue * new_value = DB_ROW_FIELD (row, u->column); @@ -2574,15 +2612,14 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else { - SqlObject * insert = db_model_create_insert (obj, table, op); + SqlObject * insert = db_model_create_insert (obj, tinfo, op); if (insert) sql_list_add (update_list, insert); } - - g_slist_free (fields); } + g_hash_table_unref (tables); stmt = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", update_list, NULL); } @@ -2646,10 +2683,53 @@ void db_model_refresh (DbModel * obj) if (priv->conn && priv->stmt) { - SqlBatch * tmp_batch = sql_batch_new (); + Field * field; + ColumnDef * def; + SqlObject * link_op; + SqlList * link_operands; + SqlBatch * tmp_batch; + GHashTableIter iter; + + // Gets all the holders from the statement + + tmp_batch = sql_batch_new (); + g_object_ref_sink (tmp_batch); sql_object_get_holders (SQL_OBJECT (priv->stmt), tmp_batch); sql_batch_merge (tmp_batch, priv->batch); - sql_batch_merge (tmp_batch, priv->internal_batch); + + // Creates the link operation + + link_op = sql_operation_new (SQL_OPERATION_TYPE_AND); + g_object_ref_sink (link_op); + + link_operands = sql_list_new (SQL_TYPE_EXPR); + sql_operation_set_operands (SQL_OPERATION (link_op), link_operands); + + g_hash_table_iter_init (&iter, priv->defaults); + + while (g_hash_table_iter_next (&iter, (gpointer) &field, (gpointer) &def)) + if (def->link) + { + SqlObject * sql_field; + SqlObject * equal_op; + SqlList * equal_operands; + + equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL); + sql_list_add (link_operands, equal_op); + + sql_field = sql_field_new_with_target ( + field->name, field->target, NULL); + + equal_operands = sql_list_new (SQL_TYPE_EXPR); + sql_list_add (equal_operands, sql_field); + sql_list_add (equal_operands, sql_value_new_with_param (def->param)); + sql_operation_set_operands (SQL_OPERATION (equal_op), equal_operands); + } + + if (sql_list_length (link_operands) > 0) + sql_batch_add (tmp_batch, "link", link_op); + + // Executes the statement if its ready if (sql_batch_is_ready (tmp_batch)) { @@ -2663,9 +2743,10 @@ void db_model_refresh (DbModel * obj) ,g_object_ref (obj) ,(GDestroyNotify) g_object_unref ); - - g_object_unref (g_object_ref_sink (tmp_batch)); } + + g_object_unref (link_op); + g_object_unref (tmp_batch); } if (!is_ready) @@ -2931,6 +3012,7 @@ typedef enum ,PROP_MAIN_TABLE ,PROP_UPDATE_FLAGS ,PROP_RESULT_POS + ,PROP_PARTIAL_DELETE } DbModelProp; @@ -2951,15 +3033,15 @@ static void db_model_set_property (DbModel * obj, guint property_id, case PROP_USE_FILE: obj->priv->use_file = g_value_get_boolean (value); break; - case PROP_MAIN_TABLE: - db_model_request_main_table (obj, g_value_get_string (value)); - break; case PROP_UPDATE_FLAGS: db_model_request_update_flags (obj, g_value_get_flags (value)); break; case PROP_RESULT_POS: obj->priv->result_pos = g_value_get_uint (value); break; + case PROP_PARTIAL_DELETE: + obj->priv->partial_delete = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); } @@ -2991,6 +3073,9 @@ static void db_model_get_property (DbModel * obj, guint property_id, case PROP_RESULT_POS: g_value_set_uint (value, obj->priv->result_pos); break; + case PROP_PARTIAL_DELETE: + g_value_set_boolean (value, obj->priv->partial_delete); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); } @@ -3008,11 +3093,11 @@ static void db_model_init (DbModel *obj) priv->sql = NULL; priv->request = NULL; priv->status = DB_MODEL_STATUS_CLEAN; - priv->mode = DB_MODEL_MODE_ON_CHANGE; priv->result = NULL; priv->result_pos = 0; priv->data = NULL; priv->column = NULL; + priv->stamp = g_random_int (); priv->column_index = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -3020,33 +3105,31 @@ static void db_model_init (DbModel *obj) NULL ); - priv->stamp = g_random_int (); + priv->defaults = g_hash_table_new_full ( + (GHashFunc) field_hash, + (GEqualFunc) field_equal, + (GDestroyNotify) field_free, + (GDestroyNotify) column_def_free + ); priv->fresh = TRUE; priv->sort_column_id = DB_MODEL_UNSORTED_SORT_COLUMN_ID; priv->default_sort_data = NULL; priv->default_sort_func = NULL; priv->default_sort_destroy = NULL; - - priv->link_op = NULL; - priv->internal_batch = NULL; - priv->column_defaults = g_hash_table_new_full ( - (GHashFunc) field_hash, - (GEqualFunc) field_equal, - (GDestroyNotify) field_free, - (GDestroyNotify) column_def_free - ); priv->updatable_data_allocated = FALSE; - priv->update_flags = 0; priv->user_update_flags = DB_MODEL_ALL; + priv->update_flags = 0; priv->main_table = NULL; - priv->user_main_table = NULL; + priv->mode = DB_MODEL_MODE_ON_CHANGE; priv->operation = NULL; priv->row_ops = NULL; - priv->join = NULL; priv->pending_request = NULL; priv->tables = NULL; + priv->column_table = NULL; + priv->partial_delete = FALSE; + priv->join = NULL; } static void db_model_finalize (DbModel * obj) @@ -3061,18 +3144,15 @@ static void db_model_finalize (DbModel * obj) g_free (priv->sql); g_hash_table_destroy (priv->column_index); db_model_set_batch (obj, NULL); - - g_clear_object (&priv->link_op); - g_clear_object (&priv->internal_batch); - g_hash_table_destroy (priv->column_defaults); + g_hash_table_destroy (priv->defaults); if (priv->updatable_data_allocated) { - g_free (priv->user_main_table); g_queue_free (priv->operation); - g_hash_table_destroy (priv->row_ops); - g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); - g_hash_table_destroy (priv->tables); + g_hash_table_unref (priv->row_ops); + g_hash_table_unref (priv->tables); + g_free (priv->column_table); +// g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); } parent->finalize (G_OBJECT (obj)); @@ -3241,7 +3321,7 @@ static void db_model_class_init (DbModelClass *k) ,_("Main Table") ,_("The main table of the model") ,NULL - ,G_PARAM_READWRITE + ,G_PARAM_READABLE )); g_object_class_install_property (klass, PROP_UPDATE_FLAGS, @@ -3263,6 +3343,15 @@ static void db_model_class_init (DbModelClass *k) ,0 ,G_PARAM_READWRITE )); + + g_object_class_install_property (klass, PROP_PARTIAL_DELETE, + g_param_spec_boolean ("partial-delete" + ,_("Partial delete") + ,_("When a row is deleted set all the fields from " + "the table to null rather than delete it.") + ,FALSE + ,G_PARAM_READWRITE + )); } GType db_model_update_flags_get_type () diff --git a/db/db-model.h b/db/db-model.h index 831988e..b8f6c0f 100644 --- a/db/db-model.h +++ b/db/db-model.h @@ -197,7 +197,6 @@ void db_model_add_pre_stmt (DbModel * obj, SqlStmt * stmt); void db_model_add_post_stmt (DbModel * obj, SqlStmt * stmt); DbModelStatus db_model_get_status (DbModel * obj); const gchar * db_model_get_main_table (DbModel * obj); -void db_model_request_main_table (DbModel * obj, const gchar * table); DbModelUpdateFlags db_model_get_update_flags (DbModel * obj); void db_model_request_update_flags (DbModel * obj ,DbModelUpdateFlags flags); diff --git a/db/db-result.c b/db/db-result.c index 2e89d9d..44aca24 100644 --- a/db/db-result.c +++ b/db/db-result.c @@ -72,6 +72,8 @@ DbResult * db_result_copy (const DbResult * obj) result->column[n].info = obj->column[n].info; result->column[n].spec = gvn_param_spec_copy (obj->column[n].spec); result->column[n].table = g_strdup (obj->column[n].table); + result->column[n].table_alias = g_strdup (obj->column[n].table_alias); + result->column[n].schema = g_strdup (obj->column[n].schema); result->column[n].name = g_strdup (obj->column[n].name); result->column[n].alias = g_strdup (obj->column[n].alias); } @@ -107,6 +109,8 @@ void db_result_free (DbResult * obj) g_free (col.name); g_free (col.alias); g_free (col.table); + g_free (col.table_alias); + g_free (col.schema); } g_free (obj->column); diff --git a/db/db-result.h b/db/db-result.h index 6c9be48..8a1a3fd 100644 --- a/db/db-result.h +++ b/db/db-result.h @@ -69,13 +69,13 @@ DbColumnInfo; **/ struct _DbColumn { - DbColumnInfo info; - GvnParamSpec * spec; - gchar * schema; - gchar * table; - gchar * table_alias; gchar * name; gchar * alias; + gchar * table; + gchar * table_alias; + gchar * schema; + DbColumnInfo info; + GvnParamSpec * spec; }; GType db_result_get_type (); diff --git a/module/data/customer.glade b/module/data/customer.glade index 27e07b4..223d9c0 100644 --- a/module/data/customer.glade +++ b/module/data/customer.glade @@ -1,11 +1,11 @@ - + - SELECT id, street, pc, city, province, ok FROM user_address WHERE #link ORDER BY id + SELECT id, street, pc, city, province, ok, user_id FROM user_address WHERE #link ORDER BY id SELECT id, name, credit, active, born, photo, object_id FROM "user" ORDER BY id @@ -348,6 +348,13 @@ True + + + User + user_id + True + + diff --git a/plugin/pg/db-pg.c b/plugin/pg/db-pg.c index 6d5325f..3ab937e 100644 --- a/plugin/pg/db-pg.c +++ b/plugin/pg/db-pg.c @@ -628,6 +628,7 @@ static DbResultSet * __db_pg_query r->column[j].info = 0; r->column[j].name = NULL; r->column[j].table = NULL; + r->column[j].table_alias = NULL; r->column[j].schema = NULL; if (GPOINTER_TO_INT (g_ptr_array_index (col_iter, j)) == 0) @@ -650,6 +651,7 @@ static DbResultSet * __db_pg_query r->column[j].alias = g_strdup (r->column[j].name); r->column[j].table = g_strdup (""); + r->column[j].table_alias = g_strdup (""); r->column[j].spec = gvn_param_spec_new_with_attrs (((GType*) g_ptr_array_index (types, ind))[j] , FALSE, FALSE, NULL); @@ -763,8 +765,12 @@ static DbResultSet * __db_pg_query guint n; if (!r->column[j].table) + { r->column[j].table = g_strdup (PQgetvalue (res_col, k, 1)); + r->column[j].table_alias = + g_strdup (r->column[j].table); + } g_strfreev (pkey); pkey = g_strsplit (PQgetvalue (res_col, k, 2), " ", G_MAXINT); diff --git a/sql/sql-batch.c b/sql/sql-batch.c index 4436b2c..8b79382 100644 --- a/sql/sql-batch.c +++ b/sql/sql-batch.c @@ -48,9 +48,12 @@ static void sql_batch_item_changed (SqlObject * item, SqlBatch * obj) static void sql_batch_free_item (SqlBatch * obj, SqlObject * item) { - g_signal_handlers_disconnect_by_func (item, - sql_batch_item_changed, obj); - g_object_unref (item); + if (item) + { + g_signal_handlers_disconnect_by_func (item, + sql_batch_item_changed, obj); + g_object_unref (item); + } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public diff --git a/sql/sql-field.h b/sql/sql-field.h index f21e85b..064bbe6 100644 --- a/sql/sql-field.h +++ b/sql/sql-field.h @@ -22,8 +22,8 @@ #include "sql-target.h" #define SQL_TYPE_FIELD (sql_field_get_type ()) -#define SQL_FIELD(object) (G_TYPE_CHECK_INSTANCE_CAST (object, SQL_TYPE_FIELD, SqlField)) -#define SQL_IS_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SQL_TYPE_FIELD)) +#define SQL_FIELD(self) (G_TYPE_CHECK_INSTANCE_CAST (self, SQL_TYPE_FIELD, SqlField)) +#define SQL_IS_FIELD(self) (G_TYPE_CHECK_INSTANCE_TYPE ((self), SQL_TYPE_FIELD)) typedef struct _SqlField SqlField; typedef struct _SqlFieldClass SqlFieldClass; @@ -49,10 +49,10 @@ SqlObject * sql_field_new_with_target (const gchar * name ,const gchar * schema); const gchar * sql_field_get_name (SqlField * self); -void sql_field_set_name (SqlField * obj, const gchar * name); +void sql_field_set_name (SqlField * self, const gchar * name); const gchar * sql_field_get_target (SqlField * self); -void sql_field_set_target (SqlField * obj, const gchar * target); +void sql_field_set_target (SqlField * self, const gchar * target); const gchar * sql_field_get_schema (SqlField * self); -void sql_field_set_schema (SqlField * obj, const gchar * schema); +void sql_field_set_schema (SqlField * self, const gchar * schema); #endif diff --git a/sql/sql-holder.c b/sql/sql-holder.c index 36df2a5..c44d255 100644 --- a/sql/sql-holder.c +++ b/sql/sql-holder.c @@ -31,36 +31,36 @@ SqlObject * sql_holder_new (const gchar * id) //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_holder_render (SqlHolder * obj, SqlRender * render, SqlBatch * batch) +static void sql_holder_render (SqlHolder * self, SqlRender * render, SqlBatch * batch) { - SqlObject * object = batch ? sql_batch_get (batch, obj->id) : NULL; + SqlObject * object = batch ? sql_batch_get (batch, self->id) : NULL; if (object) sql_render_add_object (render, object); else - sql_render_printf (render, "#%s", obj->id); + sql_render_printf (render, "#%s", self->id); } -static void sql_holder_find_holders (SqlHolder * obj, SqlBatch * batch) +static void sql_holder_find_holders (SqlHolder * self, SqlBatch * batch) { - sql_batch_add (batch, obj->id, NULL); + sql_batch_add (batch, self->id, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** * sql_holder_get_id: - * @obj: the #SqlHolder + * @self: the #SqlHolder * * Gets the identifier assigned to the holder. * * Return value: (transfer none): the id **/ -const gchar * sql_holder_get_id (SqlHolder * obj) +const gchar * sql_holder_get_id (SqlHolder * self) { - g_return_val_if_fail (SQL_IS_HOLDER (obj), NULL); + g_return_val_if_fail (SQL_IS_HOLDER (self), NULL); - return obj->id; + return self->id; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties @@ -70,44 +70,44 @@ enum PROP_ID = 1 }; -static void sql_holder_set_property (SqlHolder * obj, guint id, +static void sql_holder_set_property (SqlHolder * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_ID: - g_free (obj->id); - obj->id = g_value_dup_string (value); + g_free (self->id); + self->id = g_value_dup_string (value); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_holder_get_property (SqlHolder * obj, guint id, +static void sql_holder_get_property (SqlHolder * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_ID: - g_value_set_string (value, sql_holder_get_id (obj)); + g_value_set_string (value, sql_holder_get_id (self)); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_holder_init (SqlHolder * obj) +static void sql_holder_init (SqlHolder * self) { - obj->id = NULL; + self->id = NULL; } -static void sql_holder_finalize (SqlHolder * obj) +static void sql_holder_finalize (SqlHolder * self) { - g_free (obj->id); - G_OBJECT_CLASS (sql_holder_parent_class)->finalize (G_OBJECT (obj)); + g_free (self->id); + G_OBJECT_CLASS (sql_holder_parent_class)->finalize (G_OBJECT (self)); } static void sql_holder_class_init (SqlHolderClass * k) diff --git a/sql/sql-holder.h b/sql/sql-holder.h index 76da647..03487a7 100644 --- a/sql/sql-holder.h +++ b/sql/sql-holder.h @@ -19,8 +19,8 @@ #define SQL_HOLDER_H #define SQL_TYPE_HOLDER (sql_holder_get_type ()) -#define SQL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_HOLDER, SqlHolder)) -#define SQL_IS_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_HOLDER)) +#define SQL_HOLDER(self) (G_TYPE_CHECK_INSTANCE_CAST (self, SQL_TYPE_HOLDER, SqlHolder)) +#define SQL_IS_HOLDER(self) (G_TYPE_CHECK_INSTANCE_TYPE (self, SQL_TYPE_HOLDER)) typedef struct _SqlHolder SqlHolder; typedef struct _SqlHolderClass SqlHolderClass; @@ -41,6 +41,6 @@ struct _SqlHolderClass GType sql_holder_get_type (); SqlObject * sql_holder_new (const gchar * id); -const gchar * sql_holder_get_id (SqlHolder * obj); +const gchar * sql_holder_get_id (SqlHolder * self); #endif \ No newline at end of file diff --git a/sql/sql-join.c b/sql/sql-join.c index 9c88c23..592e433 100644 --- a/sql/sql-join.c +++ b/sql/sql-join.c @@ -47,51 +47,58 @@ static const gchar * SQL_JOIN_TYPE[] = ,"RIGHT" }; -static void sql_join_render (SqlJoin * obj, SqlRender * render) +static void sql_join_render (SqlJoin * self, 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_item (render, TRUE, NULL, self->target_left); + sql_render_add_token (render, SQL_JOIN_TYPE[self->type]); sql_render_add_token (render, "JOIN"); - sql_render_add_item (render, TRUE, NULL, obj->target_right); + sql_render_add_item (render, TRUE, NULL, self->target_right); - if (obj->has_using) + if (self->has_using) { sql_render_add_token (render, "USING"); sql_render_append (render, "("); - sql_render_add_list (render, TRUE, NULL, obj->using_fields, ","); + sql_render_add_list (render, TRUE, NULL, self->using_fields, ","); sql_render_append (render, ")"); } else - sql_render_add_item (render, FALSE, "ON", obj->condition); + sql_render_add_item (render, FALSE, "ON", self->condition); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public -void sql_join_set_target_left (SqlJoin * obj, SqlTarget * target) +SqlJoinType sql_join_get_join_type (SqlJoin * self) { - 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); + g_return_if_fail (SQL_IS_JOIN (self)); + + return self->type; } -void sql_join_set_target_right (SqlJoin * obj, SqlTarget * target) +void sql_join_set_target_left (SqlJoin * self, SqlTarget * target) { - g_return_if_fail (SQL_IS_JOIN (obj)); + g_return_if_fail (SQL_IS_JOIN (self)); 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); + sql_object_remove (self, self->target_left); + self->target_left = sql_object_add (self, target); } -void sql_join_set_condition (SqlJoin * obj, SqlExpr * condition) +void sql_join_set_target_right (SqlJoin * self, SqlTarget * target) { - g_return_if_fail (SQL_IS_JOIN (obj)); + g_return_if_fail (SQL_IS_JOIN (self)); + g_return_if_fail (SQL_IS_TARGET (target) || SQL_IS_HOLDER (target) || !target); + + sql_object_remove (self, self->target_right); + self->target_right = sql_object_add (self, target); +} + +void sql_join_set_condition (SqlJoin * self, SqlExpr * condition) +{ + g_return_if_fail (SQL_IS_JOIN (self)); 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); + sql_object_remove (self, self->condition); + self->condition = sql_object_add (self, condition); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties @@ -106,80 +113,80 @@ enum ,PROP_USING_FIELDS }; -static void sql_join_set_property (SqlJoin * obj, guint id, +static void sql_join_set_property (SqlJoin * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_TARGET_LEFT: - sql_join_set_target_left (obj, g_value_get_object (value)); + sql_join_set_target_left (self, g_value_get_object (value)); break; case PROP_TARGET_RIGHT: - sql_join_set_target_right (obj, g_value_get_object (value)); + sql_join_set_target_right (self, g_value_get_object (value)); break; case PROP_TYPE: - obj->type = g_value_get_enum (value); + self->type = g_value_get_enum (value); break; case PROP_CONDITION: - sql_join_set_condition (obj, g_value_get_object (value)); + sql_join_set_condition (self, g_value_get_object (value)); break; case PROP_HAS_USING: - obj->has_using = g_value_get_boolean (value); + self->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)); + sql_object_remove (self, self->using_fields); + self->using_fields = sql_object_add (self, g_value_get_object (value)); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_join_get_property (SqlJoin * obj, guint id, +static void sql_join_get_property (SqlJoin * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_TARGET_LEFT: - g_value_set_object (value, obj->target_left); + g_value_set_object (value, self->target_left); break; case PROP_TARGET_RIGHT: - g_value_set_object (value, obj->target_right); + g_value_set_object (value, self->target_right); break; case PROP_TYPE: - g_value_set_enum (value, obj->type); + g_value_set_enum (value, self->type); break; case PROP_CONDITION: - g_value_set_object (value, obj->condition); + g_value_set_object (value, self->condition); break; case PROP_HAS_USING: - g_value_set_boolean (value, obj->has_using); + g_value_set_boolean (value, self->has_using); break; case PROP_USING_FIELDS: - g_value_set_object (value, obj->using_fields); + g_value_set_object (value, self->using_fields); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_join_init (SqlJoin * obj) +static void sql_join_init (SqlJoin * self) { - obj->target_left = NULL; - obj->target_right = NULL; - obj->condition = NULL; - obj->using_fields = NULL; + self->target_left = NULL; + self->target_right = NULL; + self->condition = NULL; + self->using_fields = NULL; } -static void sql_join_finalize (SqlJoin * obj) +static void sql_join_finalize (SqlJoin * self) { - 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)); + sql_object_remove (self, self->target_left); + sql_object_remove (self, self->target_right); + sql_object_remove (self, self->condition); + sql_object_remove (self, self->using_fields); + G_OBJECT_CLASS (sql_join_parent_class)->finalize (G_OBJECT (self)); } static void sql_join_class_init (SqlJoinClass * klass) diff --git a/sql/sql-join.h b/sql/sql-join.h index 7e342c4..3058d3d 100644 --- a/sql/sql-join.h +++ b/sql/sql-join.h @@ -22,8 +22,8 @@ #include "sql-expr.h" #define SQL_TYPE_JOIN (sql_join_get_type ()) -#define SQL_IS_JOIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_JOIN)) -#define SQL_JOIN(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_JOIN, SqlJoin)) +#define SQL_IS_JOIN(self) (G_TYPE_CHECK_INSTANCE_TYPE (self, SQL_TYPE_JOIN)) +#define SQL_JOIN(self) (G_TYPE_CHECK_INSTANCE_CAST (self, SQL_TYPE_JOIN, SqlJoin)) #define SQL_TYPE_JOIN_TYPE (sql_join_type_get_type ()) @@ -60,8 +60,9 @@ GType sql_join_get_type (); GType sql_join_type_get_type (); SqlObject * sql_join_new (SqlTarget * left, SqlTarget * right, SqlJoinType type); -void sql_join_set_condition (SqlJoin * obj, SqlExpr * condition); -void sql_join_set_target_right (SqlJoin * obj, SqlTarget * target); -void sql_join_set_target_left (SqlJoin * obj, SqlTarget * target); +SqlJoinType sql_join_get_join_type (SqlJoin * self); +void sql_join_set_condition (SqlJoin * self, SqlExpr * condition); +void sql_join_set_target_right (SqlJoin * self, SqlTarget * target); +void sql_join_set_target_left (SqlJoin * self, SqlTarget * target); #endif \ No newline at end of file diff --git a/sql/sql-table.c b/sql/sql-table.c index e03e223..c2c3f0d 100644 --- a/sql/sql-table.c +++ b/sql/sql-table.c @@ -33,18 +33,68 @@ SqlObject * sql_table_new (const gchar * name, const gchar * schema) //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private -static void sql_table_render (SqlTable * obj, SqlRender * render) +static void sql_table_render (SqlTable * self, SqlRender * render) { - if (obj->schema) + if (self->schema) { - sql_render_add_identifier (render, obj->schema); + sql_render_add_identifier (render, self->schema); sql_render_append (render, "."); } - sql_render_add_identifier (render, obj->name); + sql_render_add_identifier (render, self->name); - if (g_strcmp0 (obj->name, SQL_TARGET (obj)->alias)) - sql_render_add_identifier (render, SQL_TARGET (obj)->alias); + if (SQL_TARGET (self)->alias) + sql_render_add_identifier (render, SQL_TARGET (self)->alias); +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public + +/** + * sql_table_get_name: + * @self: the #SqlTable + * + * Return value: the table name + **/ +const gchar * sql_table_get_name (SqlTable * self) +{ + return self->name; +} + +/** + * sql_table_set_name: + * @self: the #SqlTable + * @target: the target name + **/ +void sql_table_set_name (SqlTable * self, const gchar * name) +{ + g_return_if_fail (SQL_IS_TABLE (self)); + + g_free (self->name); + self->name = g_strdup (name); +} + +/** + * sql_table_get_schema: + * @self: the #SqlTable + * + * Return value: the schema name + **/ +const gchar * sql_table_get_schema (SqlTable * self) +{ + return self->schema; +} + +/** + * sql_table_set_schema: + * @self: the #SqlTable + * @schema: the schema name + **/ +void sql_table_set_schema (SqlTable * self, const gchar * schema) +{ + g_return_if_fail (SQL_IS_TABLE (self)); + + g_free (self->schema); + self->schema = g_strdup (schema); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties @@ -55,53 +105,53 @@ enum ,PROP_SCHEMA }; -static void sql_table_set_property (SqlTable * obj, guint id, +static void sql_table_set_property (SqlTable * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_NAME: - g_free (obj->name); - obj->name = g_value_dup_string (value); + g_free (self->name); + self->name = g_value_dup_string (value); break; case PROP_SCHEMA: - g_free (obj->schema); - obj->schema = g_value_dup_string (value); + g_free (self->schema); + self->schema = g_value_dup_string (value); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_table_get_property (SqlTable * obj, guint id, +static void sql_table_get_property (SqlTable * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_NAME: - g_value_set_string (value, obj->name); + g_value_set_string (value, self->name); break; case PROP_SCHEMA: - g_value_set_string (value, obj->schema); + g_value_set_string (value, self->schema); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_table_init (SqlTable * obj) +static void sql_table_init (SqlTable * self) { - obj->name = NULL; - obj->schema = NULL; + self->name = NULL; + self->schema = NULL; } -static void sql_table_finalize (SqlTable * obj) +static void sql_table_finalize (SqlTable * self) { - g_free (obj->name); - g_free (obj->schema); - G_OBJECT_CLASS (sql_table_parent_class)->finalize (G_OBJECT (obj)); + g_free (self->name); + g_free (self->schema); + G_OBJECT_CLASS (sql_table_parent_class)->finalize (G_OBJECT (self)); } static void sql_table_class_init (SqlTableClass * klass) diff --git a/sql/sql-table.h b/sql/sql-table.h index ed7f5b6..62c4fc1 100644 --- a/sql/sql-table.h +++ b/sql/sql-table.h @@ -21,8 +21,8 @@ #include "sql-target.h" #define SQL_TYPE_TABLE (sql_table_get_type ()) -#define SQL_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_TABLE, SqlTable)) -#define SQL_IS_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_TABLE)) +#define SQL_TABLE(self) (G_TYPE_CHECK_INSTANCE_CAST (self, SQL_TYPE_TABLE, SqlTable)) +#define SQL_IS_TABLE(self) (G_TYPE_CHECK_INSTANCE_TYPE (self, SQL_TYPE_TABLE)) typedef struct _SqlTable SqlTable; typedef struct _SqlTableClass SqlTableClass; @@ -40,7 +40,11 @@ struct _SqlTableClass SqlTargetClass parent; }; -GType sql_table_get_type (); -SqlObject * sql_table_new (const gchar * name, const gchar * schema); +GType sql_table_get_type (); +SqlObject * sql_table_new (const gchar * name, const gchar * schema); +const gchar * sql_table_get_name (SqlTable * self); +void sql_table_set_name (SqlTable * self, const gchar * name); +const gchar * sql_table_get_schema (SqlTable * self); +void sql_table_set_schema (SqlTable * self, const gchar * schema); #endif diff --git a/sql/sql-target.c b/sql/sql-target.c index 8213d9a..703867d 100644 --- a/sql/sql-target.c +++ b/sql/sql-target.c @@ -29,12 +29,28 @@ G_DEFINE_ABSTRACT_TYPE (SqlTarget, sql_target, SQL_TYPE_OBJECT); //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public -void sql_target_set_alias (SqlTarget * obj, const gchar * alias) +/** + * sql_target_set_alias: + * @self: the #SqlTargetClass + * @alias: the target alias + **/ +void sql_target_set_alias (SqlTarget * self, const gchar * alias) { - g_return_if_fail (SQL_IS_TARGET (obj)); + g_return_if_fail (SQL_IS_TARGET (self)); - g_free (obj->alias); - obj->alias = g_strdup (alias); + g_free (self->alias); + self->alias = g_strdup (alias); +} + +/** + * sql_target_get_alias: + * @self: the #SqlTargetClass + **/ +const gchar * sql_target_get_alias (SqlTarget * self) +{ + g_return_if_fail (SQL_IS_TARGET (self)); + + return self->alias; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties @@ -44,43 +60,43 @@ enum PROP_ALIAS = 1 }; -static void sql_target_set_property (SqlTarget * obj, guint id, +static void sql_target_set_property (SqlTarget * self, guint id, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_ALIAS: - sql_target_set_alias (obj, g_value_get_string (value)); + sql_target_set_alias (self, g_value_get_string (value)); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } -static void sql_target_get_property (SqlTarget * obj, guint id, +static void sql_target_get_property (SqlTarget * self, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_ALIAS: - g_value_set_string (value, obj->alias); + g_value_set_string (value, self->alias); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class -static void sql_target_init (SqlTarget * obj) +static void sql_target_init (SqlTarget * self) { - obj->alias = NULL; + self->alias = NULL; } -static void sql_target_finalize (SqlTarget * obj) +static void sql_target_finalize (SqlTarget * self) { - g_free (obj->alias); - G_OBJECT_CLASS (sql_target_parent_class)->finalize (G_OBJECT (obj)); + g_free (self->alias); + G_OBJECT_CLASS (sql_target_parent_class)->finalize (G_OBJECT (self)); } static void sql_target_class_init (SqlTargetClass * k) diff --git a/sql/sql-target.h b/sql/sql-target.h index 43a20e4..bafd2b3 100644 --- a/sql/sql-target.h +++ b/sql/sql-target.h @@ -21,8 +21,8 @@ #include "sql-object.h" #define SQL_TYPE_TARGET (sql_target_get_type ()) -#define SQL_TARGET(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, SQL_TYPE_TARGET, SqlTarget)) -#define SQL_IS_TARGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, SQL_TYPE_TARGET)) +#define SQL_TARGET(self) (G_TYPE_CHECK_INSTANCE_CAST (self, SQL_TYPE_TARGET, SqlTarget)) +#define SQL_IS_TARGET(self) (G_TYPE_CHECK_INSTANCE_TYPE (self, SQL_TYPE_TARGET)) typedef struct _SqlTarget SqlTarget; typedef struct _SqlTargetClass SqlTargetClass; @@ -39,7 +39,8 @@ struct _SqlTargetClass SqlObjectClass parent; }; -GType sql_target_get_type (); -void sql_target_set_alias (SqlTarget * obj, const gchar * alias); +GType sql_target_get_type (); +void sql_target_set_alias (SqlTarget * self, const gchar * alias); +const gchar * sql_target_get_alias (SqlTarget * self); #endif \ No newline at end of file From c0f5da67ac5631ea9bcfde9cd1b0f0a09b6b781e Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Thu, 12 Jun 2014 15:48:53 +0200 Subject: [PATCH 10/10] Reimplementado joins en el modelo --- db/db-model-private.c | 6 +- db/db-model.c | 1141 ++++++++++++++++++----------------------- db/db-model.h | 114 ++-- 3 files changed, 554 insertions(+), 707 deletions(-) diff --git a/db/db-model-private.c b/db/db-model-private.c index b9bd08a..0bd446e 100644 --- a/db/db-model-private.c +++ b/db/db-model-private.c @@ -76,7 +76,7 @@ DbOperation; **/ typedef struct { - DbModel * obj; + DbModel * self; GQueue * operations; SqlList * stmts; } @@ -180,8 +180,6 @@ typedef struct gchar * alias; GSList * pkeys; GHashTable * columns; - GSList * parent_columns; - GSList * child_columns; } TableInfo; @@ -192,8 +190,6 @@ static void table_info_free (TableInfo * table_info) 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); } //----------------------------------------------- ColumnDef diff --git a/db/db-model.c b/db/db-model.c index c2fdb3c..7d4005d 100644 --- a/db/db-model.c +++ b/db/db-model.c @@ -22,7 +22,7 @@ #include "db-row.h" #include "db-model-private.c" -#define MODEL_NOT_READY(obj) (obj->priv->status != DB_MODEL_STATUS_READY) +#define MODEL_NOT_READY(self) (self->priv->status != DB_MODEL_STATUS_READY) #define VALID_ITER(iter, model) (iter->data && iter->stamp == model->priv->stamp) #define DB_ROW_FIELD(row, field) (&((DbRow *) row)->value[field]) #define DB_ROW_POSITION(row) (((DbRow *) row)->position) @@ -97,7 +97,7 @@ struct _DbModelPrivate typedef struct { - DbModel * obj; + DbModel * self; DbIter * iter; gint col; } @@ -116,6 +116,8 @@ typedef struct { DbModelField * left; DbModelField * right; + Field * master; + Field * slave; } DbJoin; @@ -177,13 +179,13 @@ DbModel * db_model_new_with_file (DbConn * conn, const gchar * file) // Prototypes -static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj); -static void db_model_set_status (DbModel * obj +static void db_model_on_batch_changed (SqlBatch * batch, DbModel * self); +static void db_model_set_status (DbModel * self ,DbModelStatus status); -static void db_model_clear (DbModel * obj); -static void db_model_free_operation (DbModel * obj +static void db_model_clear (DbModel * self); +static void db_model_free_operation (DbModel * self ,DbOperation * op); -static void db_model_manage_join (DbModel * obj +static void db_model_manage_join (DbModel * self ,DbIter * iter ,gint col); @@ -207,43 +209,43 @@ static guint db_model_signal[LAST_SIGNAL] = {0}; // Default signal handlers -static void db_model_on_line_updated (DbModel * obj, DbIter * iter) +static void db_model_on_line_updated (DbModel * self, DbIter * iter) { - GValue * updated_value = obj->priv->updated_value; + GValue * updated_value = self->priv->updated_value; gint col; if (!updated_value || !G_IS_VALUE (updated_value)) return; - col = obj->priv->updated_col; + col = self->priv->updated_col; gvn_value_ccopy (updated_value, DB_ROW_FIELD (iter->data, col)); - db_model_manage_join (obj, iter, col); + db_model_manage_join (self, iter, col); g_value_unset (updated_value); g_free (updated_value); - obj->priv->updated_value = NULL; + self->priv->updated_value = NULL; } -static void db_model_on_line_deleted (DbModel * obj, gint position) +static void db_model_on_line_deleted (DbModel * self, gint position) { gint r_ind; - for (r_ind = position + 1; r_ind < obj->priv->result->nrows; r_ind++) - DB_ROW_POSITION (g_ptr_array_index (obj->priv->data, (guint) r_ind))--; + for (r_ind = position + 1; r_ind < self->priv->result->nrows; r_ind++) + DB_ROW_POSITION (g_ptr_array_index (self->priv->data, (guint) r_ind))--; - g_ptr_array_remove_index (obj->priv->data, (guint) position); + g_ptr_array_remove_index (self->priv->data, (guint) position); - obj->priv->result->nrows--; + self->priv->result->nrows--; } // External signal handlers -static void db_model_calculate_update_flags (DbModel * obj) +static void db_model_calculate_update_flags (DbModel * self) { gint i; Table table; TableInfo * tinfo; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; // Allocates aditional memory when the model is updatable @@ -296,8 +298,6 @@ static void db_model_calculate_update_flags (DbModel * obj) ,(GDestroyNotify) g_array_free ); tinfo->pkeys = NULL; - tinfo->parent_columns = NULL; - tinfo->child_columns = NULL; g_hash_table_insert (priv->tables, table_copy (&table), tinfo); } @@ -348,11 +348,11 @@ static void db_model_calculate_update_flags (DbModel * obj) } } -static void db_model_on_data_ready (DbRequest * request, DbModel * obj) +static void db_model_on_data_ready (DbRequest * request, DbModel * self) { gint i; DbResult * r; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; if (priv->request != request) { @@ -371,7 +371,7 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) if (!r->data && !r->column) { db_result_free (r); - db_model_set_status (obj, DB_MODEL_STATUS_CLEAN); + db_model_set_status (self, DB_MODEL_STATUS_CLEAN); } else { @@ -384,25 +384,40 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj) g_strdup (priv->column[i].alias), GINT_TO_POINTER (i)); } else - db_model_set_sort_column_id (obj, + db_model_set_sort_column_id (self, priv->old_sort_column_id, priv->old_order); - db_model_calculate_update_flags (obj); + db_model_calculate_update_flags (self); priv->fresh = FALSE; - db_model_set_status (obj, DB_MODEL_STATUS_READY); + db_model_set_status (self, DB_MODEL_STATUS_READY); } } else - db_model_set_status (obj, DB_MODEL_STATUS_ERROR); + db_model_set_status (self, DB_MODEL_STATUS_ERROR); g_clear_object (&priv->request); } -static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * row, GError * err) +static void db_model_set_table_fields_null (DbModel * self, TableInfo * tinfo, DbIter * iter) +{ + gint i; + DbModelPrivate * priv = self->priv; + + for (i = 0; i < priv->result->ncols; i++) + if (priv->column_table[i] == tinfo) + { + priv->updated_col = i; + priv->updated_value = + g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); + g_signal_emit (self, db_model_signal[LINE_UPDATED], 0, &iter); + } +} + +static void db_model_process_select (DbModel * self, DbRequest * request, DbRow * row, GError * err) { gint i, j; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; DbResult * result; DbRow * req_row; DbIter iter; @@ -411,7 +426,7 @@ static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * result = db_request_fetch_result (request, &err); - if (!(result && result->data && result->nrows > 0)) + if (!(result && result->data && result->ncols > 0)) goto exit; iter.data = row; @@ -421,7 +436,12 @@ static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * table.name = result->column[0].table_alias; table.schema = result->column[0].schema; - if ((tinfo = g_hash_table_lookup (priv->tables, &table))) + tinfo = g_hash_table_lookup (priv->tables, &table); + + if (!tinfo) + goto exit; + + if (result->nrows > 0) for (i = 0; i < result->ncols; i++) { GArray * cols = g_hash_table_lookup (tinfo->columns, result->column[i].name); @@ -438,11 +458,13 @@ static void db_model_process_insert (DbModel * obj, DbRequest * request, DbRow * g_value_copy (new_value, priv->updated_value); priv->updated_col = g_array_index (cols, gint, j); - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + g_signal_emit (self, db_model_signal[LINE_UPDATED], 0, &iter); } } + else + db_model_set_table_fields_null (self, tinfo, &iter); - exit: +exit: db_result_free (result); } @@ -453,8 +475,8 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d DbIter iter; DbOperation * op; GError * err = NULL; - DbModel * obj = data->obj; - DbModelPrivate * priv = obj->priv; + DbModel * self = data->self; + DbModelPrivate * priv = self->priv; for (l = data->operations->head; l; l = l->next) { @@ -465,7 +487,7 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d if (op->type & DB_MODEL_ROW_OP_INSERT && op->type & DB_MODEL_ROW_OP_DELETE) // INSERT + DELETE { - g_signal_emit (obj, + g_signal_emit (self, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); continue; } @@ -477,24 +499,15 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d if (op->type & DB_MODEL_ROW_OP_DELETE) // DELETE { - if (priv->partial_delete) - { - for (i = 0; i < priv->result->ncols; i++) - if (priv->column_table[i] == priv->main_table) - { - priv->updated_col = i; - priv->updated_value = - g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); - } - } - else - g_signal_emit (obj, + if (!priv->partial_delete) + g_signal_emit (self, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); + else + db_model_set_table_fields_null (self, priv->main_table, &iter); } else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { - db_model_process_insert (obj, request, op->row, err); + db_model_process_select (self, request, op->row, err); } else if (op->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE || INSERT + SELECT { @@ -510,10 +523,10 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d db_request_fetch_non_select (request, &err); if (G_OBJECT_TYPE (sql_list_get (list, j)) == SQL_TYPE_MULTI_STMT) - db_model_process_insert (obj, request, op->row, err); + db_model_process_select (self, request, op->row, err); } - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + g_signal_emit (self, db_model_signal[LINE_UPDATED], 0, &iter); } i++; @@ -529,97 +542,54 @@ static void db_model_on_operations_done (DbRequest * request, DbModelRequest * d if (!err) { while ((op = g_queue_pop_head (data->operations))) - db_model_free_operation (obj, op); + db_model_free_operation (self, op); - g_signal_emit (obj, db_model_signal[OPERATIONS_DONE], 0); + g_signal_emit (self, db_model_signal[OPERATIONS_DONE], 0); } } -static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * obj) +static void db_model_on_stmt_changed (SqlStmt * stmt, DbModel * self) { - obj->priv->fresh = TRUE; - db_model_refresh (obj); + self->priv->fresh = TRUE; + db_model_refresh (self); } -static void db_model_on_batch_changed (SqlBatch * batch, DbModel * obj) +static void db_model_on_batch_changed (SqlBatch * batch, DbModel * self) { - db_model_refresh (obj); + db_model_refresh (self); } static void db_model_on_join_query_done (DbRequest * request, JoinData * join_data) { - gint i, j; - DbResult * r; - DbIter * iter = join_data->iter; - GError * err = NULL; - DbModel * obj = join_data->obj; - DbModelPrivate * priv = obj->priv; - - while ((r = db_request_fetch_result (request, &err))) - { - for (i = 0; i < priv->result->ncols; i++) - for (j = 0; j < r->ncols; j++) - if (!g_strcmp0 (r->column[j].name, priv->column[i].name) - && !g_strcmp0 (r->column[j].table, priv->column[i].table) - && !g_strcmp0 (r->column[j].schema, priv->column[i].schema)) - { - if (r->nrows > 0) - { - GValue * new_value = - DB_ROW_FIELD (g_ptr_array_index (r->data, 0), j); - - priv->updated_value = g_new0 (GValue, 1); - g_value_init (priv->updated_value, G_VALUE_TYPE (new_value)); - gvn_value_copy (new_value, priv->updated_value); - } - else - priv->updated_value = - g_value_init (g_new0 (GValue, 1), GVN_TYPE_NULL); - - priv->updated_col = i; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, iter); - } - - db_result_free (r); - } - - if (err) - { - g_message ("%s", err->message); - g_error_free (err); - } - - priv->pending_request = - g_slist_remove (obj->priv->pending_request, request); - g_object_unref (request); + // db_model_process_select (self, request, row, err); } // Private helper methods and functions static void join_data_free (JoinData * join_data) { - g_object_unref (join_data->obj); + g_object_unref (join_data->self); db_iter_free (join_data->iter); g_free (join_data); } -static void db_model_free_operation (DbModel * obj, DbOperation * op) +static void db_model_free_operation (DbModel * self, DbOperation * op) { if (op->updated) g_slist_free_full (op->updated, (GDestroyNotify) db_updated_field_free); - g_hash_table_remove (obj->priv->row_ops, op->row); + g_hash_table_remove (self->priv->row_ops, op->row); g_free (op); } -static void db_model_clean_operations (DbModel * obj) +static void db_model_clean_operations (DbModel * self) { DbOperation * op; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; while ((op = g_queue_pop_head (priv->operation))) - db_model_free_operation (obj, op); + db_model_free_operation (self, op); } static void db_model_request_free (DbModelRequest * req) @@ -631,11 +601,11 @@ static void db_model_request_free (DbModelRequest * req) while ((op = g_queue_pop_head (req->operations))) { op->locked = FALSE; - g_queue_push_tail (req->obj->priv->operation, op); + g_queue_push_tail (req->self->priv->operation, op); } g_queue_free (req->operations); - g_object_unref (req->obj); + g_object_unref (req->self); g_object_unref (req->stmts); } @@ -652,18 +622,19 @@ static void db_operation_add_updated (DbOperation * op, gint col) return; u = g_new (DbUpdatedField, 1); - gvn_value_copy (DB_ROW_FIELD (op->row, col) - ,g_value_init (u->value = g_new0 (GValue, 1) - ,G_VALUE_TYPE (DB_ROW_FIELD (op->row, col)))); u->column = col; + u->value = g_value_init (g_new0 (GValue, 1) + ,G_VALUE_TYPE (DB_ROW_FIELD (op->row, col))); + g_value_copy (DB_ROW_FIELD (op->row, col), u->value); + op->type |= DB_MODEL_ROW_OP_UPDATE; op->updated = g_slist_prepend (op->updated, u); } -static gboolean db_model_set_row_operation (DbModel * obj, +static gboolean db_model_set_row_operation (DbModel * self, DbRow * row, DbModelRowOp type, gint col) { - DbOperation * op = g_hash_table_lookup (obj->priv->row_ops, row); + DbOperation * op = g_hash_table_lookup (self->priv->row_ops, row); if (!op) { @@ -676,8 +647,8 @@ static gboolean db_model_set_row_operation (DbModel * obj, if (type & DB_MODEL_ROW_OP_UPDATE) db_operation_add_updated (new_op, col); - g_hash_table_insert (obj->priv->row_ops, row, new_op); - g_queue_push_tail (obj->priv->operation, new_op); + g_hash_table_insert (self->priv->row_ops, row, new_op); + g_queue_push_tail (self->priv->operation, new_op); } else if (!op->locked) { @@ -693,12 +664,12 @@ static gboolean db_model_set_row_operation (DbModel * obj, return TRUE; } -void db_model_reverse_operations (DbModel * obj) +void db_model_reverse_operations (DbModel * self) { - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; DbOperation * op; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); while ((op = g_queue_pop_tail (priv->operation))) { @@ -712,15 +683,15 @@ void db_model_reverse_operations (DbModel * obj) { if (op->type & DB_MODEL_ROW_OP_INSERT) { - g_signal_emit (obj, + g_signal_emit (self, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); } else - g_signal_emit (obj, db_model_signal[LINE_TOGGLED], 0, &iter); + g_signal_emit (self, db_model_signal[LINE_TOGGLED], 0, &iter); } else if (op->type & DB_MODEL_ROW_OP_INSERT) { - g_signal_emit (obj, + g_signal_emit (self, db_model_signal[LINE_DELETED], 0, DB_ROW_POSITION (op->row)); } else if (op->type & DB_MODEL_ROW_OP_UPDATE) @@ -733,14 +704,14 @@ void db_model_reverse_operations (DbModel * obj) priv->updated_value = g_new0 (GValue, 1); g_value_init (priv->updated_value, G_VALUE_TYPE (u->value)); - gvn_value_copy (u->value, priv->updated_value); + g_value_copy (u->value, priv->updated_value); priv->updated_col = u->column; - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, &iter); + g_signal_emit (self, db_model_signal[LINE_UPDATED], 0, &iter); } } - db_model_free_operation (obj, op); + db_model_free_operation (self, op); } } @@ -833,29 +804,29 @@ static gint db_model_valcmp_desc (gpointer * a, gpointer * b, gpointer col) } -static void db_model_set_status (DbModel * obj, DbModelStatus status) +static void db_model_set_status (DbModel * self, DbModelStatus status) { - obj->priv->status = status; - g_signal_emit (obj, db_model_signal[STATUS_CHANGED], 0, status); + self->priv->status = status; + g_signal_emit (self, db_model_signal[STATUS_CHANGED], 0, status); } -static void db_model_cancel_pending_requests (DbModel * obj) +static void db_model_cancel_pending_requests (DbModel * self) { GSList * n; - for (n = obj->priv->pending_request; n; n = n->next) + for (n = self->priv->pending_request; n; n = n->next) db_request_cancel (n->data); } -static void db_model_add_pending_request (DbModel * obj, DbRequest * request) +static void db_model_add_pending_request (DbModel * self, DbRequest * request) { - obj->priv->pending_request = g_slist_prepend (obj->priv->pending_request, + self->priv->pending_request = g_slist_prepend (self->priv->pending_request, request); } -static void db_model_clear (DbModel * obj) +static void db_model_clear (DbModel * self) { - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; if (priv->request) { @@ -864,8 +835,8 @@ static void db_model_clear (DbModel * obj) } else if (priv->result) { - db_model_clean_operations (obj); - db_model_cancel_pending_requests (obj); + db_model_clean_operations (self); + db_model_cancel_pending_requests (self); db_result_free (priv->result); priv->result = NULL; @@ -884,9 +855,9 @@ static void db_model_clear (DbModel * obj) // Join related functions -static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) +static void db_model_manage_join (DbModel * self, DbIter * iter, gint col) { - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; if (priv->join && gvn_param_spec_get_editable (priv->column[col].spec) @@ -897,18 +868,6 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) gboolean send_request = FALSE, end = FALSE; SqlList * stmts = g_object_ref_sink (sql_list_new (SQL_TYPE_MULTI_STMT)); -// FIXME -// for (i = 0; i < obj->ncols; i++) -// // Check for multi-field pkeys to be fully set -// // need to know the total number of pkey fields -// if (i != col && obj->column[i].info & DB_COLUMN_PRI_KEY -// && gvn_value_is_null (DB_ROW_FIELD (iter->data, i)) -// && !g_strcmp0 (obj->column[i].table, obj->column[col].table)) -// { -// end = TRUE; -// break; -// } - if (!end) for (n = priv->join; n; n = n->next) { @@ -981,7 +940,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) DbRequest * request; join_data = g_new (JoinData, 1); - join_data->obj = g_object_ref (obj); + join_data->self = g_object_ref (self); join_data->iter = db_iter_copy (iter); join_data->col = col; @@ -992,7 +951,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col) ,join_data ,(GDestroyNotify) join_data_free ); - db_model_add_pending_request (obj, request); + db_model_add_pending_request (self, request); } g_object_unref (stmts); @@ -1037,12 +996,12 @@ static void db_join_free (DbJoin * join) g_free (join); } -static void db_model_calculate_col_def (DbModel * obj, SqlJoin * join, +static void db_model_calculate_col_def (DbModel * self, SqlJoin * join, SqlField * l_field, SqlField * r_field) { gint i, col = -1; gchar * dst = NULL; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; SqlField * f = NULL; SqlTarget * l_table = join->target_left, * r_table = join->target_right; @@ -1090,10 +1049,10 @@ static void db_model_calculate_col_def (DbModel * obj, SqlJoin * join, } if (f) - db_model_set_default_value_from_column (obj, dst, col); + db_model_set_default_value_from_column (self, dst, col); } -static void db_model_set_join_fields (DbModel * obj, SqlJoin * join, +static void db_model_set_join_fields (DbModel * self, SqlJoin * join, SqlField * lsql_field, SqlField * rsql_field, DbModelField * lfield, DbModelField * rfield) { @@ -1113,119 +1072,7 @@ static void db_model_set_join_fields (DbModel * obj, SqlJoin * join, g_strdup (check ? rsql_field->name : lsql_field->name)); } -static void db_model_post_process_query (DbModel * obj) -{ -// TODO When parser gets fully functional, these 3 lines won't be needed, -// because obj->stmt will be a parsed stmt: - gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, obj->priv->batch, NULL); - SqlObject * stmt = sql_parser_parse (rend); - - g_free (rend); - - if (stmt && SQL_IS_SELECT (stmt)) - { - DbModelField * lfield, * rfield; - SqlJoin * join; - GList * n; - SqlSelect * select = SQL_SELECT (stmt); - gboolean calculate_join = FALSE; - - for (n = sql_list_get_items (SQL_DML (select)->targets); n; n = n->next) - if ((join = n->data) - && SQL_IS_JOIN (join) - && SQL_IS_TABLE (join->target_left) - && SQL_IS_TABLE (join->target_right) - && SQL_IS_OPERATION (join->condition)) - { -// DbJoin and ColDef creation - GList * operators; - SqlOperation * op = SQL_OPERATION (join->condition); - SqlField * lsql_field = NULL, * rsql_field = NULL; - - lfield = db_model_field_new (SQL_TABLE (join->target_left)->name, NULL); - rfield = db_model_field_new (SQL_TABLE (join->target_right)->name, NULL); - - if (join->type == SQL_JOIN_TYPE_RIGHT) - rfield->main = TRUE; - else - lfield->main = TRUE; - - if (op->type == SQL_OPERATION_TYPE_AND) - { - GList * l; - - for (l = sql_list_get_items (op->operators); l; l = l->next) - { - SqlOperation * subop = l->data; - operators = sql_list_get_items (subop->operators); - - if (SQL_IS_OPERATION (subop) - && subop->type == SQL_OPERATION_TYPE_EQUAL - && operators->data // Left Field - && operators->next && operators->next->data) // Right Field - { - lsql_field = SQL_FIELD (operators->data); - rsql_field = SQL_FIELD (operators->next->data); - - db_model_set_join_fields (obj, join, - lsql_field, rsql_field, lfield, rfield); - - calculate_join = TRUE; - - if (join->type != SQL_JOIN_TYPE_INNER) - db_model_calculate_col_def - (obj, join, lsql_field, rsql_field); - } - else - { - calculate_join = FALSE; - break; - } - } - } - else - { - operators = sql_list_get_items (op->operators); - - if (op->type == SQL_OPERATION_TYPE_EQUAL && operators->data - && operators->next && operators->next->data) - { - lsql_field = SQL_FIELD (operators->data); - rsql_field = SQL_FIELD (operators->next->data); - - db_model_set_join_fields (obj, join, - lsql_field, rsql_field, lfield, rfield); - - calculate_join = TRUE; - - if (join->type != SQL_JOIN_TYPE_INNER) - db_model_calculate_col_def - (obj, join ,lsql_field, rsql_field); - } - } - - if (calculate_join) - { - DbJoin * join_res = g_new (DbJoin, 1); - join_res->left = lfield; - join_res->right = rfield; - - obj->priv->join = g_slist_prepend (obj->priv->join, join_res); - } - else - { - db_model_field_free (lfield); - db_model_field_free (rfield); - } - } - } - - if (G_IS_OBJECT (stmt)) - g_object_unref (stmt); - -} - -static gboolean db_model_analyse_join_op (DbModel * obj, SqlOperation * op) +static gboolean db_model_analyse_join_op (DbModel * self, SqlOperation * op) { gint i; gint noperands; @@ -1250,7 +1097,7 @@ static gboolean db_model_analyse_join_op (DbModel * obj, SqlOperation * op) else if (operator == SQL_OPERATION_TYPE_AND) { for (i = 0; i < noperands; i++) - if (!db_model_analyse_join_op (obj, sql_list_get (operands, i))) + if (!db_model_analyse_join_op (self, sql_list_get (operands, i))) return FALSE; return TRUE; @@ -1259,7 +1106,7 @@ static gboolean db_model_analyse_join_op (DbModel * obj, SqlOperation * op) return FALSE; } -static void db_model_analyse_join (DbModel * obj, SqlTarget * target) +static void db_model_analyse_join (DbModel * self, SqlTarget * target) { SqlJoin * join; SqlTarget * left; @@ -1278,7 +1125,7 @@ static void db_model_analyse_join (DbModel * obj, SqlTarget * target) ); if (SQL_IS_TABLE (left) || SQL_IS_TABLE (right)) - db_model_analyse_join_op (obj, on); + db_model_analyse_join_op (self, on); switch ((gint) sql_join_get_join_type (join)) { @@ -1290,18 +1137,18 @@ static void db_model_analyse_join (DbModel * obj, SqlTarget * target) break; } - db_model_analyse_join (obj, left); - db_model_analyse_join (obj, right); + db_model_analyse_join (self, left); + db_model_analyse_join (self, right); } -static void db_model_load_join (DbModel * obj) +static void db_model_load_join (DbModel * self) { gchar * sql; SqlObject * stmt; SqlObject * select; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; - sql = db_conn_render (obj->priv->conn, obj->priv->stmt, NULL, NULL); + sql = db_conn_render (self->priv->conn, self->priv->stmt, NULL, NULL); stmt = sql_parser_parse (sql); g_free (sql); @@ -1328,7 +1175,7 @@ static void db_model_load_join (DbModel * obj) g_object_get (select, "targets", &targets, NULL); for (i = 0; i < sql_list_length (targets); i++) - db_model_analyse_join (obj, sql_list_get (targets, i)); + db_model_analyse_join (self, sql_list_get (targets, i)); exit: g_object_unref (stmt); @@ -1340,23 +1187,23 @@ static void db_model_load_join (DbModel * obj) /** * db_model_set_conn: - * @obj: a #DbModel + * @self: a #DbModel * @conn: (allow-none): a #DbConn * * Sets the connection through which the communication is established with * the database. **/ -void db_model_set_conn (DbModel * obj, DbConn * conn) +void db_model_set_conn (DbModel * self, DbConn * conn) { - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); g_return_if_fail (DB_IS_CONN (conn) || !conn); if (conn) { - if (!obj->priv->conn) + if (!self->priv->conn) { - obj->priv->conn = g_object_ref (conn); - db_model_on_stmt_changed (obj->priv->stmt, obj); + self->priv->conn = g_object_ref (conn); + db_model_on_stmt_changed (self->priv->stmt, self); } else g_warning ("DbModel: The connection can only be set once"); @@ -1365,298 +1212,302 @@ void db_model_set_conn (DbModel * obj, DbConn * conn) /** * db_model_get_conn: - * @obj: a #DbModel + * @self: a #DbModel * * Returns the connection through which the communication is established with * the database. * * Return value: (transfer none): the #DbConn of the model **/ -DbConn * db_model_get_conn (DbModel * obj) +DbConn * db_model_get_conn (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); - return obj->priv->conn; + return self->priv->conn; } /** * db_model_get_spec: - * @obj: a #DbModel - * @col: the number of a column of @obj + * @self: a #DbModel + * @col: the number of a column of @self * - * Returns the #GvnParamSpec of a field in the position @col of @obj. + * Returns the #GvnParamSpec of a field in the position @col of @self. * * Return value: (transfer none): the #GvnParamSpec of the column with number @col **/ -const GvnParamSpec * db_model_get_spec (DbModel * obj, gint col) +const GvnParamSpec * db_model_get_spec (DbModel * self, gint col) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); - if ((obj->priv->result && 0 <= col - && col < obj->priv->result->ncols) - && obj->priv->column) - return obj->priv->column[col].spec; + if ((self->priv->result && 0 <= col + && col < self->priv->result->ncols) + && self->priv->column) + return self->priv->column[col].spec; return NULL; } /** * db_model_get_column_name: - * @obj: a #DbModel - * @col: the number of a column of @obj + * @self: a #DbModel + * @col: the number of a column of @self * - * Retrieves the name of a field in the position @col of @obj. + * Retrieves the name of a field in the position @col of @self. * * Return value: the name of the column with number @col **/ -const gchar * db_model_get_column_name (DbModel * obj, gint col) +const gchar * db_model_get_column_name (DbModel * self, gint col) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); - if ((obj->priv->result + if ((self->priv->result && 0 <= col - && col < obj->priv->result->ncols) - && obj->priv->column) - return obj->priv->column[col].alias; + && col < self->priv->result->ncols) + && self->priv->column) + return self->priv->column[col].alias; return NULL; } /** * db_model_get_column_index: - * @obj: a #DbModel - * @name: the name of a column of @obj + * @self: a #DbModel + * @name: the name of a column of @self * * Retrieves the position in the query of the column called @name. * * Return value: the index of the column with name @name or -1 if there isn't * a column called @name or if @name is NULL **/ -gint db_model_get_column_index (DbModel * obj, const gchar * name) +gint db_model_get_column_index (DbModel * self, const gchar * name) { - g_return_val_if_fail (DB_IS_MODEL (obj), -1); + g_return_val_if_fail (DB_IS_MODEL (self), -1); - if (!name || !obj->priv->column_index) + if (!name || !self->priv->column_index) return -1; - return GPOINTER_TO_INT (g_hash_table_lookup (obj->priv->column_index, name)); + return GPOINTER_TO_INT (g_hash_table_lookup (self->priv->column_index, name)); } /** * db_model_get_status: - * @obj: a #DbModel + * @self: a #DbModel * - * Returns the current #DbModelStatus of @obj. + * Returns the current #DbModelStatus of @self. * - * Return value: the status of @obj + * Return value: the status of @self **/ -DbModelStatus db_model_get_status (DbModel * obj) +DbModelStatus db_model_get_status (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), -1); - return obj->priv->status; + g_return_val_if_fail (DB_IS_MODEL (self), -1); + return self->priv->status; } /** * db_model_get_mode: - * @obj: a #DbModel + * @self: a #DbModel * - * Retrieves the current working mode of @obj. See #DbModelMode. + * Retrieves the current working mode of @self. See #DbModelMode. * * Return value: the current mode **/ -DbModelMode db_model_get_mode (DbModel * obj) +DbModelMode db_model_get_mode (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), -1); - return (obj->priv->mode); + g_return_val_if_fail (DB_IS_MODEL (self), -1); + return (self->priv->mode); } /** * db_model_set_mode: - * @obj: a #DbModel + * @self: a #DbModel * @mode: a #DbModelMode to set the model on * - * Sets the working mode of @obj to @mode. See #DbModelMode. + * Sets the working mode of @self to @mode. See #DbModelMode. **/ -void db_model_set_mode (DbModel * obj, DbModelMode mode) +void db_model_set_mode (DbModel * self, DbModelMode mode) { - g_return_if_fail (DB_IS_MODEL (obj)); - obj->priv->mode = mode; + g_return_if_fail (DB_IS_MODEL (self)); + self->priv->mode = mode; } /** * db_model_toggle_mode: - * @obj: a #DbModel + * @self: a #DbModel * - * Toogles the working mode of @obj. See #DbModelMode to see the two possible + * Toogles the working mode of @self. See #DbModelMode to see the two possible * modes. **/ -void db_model_toggle_mode (DbModel * obj) +void db_model_toggle_mode (DbModel * self) { - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - obj->priv->mode = (obj->priv->mode == DB_MODEL_MODE_ON_DEMAND)? + self->priv->mode = (self->priv->mode == DB_MODEL_MODE_ON_DEMAND)? DB_MODEL_MODE_ON_CHANGE: DB_MODEL_MODE_ON_DEMAND; } /** * db_model_set_result_pos: - * @obj: a #DbModel + * @self: a #DbModel * @pos: position of the query * * Sets the position where the query that will fill @model with data will be * placed in a multi-query statement. **/ -void db_model_set_result_pos (DbModel * obj, guint pos) +void db_model_set_result_pos (DbModel * self, guint pos) { - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - obj->priv->result_pos = pos; + self->priv->result_pos = pos; } /** * db_model_get_update_flags: - * @obj: a #DbModel + * @self: a #DbModel * - * Retrieves the update flags of @obj. See #DbModelUpdateFlags for the details + * Retrieves the update flags of @self. See #DbModelUpdateFlags for the details * of those flags. See also db_model_request_update_flags(). * - * Return value: the #DbModelUpdateFlags of @obj + * Return value: the #DbModelUpdateFlags of @self **/ -DbModelUpdateFlags db_model_get_update_flags (DbModel * obj) +DbModelUpdateFlags db_model_get_update_flags (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); - return obj->priv->update_flags; + return self->priv->update_flags; } /** * db_model_request_update_flags: - * @obj: a #DbModel - * @flags: the set of #DbModelUpdateFlags to be set to @obj + * @self: a #DbModel + * @flags: the set of #DbModelUpdateFlags to be set to @self * - * Requests the update flags of @obj. See #DbModelUpdateFlags for the details - * of those flags. If @obj does not allow an operation by itself, it will + * Requests the update flags of @self. See #DbModelUpdateFlags for the details + * of those flags. If @self does not allow an operation by itself, it will * log a warning when trying to set this operation. If the flag set is * #DB_MODEL_UPDATE it may not log until trying to update a non-updatable * field, see db_model_set_value(). See also db_model_get_update_flags() and * db_model_unset_update_flags(). **/ -void db_model_request_update_flags (DbModel * obj, DbModelUpdateFlags flags) +void db_model_request_update_flags (DbModel * self, DbModelUpdateFlags flags) { - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - obj->priv->user_update_flags = flags; - db_model_calculate_update_flags (obj); + self->priv->user_update_flags = flags; + db_model_calculate_update_flags (self); } /** * db_model_unset_update_flags: - * @obj: a #DbModel - * @flags: the set of #DbModelUpdateFlags to be unset in @obj + * @self: a #DbModel + * @flags: the set of #DbModelUpdateFlags to be unset in @self * - * Unsets the update flags of @obj. See #DbModelUpdateFlags for the details + * Unsets the update flags of @self. See #DbModelUpdateFlags for the details * of those flags. See also db_model_get_update_flags() and * db_model_request_update_flags(). **/ -void db_model_unset_update_flags (DbModel * obj, DbModelUpdateFlags flags) +void db_model_unset_update_flags (DbModel * self, DbModelUpdateFlags flags) { - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - obj->priv->user_update_flags &= ~flags; - db_model_calculate_update_flags (obj); + self->priv->user_update_flags &= ~flags; + db_model_calculate_update_flags (self); } /** * db_model_get_last: - * @obj: a @DbModel + * @self: a @DbModel * @iter: (out): an unitialized #DbIter * - * Points @iter to the last row of @obj. + * Points @iter to the last row of @self. * - * Return value: %FALSE if @obj is a valid #DbModel, %TRUE otherwise + * Return value: %FALSE if @self is a valid #DbModel, %TRUE otherwise **/ -gboolean db_model_get_last (DbModel * obj, DbIter * iter) +gboolean db_model_get_last (DbModel * self, DbIter * iter) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); iter->data = g_ptr_array_index - (obj->priv->data, (guint) obj->priv->data->len - 1); - iter->stamp = obj->priv->stamp; + (self->priv->data, (guint) self->priv->data->len - 1); + iter->stamp = self->priv->stamp; return TRUE; } /** - * db_model_add_join_columns: - * @obj: a #DbModel - * @left: the field on the left of the join - * @right: the field on the right of the join + * db_model_add_join: + * @self: a #DbModel + * @master_field: the field on the left of the join + * @slave_field: the field on the right of the join * * Sets the binding betwen two joined fields. This will generate a SELECT query * to the database to change the corresponding values in the model. Currently * it's used by the internal parser. **/ -void db_model_add_join_columns (DbModel * obj, const gchar * left, const gchar * right) +void db_model_add_join (DbModel * self, + const gchar * master_field, const gchar * slave_field) { - g_return_if_fail (DB_IS_MODEL (obj)); + DbJoin * join; - DbJoin * join = g_new (DbJoin, 1); -// join->left = db_model_field_new_from_string (left); -// join->right = db_model_field_new_from_string (right); - - obj->priv->join = g_slist_prepend (obj->priv->join, join); + g_return_if_fail (DB_IS_MODEL (self)); + g_return_if_fail (master_field); + g_return_if_fail (slave_field); + + join = g_new (DbJoin, 1); + join->master = field_new_from_string (master_field); + join->slave = field_new_from_string (slave_field); + self->priv->join = g_slist_prepend (self->priv->join, join); } /** * db_model_get_batch: - * @obj: a #DbModel + * @self: a #DbModel * @return: the #SqlBatch * * Gets the batch used by the model. **/ -SqlBatch * db_model_get_batch (DbModel * obj) +SqlBatch * db_model_get_batch (DbModel * self) { - return obj->priv->batch; + return self->priv->batch; } /** * db_model_set_batch: - * @obj: a #DbModel + * @self: a #DbModel * @batch: the #SqlBatch * * Sets the batch used by the model. **/ -void db_model_set_batch (DbModel * obj, SqlBatch * batch) +void db_model_set_batch (DbModel * self, SqlBatch * batch) { DbModelPrivate * priv; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); g_return_if_fail (SQL_IS_BATCH (batch) || !batch); - priv = obj->priv; + priv = self->priv; if (priv->batch) { g_signal_handlers_disconnect_by_func (priv->batch, - db_model_on_batch_changed, obj); + db_model_on_batch_changed, self); g_object_unref (priv->batch); } if (batch) { g_signal_connect (batch, "changed", - G_CALLBACK (db_model_on_batch_changed), obj); + G_CALLBACK (db_model_on_batch_changed), self); g_object_ref_sink (batch); } priv->batch = batch; } -static ColumnDef * db_model_create_column_def (DbModel * obj, const gchar * field_str) +static ColumnDef * db_model_create_column_def (DbModel * self, const gchar * field_str) { Field * field = field_new_from_string (field_str); if (field->name && field->target && !field->schema) { ColumnDef * def = column_def_new (); - g_hash_table_insert (obj->priv->defaults, field, def); + g_hash_table_insert (self->priv->defaults, field, def); return def; } else @@ -1668,27 +1519,27 @@ static ColumnDef * db_model_create_column_def (DbModel * obj, const gchar * fiel return NULL; } -static void db_model_on_param_changed (GvnParam * param, GValue * value, DbModel * obj) +static void db_model_on_param_changed (GvnParam * param, GValue * value, DbModel * self) { - db_model_refresh (obj); + db_model_refresh (self); } /** * db_model_set_default_value_from_column: - * @obj: a #DbModel + * @self: a #DbModel * @field_str: the field to be set * @column_str: field from wich the value is picked **/ -void db_model_set_default_value_from_column (DbModel * obj, +void db_model_set_default_value_from_column (DbModel * self, const gchar * field_str, const gchar * column_str) { ColumnDef * def; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); g_return_if_fail (field_str); g_return_if_fail (column_str); - def = db_model_create_column_def (obj, field_str); + def = db_model_create_column_def (self, field_str); if (def) def->src_column = field_new_from_string (column_str); @@ -1696,23 +1547,23 @@ void db_model_set_default_value_from_column (DbModel * obj, /** * db_model_set_default_value_from_param: - * @obj: a #DbModel + * @self: a #DbModel * @field_str: the field to be set * @param: a #GvnParam * @link: * - * Get the default value for @dst_field from @param. + * Get the default value for @field_str from @param. **/ -void db_model_set_default_value_from_param (DbModel * obj, +void db_model_set_default_value_from_param (DbModel * self, const gchar * field_str, GvnParam * param, gboolean link) { ColumnDef * def; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); g_return_if_fail (field_str); g_return_if_fail (GVN_IS_PARAM (param)); - def = db_model_create_column_def (obj, field_str); + def = db_model_create_column_def (self, field_str); if (!def) return; @@ -1721,14 +1572,14 @@ void db_model_set_default_value_from_param (DbModel * obj, if (link) def->link = g_signal_connect (param, "value-changed", - G_CALLBACK (db_model_on_param_changed), obj); + G_CALLBACK (db_model_on_param_changed), self); } /** * db_model_get_main_table: - * @obj: a #DbModel + * @self: a #DbModel * - * Returns the string with the name of the main table of @obj. The main table + * Returns the string with the name of the main table of @self. The main table * is the only table on a #DbModel whose rows can be deleted or inserted. By * default the main table is set to the table the first column field belongs. * To override this behaviour, use @db_model_request_main_table. @@ -1736,83 +1587,83 @@ void db_model_set_default_value_from_param (DbModel * obj, * Note that the requested main table may be different fron the actual main * table used by the model * - * Return value: the name of the main table of @obj + * Return value: the name of the main table of @self **/ -const gchar * db_model_get_main_table (DbModel * obj) +const gchar * db_model_get_main_table (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); - if (obj->priv->main_table) - return obj->priv->main_table->name; + if (self->priv->main_table) + return self->priv->main_table->name; return NULL; } /** * db_model_get_stmt: - * @obj: a #DbModel + * @self: a #DbModel * - * Returns the #SqlStmt which queries to the database about the data of @obj. + * Returns the #SqlStmt which queries to the database about the data of @self. * - * Return value: (transfer none): the #SqlStmt property of @obj + * Return value: (transfer none): the #SqlStmt property of @self **/ -const SqlStmt * db_model_get_stmt (DbModel * obj) +const SqlStmt * db_model_get_stmt (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); - return obj->priv->stmt; + return self->priv->stmt; } /** * db_model_set_stmt: - * @obj: a #DbModel + * @self: a #DbModel * @stmt: the #SqlStmt * * Sets the "stmt" property of the model. **/ -void db_model_set_stmt (DbModel * obj, SqlStmt * stmt) +void db_model_set_stmt (DbModel * self, SqlStmt * stmt) { if (!stmt) return; - g_return_if_fail (!obj->priv->stmt); + g_return_if_fail (!self->priv->stmt); g_return_if_fail (SQL_IS_STRING (stmt) || SQL_IS_SELECT (stmt)); - obj->priv->stmt = g_object_ref_sink (stmt); - g_signal_connect (stmt, "changed", G_CALLBACK (db_model_on_stmt_changed), obj); - db_model_on_stmt_changed (stmt, obj); + self->priv->stmt = g_object_ref_sink (stmt); + g_signal_connect (stmt, "changed", G_CALLBACK (db_model_on_stmt_changed), self); + db_model_on_stmt_changed (stmt, self); } /** * db_model_set_sql: - * @obj: a #DbModel + * @self: a #DbModel * @sql: a value for the "sql property * * Sets the "sql" property to @sql. **/ -void db_model_set_sql (DbModel * obj, const gchar * sql) +void db_model_set_sql (DbModel * self, const gchar * sql) { SqlObject * string; if (!sql) return; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - g_free (obj->priv->sql); - obj->priv->sql = g_strdup (sql); + g_free (self->priv->sql); + self->priv->sql = g_strdup (sql); - if (obj->priv->use_file) - string = db_conn_create_stmt_from_file (obj->priv->conn, sql); + if (self->priv->use_file) + string = db_conn_create_stmt_from_file (self->priv->conn, sql); else string = sql_string_new (sql); - db_model_set_stmt (obj, SQL_STMT (string)); + db_model_set_stmt (self, SQL_STMT (string)); } /** * db_model_get: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter * @...: (out callee-allocates): pairs of column number and value return * locations, terminated by -1 @@ -1825,24 +1676,24 @@ void db_model_set_sql (DbModel * obj, const gchar * sql) * type G_TYPE_STRING or G_TYPE_BOXED have to be freed. Other values are passed * by value. **/ -void db_model_get (DbModel * obj, DbIter * iter, ...) +void db_model_get (DbModel * self, DbIter * iter, ...) { va_list va; gint column; GValue * val; - g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (obj->priv->result); + g_return_if_fail (DB_IS_MODEL (self)); + g_return_if_fail (self->priv->result); g_return_if_fail (iter != NULL); va_start (va, iter); - while ((column = (va_arg (va, gint))) >= 0 && column < obj->priv->result->ncols) + while ((column = (va_arg (va, gint))) >= 0 && column < self->priv->result->ncols) { val = DB_ROW_FIELD (iter->data, column); if (gvn_value_is_null (val)) - switch (gvn_param_spec_get_gtype (obj->priv->column[column].spec)) + switch (gvn_param_spec_get_gtype (self->priv->column[column].spec)) { case G_TYPE_CHAR: *va_arg (va, gchar*) = 0; @@ -1872,7 +1723,7 @@ void db_model_get (DbModel * obj, DbIter * iter, ...) /** * db_model_set: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter * @...: pairs of column number and value, terminated by -1 * @@ -1882,25 +1733,25 @@ void db_model_get (DbModel * obj, DbIter * iter, ...) * The value will be referenced by the model if it is a G_TYPE_OBJECT, and it * will be copied if it is a G_TYPE_STRING or G_TYPE_BOXED. **/ -void db_model_set (DbModel * obj, DbIter * iter, ...) +void db_model_set (DbModel * self, DbIter * iter, ...) { gint column; gpointer content; GValue val = {0}; va_list va; - g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (obj->priv->result); + g_return_if_fail (DB_IS_MODEL (self)); + g_return_if_fail (self->priv->result); g_return_if_fail (iter != NULL); va_start (va, iter); - while ((column = (va_arg (va, gint))) >= 0 && column < obj->priv->result->ncols) + while ((column = (va_arg (va, gint))) >= 0 && column < self->priv->result->ncols) { content = va_arg (va, gpointer); gvn_value_new_with_content (&val, - gvn_param_spec_get_gtype (obj->priv->column[column].spec), content); - gvn_value_copy (&val, DB_ROW_FIELD (iter->data, column)); + gvn_param_spec_get_gtype (self->priv->column[column].spec), content); + db_model_set_value (self, iter, column, &val, NULL); g_value_unset (&val); } @@ -1910,22 +1761,22 @@ void db_model_set (DbModel * obj, DbIter * iter, ...) /** * db_model_get_value: - * @obj: a #DbModel - * @iter: a #DbIter pointing to a row of @obj + * @self: a #DbModel + * @iter: a #DbIter pointing to a row of @self * @col: the number of the field to get the value * @err: (out) (allow-none): a #GError or %NULL to ignore errors * - * Gets a value from @obj pointed to by @iter and @col and puts it in @err. + * Gets a value from @self pointed to by @iter and @col and puts it in @err. * * Return value: the value pointed to by @iter and @col or %NULL in case of error **/ -const GValue * db_model_get_value (DbModel * obj, DbIter * iter, gint col, GError ** err) +const GValue * db_model_get_value (DbModel * self, DbIter * iter, gint col, GError ** err) { - g_return_val_if_fail (DB_IS_MODEL (obj), NULL); - g_return_val_if_fail (obj->priv->data && obj->priv->result, NULL); - g_return_val_if_fail (VALID_ITER (iter, obj), NULL); + g_return_val_if_fail (DB_IS_MODEL (self), NULL); + g_return_val_if_fail (self->priv->data && self->priv->result, NULL); + g_return_val_if_fail (VALID_ITER (iter, self), NULL); - if (MODEL_NOT_READY (obj)) + if (MODEL_NOT_READY (self)) { g_set_error (err ,DB_MODEL_LOG_DOMAIN @@ -1934,7 +1785,7 @@ const GValue * db_model_get_value (DbModel * obj, DbIter * iter, gint col, GErro return NULL; } - if (0 > col || col >= obj->priv->result->ncols) + if (0 > col || col >= self->priv->result->ncols) { g_set_error (err ,DB_MODEL_LOG_DOMAIN @@ -1948,13 +1799,13 @@ const GValue * db_model_get_value (DbModel * obj, DbIter * iter, gint col, GErro /** * db_model_set_value: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter pointing to the row to be set * @col: the column of the field to be set * @value: new value for the field pointed to by @iter and @col * @err: (out) (allow-none): a #GError or %NULL to ignore errors * - * Sets the value of a single field to @value on @obj as well as on the database. + * Sets the value of a single field to @value on @self as well as on the database. * If the database update fails, the model is not updated and err is set * if it's not %NULL. * If @iter is pointing a new row (inserted by db_model_insert() but not yet @@ -1963,15 +1814,15 @@ const GValue * db_model_get_value (DbModel * obj, DbIter * iter, gint col, GErro * * Return value: %TRUE on success, %FALSE otherwise **/ -gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValue * value, GError ** err) +gboolean db_model_set_value (DbModel * self, DbIter * iter, gint col, const GValue * value, GError ** err) { - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; gboolean ret = FALSE; - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - g_return_val_if_fail (VALID_ITER (iter, obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); + g_return_val_if_fail (VALID_ITER (iter, self), FALSE); - if (MODEL_NOT_READY (obj) || !priv->result) + if (MODEL_NOT_READY (self) || !priv->result) { g_set_error (err, DB_MODEL_LOG_DOMAIN ,DB_MODEL_ERROR_NOT_READY, "Model not ready"); @@ -2001,7 +1852,7 @@ gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValu { ret = TRUE; } - else if (!db_model_set_row_operation (obj, row, DB_MODEL_ROW_OP_UPDATE, col)) + else if (!db_model_set_row_operation (self, row, DB_MODEL_ROW_OP_UPDATE, col)) { g_set_error (err, DB_MODEL_LOG_DOMAIN ,DB_MODEL_ERROR_NOT_UPDATABLE, "Row locked. " @@ -2011,14 +1862,14 @@ gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValu { priv->updated_col = col; priv->updated_value = g_new0 (GValue, 1); - gvn_value_copy (&new_value - ,g_value_init (priv->updated_value, G_VALUE_TYPE (&new_value))); + g_value_init (priv->updated_value, G_VALUE_TYPE (&new_value)); + g_value_copy (&new_value, priv->updated_value); - g_signal_emit (obj, db_model_signal[LINE_UPDATED], 0, iter); + g_signal_emit (self, db_model_signal[LINE_UPDATED], 0, iter); if (priv->mode == DB_MODEL_MODE_ON_CHANGE && !(row_op & DB_MODEL_ROW_OP_INSERT)) - db_model_perform_operations (obj, FALSE); + db_model_perform_operations (self, FALSE); ret = TRUE; } @@ -2031,24 +1882,24 @@ gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValu /** * db_model_insert: - * @obj: a #DbModel + * @self: a #DbModel * @iter: (out): a #DbIter that will point to the new row * - * Inserts an empty row at the end of @obj. The values for this row must be + * Inserts an empty row at the end of @self. The values for this row must be * set one by one using db_model_set_value() or all at once with db_model_set(). * And then committed with db_model_perform_operations(). **/ -gboolean db_model_insert (DbModel * obj, DbIter * iter) +gboolean db_model_insert (DbModel * self, DbIter * iter) { gint i; DbRow * row; DbModelPrivate * priv; - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); - priv = obj->priv; + priv = self->priv; - if (MODEL_NOT_READY (obj) || !priv->result) + if (MODEL_NOT_READY (self) || !priv->result) { g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN) ,G_LOG_LEVEL_WARNING, "Model not ready"); @@ -2096,36 +1947,36 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter) iter->stamp = priv->stamp; priv->result->nrows++; - db_model_set_row_operation (obj, iter->data, DB_MODEL_ROW_OP_INSERT, 0); + db_model_set_row_operation (self, iter->data, DB_MODEL_ROW_OP_INSERT, 0); - g_signal_emit (obj, db_model_signal[LINE_INSERTED], 0, iter); + g_signal_emit (self, db_model_signal[LINE_INSERTED], 0, iter); return TRUE; } /** * db_model_delete: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter pointing to the row to be deleted * - * Deletes the row pointed to by @iter on @obj, as well as on the database (if + * Deletes the row pointed to by @iter on @self, as well as on the database (if * it was already there, i.e. it's not a new row). - * If the deletion on the database fails, then the row on @obj is not deleted + * If the deletion on the database fails, then the row on @self is not deleted * and a log message is emitted. **/ -void db_model_delete (DbModel * obj, DbIter * iter) +void db_model_delete (DbModel * self, DbIter * iter) { - g_return_if_fail (DB_IS_MODEL (obj)); - g_return_if_fail (VALID_ITER (iter, obj)); + g_return_if_fail (DB_IS_MODEL (self)); + g_return_if_fail (VALID_ITER (iter, self)); - if (MODEL_NOT_READY (obj)) + if (MODEL_NOT_READY (self)) { g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN) ,G_LOG_LEVEL_WARNING, "Model not ready"); return; } - if (!(obj->priv->update_flags & DB_MODEL_DELETE)) + if (!(self->priv->update_flags & DB_MODEL_DELETE)) { g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN) ,G_LOG_LEVEL_WARNING, "Can't delete from this Model"); @@ -2133,30 +1984,30 @@ void db_model_delete (DbModel * obj, DbIter * iter) } if (!db_model_set_row_operation - (obj, g_ptr_array_index (obj->priv->data, DB_ROW_POSITION (iter->data)), + (self, g_ptr_array_index (self->priv->data, DB_ROW_POSITION (iter->data)), DB_MODEL_ROW_OP_DELETE, 0)) return; - g_signal_emit (obj, db_model_signal[LINE_TOGGLED], 0, iter); + g_signal_emit (self, db_model_signal[LINE_TOGGLED], 0, iter); - if (obj->priv->mode == DB_MODEL_MODE_ON_CHANGE) - db_model_perform_operations (obj, FALSE); + if (self->priv->mode == DB_MODEL_MODE_ON_CHANGE) + db_model_perform_operations (self, FALSE); } /** * db_model_order_by: - * @obj: a #DbModel + * @self: a #DbModel * @col: the number of the column that will be the sort criteria * @order: the order to sort in * - * Sorts @obj in the order indicated by @order and using the data + * Sorts @self in the order indicated by @order and using the data * on the field @col. **/ -void db_model_order_by (DbModel * obj, gint col, DbSortType order) +void db_model_order_by (DbModel * self, gint col, DbSortType order) { DbModelPrivate * priv; - g_return_if_fail (DB_IS_MODEL (obj)); - priv = obj->priv; + g_return_if_fail (DB_IS_MODEL (self)); + priv = self->priv; g_return_if_fail (priv->result && col >= -2 && col < priv->result->ncols); g_return_if_fail (order == DB_SORT_ASCENDING || order == DB_SORT_DESCENDING); @@ -2176,7 +2027,7 @@ void db_model_order_by (DbModel * obj, gint col, DbSortType order) priv->order = order; priv->sort_column_id = col; - g_signal_emit (obj, db_model_signal[SORT_CHANGED], 0, NULL); + g_signal_emit (self, db_model_signal[SORT_CHANGED], 0, NULL); if (order == DB_SORT_DESCENDING) g_ptr_array_sort_with_data (priv->data @@ -2194,12 +2045,12 @@ void db_model_order_by (DbModel * obj, gint col, DbSortType order) DB_ROW_POSITION (row_iter) = i++; } - g_signal_emit (obj, db_model_signal[LINES_REORDERED], 0, col, new_order); + g_signal_emit (self, db_model_signal[LINES_REORDERED], 0, col, new_order); } /** * db_model_search: - * @obj: a #DbModel + * @self: a #DbModel * @col: the field to search in * @iter: a #DbIter that will point the first found element * @content: the value looked for or %NULL @@ -2208,20 +2059,20 @@ void db_model_order_by (DbModel * obj, gint col, DbSortType order) * * Return value: Returns %TRUE if the value is found and %FALSE otherwise **/ -gboolean db_model_search (DbModel * obj, gint col, DbIter * iter, gpointer content) +gboolean db_model_search (DbModel * self, gint col, DbIter * iter, gpointer content) { gboolean ret; GValue value = {0}; - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - g_return_val_if_fail (obj->priv->result - && 0 <= obj->priv->result->ncols - && col < obj->priv->result->ncols , FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); + g_return_val_if_fail (self->priv->result + && 0 <= self->priv->result->ncols + && col < self->priv->result->ncols , FALSE); gvn_value_new_with_content (&value, - gvn_param_spec_get_gtype (obj->priv->column[col].spec), content); + gvn_param_spec_get_gtype (self->priv->column[col].spec), content); - ret = db_model_search_value (obj, col, iter, &value); + ret = db_model_search_value (self, col, iter, &value); g_value_unset (&value); return ret; @@ -2229,7 +2080,7 @@ gboolean db_model_search (DbModel * obj, gint col, DbIter * iter, gpointer conte /** * db_model_search_value: - * @obj: a #DbModel + * @self: a #DbModel * @col: the field to search in * @iter: a #DbIter that will point the first found element * @value: the value to search for @@ -2239,28 +2090,28 @@ gboolean db_model_search (DbModel * obj, gint col, DbIter * iter, gpointer conte * Return value: Returns %TRUE if the value is found and %FALSE otherwise **/ gboolean db_model_search_value - (DbModel * obj, gint col, DbIter * iter, const GValue * value) + (DbModel * self, gint col, DbIter * iter, const GValue * value) { gint i; GType type; DbRow * row; - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE); - g_return_val_if_fail (obj->priv->result + g_return_val_if_fail (self->priv->result && 0 <= col - && col < obj->priv->result->ncols, FALSE); + && col < self->priv->result->ncols, FALSE); - type = gvn_param_spec_get_gtype (obj->priv->column[col].spec); + type = gvn_param_spec_get_gtype (self->priv->column[col].spec); if (gvn_value_is_null (value) || G_VALUE_TYPE (value) == type) - for (i = 0; i < obj->priv->result->nrows; i++) + for (i = 0; i < self->priv->result->nrows; i++) { - row = g_ptr_array_index (obj->priv->data, i); + row = g_ptr_array_index (self->priv->data, i); if (gvn_value_compare (DB_ROW_FIELD (row, col), value)) { - iter->stamp = obj->priv->stamp; + iter->stamp = self->priv->stamp; iter->data = row; return TRUE; } @@ -2271,7 +2122,7 @@ gboolean db_model_search_value /** * db_model_get_row_operations: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter * * Returns #DbModelRowOp flags indicating the operations being applied to the @@ -2280,36 +2131,36 @@ gboolean db_model_search_value * * Return value: the #DbModelRowOp of the row or 0 **/ -DbModelRowOp db_model_get_row_operations (DbModel * obj, DbIter * iter) +DbModelRowOp db_model_get_row_operations (DbModel * self, DbIter * iter) { DbOperation * op; - g_return_val_if_fail (DB_IS_MODEL (obj), 0); - g_return_val_if_fail (VALID_ITER (iter, obj), 0); + g_return_val_if_fail (DB_IS_MODEL (self), 0); + g_return_val_if_fail (VALID_ITER (iter, self), 0); - op = g_hash_table_lookup (obj->priv->row_ops, (DbRow *) iter->data); + op = g_hash_table_lookup (self->priv->row_ops, (DbRow *) iter->data); return op ? op->type : 0; } /** * db_model_has_pending_operations: - * @obj: a #DbModel + * @self: a #DbModel * * Returns whether there are pending operations in the model. * * Return value: #TRUE if the model has pending operations, #FALSE otherwise **/ -gboolean db_model_has_pending_operations (DbModel * obj) +gboolean db_model_has_pending_operations (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); - if (obj->priv->row_ops) - return g_hash_table_size (obj->priv->row_ops) > 0; + if (self->priv->row_ops) + return g_hash_table_size (self->priv->row_ops) > 0; return FALSE; } -static SqlObject * db_model_create_where (DbModel * obj, +static SqlObject * db_model_create_where (DbModel * self, TableInfo * tinfo, DbOperation * operation, gboolean for_insert) { GSList * l; @@ -2317,7 +2168,7 @@ static SqlObject * db_model_create_where (DbModel * obj, GValue * g_value; SqlObject * value; DbRow * row = operation->row; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; SqlObject * where; SqlList * and_operands; @@ -2375,11 +2226,11 @@ static SqlObject * db_model_create_where (DbModel * obj, return where; } -static SqlObject * db_model_create_insert (DbModel * obj, +static SqlObject * db_model_create_insert (DbModel * self, TableInfo * tinfo, DbOperation * operation) { gint i; - DbModelPrivate * priv = obj->priv; + DbModelPrivate * priv = self->priv; DbRow * row = operation->row; const GValue * value; SqlList * targets, * stmts, * sets, * fields, * values, * select_fields; @@ -2390,7 +2241,7 @@ static SqlObject * db_model_create_insert (DbModel * obj, GArray * cols; gchar * colname; - where = db_model_create_where (obj, tinfo, operation, TRUE); + where = db_model_create_where (self, tinfo, operation, TRUE); if (!where) return NULL; @@ -2470,17 +2321,17 @@ static SqlObject * db_model_create_insert (DbModel * obj, /** * db_model_perform_operations: - * @obj: a #DbModel with a new row, not yet inserted + * @self: a #DbModel with a new row, not yet inserted * @retry: whether to retry the failed operations (not implemented) * * Commits the changes made by db_model_set_value() to a new row, inserted * by db_model_insert(). * Note that if this method is not called after db_model_insert(), all the * changes made on the new row will be lost. - * If the @obj is working in the #DB_MODEL_MODE_ON_DEMAND, non-interactive, + * If the @self is working in the #DB_MODEL_MODE_ON_DEMAND, non-interactive, * mode, this method will perform every actions taken and not yet submitted. **/ -void db_model_perform_operations (DbModel * obj, gboolean retry) +void db_model_perform_operations (DbModel * self, gboolean retry) { GList * l; DbOperation * op; @@ -2491,16 +2342,16 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) DbRequest * request; gboolean error = FALSE; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - if (MODEL_NOT_READY (obj)) + if (MODEL_NOT_READY (self)) { g_log (g_quark_to_string (DB_MODEL_LOG_DOMAIN), G_LOG_LEVEL_WARNING, "Model not ready"); return; } - priv = obj->priv; + priv = self->priv; if (!priv->operation->length) return; @@ -2520,7 +2371,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) { if (!(op->type & DB_MODEL_ROW_OP_INSERT)) { - where = db_model_create_where (obj, priv->main_table, op, FALSE); + where = db_model_create_where (self, priv->main_table, op, FALSE); if (where) { @@ -2542,7 +2393,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else if (op->type & DB_MODEL_ROW_OP_INSERT) // INSERT + SELECT { - stmt = db_model_create_insert (obj, priv->main_table, op); + stmt = db_model_create_insert (self, priv->main_table, op); if (!stmt) error = TRUE; @@ -2583,7 +2434,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) while (g_hash_table_iter_next (&iter, (gpointer) &tinfo, (gpointer) &fields)) { - where = db_model_create_where (obj, tinfo, op, FALSE); + where = db_model_create_where (self, tinfo, op, FALSE); if (where) { @@ -2612,7 +2463,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) } else { - SqlObject * insert = db_model_create_insert (obj, tinfo, op); + SqlObject * insert = db_model_create_insert (self, tinfo, op); if (insert) sql_list_add (update_list, insert); @@ -2635,7 +2486,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) g_queue_push_tail (ops, op); DbModelRequest * data = g_new (DbModelRequest, 1); - data->obj = g_object_ref (obj); + data->self = g_object_ref (self); data->operations = ops; data->stmts = g_object_ref_sink (stmts); @@ -2651,7 +2502,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) ,data ,(GDestroyNotify) db_model_request_free ); - db_model_add_pending_request (obj, request); + db_model_add_pending_request (self, request); } else { @@ -2667,19 +2518,19 @@ void db_model_perform_operations (DbModel * obj, gboolean retry) /** * db_model_refresh: - * @obj: a #DbModel + * @self: a #DbModel * - * Executes the SELECT query and fills @obj with the data returned by it. + * Executes the SELECT query and fills @self with the data returned by it. **/ -void db_model_refresh (DbModel * obj) +void db_model_refresh (DbModel * self) { DbModelPrivate * priv; gboolean is_ready = FALSE; - g_return_if_fail (DB_IS_MODEL (obj)); + g_return_if_fail (DB_IS_MODEL (self)); - priv = obj->priv; - db_model_clear (obj); + priv = self->priv; + db_model_clear (self); if (priv->conn && priv->stmt) { @@ -2734,13 +2585,13 @@ void db_model_refresh (DbModel * obj) if (sql_batch_is_ready (tmp_batch)) { is_ready = TRUE; - db_model_set_status (obj, DB_MODEL_STATUS_LOADING); + db_model_set_status (self, DB_MODEL_STATUS_LOADING); priv->request = db_conn_query_with_stmt_async (priv->conn ,priv->stmt ,tmp_batch ,(DbRequestDoneCallback) db_model_on_data_ready - ,g_object_ref (obj) + ,g_object_ref (self) ,(GDestroyNotify) g_object_unref ); } @@ -2750,23 +2601,23 @@ void db_model_refresh (DbModel * obj) } if (!is_ready) - db_model_set_status (obj, DB_MODEL_STATUS_CLEAN); + db_model_set_status (self, DB_MODEL_STATUS_CLEAN); } /** * db_model_get_nrows: - * @obj: a #DbModel + * @self: a #DbModel * - * Returns the current number of rows on #obj. + * Returns the current number of rows on @self. * * Return value: the number of rows **/ -gint db_model_get_nrows (DbModel * obj) +gint db_model_get_nrows (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), 0); + g_return_val_if_fail (DB_IS_MODEL (self), 0); - if (obj->priv->result) - return obj->priv->result->nrows; + if (self->priv->result) + return self->priv->result->nrows; else return 0; } @@ -2778,93 +2629,93 @@ gint db_model_get_nrows (DbModel * obj) * * Checks if @iter is a valid #DbIter pointing inside @model. **/ -gboolean db_model_iter_is_valid (DbIter * iter, DbModel * obj) +gboolean db_model_iter_is_valid (DbIter * iter, DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); - return (iter && iter->data && obj->priv->stamp == iter->stamp); + return (iter && iter->data && self->priv->stamp == iter->stamp); } // GtkTreeModel implementation methods. /** * db_model_get_ncols: - * @obj: a #DbModel + * @self: a #DbModel * - * Returns the number of columns supported by @obj. + * Returns the number of columns supported by @self. * * Return value: the number of columns **/ -gint db_model_get_ncols (DbModel * obj) +gint db_model_get_ncols (DbModel * self) { - g_return_val_if_fail (DB_IS_MODEL (obj), -1); + g_return_val_if_fail (DB_IS_MODEL (self), -1); - if (obj->priv->result) - return obj->priv->result->ncols; + if (self->priv->result) + return self->priv->result->ncols; else return 0; } /** * db_model_get_column_type: - * @obj: a #DbModel + * @self: a #DbModel * @index: the number of the column * * Retrieves the type of the column specified by @index. * * Return value: the type of the column **/ -GType db_model_get_column_type (DbModel * obj, gint index) +GType db_model_get_column_type (DbModel * self, gint index) { - g_return_val_if_fail (DB_IS_MODEL (obj), G_TYPE_INVALID); - g_return_val_if_fail (obj->priv->result - && 0 <= index && index < obj->priv->result->ncols, G_TYPE_INVALID); + g_return_val_if_fail (DB_IS_MODEL (self), G_TYPE_INVALID); + g_return_val_if_fail (self->priv->result + && 0 <= index && index < self->priv->result->ncols, G_TYPE_INVALID); - if (obj->priv->column) - if (obj->priv->column[index].spec) - return gvn_param_spec_get_gtype (obj->priv->column[index].spec); + if (self->priv->column) + if (self->priv->column[index].spec) + return gvn_param_spec_get_gtype (self->priv->column[index].spec); return G_TYPE_INVALID; } /** * db_model_get_path: - * @obj: a #DbModel + * @self: a #DbModel * @iter: a #DbIter * * Returns the number of the row pointed to by @iter. * * Return value: the number of the row pointed to by @iter **/ -gint db_model_get_path (DbModel * obj, DbIter * iter) +gint db_model_get_path (DbModel * self, DbIter * iter) { - g_return_val_if_fail (DB_IS_MODEL (obj), 0); - if (MODEL_NOT_READY (obj)) return 0; - g_return_val_if_fail (VALID_ITER (iter, obj), 0); + g_return_val_if_fail (DB_IS_MODEL (self), 0); + if (MODEL_NOT_READY (self)) return 0; + g_return_val_if_fail (VALID_ITER (iter, self), 0); return DB_ROW_POSITION (iter->data); } /** * db_model_get_iter: - * @obj: a #DbModel + * @self: a #DbModel * @iter: (out): an unitialized #DbIter * @path: the number of the row being accessed * - * Sets @iter pointing to the row of @obj specified by @path. + * Sets @iter pointing to the row of @self specified by @path. * * Return value: %TRUE if the position is found, %FALSE otherwise **/ -gboolean db_model_get_iter (DbModel * obj, DbIter * iter, gint path) +gboolean db_model_get_iter (DbModel * self, DbIter * iter, gint path) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); if ((0 > path - || (obj->priv->result && path >= obj->priv->result->nrows)) - || MODEL_NOT_READY (obj)) + || (self->priv->result && path >= self->priv->result->nrows)) + || MODEL_NOT_READY (self)) return FALSE; - iter->stamp = obj->priv->stamp; - iter->data = g_ptr_array_index (obj->priv->data, (guint) path); + iter->stamp = self->priv->stamp; + iter->data = g_ptr_array_index (self->priv->data, (guint) path); if (iter->data) return TRUE; @@ -2873,24 +2724,24 @@ gboolean db_model_get_iter (DbModel * obj, DbIter * iter, gint path) /** * db_model_get_iter_first: - * @obj: a #DbModel + * @self: a #DbModel * @iter: (out): an unitialized #DbIter * - * Sets @iter pointing to the first row of @obj. + * Sets @iter pointing to the first row of @self. * * Return value: %TRUE if @iter is set right **/ -gboolean db_model_get_iter_first (DbModel * obj, DbIter * iter) +gboolean db_model_get_iter_first (DbModel * self, DbIter * iter) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - if (MODEL_NOT_READY(obj) - || !obj->priv->result || !obj->priv->result->nrows) + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); + if (MODEL_NOT_READY(self) + || !self->priv->result || !self->priv->result->nrows) return FALSE; - if (obj->priv->data) + if (self->priv->data) { - iter->stamp = obj->priv->stamp; - iter->data = g_ptr_array_index (obj->priv->data, 0); + iter->stamp = self->priv->stamp; + iter->data = g_ptr_array_index (self->priv->data, 0); } else return FALSE; @@ -2900,51 +2751,51 @@ gboolean db_model_get_iter_first (DbModel * obj, DbIter * iter) /** * db_model_iter_prev: - * @obj: a #DbModel + * @self: a #DbModel * @iter: (inout): a valid #DbIter * - * Sets @iter pointing to the previous row of @obj. + * Sets @iter pointing to the previous row of @self. * * Return value: %TRUE if the iter has been changed to the previous row **/ -gboolean db_model_iter_prev (DbModel * obj, DbIter * iter) +gboolean db_model_iter_prev (DbModel * self, DbIter * iter) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - if (MODEL_NOT_READY(obj) - || !obj->priv->result || !obj->priv->result->nrows) + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); + if (MODEL_NOT_READY(self) + || !self->priv->result || !self->priv->result->nrows) return FALSE; - g_return_val_if_fail (VALID_ITER (iter, obj), FALSE); + g_return_val_if_fail (VALID_ITER (iter, self), FALSE); if ((iter->data = g_ptr_array_index - (obj->priv->data, (guint) DB_ROW_POSITION (iter->data) - 1))) + (self->priv->data, (guint) DB_ROW_POSITION (iter->data) - 1))) return TRUE; return FALSE; } /** * db_model_iter_next: - * @obj: a #DbModel + * @self: a #DbModel * @iter: (inout): a valid #DbIter * - * Sets @iter pointing to the next row of @obj. + * Sets @iter pointing to the next row of @self. * * Return value: %TRUE if the iter has been changed to the next row **/ -gboolean db_model_iter_next (DbModel * obj, DbIter * iter) +gboolean db_model_iter_next (DbModel * self, DbIter * iter) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); - if (MODEL_NOT_READY(obj) - || !obj->priv->result || !obj->priv->result->nrows) + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); + if (MODEL_NOT_READY(self) + || !self->priv->result || !self->priv->result->nrows) return FALSE; - g_return_val_if_fail (VALID_ITER (iter, obj), FALSE); + g_return_val_if_fail (VALID_ITER (iter, self), FALSE); gint pos = DB_ROW_POSITION (iter->data); - if (pos < obj->priv->result->nrows-1) + if (pos < self->priv->result->nrows-1) { - iter->data = g_ptr_array_index (obj->priv->data, (guint) pos + 1); + iter->data = g_ptr_array_index (self->priv->data, (guint) pos + 1); return TRUE; } @@ -2957,7 +2808,7 @@ gboolean db_model_iter_next (DbModel * obj, DbIter * iter) /** * db_model_get_sort_column_id: - * @obj: a #DbModel + * @self: a #DbModel * @sort_column_id: (out): an integer * @order: (out): a @DbSortType * @@ -2967,19 +2818,19 @@ gboolean db_model_iter_next (DbModel * obj, DbIter * iter) * Return value: %TRUE if the sort column is not one of the special sort column * ids **/ -gboolean db_model_get_sort_column_id (DbModel * obj, gint * sort_column_id, +gboolean db_model_get_sort_column_id (DbModel * self, gint * sort_column_id, DbSortType * order) { - g_return_val_if_fail (DB_IS_MODEL (obj), FALSE); + g_return_val_if_fail (DB_IS_MODEL (self), FALSE); if (sort_column_id) - * sort_column_id = obj->priv->sort_column_id; + * sort_column_id = self->priv->sort_column_id; if (order) - * order = obj->priv->order; + * order = self->priv->order; - if (obj->priv->sort_column_id == DB_MODEL_DEFAULT_SORT_COLUMN_ID - || obj->priv->sort_column_id == DB_MODEL_UNSORTED_SORT_COLUMN_ID) + if (self->priv->sort_column_id == DB_MODEL_DEFAULT_SORT_COLUMN_ID + || self->priv->sort_column_id == DB_MODEL_UNSORTED_SORT_COLUMN_ID) return FALSE; else return TRUE; @@ -2987,18 +2838,18 @@ gboolean db_model_get_sort_column_id (DbModel * obj, gint * sort_column_id, /** * db_model_set_sort_column_id: - * @obj: a #DbModel + * @self: a #DbModel * @sort_column_id: the column to sort by * @order: the order in which the sort will be done * - * Sets @sort_column_id to be the current sort column. @obj will resort itself + * Sets @sort_column_id to be the current sort column. @self will resort itself * to reflect this change. See #GtkTreeSortable. **/ -void db_model_set_sort_column_id (DbModel * obj, gint sort_column_id, +void db_model_set_sort_column_id (DbModel * self, gint sort_column_id, DbSortType order) { - g_return_if_fail (DB_IS_MODEL (obj)); - db_model_order_by (obj, sort_column_id, order); + g_return_if_fail (DB_IS_MODEL (self)); + db_model_order_by (self, sort_column_id, order); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class @@ -3016,75 +2867,75 @@ typedef enum } DbModelProp; -static void db_model_set_property (DbModel * obj, guint property_id, +static void db_model_set_property (DbModel * self, guint property_id, const GValue * value, GParamSpec * pspec) { switch (property_id) { case PROP_CONN: - db_model_set_conn (obj, g_value_get_object (value)); + db_model_set_conn (self, g_value_get_object (value)); break; case PROP_STMT: - db_model_set_stmt (obj, g_value_get_object (value)); + db_model_set_stmt (self, g_value_get_object (value)); break; case PROP_SQL: - db_model_set_sql (obj, g_value_get_string (value)); + db_model_set_sql (self, g_value_get_string (value)); break; case PROP_USE_FILE: - obj->priv->use_file = g_value_get_boolean (value); + self->priv->use_file = g_value_get_boolean (value); break; case PROP_UPDATE_FLAGS: - db_model_request_update_flags (obj, g_value_get_flags (value)); + db_model_request_update_flags (self, g_value_get_flags (value)); break; case PROP_RESULT_POS: - obj->priv->result_pos = g_value_get_uint (value); + self->priv->result_pos = g_value_get_uint (value); break; case PROP_PARTIAL_DELETE: - obj->priv->partial_delete = g_value_get_boolean (value); + self->priv->partial_delete = g_value_get_boolean (value); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec); } } -static void db_model_get_property (DbModel * obj, guint property_id, +static void db_model_get_property (DbModel * self, guint property_id, GValue * value, GParamSpec * pspec) { switch (property_id) { case PROP_CONN: - g_value_set_object (value, obj->priv->conn); + g_value_set_object (value, self->priv->conn); break; case PROP_STMT: - g_value_set_object (value, obj->priv->stmt); + g_value_set_object (value, self->priv->stmt); break; case PROP_SQL: - g_value_set_string (value, obj->priv->sql); + g_value_set_string (value, self->priv->sql); break; case PROP_USE_FILE: - g_value_set_boolean (value, obj->priv->use_file); + g_value_set_boolean (value, self->priv->use_file); break; case PROP_MAIN_TABLE: - g_value_set_string (value, db_model_get_main_table (obj)); + g_value_set_string (value, db_model_get_main_table (self)); break; case PROP_UPDATE_FLAGS: - g_value_set_flags (value, obj->priv->update_flags); + g_value_set_flags (value, self->priv->update_flags); break; case PROP_RESULT_POS: - g_value_set_uint (value, obj->priv->result_pos); + g_value_set_uint (value, self->priv->result_pos); break; case PROP_PARTIAL_DELETE: - g_value_set_boolean (value, obj->priv->partial_delete); + g_value_set_boolean (value, self->priv->partial_delete); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec); } } -static void db_model_init (DbModel *obj) +static void db_model_init (DbModel * self) { - DbModelPrivate * priv = obj->priv = - G_TYPE_INSTANCE_GET_PRIVATE (obj, DB_TYPE_MODEL, DbModelPrivate); + DbModelPrivate * priv = self->priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, DB_TYPE_MODEL, DbModelPrivate); priv->conn = NULL; priv->batch = NULL; @@ -3132,18 +2983,18 @@ static void db_model_init (DbModel *obj) priv->join = NULL; } -static void db_model_finalize (DbModel * obj) +static void db_model_finalize (DbModel * self) { - DbModelPrivate * priv = obj->priv; - GObjectClass * parent = g_type_class_peek_parent (DB_MODEL_GET_CLASS (obj)); + DbModelPrivate * priv = self->priv; + GObjectClass * parent = g_type_class_peek_parent (DB_MODEL_GET_CLASS (self)); - db_model_clear (obj); + db_model_clear (self); g_clear_object (&priv->conn); g_clear_object (&priv->stmt); g_free (priv->sql); g_hash_table_destroy (priv->column_index); - db_model_set_batch (obj, NULL); + db_model_set_batch (self, NULL); g_hash_table_destroy (priv->defaults); if (priv->updatable_data_allocated) @@ -3155,7 +3006,7 @@ static void db_model_finalize (DbModel * obj) // g_slist_free_full (priv->join, (GDestroyNotify) db_join_free); } - parent->finalize (G_OBJECT (obj)); + parent->finalize (G_OBJECT (self)); } static void db_model_class_init (DbModelClass *k) diff --git a/db/db-model.h b/db/db-model.h index b8f6c0f..f58e782 100644 --- a/db/db-model.h +++ b/db/db-model.h @@ -27,11 +27,11 @@ #define DB_MODEL_LOG_DOMAIN (g_quark_from_string ("DbModel")) #define DB_TYPE_MODEL (db_model_get_type()) -#define DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DB_TYPE_MODEL, DbModel)) -#define DB_IS_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DB_TYPE_MODEL)) +#define DB_MODEL(self) (G_TYPE_CHECK_INSTANCE_CAST ((self), DB_TYPE_MODEL, DbModel)) +#define DB_IS_MODEL(self) (G_TYPE_CHECK_INSTANCE_TYPE ((self), DB_TYPE_MODEL)) #define DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DB_TYPE_MODEL, DbModelClass)) #define DB_IS_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DB_TYPE_MODEL)) -#define DB_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DB_TYPE_MODEL, DbModelClass)) +#define DB_MODEL_GET_CLASS(self) (G_TYPE_INSTANCE_GET_CLASS ((self), DB_TYPE_MODEL, DbModelClass)) #define DB_TYPE_MODEL_UPDATE_FLAGS (db_model_update_flags_get_type()) @@ -185,102 +185,102 @@ GType db_model_update_flags_get_type () G_GNUC_CONST; DbModel * db_model_new (DbConn * conn, SqlStmt * stmt); DbModel * db_model_new_with_sql (DbConn * conn, const gchar * sql); DbModel * db_model_new_with_file (DbConn * conn, const gchar * file); -DbConn * db_model_get_conn (DbModel * obj); -void db_model_set_conn (DbModel * obj, DbConn * conn); -const GvnParamSpec * db_model_get_spec (DbModel * obj, gint col); -const gchar * db_model_get_column_name (DbModel * obj, gint col); -gint db_model_get_column_index (DbModel * obj, const gchar * name); -void db_model_refresh (DbModel * obj); -const SqlStmt * db_model_get_stmt (DbModel * obj); -void db_model_set_stmt (DbModel * obj, SqlStmt * stmt); -void db_model_add_pre_stmt (DbModel * obj, SqlStmt * stmt); -void db_model_add_post_stmt (DbModel * obj, SqlStmt * stmt); -DbModelStatus db_model_get_status (DbModel * obj); -const gchar * db_model_get_main_table (DbModel * obj); -DbModelUpdateFlags db_model_get_update_flags (DbModel * obj); -void db_model_request_update_flags (DbModel * obj +DbConn * db_model_get_conn (DbModel * self); +void db_model_set_conn (DbModel * self, DbConn * conn); +const GvnParamSpec * db_model_get_spec (DbModel * self, gint col); +const gchar * db_model_get_column_name (DbModel * self, gint col); +gint db_model_get_column_index (DbModel * self, const gchar * name); +void db_model_refresh (DbModel * self); +const SqlStmt * db_model_get_stmt (DbModel * self); +void db_model_set_stmt (DbModel * self, SqlStmt * stmt); +void db_model_add_pre_stmt (DbModel * self, SqlStmt * stmt); +void db_model_add_post_stmt (DbModel * self, SqlStmt * stmt); +DbModelStatus db_model_get_status (DbModel * self); +const gchar * db_model_get_main_table (DbModel * self); +DbModelUpdateFlags db_model_get_update_flags (DbModel * self); +void db_model_request_update_flags (DbModel * self ,DbModelUpdateFlags flags); -void db_model_unset_update_flags (DbModel * obj +void db_model_unset_update_flags (DbModel * self ,DbModelUpdateFlags flags); -void db_model_set_mode (DbModel * obj, DbModelMode mode); -DbModelMode db_model_get_mode (DbModel * obj); -void db_model_toggle_mode (DbModel * obj); -gboolean db_model_get_last (DbModel * obj, DbIter * iter); -void db_model_get (DbModel * obj +void db_model_set_mode (DbModel * self, DbModelMode mode); +DbModelMode db_model_get_mode (DbModel * self); +void db_model_toggle_mode (DbModel * self); +gboolean db_model_get_last (DbModel * self, DbIter * iter); +void db_model_get (DbModel * self ,DbIter * iter ,...); -void db_model_set (DbModel * obj +void db_model_set (DbModel * self ,DbIter * iter ,...); -const GValue * db_model_get_value (DbModel * obj, +const GValue * db_model_get_value (DbModel * self, DbIter * iter, gint col, GError ** err); -gboolean db_model_set_value (DbModel * obj, +gboolean db_model_set_value (DbModel * self, DbIter * iter, gint col, const GValue * value, GError ** err); -gboolean db_model_insert (DbModel * obj, DbIter * iter); -void db_model_delete (DbModel * obj, DbIter * iter); -DbModelRowOp db_model_get_row_operations (DbModel * obj, DbIter * iter); -gboolean db_model_has_pending_operations (DbModel * obj); -void db_model_perform_operations (DbModel * obj, gboolean retry); -void db_model_reverse_operations (DbModel * obj); -void db_model_order_by (DbModel * obj, +gboolean db_model_insert (DbModel * self, DbIter * iter); +void db_model_delete (DbModel * self, DbIter * iter); +DbModelRowOp db_model_get_row_operations (DbModel * self, DbIter * iter); +gboolean db_model_has_pending_operations (DbModel * self); +void db_model_perform_operations (DbModel * self, gboolean retry); +void db_model_reverse_operations (DbModel * self); +void db_model_order_by (DbModel * self, gint col, DbSortType order); -gboolean db_model_search (DbModel * obj, +gboolean db_model_search (DbModel * self, gint col, DbIter * iter, gpointer content); -gboolean db_model_search_value (DbModel * obj, +gboolean db_model_search_value (DbModel * self, gint col, DbIter * iter, const GValue * value); -gint db_model_get_nrows (DbModel * obj); +gint db_model_get_nrows (DbModel * self); gboolean db_model_iter_is_valid (DbIter * iter ,DbModel * model); -void db_model_add_join_columns (DbModel * obj - ,const gchar * left - ,const gchar * right); -SqlBatch * db_model_get_batch (DbModel * obj); -void db_model_set_batch (DbModel * obj, SqlBatch * batch); +void db_model_add_join (DbModel * self + ,const gchar * master_field + ,const gchar * slave_field); +SqlBatch * db_model_get_batch (DbModel * self); +void db_model_set_batch (DbModel * self, SqlBatch * batch); -void db_model_set_default_value_from_column (DbModel * obj, const gchar * field, const gchar * column); -void db_model_set_default_value_from_param (DbModel * obj, const gchar * field, GvnParam * param, gboolean link); +void db_model_set_default_value_from_column (DbModel * self, const gchar * field, const gchar * column); +void db_model_set_default_value_from_param (DbModel * self, const gchar * field, GvnParam * param, gboolean link); //GtkTreeModel-like methods -gint db_model_get_ncols (DbModel * obj); -GType db_model_get_column_type (DbModel * obj, gint index); -gboolean db_model_get_iter_first (DbModel * obj, DbIter * iter); -gboolean db_model_get_iter (DbModel * obj, +gint db_model_get_ncols (DbModel * self); +GType db_model_get_column_type (DbModel * self, gint index); +gboolean db_model_get_iter_first (DbModel * self, DbIter * iter); +gboolean db_model_get_iter (DbModel * self, DbIter * iter, gint path); -gint db_model_get_path (DbModel * obj, DbIter * iter); -gboolean db_model_iter_next (DbModel * obj, DbIter * iter); -gboolean db_model_iter_prev (DbModel * obj, DbIter * iter); -void db_model_ref_node (DbModel * obj, DbIter * iter); -void db_model_unref_node (DbModel * obj, DbIter * iter); +gint db_model_get_path (DbModel * self, DbIter * iter); +gboolean db_model_iter_next (DbModel * self, DbIter * iter); +gboolean db_model_iter_prev (DbModel * self, DbIter * iter); +void db_model_ref_node (DbModel * self, DbIter * iter); +void db_model_unref_node (DbModel * self, DbIter * iter); //GtkTreeSortable-like methods -gboolean db_model_get_sort_column_id (DbModel * obj, +gboolean db_model_get_sort_column_id (DbModel * self, gint * sort_column_id, DbSortType * order); -void db_model_set_sort_column_id (DbModel * obj, +void db_model_set_sort_column_id (DbModel * self, gint sort_column_id, DbSortType order); -void db_model_set_sort_func (DbModel * obj, +void db_model_set_sort_func (DbModel * self, gint sort_column_id, DbIterCompareFunc func, gpointer data, GDestroyNotify destroy); -void db_model_set_default_sort_func (DbModel * obj, +void db_model_set_default_sort_func (DbModel * self, DbIterCompareFunc func, gpointer data, GDestroyNotify destroy); -gboolean db_model_has_default_sort_func (DbModel * obj); +gboolean db_model_has_default_sort_func (DbModel * self); #endif