1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7TEST_CASE("Test results API", "[api]") {
8 DuckDB db(nullptr);
9 Connection con(db);
10
11 // result equality
12 auto result = con.Query("SELECT 42");
13 auto result2 = con.Query("SELECT 42");
14 REQUIRE(result->Equals(*result2));
15
16 // result inequality
17 result = con.Query("SELECT 42");
18 result2 = con.Query("SELECT 43");
19 REQUIRE(!result->Equals(*result2));
20
21 // stream query to string
22 auto stream_result = con.SendQuery("SELECT 42");
23 auto str = stream_result->ToString();
24 REQUIRE(!str.empty());
25
26 // materialized query to string
27 result = con.Query("SELECT 42");
28 str = result->ToString();
29 REQUIRE(!str.empty());
30
31 // error to string
32 result = con.Query("SELEC 42");
33 str = result->ToString();
34 REQUIRE(!str.empty());
35}
36
37TEST_CASE("Test iterating over results", "[api]") {
38 DuckDB db(nullptr);
39 Connection con(db);
40
41 REQUIRE_NO_FAIL(con.Query("CREATE TABLE data(i INTEGER, j VARCHAR)"));
42 REQUIRE_NO_FAIL(con.Query("INSERT INTO data VALUES (1, 'hello'), (2, 'test')"));
43
44 vector<int> i_values = {1, 2};
45 vector<string> j_values = {"hello", "test"};
46 idx_t row_count = 0;
47 auto result = con.Query("SELECT * FROM data;");
48 for (auto &row : *result) {
49 REQUIRE(row.GetValue<int>(0) == i_values[row.row]);
50 REQUIRE(row.GetValue<string>(1) == j_values[row.row]);
51 row_count++;
52 }
53 REQUIRE(row_count == 2);
54}
55
56TEST_CASE("Error in streaming result after initial query", "[api]") {
57 DuckDB db(nullptr);
58 Connection con(db);
59
60 // create a big table with strings that are numbers
61 REQUIRE_NO_FAIL(con.Query("CREATE TABLE strings(v VARCHAR)"));
62 for (size_t i = 0; i < STANDARD_VECTOR_SIZE * 2 - 1; i++) {
63 REQUIRE_NO_FAIL(con.Query("INSERT INTO strings VALUES ('" + to_string(i) + "')"));
64 }
65 // now insert one non-numeric value
66 REQUIRE_NO_FAIL(con.Query("INSERT INTO strings VALUES ('hello')"));
67
68 // now create a streaming result
69 auto result = con.SendQuery("SELECT CAST(v AS INTEGER) FROM strings");
70 REQUIRE_NO_FAIL(*result);
71 // initial query does not fail!
72 auto chunk = result->Fetch();
73 REQUIRE(chunk);
74 // but subsequent query fails!
75 chunk = result->Fetch();
76 REQUIRE(!chunk);
77 REQUIRE(!result->success);
78 auto str = result->ToString();
79 REQUIRE(!str.empty());
80}
81