File: test_capi_table_description.cpp

package info (click to toggle)
duckdb 1.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 299,196 kB
  • sloc: cpp: 865,414; ansic: 57,292; python: 18,871; sql: 12,663; lisp: 11,751; yacc: 7,412; lex: 1,682; sh: 747; makefile: 558
file content (127 lines) | stat: -rw-r--r-- 5,140 bytes parent folder | download | duplicates (3)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "capi_tester.hpp"
#include "duckdb.h"

using namespace duckdb;
using namespace std;

TEST_CASE("Test the table description in the C API", "[capi]") {
	CAPITester tester;
	REQUIRE(tester.OpenDatabase(nullptr));
	duckdb_table_description table_description = nullptr;
	tester.Query("SET threads=1;");

	// Test a non-existent table.
	auto status = duckdb_table_description_create(tester.connection, nullptr, "test", &table_description);
	REQUIRE(status == DuckDBError);
	duckdb_table_description_destroy(&table_description);

	status = duckdb_table_description_create_ext(tester.connection, "hello", "world", "test", &table_description);
	REQUIRE(status == DuckDBError);
	duckdb_table_description_destroy(&table_description);

	// Create an in-memory table and a table in an external file.
	tester.Query("CREATE TABLE test (i INTEGER, j INTEGER default 5)");
	auto test_dir = TestDirectoryPath();
	auto attach_query = "ATTACH '" + test_dir + "/ext_description.db'";
	tester.Query(attach_query);
	tester.Query("CREATE TABLE ext_description.test(my_column INTEGER)");

	// Test invalid catalog and schema.
	status =
	    duckdb_table_description_create_ext(tester.connection, "non-existent", nullptr, "test", &table_description);
	REQUIRE(status == DuckDBError);
	duckdb_table_description_destroy(&table_description);

	status = duckdb_table_description_create(tester.connection, "non-existent", "test", &table_description);
	REQUIRE(status == DuckDBError);
	duckdb_table_description_destroy(&table_description);

	status = duckdb_table_description_create(tester.connection, nullptr, "test", &table_description);
	REQUIRE(status == DuckDBSuccess);
	REQUIRE(duckdb_table_description_error(table_description) == nullptr);

	bool has_default;
	SECTION("Passing nullptr to has_default") {
		REQUIRE(duckdb_column_has_default(table_description, 2, nullptr) == DuckDBError);
		REQUIRE(duckdb_column_has_default(nullptr, 2, &has_default) == DuckDBError);
	}
	SECTION("Out of range column for has_default") {
		REQUIRE(duckdb_column_has_default(table_description, 2, &has_default) == DuckDBError);
	}
	SECTION("In range column - not default") {
		REQUIRE(duckdb_column_has_default(table_description, 0, &has_default) == DuckDBSuccess);
		REQUIRE(has_default == false);
	}
	SECTION("In range column - default") {
		REQUIRE(duckdb_column_has_default(table_description, 1, &has_default) == DuckDBSuccess);
		REQUIRE(has_default == true);
	}
	duckdb_table_description_destroy(&table_description);

	// Let's get information about the external table.
	status =
	    duckdb_table_description_create_ext(tester.connection, "ext_description", nullptr, "test", &table_description);
	REQUIRE(status == DuckDBSuccess);
	REQUIRE(duckdb_table_description_error(table_description) == nullptr);

	SECTION("Passing nullptr to get_column_count") {
		REQUIRE(duckdb_table_description_get_column_count(nullptr) == 0);
	}
	SECTION("Passing nullptr to get_name") {
		REQUIRE(duckdb_table_description_get_column_name(nullptr, 0) == nullptr);
	}
	SECTION("Passing nullptr to get_type") {
		REQUIRE(duckdb_table_description_get_column_type(nullptr, 0) == nullptr);
	}
	SECTION("Out of range column for get_name") {
		REQUIRE(duckdb_table_description_get_column_name(table_description, 1) == nullptr);
	}
	SECTION("Out of range column for get_type") {
		REQUIRE(duckdb_table_description_get_column_type(table_description, 1) == nullptr);
	}
	SECTION("get the column count") {
		auto column_count = duckdb_table_description_get_column_count(table_description);
		REQUIRE(column_count == 1);
	}
	SECTION("In range column - get the name") {
		auto column_name = duckdb_table_description_get_column_name(table_description, 0);
		string expected = "my_column";
		REQUIRE(!expected.compare(column_name));
		duckdb_free(column_name);
	}
	SECTION("In range column - get the type") {
		auto column_type = duckdb_table_description_get_column_type(table_description, 0);
		auto type_id = duckdb_get_type_id(column_type);
		REQUIRE(type_id == DUCKDB_TYPE_INTEGER);
		duckdb_destroy_logical_type(&column_type);
	}
	duckdb_table_description_destroy(&table_description);
}

TEST_CASE("Test getting the table names of a query in the C API", "[capi]") {
	CAPITester tester;
	REQUIRE(tester.OpenDatabase(nullptr));

	tester.Query("CREATE SCHEMA schema1");
	tester.Query("CREATE SCHEMA \"schema.2\"");
	tester.Query("CREATE TABLE schema1.\"table.1\"(i INT)");
	tester.Query("CREATE TABLE \"schema.2\".\"table.2\"(i INT)");

	string query = "SELECT * FROM schema1.\"table.1\", \"schema.2\".\"table.2\"";
	auto table_name_values = duckdb_get_table_names(tester.connection, query.c_str(), true);

	auto size = duckdb_get_list_size(table_name_values);
	REQUIRE(size == 2);

	duckdb::unordered_set<string> expected_names = {"schema1.\"table.1\"", "\"schema.2\".\"table.2\""};
	for (idx_t i = 0; i < size; i++) {
		auto name_value = duckdb_get_list_child(table_name_values, i);
		auto name = duckdb_get_varchar(name_value);
		REQUIRE(expected_names.count(name) == 1);
		duckdb_free(name);
		duckdb_destroy_value(&name_value);
	}

	duckdb_destroy_value(&table_name_values);
	tester.Cleanup();
}