Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package seagull for openSUSE:Factory checked in at 2025-10-03 15:44:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/seagull (Old) and /work/SRC/openSUSE:Factory/.seagull.new.11973 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "seagull" Fri Oct 3 15:44:37 2025 rev:3 rq:1308728 version:0.5.0 Changes: -------- --- /work/SRC/openSUSE:Factory/seagull/seagull.changes 2025-06-26 14:06:40.313241824 +0200 +++ /work/SRC/openSUSE:Factory/.seagull.new.11973/seagull.changes 2025-10-03 15:45:53.194654434 +0200 @@ -1,0 +2,9 @@ +Fri Jun 27 12:12:12 UTC 2025 - Richard Rahl <[email protected]> + +- update to 0.5.0: + * Add API for handling enums and flags + * Add helpers for handling GLib.DateTime values + * Fix a bug where parameters without a prefix would match properties even + though a prefix was provided + +------------------------------------------------------------------- Old: ---- seagull-0.4.0.tar.xz seagull-0.4.0.tar.xz.asc New: ---- seagull-0.5.0.tar.xz seagull-0.5.0.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ seagull.spec ++++++ --- /var/tmp/diff_new_pack.1R0pnh/_old 2025-10-03 15:45:54.310701190 +0200 +++ /var/tmp/diff_new_pack.1R0pnh/_new 2025-10-03 15:45:54.310701190 +0200 @@ -18,7 +18,7 @@ %define sover 0 Name: seagull -Version: 0.4.0 +Version: 0.5.0 Release: 0 Summary: A SQLite helper library License: LGPL-2.1-or-later ++++++ seagull-0.4.0.tar.xz -> seagull-0.5.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/.hg_archival.txt new/seagull-0.5.0/.hg_archival.txt --- old/seagull-0.4.0/.hg_archival.txt 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/.hg_archival.txt 2025-06-27 06:38:49.000000000 +0200 @@ -1,4 +1,4 @@ repo: 3c210e7a53be9dacf85a643e66330f36daf34679 -node: f6d0eaff71a78a5c7a7cc0034561cf8534bbeeb1 +node: 401b37566e0348f13f301f134f0f832b17aba1af branch: default -tag: v0.4.0 +tag: v0.5.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/ChangeLog new/seagull-0.5.0/ChangeLog --- old/seagull-0.4.0/ChangeLog 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/ChangeLog 2025-06-27 06:38:49.000000000 +0200 @@ -1,3 +1,10 @@ +0.5.0: 2025-06-27 + * Add API for handling enums and flags (SEAGULL-12) (RR 4033) (Gary Kramlich) + * Add helpers for handling GLib.DateTime values (SEAGULL-10) (RR 4034) (Gary + Kramlich) + * Fix a bug where parameters without a prefix would match properties even + though a prefix was provided (SEAGULL-13) (RR 4035) (Gary Kramlich) + 0.4.0: 2025-06-24 * Add aliases for columns (RR 3926) (Gary Kramlich) * Add seagull_statement_bind_object (SEAGULL-3) (RR 4020) (Gary Kramlich) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/meson.build new/seagull-0.5.0/meson.build --- old/seagull-0.4.0/meson.build 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/meson.build 2025-06-27 06:38:49.000000000 +0200 @@ -1,5 +1,5 @@ project('seagull', 'c', - version : '0.4.0', + version : '0.5.0', meson_version : '>=1.1.0', default_options : ['c_std=c17', 'warning_level=2'], license: 'LGPL-2.1-or-later', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/seagull/seagullstatement.c new/seagull-0.5.0/seagull/seagullstatement.c --- old/seagull-0.4.0/seagull/seagullstatement.c 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/seagull/seagullstatement.c 2025-06-27 06:38:49.000000000 +0200 @@ -232,7 +232,11 @@ /* Increment past the named parameter prefix character of $, :, or @. */ parameter_name += 1; - if(prefix != NULL && g_str_has_prefix(parameter_name, prefix)) { + if(prefix != NULL) { + if(!g_str_has_prefix(parameter_name, prefix)) { + return NULL; + } + prefix_len = strlen(prefix); } @@ -425,6 +429,23 @@ * Public API *****************************************************************************/ gboolean +seagull_statement_bind_date_time(SeagullStatement *statement, + const char *name, GDateTime *value, + GError **error) +{ + char *str = NULL; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE); + + if(value != NULL) { + str = g_date_time_format_iso8601(value); + } + + return seagull_statement_bind_text(statement, name, str, -1, g_free, + error); +} + +gboolean seagull_statement_bind_double(SeagullStatement *statement, const char *name, double value, GError **error) { @@ -457,6 +478,24 @@ } gboolean +seagull_statement_bind_enum(SeagullStatement *statement, const char *name, + int value, GError **error) +{ + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE); + + return seagull_statement_bind_int(statement, name, value, error); +} + +gboolean +seagull_statement_bind_flags(SeagullStatement *statement, const char *name, + guint value, GError **error) +{ + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE); + + return seagull_statement_bind_int(statement, name, (int)value, error); +} + +gboolean seagull_statement_bind_int(SeagullStatement *statement, const char *name, int value, GError **error) { @@ -544,6 +583,10 @@ parameter_name = sqlite3_bind_parameter_name(statement->statement, i); property_name = seagull_statement_parameter_to_property_name(parameter_name, prefix); + if(property_name == NULL) { + continue; + } + pspec = g_object_class_find_property(obj_class, property_name); g_clear_pointer(&property_name, g_free); @@ -561,6 +604,10 @@ seagull_statement_bind_int(statement, parameter_name, g_value_get_boolean(&value), &local_error); + } else if(type == G_TYPE_DATE_TIME) { + seagull_statement_bind_date_time(statement, parameter_name, + g_value_get_boxed(&value), + &local_error); } else if(type == G_TYPE_DOUBLE) { seagull_statement_bind_double(statement, parameter_name, g_value_get_double(&value), @@ -574,6 +621,13 @@ -1, g_free, &local_error); + } else if(G_TYPE_IS_ENUM(type)) { + seagull_statement_bind_enum(statement, parameter_name, + g_value_get_enum(&value), &local_error); + } else if(G_TYPE_IS_FLAGS(type)) { + seagull_statement_bind_flags(statement, parameter_name, + g_value_get_flags(&value), + &local_error); } else { local_error = g_error_new(SEAGULL_STATEMENT_ERROR, SEAGULL_STATEMENT_ERROR_BIND_OBJECT_PROPERTY_UNKNOWN_TYPE, @@ -677,6 +731,56 @@ } int +seagull_statement_column_enum(SeagullStatement *statement, const char *name, + GError **error) +{ + int column = -1; + int column_type = 0; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), 0); + g_return_val_if_fail(name != NULL, 0); + + column = seagull_statement_find_column(statement, name, error); + if(column == -1) { + return 0; + } + + column_type = sqlite3_column_type(statement->statement, column); + if(!seagull_statement_check_column_type(SQLITE_INTEGER, column_type, + error)) + { + return 0; + } + + return sqlite3_column_int(statement->statement, column); +} + +guint +seagull_statement_column_flags(SeagullStatement *statement, const char *name, + GError **error) +{ + int column = -1; + int column_type = 0; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), 0); + g_return_val_if_fail(name != NULL, 0); + + column = seagull_statement_find_column(statement, name, error); + if(column == -1) { + return 0; + } + + column_type = sqlite3_column_type(statement->statement, column); + if(!seagull_statement_check_column_type(SQLITE_INTEGER, column_type, + error)) + { + return 0; + } + + return (guint)sqlite3_column_int(statement->statement, column); +} + +int seagull_statement_column_int(SeagullStatement *statement, const char *name, GError **error) { @@ -749,28 +853,44 @@ continue; } - switch(pspec->value_type) { - case G_TYPE_BOOLEAN: + if(pspec->value_type == G_TYPE_BOOLEAN) { g_value_init(&value, G_TYPE_BOOLEAN); g_value_set_boolean(&value, sqlite3_column_int(statement->statement, i)); - break; - case G_TYPE_DOUBLE: + } else if(pspec->value_type == G_TYPE_DATE_TIME) { + GDateTime *dt = NULL; + const char *str = NULL; + + str = (const char *)sqlite3_column_text(statement->statement, i); + if(str != NULL) { + GTimeZone *tz = g_time_zone_new_utc(); + + dt = g_date_time_new_from_iso8601(str, tz); + g_time_zone_unref(tz); + } + g_value_init(&value, G_TYPE_DATE_TIME); + g_value_take_boxed(&value, dt); + } else if(pspec->value_type == G_TYPE_DOUBLE) { g_value_init(&value, G_TYPE_DOUBLE); g_value_set_double(&value, sqlite3_column_double(statement->statement, i)); - break; - case G_TYPE_INT: + } else if(pspec->value_type == G_TYPE_INT) { g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, sqlite3_column_int(statement->statement, i)); - break; - case G_TYPE_STRING: + } else if(pspec->value_type == G_TYPE_STRING) { g_value_init(&value, G_TYPE_STRING); g_value_set_string(&value, (const char *)sqlite3_column_text(statement->statement, i)); - break; - default: + } else if(G_TYPE_IS_ENUM(pspec->value_type)) { + g_value_init(&value, pspec->value_type); + g_value_set_enum(&value, + sqlite3_column_int(statement->statement, i)); + } else if(G_TYPE_IS_FLAGS(pspec->value_type)) { + g_value_init(&value, pspec->value_type); + g_value_set_flags(&value, + (guint)sqlite3_column_int(statement->statement, i)); + } else { local_error = g_error_new(SEAGULL_STATEMENT_ERROR, SEAGULL_STATEMENT_ERROR_COLUMN_OBJECT_PROPERTY_UNKNOWN_TYPE, "found object property %s for column %s which has unknown type %s", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/seagull/seagullstatement.h new/seagull-0.5.0/seagull/seagullstatement.h --- old/seagull-0.4.0/seagull/seagullstatement.h 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/seagull/seagullstatement.h 2025-06-27 06:38:49.000000000 +0200 @@ -125,6 +125,25 @@ GObject) /** + * seagull_statement_bind_date_time: + * @name: the name of the parameter + * @value: (transfer none): the value + * @error: (out) (optional): a return address for a #GError + * + * Binds a [[email protected]] to the named parameter. + * + * The date time will be bound as an ISO-8601 string. + * + * @name must be the exact name as specified in the query. + * + * Returns: true on success; otherwise false with error set. + * + * Since: 0.5 + */ +SEAGULL_AVAILABLE_IN_0_5 +gboolean seagull_statement_bind_date_time(SeagullStatement *statement, const char *name, GDateTime *value, GError **error); + +/** * seagull_statement_bind_double: * @name: the name of the parameter * @value: the value. @@ -142,6 +161,40 @@ gboolean seagull_statement_bind_double(SeagullStatement *statement, const char *name, double value, GError **error); /** + * seagull_statement_bind_enum: + * @name: the name of the parameter + * @value: the value + * @error: (out) (optional): a return address for a #GError + * + * Binds an enum value to the named parameter. + * + * @name must be the exact name as specified in the query. + * + * Returns: true on success; otherwise false with error set. + * + * Since: 0.5 + */ +SEAGULL_AVAILABLE_IN_0_5 +gboolean seagull_statement_bind_enum(SeagullStatement *stmt, const char *name, int value, GError **error); + +/** + * seagull_statement_bind_flags: + * @name: the name of the parameter + * @value: the value + * @error: (out) (optional): a return address for a #GError + * + * Binds a flags value to the named parameter. + * + * @name must be the exact name as specified in the query. + * + * Returns: true on success; otherwise false with error set. + * + * Since: 0.5 + */ +SEAGULL_AVAILABLE_IN_0_5 +gboolean seagull_statement_bind_flags(SeagullStatement *stmt, const char *name, guint value, GError **error); + +/** * seagull_statement_bind_int: * @name: the name of the parameter * @value: the value. @@ -273,6 +326,40 @@ double seagull_statement_column_double(SeagullStatement *statement, const char *name, GError **error); /** + * seagull_statement_column_enum: + * @name: the name of the column + * @error: (out) (optional): a return address for a #GError + * + * Gets the value of a column from the current result of a statement. + * + * @name must be the exact name or alias of the column as specified in the + * query. + * + * Returns: The value on success or 0 on error with error set. + * + * Since: 0.5 + */ +SEAGULL_AVAILABLE_IN_0_5 +int seagull_statement_column_enum(SeagullStatement *statement, const char *name, GError **error); + +/** + * seagull_statement_column_flags: + * @name: the name of the column + * @error: (out) (optional): a return address for a #GError + * + * Gets the value of a column from the current result of a statement. + * + * @name must be the exact name or alias of the column as specified in the + * query. + * + * Returns: The value on success or 0 on error with error set. + * + * Since: 0.5 + */ +SEAGULL_AVAILABLE_IN_0_5 +guint seagull_statement_column_flags(SeagullStatement *statement, const char *name, GError **error); + +/** * seagull_statement_column_int: * @name: the name of the column * @error: (out) (optional): a return address for a #GError diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/seagull/seagullversion.h new/seagull-0.5.0/seagull/seagullversion.h --- old/seagull-0.4.0/seagull/seagullversion.h 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/seagull/seagullversion.h 2025-06-27 06:38:49.000000000 +0200 @@ -129,8 +129,8 @@ /** * SEAGULL_VERSION_0_1: * - * A macro that evaluates to the 0.1 version of seagull, in a format that can be - * used by the C pre-processor. + * A macro that evaluates to the 0.1 version of seagull, in a format that can + * be used by the C pre-processor. * * Since: 0.1 */ @@ -153,8 +153,8 @@ /** * SEAGULL_VERSION_0_2: * - * A macro that evaluates to the 0.2 version of seagull, in a format that can be - * used by the C pre-processor. + * A macro that evaluates to the 0.2 version of seagull, in a format that can + * be used by the C pre-processor. * * Since: 0.2 */ @@ -177,8 +177,8 @@ /** * SEAGULL_VERSION_0_3: * - * A macro that evaluates to the 0.3 version of seagull, in a format that can be - * used by the C pre-processor. + * A macro that evaluates to the 0.3 version of seagull, in a format that can + * be used by the C pre-processor. * * Since: 0.3 */ @@ -201,8 +201,8 @@ /** * SEAGULL_VERSION_0_4: * - * A macro that evaluates to the 0.4 version of seagull, in a format that can be - * used by the C pre-processor. + * A macro that evaluates to the 0.4 version of seagull, in a format that can + * be used by the C pre-processor. * * Since: 0.4 */ @@ -222,6 +222,30 @@ #define SEAGULL_AVAILABLE_TYPE_IN_0_4 #endif +/** + * SEAGULL_VERSION_0_5: + * + * A macro that evaluates to the 0.5 version of seagull, in a format that can + * be used by the C pre-processor. + * + * Since: 0.5 + */ +#define SEAGULL_VERSION_0_5 (G_ENCODE_VERSION(0, 5)) + +#if SEAGULL_VERSION_MAX_ALLOWED < SEAGULL_VERSION_0_5 +#define SEAGULL_AVAILABLE_IN_0_5 SEAGULL_UNAVAILABLE(0, 5) +#define SEAGULL_AVAILABLE_ENUMERATOR_IN_0_5 SEAGULL_UNAVAILABLE_ENUMERATOR(0, 5) +#define SEAGULL_AVAILABLE_MACRO_IN_0_5 SEAGULL_UNAVAILABLE_MACRO(0, 5) +#define SEAGULL_AVAILABLE_STATIC_INLINE_IN_0_5 SEAGULL_UNAVAILABLE_STATIC_INLINE(0, 5) +#define SEAGULL_AVAILABLE_TYPE_IN_0_5 SEAGULL_UNAVAILABLE_TYPE(0, 5) +#else +#define SEAGULL_AVAILABLE_IN_0_5 _SEAGULL_EXTERN +#define SEAGULL_AVAILABLE_ENUMERATOR_IN_0_5 +#define SEAGULL_AVAILABLE_MACRO_IN_0_5 +#define SEAGULL_AVAILABLE_STATIC_INLINE_IN_0_5 +#define SEAGULL_AVAILABLE_TYPE_IN_0_5 +#endif + G_BEGIN_DECLS /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/seagull/tests/test_statement.c new/seagull-0.5.0/seagull/tests/test_statement.c --- old/seagull-0.4.0/seagull/tests/test_statement.c 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/seagull/tests/test_statement.c 2025-06-27 06:38:49.000000000 +0200 @@ -333,6 +333,72 @@ } static void +test_seagull_statement_bind_date_time_null(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + char *expanded = NULL; + gboolean result = FALSE; + + db = seagull_db_new_in_memory(&error); + g_assert_no_error(error); + g_assert_nonnull(db); + + statement = seagull_statement_new(db, "SELECT :foo", &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + result = seagull_statement_bind_date_time(statement, ":foo", NULL, &error); + g_assert_no_error(error); + g_assert_true(result); + + expanded = seagull_statement_get_expanded_sql(statement); + g_assert_cmpstr(expanded, ==, "SELECT NULL"); + seagull_free(expanded); + + g_assert_finalize_object(statement); + + result = seagull_db_close(db, &error); + g_assert_no_error(error); + g_assert_true(result); +} + +static void +test_seagull_statement_bind_date_time_normal(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GDateTime *dt = NULL; + GError *error = NULL; + char *expanded = NULL; + gboolean result = FALSE; + + db = seagull_db_new_in_memory(&error); + g_assert_no_error(error); + g_assert_nonnull(db); + + statement = seagull_statement_new(db, "SELECT :foo", &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + dt = g_date_time_new_from_iso8601("2025-06-27T02:22:19Z", NULL); + result = seagull_statement_bind_date_time(statement, ":foo", dt, &error); + g_date_time_unref(dt); + + g_assert_no_error(error); + g_assert_true(result); + + expanded = seagull_statement_get_expanded_sql(statement); + g_assert_cmpstr(expanded, ==, "SELECT '2025-06-27T02:22:19Z'"); + seagull_free(expanded); + + g_assert_finalize_object(statement); + + result = seagull_db_close(db, &error); + g_assert_no_error(error); + g_assert_true(result); +} + +static void test_seagull_statement_bind_double_normal(void) { SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; @@ -1060,6 +1126,10 @@ g_test_add_func("/seagull/statement/expanded/dollar-sign-not-bound", test_seagull_statement_expanded_dollar_sign_not_bound); + g_test_add_func("/seagull/statement/bind/date-time/null", + test_seagull_statement_bind_date_time_null); + g_test_add_func("/seagull/statement/bind/date-time/normal", + test_seagull_statement_bind_date_time_normal); g_test_add_func("/seagull/statement/bind/double/normal", test_seagull_statement_bind_double_normal); g_test_add_func("/seagull/statement/bind/double/not-found", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.4.0/seagull/tests/test_statement_object.c new/seagull-0.5.0/seagull/tests/test_statement_object.c --- old/seagull-0.4.0/seagull/tests/test_statement_object.c 2025-06-24 06:19:21.000000000 +0200 +++ new/seagull-0.5.0/seagull/tests/test_statement_object.c 2025-06-27 06:38:49.000000000 +0200 @@ -33,7 +33,10 @@ GObject parent; gboolean v_boolean; + GDateTime *v_date_time; double v_double; + GConverterResult v_enum; + GConverterFlags v_flags; int v_integer; char *v_string; }; @@ -41,7 +44,10 @@ enum { PROP_0, PROP_BOOLEAN, + PROP_DATE_TIME, PROP_DOUBLE, + PROP_ENUM, + PROP_FLAGS, PROP_INTEGER, PROP_STRING, N_PROPERTIES, @@ -54,6 +60,7 @@ test_seagull_object_finalize(GObject *obj) { TestSeagullObject *test_object = TEST_SEAGULL_OBJECT(obj); + g_clear_pointer(&test_object->v_date_time, g_date_time_unref); g_clear_pointer(&test_object->v_string, g_free); G_OBJECT_CLASS(test_seagull_object_parent_class)->finalize(obj); @@ -69,9 +76,18 @@ case PROP_BOOLEAN: g_value_set_boolean(value, seagull_obj->v_boolean); break; + case PROP_DATE_TIME: + g_value_set_boxed(value, seagull_obj->v_date_time); + break; case PROP_DOUBLE: g_value_set_double(value, seagull_obj->v_double); break; + case PROP_ENUM: + g_value_set_enum(value, seagull_obj->v_enum); + break; + case PROP_FLAGS: + g_value_set_flags(value, seagull_obj->v_flags); + break; case PROP_INTEGER: g_value_set_int(value, seagull_obj->v_integer); break; @@ -94,9 +110,19 @@ case PROP_BOOLEAN: test_obj->v_boolean = g_value_get_boolean(value); break; + case PROP_DATE_TIME: + g_clear_pointer(&test_obj->v_date_time, g_date_time_unref); + test_obj->v_date_time = g_value_dup_boxed(value); + break; case PROP_DOUBLE: test_obj->v_double = g_value_get_double(value); break; + case PROP_ENUM: + test_obj->v_enum = g_value_get_enum(value); + break; + case PROP_FLAGS: + test_obj->v_flags = g_value_get_flags(value); + break; case PROP_INTEGER: test_obj->v_integer = g_value_get_int(value); break; @@ -127,11 +153,32 @@ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_DATE_TIME] = g_param_spec_boxed( + "vdatetime", NULL, NULL, + G_TYPE_DATE_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_DOUBLE] = g_param_spec_double( "vdouble", NULL, NULL, 0.0, 100.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /* We use GConverterResult because it exists and we don't have to define + * the enum in the type system. + */ + properties[PROP_ENUM] = g_param_spec_enum( + "venum", NULL, NULL, + G_TYPE_CONVERTER_RESULT, G_CONVERTER_ERROR, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* We use GConverterFlags because it exists and we don't have to define the + * flags in the type system. + */ + properties[PROP_FLAGS] = g_param_spec_flags( + "vflags", NULL, NULL, + G_TYPE_CONVERTER_FLAGS, G_CONVERTER_NO_FLAGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_INTEGER] = g_param_spec_int( "vinteger", NULL, NULL, 0, 100, 0, @@ -147,12 +194,23 @@ static TestSeagullObject * test_seagull_object_new(void) { - return g_object_new(test_seagull_object_get_type(), - "vboolean", TRUE, - "vdouble", 3.14, - "vinteger", 42, - "vstring", "sammy", - NULL); + TestSeagullObject *ret = NULL; + GDateTime *dt = NULL; + + dt = g_date_time_new_from_iso8601("2025-02-04T21:54:18Z", NULL); + ret = g_object_new(test_seagull_object_get_type(), + "vboolean", TRUE, + "vdatetime", dt, + "vdouble", 3.14, + "venum", G_CONVERTER_FINISHED, + "vflags", G_CONVERTER_INPUT_AT_END | G_CONVERTER_FLUSH, + "vinteger", 42, + "vstring", "sammy", + NULL); + + g_date_time_unref(dt); + + return ret; } static TestSeagullObject * @@ -162,12 +220,23 @@ static TestSeagullObject * test_seagull_object_new_other(void) { - return g_object_new(test_seagull_object_get_type(), - "vboolean", FALSE, - "vdouble", 6.28, - "vinteger", 24, - "vstring", "ymmas", - NULL); + TestSeagullObject *ret = NULL; + GDateTime *dt = NULL; + + dt = g_date_time_new_from_iso8601("2025-06-27T02:22:19Z", NULL); + ret = g_object_new(test_seagull_object_get_type(), + "vboolean", FALSE, + "vdatetime", dt, + "vdouble", 6.28, + "venum", G_CONVERTER_FLUSHED, + "vflags", G_CONVERTER_FLUSH, + "vinteger", 24, + "vstring", "ymmas", + NULL); + + g_date_time_unref(dt); + + return ret; } /****************************************************************************** @@ -219,14 +288,19 @@ gboolean result = FALSE; char *expanded = NULL; const char *migrations[] = { - "CREATE TABLE obj(vboolean INTEGER, vdouble DOUBLE, vinteger INTEGER, " + "CREATE TABLE obj(vboolean INTEGER, vdatetime TEXT, vdouble DOUBLE, " + " venum INTEGER, vflags INTEGER, vinteger INTEGER, " " vstring TEXT);", NULL }; - const char *query = "INSERT INTO obj(vboolean, vdouble, vinteger, vstring) " - "VALUES(:vboolean, @vdouble, $vinteger, :vstring)"; - const char *expected = "INSERT INTO obj(vboolean, vdouble, vinteger, " - "vstring) VALUES(1, 3.14, 42, 'sammy')"; + const char *query = "INSERT INTO obj(vboolean, vdatetime, vdouble, venum, " + "vflags, vinteger, vstring) " + "VALUES(:vboolean, :vdatetime, @vdouble, $venum, " + ":vflags, $vinteger, :vstring)"; + const char *expected = "INSERT INTO obj(vboolean, vdatetime, vdouble, " + "venum, vflags, vinteger, vstring) " + "VALUES(1, '2025-02-04T21:54:18Z', 3.14, 2, 3, " + "42, 'sammy')"; obj = test_seagull_object_new(); @@ -269,15 +343,20 @@ gboolean result = FALSE; char *expanded = NULL; const char *migrations[] = { - "CREATE TABLE obj(vboolean INTEGER, vdouble DOUBLE, vinteger INTEGER, " + "CREATE TABLE obj(vboolean INTEGER, vdatetime TEXT, vdouble DOUBLE, " + " venum INTEGER, vflags INTEGER, vinteger INTEGER, " " vstring TEXT);", NULL }; - const char *query = "INSERT INTO obj(vboolean, vdouble, vinteger, vstring) " - "VALUES(:prefix_vboolean, @prefix_vdouble, " + const char *query = "INSERT INTO obj(vboolean, vdatetime, vdouble, venum, " + "vflags, vinteger, vstring) " + "VALUES(:prefix_vboolean, $prefix_vdatetime, " + "@prefix_vdouble, @prefix_venum, :prefix_vflags, " "$prefix_vinteger, :prefix_vstring)"; - const char *expected = "INSERT INTO obj(vboolean, vdouble, vinteger, " - "vstring) VALUES(1, 3.14, 42, 'sammy')"; + const char *expected = "INSERT INTO obj(vboolean, vdatetime, vdouble, " + "venum, vflags, vinteger, vstring) " + "VALUES(1, '2025-02-04T21:54:18Z', 3.14, 2, 3, 42, " + "'sammy')"; obj = test_seagull_object_new(); @@ -426,6 +505,55 @@ g_assert_finalize_object(obj); } +static void +test_seagull_bind_object_prefix_must_match(void) { + TestSeagullObject *obj = NULL; + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + gboolean result = FALSE; + char *expanded = NULL; + const char *migrations[] = { + "CREATE TABLE obj(vboolean INTEGER, vinteger INTEGER);", + NULL + }; + const char *query = "INSERT INTO obj(vboolean, vinteger) " + "VALUES(:prefix_vboolean, @vinteger)"; + const char *expected = "INSERT INTO obj(vboolean, vinteger) " + "VALUES(1, NULL)"; + + obj = test_seagull_object_new(); + + db = seagull_db_new_in_memory(&error); + g_assert_no_error(error); + g_assert_nonnull(db); + + result = seagull_migrations_run_from_strings(db, migrations, &error); + g_assert_no_error(error); + g_assert_true(result); + + statement = seagull_statement_new(db, query, &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + result = seagull_statement_bind_object(statement, "prefix_", G_OBJECT(obj), + &error); + g_assert_no_error(error); + g_assert_true(result); + + expanded = seagull_statement_get_expanded_sql(statement); + g_assert_cmpstr(expanded, ==, expected); + seagull_free(expanded); + + g_assert_finalize_object(statement); + + result = seagull_db_close(db, &error); + g_assert_no_error(error); + g_assert_true(result); + + g_assert_finalize_object(obj); +} + /****************************************************************************** * Column Tests *****************************************************************************/ @@ -470,16 +598,21 @@ TestSeagullObject *obj = NULL; SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; + GDateTime *dt = NULL; GError *error = NULL; gboolean result = FALSE; const char *migrations[] = { - "CREATE TABLE obj(vboolean INTEGER, vdouble DOUBLE, vinteger INTEGER, " + "CREATE TABLE obj(vboolean INTEGER, vdatetime TEXT, vdouble DOUBLE, " + " venum INTEGER, vflags INTEGER, vinteger INTEGER, " " vstring TEXT);" - "INSERT INTO obj(vboolean, vdouble, vinteger, vstring) VALUES " - " (1, 3.14, 42, 'sammy');", + "INSERT INTO obj(vboolean, vdatetime, vdouble, venum, vflags, " + " vinteger, vstring) " + " VALUES (1, '2025-02-04T21:54:18Z', 3.14, 2, 3, 42, " + " 'sammy');", NULL }; - const char *query = "SELECT vboolean, vdouble, vinteger, vstring FROM obj"; + const char *query = "SELECT vboolean, vdatetime, vdouble, venum, vflags, " + "vinteger, vstring FROM obj"; obj = test_seagull_object_new_empty(); @@ -504,8 +637,14 @@ g_assert_no_error(error); g_assert_true(result); - g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_true(obj->v_boolean); + + dt = g_date_time_new_from_iso8601("2025-02-04T21:54:18Z", NULL); + g_assert_nonnull(obj->v_date_time); + g_assert_true(g_date_time_equal(obj->v_date_time, dt)); + g_clear_pointer(&dt, g_date_time_unref); + + g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_cmpint(obj->v_integer, ==, 42); g_assert_cmpstr(obj->v_string, ==, "sammy"); @@ -527,18 +666,25 @@ TestSeagullObject *obj = NULL; SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; + GDateTime *dt = NULL; GError *error = NULL; gboolean result = FALSE; const char *migrations[] = { - "CREATE TABLE obj(vboolean INTEGER, vdouble DOUBLE, vinteger INTEGER, " + "CREATE TABLE obj(vboolean INTEGER, vdatetime TEXT, vdouble DOUBLE, " + " venum INTEGER, vflags INTEGER, vinteger INTEGER, " " vstring TEXT);" - "INSERT INTO obj(vboolean, vdouble, vinteger, vstring) VALUES " - " (1, 3.14, 42, 'sammy');", + "INSERT INTO obj(vboolean, vdatetime, vdouble, venum, vflags, " + " vinteger, vstring) " + " VALUES (1, '2025-02-04T21:54:18Z', 3.14, 2, 3, 42, " + " 'sammy');", NULL }; const char *query = "SELECT " "vboolean AS prefix_vboolean, " + "vdatetime AS prefix_vdatetime, " "vdouble AS prefix_vdouble, " + "venum AS prefix_venum, " + "vflags AS prefix_vflags, " "vinteger AS prefix_vinteger, " "vstring AS prefix_vstring " "FROM obj"; @@ -566,8 +712,14 @@ g_assert_no_error(error); g_assert_true(result); - g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_true(obj->v_boolean); + + dt = g_date_time_new_from_iso8601("2025-02-04T21:54:18Z", NULL); + g_assert_nonnull(obj->v_date_time); + g_assert_true(g_date_time_equal(obj->v_date_time, dt)); + g_clear_pointer(&dt, g_date_time_unref); + + g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_cmpint(obj->v_integer, ==, 42); g_assert_cmpstr(obj->v_string, ==, "sammy"); @@ -741,6 +893,9 @@ g_test_add_func("/seagull/statement/bind-object/mixed", test_seagull_statement_bind_object_mixed); + g_test_add_func("/seagull/statement/bind-object/prefix-must-match", + test_seagull_bind_object_prefix_must_match); + g_test_add_func("/seagull/statement/column-object/no-matches", test_seagull_statement_column_object_no_matches); g_test_add_func("/seagull/statement/column-object/no-prefix", ++++++ seagull.keyring ++++++ --- /var/tmp/diff_new_pack.1R0pnh/_old 2025-10-03 15:45:54.490708731 +0200 +++ /var/tmp/diff_new_pack.1R0pnh/_new 2025-10-03 15:45:54.498709066 +0200 @@ -1,6 +1,6 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: Hockeypuck 2.2 Comment: Hostname: +Version: Hockeypuck 2.2 xsFNBF05DzkBEADFEFM1ZALjngGoeIalaW9aXCA5Gr505LDK8WIVVeQD/Izggx9z Y0wi2UJR97eIXllL8FPZIe8DywJqXKhuafL+E/TI9UqRH/WtmNxZTFW6ZAvYlaHu
