# HG changeset patch
# Node ID d889d5692c6af30b4cf411f92a78ccf1b1f54869
# Parent  b58d365fa240617ad2413ca6ade9cebc93fe4706
diff --git a/seagull/seagullstatement.c b/seagull/seagullstatement.c
--- a/seagull/seagullstatement.c
+++ b/seagull/seagullstatement.c
@@ -30,6 +30,9 @@
 	char *sql;
 
 	SeagullSqlite3Stmt *statement;
+
+	/* This is a cache of parameters names to their indices. */
+	GHashTable *parameters;
 };
 
 enum {
@@ -60,6 +63,37 @@
 	}
 }
 
+static int
+seagull_statement_find_parameter(SeagullStatement *statement, const char *name,
+                                 GError **error)
+{
+	gpointer value = NULL;
+	int index = 0;
+
+	g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), 0);
+
+	value = g_hash_table_lookup(statement->parameters, name);
+	if(value != NULL) {
+		return GPOINTER_TO_INT(value);
+	}
+
+	index = sqlite3_bind_parameter_index(statement->statement, name);
+	if(index == 0) {
+		g_set_error(error,
+		            SEAGULL_STATEMENT_ERROR,
+		            SEAGULL_STATEMENT_ERROR_BIND_PARAMETER_NOT_FOUND,
+		            "failed to find a parameter named '%s'",
+		            name);
+
+		return FALSE;
+	}
+
+	g_hash_table_insert(statement->parameters, g_strdup(name),
+	                    GINT_TO_POINTER(value));
+
+	return index;
+}
+
 /******************************************************************************
  * GInitable Implementation
  *****************************************************************************/
@@ -138,6 +172,8 @@
 
 	g_clear_pointer(&statement->statement, sqlite3_finalize);
 
+	g_clear_pointer(&statement->parameters, g_hash_table_unref);
+
 	G_OBJECT_CLASS(seagull_statement_parent_class)->finalize(obj);
 }
 
@@ -183,7 +219,9 @@
 }
 
 static void
-seagull_statement_init(G_GNUC_UNUSED SeagullStatement *statement) {
+seagull_statement_init(SeagullStatement *statement) {
+	statement->parameters = g_hash_table_new_full(g_str_hash, g_str_equal,
+	                                              g_free, NULL);
 }
 
 static void
@@ -234,6 +272,161 @@
 /******************************************************************************
  * Public API
  *****************************************************************************/
+gboolean
+seagull_statement_bind_double(SeagullStatement *statement, const char *name,
+                              double 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_double(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_int(SeagullStatement *statement, const char *name,
+                           int 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_int(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)
+{
+	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_null(statement->statement, index);
+	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_text(SeagullStatement *statement, const char *name,
+                            const char *value, int len,
+                            GDestroyNotify destroy_notify, GError **error)
+{
+	GError *local_error = NULL;
+	int rc = 0;
+	int index = 0;
+	gpointer sqlite3_notify = SQLITE_STATIC;
+
+	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;
+	}
+
+	if(destroy_notify != NULL) {
+		sqlite3_notify = destroy_notify;
+	}
+
+	rc = sqlite3_bind_text(statement->statement, index, value, len,
+	                       sqlite3_notify);
+	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_clear_bindings(SeagullStatement *statement, GError **error) {
+	int rc = SQLITE_OK;
+
+	g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), FALSE);
+
+	rc = sqlite3_clear_bindings(statement->statement);
+	if(rc != SQLITE_OK) {
+		g_set_error(error,
+		            SEAGULL_STATEMENT_ERROR,
+		            SEAGULL_STATEMENT_ERROR_CLEAR_BINDINGS_FAILED,
+		            "failed to clear bindings: %s",
+		            sqlite3_errmsg(statement->db));
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 SeagullSqlite3 *
 seagull_statement_get_db(SeagullStatement *statement) {
 	g_return_val_if_fail(SEAGULL_IS_STATEMENT(statement), NULL);
diff --git a/seagull/seagullstatement.h b/seagull/seagullstatement.h
--- a/seagull/seagullstatement.h
+++ b/seagull/seagullstatement.h
@@ -45,6 +45,11 @@
  *  prepare.
  * @SEAGULL_STATEMENT_ERROR_MORE_THAN_ONE_STATEMENT: More than one SQL
  *  statement was provided.
+ * @SEAGULL_STATEMENT_ERROR_BIND_PARAMETER_NOT_FOUND: The named column was not
+ *  found.
+ * @SEAGULL_STATEMENT_ERROR_BIND_FAILED: Binding a parameter failed.
+ * @SEAGULL_STATEMENT_ERROR_CLEAR_BINDINGS_FAILED: Clearing the bindings
+ *  failed.
  *
  * Error codes returned by statements.
  *
@@ -55,6 +60,9 @@
 	SEAGULL_STATEMENT_ERROR_NO_SQL_PROVIDED SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
 	SEAGULL_STATEMENT_ERROR_PREPARATION_FAILED SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
 	SEAGULL_STATEMENT_ERROR_MORE_THAN_ONE_STATEMENT SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
+	SEAGULL_STATEMENT_ERROR_BIND_PARAMETER_NOT_FOUND SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
+	SEAGULL_STATEMENT_ERROR_BIND_FAILED SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
+	SEAGULL_STATEMENT_ERROR_CLEAR_BINDINGS_FAILED SEAGULL_AVAILABLE_ENUMERATOR_IN_0_3,
 } SeagullStatementError;
 
 /**
@@ -84,6 +92,88 @@
                      GObject)
 
 /**
+ * seagull_statement_bind_double:
+ * @name: the name of the parameter
+ * @value: the value.
+ * @error: (out) (optional): a return address for a #GError
+ *
+ * Binds a double 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.3
+ */
+SEAGULL_AVAILABLE_IN_0_3
+gboolean seagull_statement_bind_double(SeagullStatement *statement, const char *name, double value, GError **error);
+
+/**
+ * seagull_statement_bind_int:
+ * @name: the name of the parameter
+ * @value: the value.
+ * @error: (out) (optional): a return address for a #GError
+ *
+ * Binds an integer 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.3
+ */
+SEAGULL_AVAILABLE_IN_0_3
+gboolean seagull_statement_bind_int(SeagullStatement *statement, const char *name, int value, GError **error);
+
+/**
+ * seagull_statement_bind_null:
+ * @name: the name of the parameter
+ * @error: (out) (optional): a return address for a #GError
+ *
+ * Binds a NULL 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.3
+ */
+SEAGULL_AVAILABLE_IN_0_3
+gboolean seagull_statement_bind_null(SeagullStatement *statement, const char *name, GError **error);
+
+/**
+ * seagull_statement_bind_text:
+ * @name: the name of the parameter
+ * @value: the value.
+ * @len: the length of the value in bytes, or -1 for NULL terminated
+ * @destroy_notify: (nullable): a function to be called to free the value
+ * @error: (out) (optional): a return address for a #GError
+ *
+ * Binds a text 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.3
+ */
+SEAGULL_AVAILABLE_IN_0_3
+gboolean seagull_statement_bind_text(SeagullStatement *statement, const char *name, const char *value, int len, GDestroyNotify destroy_notify, GError **error);
+
+/**
+ * seagull_statement_clear_bindings:
+ * @error: (out) (optional): a return address for a #GError
+ *
+ * Clears all of the bindings.
+ *
+ * Returns: true on success.
+ *
+ * Since: 0.3
+ */
+SEAGULL_AVAILABLE_IN_0_3
+gboolean seagull_statement_clear_bindings(SeagullStatement *statement, GError **error);
+
+/**
  * seagull_statement_get_db:
  *
  * Gets the database.
diff --git a/seagull/tests/test_statement.c b/seagull/tests/test_statement.c
--- a/seagull/tests/test_statement.c
+++ b/seagull/tests/test_statement.c
@@ -332,6 +332,334 @@
 	g_assert_true(result);
 }
 
+static void
+test_seagull_statement_bind_double_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_double(statement, ":foo", 6.28, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT 6.28");
+	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_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_int(statement, ":bar", 6.28, &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_int_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_int(statement, ":foo", 1337, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT 1337");
+	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_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_int(statement, ":bar", 1337, &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_null_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_null(statement, ":foo", &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_null_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_null(statement, ":bar", &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_text_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_text(statement, ":foo", "bar", -1, NULL,
+	                                     &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT 'bar'");
+	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_text_with_destroy(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_text(statement, ":foo", g_strdup("bar"),
+	                                     -1, g_free, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT 'bar'");
+	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_text_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_text(statement, ":bar", "baz", -1, NULL,
+	                                     &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;
+	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, $bar, @baz, :qux",
+	                                  &error);
+	g_assert_no_error(error);
+	g_assert_true(SEAGULL_IS_STATEMENT(statement));
+
+	result = seagull_statement_bind_text(statement, ":foo", g_strdup("bar"),
+	                                     -1, g_free, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	result = seagull_statement_bind_int(statement, "$bar", 1337, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	result = seagull_statement_bind_null(statement, "@baz", &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	result = seagull_statement_bind_double(statement, ":qux", 6.28, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT 'bar', 1337, NULL, 6.28");
+	seagull_free(expanded);
+
+	/* Clear the bindings and verify it worked. */
+	result = seagull_statement_clear_bindings(statement, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+
+	expanded = seagull_statement_get_expanded_sql(statement);
+	g_assert_cmpstr(expanded, ==, "SELECT NULL, NULL, NULL, NULL");
+	seagull_free(expanded);
+
+	g_assert_finalize_object(statement);
+
+	result = seagull_db_close(db, &error);
+	g_assert_no_error(error);
+	g_assert_true(result);
+}
+
 /******************************************************************************
  * Main
  *****************************************************************************/
@@ -367,5 +695,26 @@
 	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/double/normal",
+	                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/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/null/normal",
+	                test_seagull_statement_bind_null_normal);
+	g_test_add_func("/seagull/statement/bind/null/not-found",
+	                test_seagull_statement_bind_null_not_found);
+	g_test_add_func("/seagull/statement/bind/text/normal",
+	                test_seagull_statement_bind_text_normal);
+	g_test_add_func("/seagull/statement/bind/text/with-destroy",
+	                test_seagull_statement_bind_text_with_destroy);
+	g_test_add_func("/seagull/statement/bind/text/not-found",
+	                test_seagull_statement_bind_text_not_found);
+	g_test_add_func("/seagull/statement/bind/mixed",
+	                test_seagull_statement_bind_mixed);
+
 	return g_test_run();
 }
