1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
#include "capi_tester.hpp"
using namespace duckdb;
using namespace std;
TEST_CASE("Test Custom Configuration Options in C API", "[capi]") {
CAPITester tester;
duckdb::unique_ptr<CAPIResult> result;
// Create a connection and get client context
REQUIRE(tester.OpenDatabase(nullptr));
duckdb_client_context context;
duckdb_connection_get_client_context(tester.connection, &context);
REQUIRE(context != nullptr);
// Setup some types for config options
auto str_type = duckdb_create_logical_type(DUCKDB_TYPE_VARCHAR);
auto int_type = duckdb_create_logical_type(DUCKDB_TYPE_INTEGER);
auto default_str_value = duckdb_create_varchar("default_string");
auto default_int_value = duckdb_create_int32(42);
// Test 1: Create a string config option
auto str_opt = duckdb_create_config_option();
REQUIRE(str_opt != nullptr);
duckdb_config_option_set_name(str_opt, "test_string_option");
duckdb_config_option_set_type(str_opt, str_type);
duckdb_config_option_set_description(str_opt, "A test string configuration option");
duckdb_config_option_set_default_value(str_opt, default_str_value);
REQUIRE(duckdb_register_config_option(tester.connection, str_opt) == DuckDBSuccess);
// Get and verify the string option
result = tester.Query("SELECT current_setting('test_string_option')");
REQUIRE_NO_FAIL(*result);
REQUIRE(result->Fetch<string>(0, 0) == "default_string");
// Set and verify the string option
REQUIRE_NO_FAIL(tester.Query("SET test_string_option = 'new_value'"));
result = tester.Query("SELECT current_setting('test_string_option')");
REQUIRE_NO_FAIL(*result);
REQUIRE(result->Fetch<string>(0, 0) == "new_value");
// Also get it from the client context
duckdb_config_option_scope scope;
auto retrieved_str = duckdb_client_context_get_config_option(context, "test_string_option", &scope);
REQUIRE(retrieved_str != nullptr);
duckdb_destroy_value(&retrieved_str);
// By default, the scope should be SESSION
REQUIRE(scope == DUCKDB_CONFIG_OPTION_SCOPE_SESSION);
duckdb_destroy_config_option(&str_opt);
duckdb_destroy_config_option(&str_opt);
// Fetch it from the duckdb_settings() function
result =
tester.Query("SELECT name, value, input_type, scope FROM duckdb_settings() WHERE name = 'test_string_option'");
REQUIRE_NO_FAIL(*result);
REQUIRE(result->ChunkCount() == 1);
REQUIRE(result->Fetch<string>(0, 0) == "test_string_option");
REQUIRE(result->Fetch<string>(1, 0) == "new_value");
REQUIRE(result->Fetch<string>(2, 0) == "VARCHAR");
REQUIRE(result->Fetch<string>(3, 0) == "LOCAL");
// Test 2: Create an integer config option, with the type inferred from the default value
auto int_opt = duckdb_create_config_option();
REQUIRE(int_opt != nullptr);
duckdb_config_option_set_name(int_opt, "test_integer_option");
duckdb_config_option_set_description(int_opt, "A test integer configuration option");
duckdb_config_option_set_default_value(int_opt, default_int_value);
duckdb_config_option_set_default_scope(int_opt, DUCKDB_CONFIG_OPTION_SCOPE_GLOBAL);
REQUIRE(duckdb_register_config_option(tester.connection, int_opt) == DuckDBSuccess);
// Get and verify the integer option
result = tester.Query("SELECT current_setting('test_integer_option')");
REQUIRE_NO_FAIL(*result);
REQUIRE(result->Fetch<int32_t>(0, 0) == 42);
// Also get it from the client context. Try without specifying scope first
auto retrieved_int = duckdb_client_context_get_config_option(context, "test_integer_option", nullptr);
REQUIRE(retrieved_int != nullptr);
REQUIRE(duckdb_get_int32(retrieved_int) == 42);
duckdb_destroy_value(&retrieved_int);
// By default, the scope should be GLOBAL, as that was what we defined this option with
retrieved_int = duckdb_client_context_get_config_option(context, "test_integer_option", &scope);
REQUIRE(retrieved_int != nullptr);
duckdb_destroy_value(&retrieved_int);
// Also check in duckdb_settings()
result =
tester.Query("SELECT name, value, input_type, scope FROM duckdb_settings() WHERE name = 'test_integer_option'");
REQUIRE_NO_FAIL(*result);
REQUIRE(result->ChunkCount() == 1);
REQUIRE(result->Fetch<string>(0, 0) == "test_integer_option");
REQUIRE(result->Fetch<string>(1, 0) == "42");
REQUIRE(result->Fetch<string>(2, 0) == "INTEGER");
REQUIRE(result->Fetch<string>(3, 0) == "GLOBAL");
duckdb_destroy_config_option(&int_opt);
duckdb_destroy_config_option(&int_opt);
// Cleanup
duckdb_destroy_client_context(&context);
duckdb_destroy_logical_type(&str_type);
duckdb_destroy_logical_type(&int_type);
duckdb_destroy_value(&default_str_value);
duckdb_destroy_value(&default_int_value);
}
|