Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package seagull for openSUSE:Factory checked in at 2026-02-03 21:29:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/seagull (Old) and /work/SRC/openSUSE:Factory/.seagull.new.1995 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "seagull" Tue Feb 3 21:29:54 2026 rev:6 rq:1330424 version:0.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/seagull/seagull.changes 2026-01-21 14:18:03.024640190 +0100 +++ /work/SRC/openSUSE:Factory/.seagull.new.1995/seagull.changes 2026-02-03 21:31:12.219907472 +0100 @@ -1,0 +2,7 @@ +Mon Feb 2 13:44:34 UTC 2026 - Richard Rahl <[email protected]> + +- Update to version 0.7.0: + * Add support for int64s + * Add support for GError + +------------------------------------------------------------------- Old: ---- seagull-0.6.1.tar.xz seagull-0.6.1.tar.xz.asc New: ---- seagull-0.7.0.tar.xz seagull-0.7.0.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ seagull.spec ++++++ --- /var/tmp/diff_new_pack.7HdkUJ/_old 2026-02-03 21:31:12.839933705 +0100 +++ /var/tmp/diff_new_pack.7HdkUJ/_new 2026-02-03 21:31:12.839933705 +0100 @@ -1,7 +1,7 @@ # # spec file for package seagull # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define sover 0 Name: seagull -Version: 0.6.1 +Version: 0.7.0 Release: 0 Summary: A SQLite helper library License: LGPL-2.1-or-later ++++++ seagull-0.6.1.tar.xz -> seagull-0.7.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/.hg_archival.txt new/seagull-0.7.0/.hg_archival.txt --- old/seagull-0.6.1/.hg_archival.txt 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/.hg_archival.txt 2026-02-01 09:33:36.000000000 +0100 @@ -1,4 +1,4 @@ repo: 3c210e7a53be9dacf85a643e66330f36daf34679 -node: 493357457eaa1fbed688866fa5bafa64577bc195 +node: 6436bd889bdb5de1acb4c1c4878ce8d22b531450 branch: default -tag: v0.6.1 +tag: v0.7.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/ChangeLog new/seagull-0.7.0/ChangeLog --- old/seagull-0.6.1/ChangeLog 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/ChangeLog 2026-02-01 09:33:36.000000000 +0100 @@ -1,3 +1,7 @@ +0.7.0: 2026-02-01 + * Add support for int64s (SEAGULL-19) (RR 4331) (Gary Kramlich) + * Add support for GError (SEAGULL-9) (RR 4332) (Gary Kramlich) + 0.6.1: 2026-01-13 * Add a codespell unit tests (RR 4267) (Gary Kramlich) * Allow passing NULL to Seagull.Statement.bind_time_zone (RR 4325) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/meson.build new/seagull-0.7.0/meson.build --- old/seagull-0.6.1/meson.build 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/meson.build 2026-02-01 09:33:36.000000000 +0100 @@ -1,5 +1,5 @@ project('seagull', 'c', - version : '0.6.1', + version : '0.7.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.6.1/seagull/seagullstatement.c new/seagull-0.7.0/seagull/seagullstatement.c --- old/seagull-0.6.1/seagull/seagullstatement.c 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/seagull/seagullstatement.c 2026-02-01 09:33:36.000000000 +0100 @@ -23,6 +23,8 @@ #include "seagullstatement.h" +#define SEAGULL_STATEMENT_GERROR_VARIANT_FORMAT "(sis)" + struct _SeagullStatement { GObject parent; @@ -544,6 +546,34 @@ } gboolean +seagull_statement_bind_error(SeagullStatement *statement, const char *name, + GError *value, GError **error) +{ + GVariant *variant = NULL; + GBytes *bytes = NULL; + gboolean ret = FALSE; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE); + + if(value == NULL) { + return seagull_statement_bind_null(statement, name, error); + } + + variant = g_variant_new(SEAGULL_STATEMENT_GERROR_VARIANT_FORMAT, + g_quark_to_string(value->domain), + value->code, value->message); + bytes = g_variant_get_data_as_bytes(variant); + g_clear_pointer(&variant, g_variant_unref); + + ret = seagull_statement_bind_bytes(statement, name, bytes, error); + + g_clear_pointer(&bytes, g_bytes_unref); + + return ret; +} + + +gboolean seagull_statement_bind_flags(SeagullStatement *statement, const char *name, guint value, GError **error) { @@ -585,6 +615,38 @@ } gboolean +seagull_statement_bind_int64(SeagullStatement *statement, const char *name, + gint64 value, GError **error) +{ + GError *local_error = NULL; + int rc = 0; + int index = 0; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE); + + index = seagull_statement_find_parameter(statement, name, &local_error); + if(local_error != NULL) { + g_propagate_error(error, local_error); + + return FALSE; + } + + rc = sqlite3_bind_int64(statement->statement, index, value); + if(rc != SQLITE_OK) { + g_set_error(error, + SEAGULL_STATEMENT_ERROR, + SEAGULL_STATEMENT_ERROR_BIND_FAILED, + "failed to bind parameter '%s': %s", + name, + sqlite3_errmsg(statement->db)); + + return FALSE; + } + + return TRUE; +} + +gboolean seagull_statement_bind_null(SeagullStatement *statement, const char *name, GError **error) { @@ -673,9 +735,17 @@ seagull_statement_bind_double(statement, parameter_name, g_value_get_double(&value), &local_error); + } else if(type == G_TYPE_ERROR) { + seagull_statement_bind_error(statement, parameter_name, + g_value_get_boxed(&value), + &local_error); } else if(type == G_TYPE_INT) { seagull_statement_bind_int(statement, parameter_name, g_value_get_int(&value), &local_error); + } else if(type == G_TYPE_INT64) { + seagull_statement_bind_int64(statement, parameter_name, + g_value_get_int64(&value), + &local_error); } else if(type == G_TYPE_STRING) { seagull_statement_bind_text(statement, parameter_name, g_value_steal_string(&value), @@ -927,6 +997,49 @@ return sqlite3_column_int(statement->statement, column); } +GError * +seagull_statement_column_error(SeagullStatement *statement, const char *name, + GError **error) +{ + GBytes *bytes = NULL; + GError *local_error = NULL; + GError *value = NULL; + GVariant *variant = NULL; + int code; + const char *domain = NULL; + const char *message = NULL; + + g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), 0); + g_return_val_if_fail(name != NULL, 0); + + bytes = seagull_statement_column_bytes(statement, name, &local_error); + if(local_error != NULL) { + g_propagate_error(error, local_error); + + return NULL; + } + + if(bytes == NULL) { + return NULL; + } + + variant = g_variant_new_from_bytes(G_VARIANT_TYPE(SEAGULL_STATEMENT_GERROR_VARIANT_FORMAT), + bytes, TRUE); + g_clear_pointer(&bytes, g_bytes_unref); + + /* Pull the values out of the variant. */ + g_variant_get_child(variant, 0, "&s", &domain); + g_variant_get_child(variant, 1, "i", &code); + g_variant_get_child(variant, 2, "&s", &message); + + /* Build the error. */ + value = g_error_new(g_quark_from_string(domain), code, message); + + g_variant_unref(variant); + + return value; +} + guint seagull_statement_column_flags(SeagullStatement *statement, const char *name, GError **error) @@ -969,7 +1082,7 @@ column_type = sqlite3_column_type(statement->statement, column); if(!seagull_statement_check_column_type(SQLITE_INTEGER, column_type, - error)) + error)) { return 0; } @@ -977,6 +1090,31 @@ return sqlite3_column_int(statement->statement, column); } +gint64 +seagull_statement_column_int64(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_int64(statement->statement, column); +} + gboolean seagull_statement_column_object(SeagullStatement *statement, const char *prefix, @@ -1060,10 +1198,52 @@ g_value_init(&value, G_TYPE_DOUBLE); g_value_set_double(&value, sqlite3_column_double(statement->statement, i)); + } else if(pspec->value_type == G_TYPE_ERROR) { + GBytes *bytes = NULL; + GError *error_value = NULL; + gsize data_size = 0; + + data_size = sqlite3_column_bytes(statement->statement, i); + if(data_size > 0) { + gconstpointer data = NULL; + + data = sqlite3_column_blob(statement->statement, i); + bytes = g_bytes_new(data, data_size); + } + + if(bytes != NULL) { + GVariant *variant = NULL; + const char *domain = NULL; + const char *message = NULL; + int code = 0; + + variant = g_variant_new_from_bytes(G_VARIANT_TYPE(SEAGULL_STATEMENT_GERROR_VARIANT_FORMAT), + bytes, TRUE); + + g_clear_pointer(&bytes, g_bytes_unref); + + /* Pull the values out of the variant. */ + g_variant_get_child(variant, 0, "&s", &domain); + g_variant_get_child(variant, 1, "i", &code); + g_variant_get_child(variant, 2, "&s", &message); + + /* Build the error. */ + error_value = g_error_new(g_quark_from_string(domain), code, + message); + + g_clear_pointer(&variant, g_variant_unref); + } + + g_value_init(&value, G_TYPE_ERROR); + g_value_take_boxed(&value, error_value); } 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)); + } else if(pspec->value_type == G_TYPE_INT64) { + g_value_init(&value, G_TYPE_INT64); + g_value_set_int64(&value, + sqlite3_column_int64(statement->statement, i)); } else if(pspec->value_type == G_TYPE_STRING) { g_value_init(&value, G_TYPE_STRING); g_value_set_string(&value, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/seagull/seagullstatement.h new/seagull-0.7.0/seagull/seagullstatement.h --- old/seagull-0.6.1/seagull/seagullstatement.h 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/seagull/seagullstatement.h 2026-02-01 09:33:36.000000000 +0100 @@ -180,7 +180,7 @@ /** * seagull_statement_bind_double: * @name: the name of the parameter - * @value: the value. + * @value: the value * @error: (out) (nullable): a return address for a #GError * * Binds a double value to the named parameter. @@ -212,6 +212,27 @@ gboolean seagull_statement_bind_enum(SeagullStatement *stmt, const char *name, int value, GError **error); /** + * seagull_statement_bind_error: + * @name: the name of the parameter + * @value: (transfer none) (nullable): the value + * @error: (out) (nullable): a return address for a #GError + * + * Binds a [[email protected]] value to the named parameter. + * + * The error will be encoded as a [[email protected]] with a format of `(sis)` + * and is expecting to be bound to a bytes column. The domain is stored as a + * string in the event the quark hasn't been created before it was needed. + * + * @name must be the exact name as specified in the query. + * + * Returns: true on success; otherwise false with error set. + * + * Since: 0.7 + */ +SEAGULL_AVAILABLE_IN_0_7 +gboolean seagull_statement_bind_error(SeagullStatement *statement, const char *name, GError *value, GError **error); + +/** * seagull_statement_bind_flags: * @name: the name of the parameter * @value: the value @@ -231,7 +252,7 @@ /** * seagull_statement_bind_int: * @name: the name of the parameter - * @value: the value. + * @value: the value * @error: (out) (nullable): a return address for a #GError * * Binds an integer value to the named parameter. @@ -246,6 +267,23 @@ gboolean seagull_statement_bind_int(SeagullStatement *statement, const char *name, int value, GError **error); /** + * seagull_statement_bind_int64: + * @name: the name of the parameter + * @value: the value + * @error: (out) (nullable): a return address for a #GError + * + * Binds an int64 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.7 + */ +SEAGULL_AVAILABLE_IN_0_7 +gboolean seagull_statement_bind_int64(SeagullStatement *statement, const char *name, gint64 value, GError **error); + +/** * seagull_statement_bind_null: * @name: the name of the parameter * @error: (out) (nullable): a return address for a #GError @@ -450,6 +488,27 @@ int seagull_statement_column_enum(SeagullStatement *statement, const char *name, GError **error); /** + * seagull_statement_column_error: + * @name: the name of the column + * @error: (out) (nullable): a return address for a #GError + * + * Gets the error 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. + * + * The column must be of the bytes type and have a serialized GVariant with a + * format of `(sis)`. + * + * Returns: (transfer full) (nullable): The error on success or %NULL on error + * with error set. + * + * Since: 0.7 + */ +SEAGULL_AVAILABLE_IN_0_7 +GError *seagull_statement_column_error(SeagullStatement *statement, const char *name, GError **error); + +/** * seagull_statement_column_flags: * @name: the name of the column * @error: (out) (nullable): a return address for a #GError @@ -484,6 +543,23 @@ int seagull_statement_column_int(SeagullStatement *statement, const char *name, GError **error); /** + * seagull_statement_column_int64: + * @name: the name of the column + * @error: (out) (nullable): 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.7 + */ +SEAGULL_AVAILABLE_IN_0_7 +gint64 seagull_statement_column_int64(SeagullStatement *statement, const char *name, GError **error); + +/** * seagull_statement_column_object: * @prefix: (nullable): an optional prefix * @obj: the object diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/seagull/seagullversion.h new/seagull-0.7.0/seagull/seagullversion.h --- old/seagull-0.6.1/seagull/seagullversion.h 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/seagull/seagullversion.h 2026-02-01 09:33:36.000000000 +0100 @@ -270,6 +270,30 @@ #define SEAGULL_AVAILABLE_TYPE_IN_0_6 #endif +/** + * SEAGULL_VERSION_0_7: + * + * A macro that evaluates to the 0.7 version of seagull, in a format that can + * be used by the C pre-processor. + * + * Since: 0.7 + */ +#define SEAGULL_VERSION_0_7 (G_ENCODE_VERSION(0, 7)) + +#if SEAGULL_VERSION_MAX_ALLOWED < SEAGULL_VERSION_0_7 +#define SEAGULL_AVAILABLE_IN_0_7 SEAGULL_UNAVAILABLE(0, 7) +#define SEAGULL_AVAILABLE_ENUMERATOR_IN_0_7 SEAGULL_UNAVAILABLE_ENUMERATOR(0, 7) +#define SEAGULL_AVAILABLE_MACRO_IN_0_7 SEAGULL_UNAVAILABLE_MACRO(0, 7) +#define SEAGULL_AVAILABLE_STATIC_INLINE_IN_0_7 SEAGULL_UNAVAILABLE_STATIC_INLINE(0, 7) +#define SEAGULL_AVAILABLE_TYPE_IN_0_7 SEAGULL_UNAVAILABLE_TYPE(0, 7) +#else +#define SEAGULL_AVAILABLE_IN_0_7 _SEAGULL_EXTERN +#define SEAGULL_AVAILABLE_ENUMERATOR_IN_0_7 +#define SEAGULL_AVAILABLE_MACRO_IN_0_7 +#define SEAGULL_AVAILABLE_STATIC_INLINE_IN_0_7 +#define SEAGULL_AVAILABLE_TYPE_IN_0_7 +#endif + G_BEGIN_DECLS /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/seagull/tests/test_statement.c new/seagull-0.7.0/seagull/tests/test_statement.c --- old/seagull-0.6.1/seagull/tests/test_statement.c 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/seagull/tests/test_statement.c 2026-02-01 09:33:36.000000000 +0100 @@ -589,6 +589,106 @@ } static void +test_seagull_statement_bind_error_normal(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + GError *value = 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)); + + value = g_error_new(SEAGULL_STATEMENT_ERROR, -1337, "test value"); + result = seagull_statement_bind_error(statement, ":foo", value, &error); + g_clear_error(&value); + + g_assert_no_error(error); + g_assert_true(result); + + expanded = seagull_statement_get_expanded_sql(statement); + g_assert_cmpstr(expanded, ==, + "SELECT x'73656167756c6c2d73746174656d656e742d6572726f7200c7faffff746573742076616c75650018'"); + 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_error_not_found(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + GError *value = 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)); + + value = g_error_new(SEAGULL_STATEMENT_ERROR, -1337, "test value"); + result = seagull_statement_bind_error(statement, ":bar", value, &error); + g_clear_error(&value); + + g_assert_error(error, + SEAGULL_STATEMENT_ERROR, + SEAGULL_STATEMENT_ERROR_BIND_PARAMETER_NOT_FOUND); + g_clear_error(&error); + g_assert_false(result); + + 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_error_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_error(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_int_normal(void) { SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; @@ -649,6 +749,70 @@ } static void +test_seagull_statement_bind_int64_normal(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_int64(statement, ":foo", + G_GINT64_CONSTANT(0x1cedc0ffee), + &error); + g_assert_no_error(error); + g_assert_true(result); + + expanded = seagull_statement_get_expanded_sql(statement); + g_assert_cmpstr(expanded, ==, "SELECT 124247932910"); + 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_int64_not_found(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = 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_int64(statement, ":bar", + G_GINT64_CONSTANT(0x1cedc0ffee), + &error); + g_assert_error(error, + SEAGULL_STATEMENT_ERROR, + SEAGULL_STATEMENT_ERROR_BIND_PARAMETER_NOT_FOUND); + g_clear_error(&error); + g_assert_false(result); + + 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_mixed(void) { SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; @@ -1510,6 +1674,135 @@ } static void +test_seagull_statement_column_error_null(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + GError *value = NULL; + gboolean result = FALSE; + const char *migrations[] = { + "CREATE TABLE foo(bar BYTES);", + "INSERT INTO foo(bar) VALUES(null);", + NULL + }; + + 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, "SELECT * from foo", &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + result = seagull_statement_step(statement, &error); + g_assert_no_error(error); + g_assert_true(result); + + value = seagull_statement_column_error(statement, "bar", &error); + g_assert_no_error(error); + g_assert_null(value); + + /* Clean up */ + 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_column_error_normal(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + GError *value = NULL; + gboolean result = FALSE; + const char *migrations[] = { + "CREATE TABLE foo(bar BYTES);", + "INSERT INTO foo(bar) VALUES(x'73656167756c6c2d73746174656d656e742d6572726f7200c7faffff746573742076616c75650018');", + NULL + }; + + 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, "SELECT * from foo", &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + result = seagull_statement_step(statement, &error); + g_assert_no_error(error); + g_assert_true(result); + + value = seagull_statement_column_error(statement, "bar", &error); + g_assert_no_error(error); + g_assert_nonnull(value); + + g_assert_error(value, SEAGULL_STATEMENT_ERROR, -1337); + g_assert_cmpstr(value->message, ==, "test value"); + + g_clear_error(&value); + + /* Clean up */ + 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_column_int64_normal(void) { + SeagullStatement *statement = NULL; + SeagullSqlite3 *db = NULL; + GError *error = NULL; + gboolean result = FALSE; + gint64 value = 0; + const char *migrations[] = { + "CREATE TABLE foo(bar int64);", + "INSERT INTO foo(bar) VALUES(0x1cedc0ffee);", + NULL + }; + + 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, "SELECT * from foo", &error); + g_assert_no_error(error); + g_assert_true(SEAGULL_IS_STATEMENT(statement)); + + result = seagull_statement_step(statement, &error); + g_assert_no_error(error); + g_assert_true(result); + + value = seagull_statement_column_int64(statement, "bar", &error); + g_assert_no_error(error); + + g_assert_true(value == G_GINT64_CONSTANT(0x1cedc0ffee)); + + /* Clean up */ + 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_column_time_zone_null(void) { SeagullStatement *statement = NULL; SeagullSqlite3 *db = NULL; @@ -1651,10 +1944,20 @@ test_seagull_statement_bind_double_normal); g_test_add_func("/seagull/statement/bind/double/not-found", test_seagull_statement_bind_double_not_found); + g_test_add_func("/seagull/statement/bind/error/normal", + test_seagull_statement_bind_error_normal); + g_test_add_func("/seagull/statement/bind/error/not-found", + test_seagull_statement_bind_error_not_found); + g_test_add_func("/seagull/statement/bind/error/null", + test_seagull_statement_bind_error_null); g_test_add_func("/seagull/statement/bind/int/normal", test_seagull_statement_bind_int_normal); g_test_add_func("/seagull/statement/bind/int/not-found", test_seagull_statement_bind_int_not_found); + g_test_add_func("/seagull/statement/bind/int64/normal", + test_seagull_statement_bind_int64_normal); + g_test_add_func("/seagull/statement/bind/int64/not-found", + test_seagull_statement_bind_int64_not_found); g_test_add_func("/seagull/statement/bind/mixed", test_seagull_statement_bind_mixed); g_test_add_func("/seagull/statement/bind/null/normal", @@ -1696,6 +1999,12 @@ test_seagull_statement_column_date_time_null); g_test_add_func("/seagull/statement/column/date-time/normal", test_seagull_statement_column_date_time_normal); + g_test_add_func("/seagull/statement/column/error/null", + test_seagull_statement_column_error_null); + g_test_add_func("/seagull/statement/column/error/normal", + test_seagull_statement_column_error_normal); + g_test_add_func("/seagull/statement/column/int64/normal", + test_seagull_statement_column_int64_normal); g_test_add_func("/seagull/statement/column/time-zone/null", test_seagull_statement_column_time_zone_null); g_test_add_func("/seagull/statement/column/time-zone/normal", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/seagull-0.6.1/seagull/tests/test_statement_object.c new/seagull-0.7.0/seagull/tests/test_statement_object.c --- old/seagull-0.6.1/seagull/tests/test_statement_object.c 2026-01-16 08:41:15.000000000 +0100 +++ new/seagull-0.7.0/seagull/tests/test_statement_object.c 2026-02-01 09:33:36.000000000 +0100 @@ -37,8 +37,10 @@ GDateTime *v_date_time; double v_double; GConverterResult v_enum; + GError *v_error; GConverterFlags v_flags; int v_integer; + gint64 v_integer64; char *v_string; GTimeZone *v_time_zone; }; @@ -50,8 +52,10 @@ PROP_DATE_TIME, PROP_DOUBLE, PROP_ENUM, + PROP_ERROR, PROP_FLAGS, PROP_INTEGER, + PROP_INTEGER64, PROP_STRING, PROP_TIME_ZONE, N_PROPERTIES, @@ -66,6 +70,7 @@ g_clear_pointer(&test_object->v_bytes, g_bytes_unref); g_clear_pointer(&test_object->v_date_time, g_date_time_unref); + g_clear_error(&test_object->v_error); g_clear_pointer(&test_object->v_string, g_free); g_clear_pointer(&test_object->v_time_zone, g_time_zone_unref); @@ -94,12 +99,18 @@ case PROP_ENUM: g_value_set_enum(value, seagull_obj->v_enum); break; + case PROP_ERROR: + g_value_set_boxed(value, seagull_obj->v_error); + 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; + case PROP_INTEGER64: + g_value_set_int64(value, seagull_obj->v_integer64); + break; case PROP_STRING: g_value_set_string(value, seagull_obj->v_string); break; @@ -136,12 +147,19 @@ case PROP_ENUM: test_obj->v_enum = g_value_get_enum(value); break; + case PROP_ERROR: + g_clear_error(&test_obj->v_error); + test_obj->v_error = g_value_dup_boxed(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; + case PROP_INTEGER64: + test_obj->v_integer64 = g_value_get_int64(value); + break; case PROP_STRING: g_clear_pointer(&test_obj->v_string, g_free); test_obj->v_string = g_value_dup_string(value); @@ -196,6 +214,11 @@ G_TYPE_CONVERTER_RESULT, G_CONVERTER_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_ERROR] = g_param_spec_boxed( + "verror", NULL, NULL, + G_TYPE_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. */ @@ -209,6 +232,11 @@ 0, 100, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_INTEGER64] = g_param_spec_int64( + "vinteger64", NULL, NULL, + G_MININT64, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_STRING] = g_param_spec_string( "vstring", NULL, NULL, NULL, @@ -227,10 +255,12 @@ TestSeagullObject *ret = NULL; GBytes *bytes = NULL; GDateTime *dt = NULL; + GError *error = NULL; GTimeZone *tz = NULL; bytes = g_bytes_new("seagull", 7); dt = g_date_time_new_from_iso8601("2025-02-04T21:54:18Z", NULL); + error = g_error_new(SEAGULL_STATEMENT_ERROR, -1337, "test value"); tz = g_time_zone_new_utc(); ret = g_object_new(test_seagull_object_get_type(), "vboolean", TRUE, @@ -238,14 +268,17 @@ "vdatetime", dt, "vdouble", 3.14, "venum", G_CONVERTER_FINISHED, + "verror", error, "vflags", G_CONVERTER_INPUT_AT_END | G_CONVERTER_FLUSH, "vinteger", 42, + "vinteger64", G_GINT64_CONSTANT(0x1cedc0ffee), "vstring", "sammy", "vtimezone", tz, NULL); g_bytes_unref(bytes); g_date_time_unref(dt); + g_clear_error(&error); g_time_zone_unref(tz); return ret; @@ -261,10 +294,12 @@ TestSeagullObject *ret = NULL; GBytes *bytes = NULL; GDateTime *dt = NULL; + GError *error = NULL; GTimeZone *tz = NULL; bytes = g_bytes_new("landgull", 8); dt = g_date_time_new_from_iso8601("2025-06-27T02:22:19Z", NULL); + error = g_error_new(SEAGULL_STATEMENT_ERROR, 42, "other value"); tz = g_time_zone_new_identifier("-0500"); ret = g_object_new(test_seagull_object_get_type(), "vboolean", FALSE, @@ -272,14 +307,17 @@ "vdatetime", dt, "vdouble", 6.28, "venum", G_CONVERTER_FLUSHED, + "verror", error, "vflags", G_CONVERTER_FLUSH, "vinteger", 24, + "vinteger64", 0x1337, "vstring", "ymmas", "vtimezone", tz, NULL); g_bytes_unref(bytes); g_date_time_unref(dt); + g_clear_error(&error); g_time_zone_unref(tz); return ret; @@ -335,21 +373,24 @@ char *expanded = NULL; const char *migrations[] = { "CREATE TABLE obj(vboolean INTEGER, vbytes BLOB, vdatetime TEXT, " - " vdouble DOUBLE, venum INTEGER, vflags INTEGER, " - " vinteger INTEGER, vstring TEXT, vtimezone TEXT);", + " vdouble DOUBLE, venum INTEGER, verror BYTES, " + " vflags INTEGER, vinteger INTEGER, " + " vinteger64 INTEGER, vstring TEXT, vtimezone TEXT);", NULL }; const char *query = "INSERT INTO obj(vboolean, vbytes, vdatetime, " - "vdouble, venum, vflags, vinteger, vstring, " - "vtimezone) " + "vdouble, venum, verror, vflags, vinteger, " + "vinteger64, vstring, vtimezone) " "VALUES(:vboolean, :vbytes, :vdatetime, @vdouble, " - "$venum, :vflags, $vinteger, :vstring, @vtimezone)"; + "$venum, @verror, :vflags, $vinteger, @vinteger64, " + ":vstring, @vtimezone)"; const char *expected = "INSERT INTO obj(vboolean, vbytes, vdatetime, " - "vdouble, venum, vflags, vinteger, vstring, " - "vtimezone) " + "vdouble, venum, verror, vflags, vinteger, " + "vinteger64, vstring, vtimezone) " "VALUES(1, x'73656167756c6c', " - "'2025-02-04T21:54:18Z', 3.14, 2, 3, 42, 'sammy', " - "'UTC')"; + "'2025-02-04T21:54:18Z', 3.14, 2, " + "x'73656167756c6c2d73746174656d656e742d6572726f7200c7faffff746573742076616c75650018', " + "3, 42, 124247932910, 'sammy', 'UTC')"; obj = test_seagull_object_new(); @@ -393,23 +434,26 @@ char *expanded = NULL; const char *migrations[] = { "CREATE TABLE obj(vboolean INTEGER, vbytes BLOB, vdatetime TEXT, " - " vdouble DOUBLE, venum INTEGER, vflags INTEGER, " - " vinteger INTEGER, vstring TEXT, vtimezone TEXT);", + " vdouble DOUBLE, venum INTEGER, verror BYTES, " + " vflags INTEGER, vinteger INTEGER, " + " vinteger64 INTEGER, vstring TEXT, vtimezone TEXT);", NULL }; const char *query = "INSERT INTO obj(vboolean, vbytes, vdatetime, " - "vdouble, venum, vflags, vinteger, vstring, " - "vtimezone) " + "vdouble, venum, verror, vflags, vinteger, " + "vinteger64, vstring, vtimezone) " "VALUES(:prefix_vboolean, :prefix_vbytes, " "$prefix_vdatetime, @prefix_vdouble, @prefix_venum, " - ":prefix_vflags, $prefix_vinteger, :prefix_vstring, " + "$prefix_verror, :prefix_vflags, $prefix_vinteger, " + "@prefix_vinteger64, :prefix_vstring, " "@prefix_vtimezone)"; const char *expected = "INSERT INTO obj(vboolean, vbytes, vdatetime, " - "vdouble, venum, vflags, vinteger, vstring, " - "vtimezone) " + "vdouble, venum, verror, vflags, vinteger, " + "vinteger64, vstring, vtimezone) " "VALUES(1, x'73656167756c6c', " - "'2025-02-04T21:54:18Z', 3.14, 2, 3, 42, 'sammy', " - "'UTC')"; + "'2025-02-04T21:54:18Z', 3.14, 2, " + "x'73656167756c6c2d73746174656d656e742d6572726f7200c7faffff746573742076616c75650018', " + "3, 42, 124247932910, 'sammy', 'UTC')"; obj = test_seagull_object_new(); @@ -656,19 +700,24 @@ GTimeZone *tz = NULL; gboolean result = FALSE; gconstpointer data = NULL; + gint64 v_integer64 = G_GINT64_CONSTANT(0x1cedc0ffee); gsize data_size = 0; const char *migrations[] = { "CREATE TABLE obj(vboolean INTEGER, vbytes BLOB, vdatetime TEXT, " - " vdouble DOUBLE, venum INTEGER, vflags INTEGER, " - " vinteger INTEGER, vstring TEXT, vtimezone TEXT);" - "INSERT INTO obj(vboolean, vbytes, vdatetime, vdouble, venum, vflags, " - " vinteger, vstring, vtimezone) " + " vdouble DOUBLE, venum INTEGER, verror BYTES, " + " vflags INTEGER, vinteger INTEGER, " + " vinteger64 INTEGER, vstring TEXT, vtimezone TEXT);" + "INSERT INTO obj(vboolean, vbytes, vdatetime, vdouble, venum, verror, " + " vflags, vinteger, vinteger64, vstring, vtimezone) " " VALUES (1, x'73656167756c6c', '2025-02-04T21:54:18Z', " - " 3.14, 2, 3, 42, 'sammy', 'UTC');", + " 3.14, 2, " + " x'73656167756c6c2d73746174656d656e742d6572726f7200c7faffff746573742076616c75650018'," + " 3, 42, 124247932910, 'sammy', 'UTC');", NULL }; const char *query = "SELECT vboolean, vbytes, vdatetime, vdouble, venum, " - "vflags, vinteger, vstring, vtimezone FROM obj"; + "verror, vflags, vinteger, vinteger64, vstring, " + "vtimezone FROM obj"; obj = test_seagull_object_new_empty(); @@ -704,8 +753,12 @@ g_assert_true(g_date_time_equal(obj->v_date_time, dt)); g_clear_pointer(&dt, g_date_time_unref); + g_assert_error(obj->v_error, SEAGULL_STATEMENT_ERROR, -1337); + g_assert_cmpstr(obj->v_error->message, ==, "test value"); + g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_cmpint(obj->v_integer, ==, 42); + g_assert_true(obj->v_integer64 == v_integer64); g_assert_cmpstr(obj->v_string, ==, "sammy"); tz = g_time_zone_new_utc(); @@ -741,11 +794,12 @@ const char *migrations[] = { "CREATE TABLE obj(vboolean INTEGER, vbytes BLOB, vdatetime TEXT, " " vdouble DOUBLE, venum INTEGER, vflags INTEGER, " - " vinteger INTEGER, vstring TEXT, vtimezone TEXT);" + " vinteger INTEGER, vinteger64 INTEGER, vstring TEXT, " + " vtimezone TEXT);" "INSERT INTO obj(vboolean, vbytes, vdatetime, vdouble, venum, vflags, " - " vinteger, vstring, vtimezone) " + " vinteger, vinteger64, vstring, vtimezone) " " VALUES (1, x'73656167756c6c', '2025-02-04T21:54:18Z', " - " 3.14, 2, 3, 42, 'sammy', 'UTC');", + " 3.14, 2, 3, 42, 124247932910, 'sammy', 'UTC');", NULL }; const char *query = "SELECT " @@ -756,6 +810,7 @@ "venum AS prefix_venum, " "vflags AS prefix_vflags, " "vinteger AS prefix_vinteger, " + "vinteger64 AS prefix_vinteger64, " "vstring AS prefix_vstring, " "vtimezone AS prefix_vtimezone " "FROM obj"; @@ -796,6 +851,7 @@ g_assert_cmpfloat(obj->v_double, ==, 3.14); g_assert_cmpint(obj->v_integer, ==, 42); + g_assert_true(obj->v_integer64 == G_GINT64_CONSTANT(0x1cedc0ffee)); g_assert_cmpstr(obj->v_string, ==, "sammy"); tz = g_time_zone_new_utc();
