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); + } } /*