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
|
#include "capi_tester.hpp"
using namespace duckdb;
using namespace std;
struct MyBaseNumber {
int number;
};
void destroy_base_number(void *data) {
auto num = (MyBaseNumber *)data;
delete num;
}
void number_scanner(duckdb_replacement_scan_info info, const char *table_name, void *data) {
// check if the table name is a number
long long number;
try {
number = std::stoll(table_name);
} catch (...) {
// not a number!
return;
}
auto num_data = (MyBaseNumber *)data;
duckdb_replacement_scan_set_function_name(info, "range");
auto val = duckdb_create_int64(number + num_data->number);
duckdb_replacement_scan_add_parameter(info, val);
duckdb_destroy_value(&val);
}
TEST_CASE("Test replacement scans in C API", "[capi]") {
CAPITester tester;
duckdb::unique_ptr<CAPIResult> result;
// open the database in in-memory mode
REQUIRE(tester.OpenDatabase(nullptr));
auto base_number = new MyBaseNumber();
base_number->number = 3;
duckdb_add_replacement_scan(tester.database, number_scanner, (void *)base_number, destroy_base_number);
// 0-4
result = tester.Query("SELECT * FROM \"2\"");
REQUIRE(result->row_count() == 5);
REQUIRE(result->Fetch<int64_t>(0, 0) == 0);
REQUIRE(result->Fetch<int64_t>(0, 1) == 1);
REQUIRE(result->Fetch<int64_t>(0, 2) == 2);
REQUIRE(result->Fetch<int64_t>(0, 3) == 3);
REQUIRE(result->Fetch<int64_t>(0, 4) == 4);
base_number->number = 1;
// 0-2
result = tester.Query("SELECT * FROM \"2\"");
REQUIRE(result->row_count() == 3);
REQUIRE(result->Fetch<int64_t>(0, 0) == 0);
REQUIRE(result->Fetch<int64_t>(0, 1) == 1);
REQUIRE(result->Fetch<int64_t>(0, 2) == 2);
// not a number
REQUIRE_FAIL(tester.Query("SELECT * FROM nonexistant"));
}
void error_replacement_scan(duckdb_replacement_scan_info info, const char *table_name, void *data) {
duckdb_replacement_scan_set_error(NULL, NULL);
duckdb_replacement_scan_set_error(info, NULL);
duckdb_replacement_scan_set_error(info, "error in replacement scan");
}
TEST_CASE("Test error replacement scan", "[capi]") {
CAPITester tester;
duckdb::unique_ptr<CAPIResult> result;
// open the database in in-memory mode
REQUIRE(tester.OpenDatabase(nullptr));
duckdb_add_replacement_scan(tester.database, error_replacement_scan, NULL, NULL);
// error
REQUIRE_FAIL(tester.Query("SELECT * FROM nonexistant"));
}
|