226 lines
7.0 KiB
C++
226 lines
7.0 KiB
C++
#include "catch.hpp"
|
|
#include "test_helpers.hpp"
|
|
#include "duckdb/common/types/date.hpp"
|
|
#include "duckdb/common/types/time.hpp"
|
|
#include "duckdb/common/types/timestamp.hpp"
|
|
|
|
using namespace duckdb;
|
|
using namespace std;
|
|
|
|
TEST_CASE("Test results API", "[api]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
// result equality
|
|
auto result = con.Query("SELECT 42");
|
|
auto result2 = con.Query("SELECT 42");
|
|
REQUIRE(result->Equals(*result2));
|
|
|
|
// result inequality
|
|
result = con.Query("SELECT 42");
|
|
result2 = con.Query("SELECT 43");
|
|
REQUIRE(!result->Equals(*result2));
|
|
|
|
// stream query to string
|
|
auto stream_result = con.SendQuery("SELECT 42");
|
|
auto str = stream_result->ToString();
|
|
REQUIRE(!str.empty());
|
|
|
|
// materialized query to string
|
|
result = con.Query("SELECT 42");
|
|
str = result->ToString();
|
|
REQUIRE(!str.empty());
|
|
|
|
// error to string
|
|
result = con.Query("SELEC 42");
|
|
str = result->ToString();
|
|
REQUIRE(!str.empty());
|
|
}
|
|
|
|
TEST_CASE("Test iterating over results", "[api]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
REQUIRE_NO_FAIL(con.Query("CREATE TABLE data(i INTEGER, j VARCHAR)"));
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO data VALUES (1, 'hello'), (2, 'test')"));
|
|
|
|
duckdb::vector<int> i_values = {1, 2};
|
|
duckdb::vector<string> j_values = {"hello", "test"};
|
|
idx_t row_count = 0;
|
|
auto result = con.Query("SELECT * FROM data;");
|
|
for (auto &row : *result) {
|
|
REQUIRE(row.GetValue<int>(0) == i_values[row.row]);
|
|
REQUIRE(row.GetValue<string>(1) == j_values[row.row]);
|
|
row_count++;
|
|
}
|
|
REQUIRE(row_count == 2);
|
|
}
|
|
|
|
TEST_CASE("Test different result types", "[api]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
REQUIRE_NO_FAIL(
|
|
con.Query("CREATE TABLE data(i INTEGER, j VARCHAR, k DECIMAL(38,1), l DECIMAL(18,3), m HUGEINT, n DOUBLE)"));
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO data VALUES (23, '17.1', 94289, 9842, 4982412, 17.3)"));
|
|
|
|
idx_t row_count = 0;
|
|
auto result = con.Query("SELECT * FROM data;");
|
|
for (auto &row : *result) {
|
|
REQUIRE(row.GetValue<int>(0) == 23);
|
|
REQUIRE(row.GetValue<int64_t>(0) == 23);
|
|
REQUIRE(row.GetValue<double>(0) == 23);
|
|
REQUIRE(row.GetValue<string>(0) == "23");
|
|
|
|
REQUIRE(row.GetValue<int>(1) == 17);
|
|
REQUIRE(row.GetValue<int64_t>(1) == 17);
|
|
REQUIRE(row.GetValue<double>(1) == 17.1);
|
|
REQUIRE(row.GetValue<string>(1) == "17.1");
|
|
|
|
REQUIRE(row.GetValue<int>(2) == 94289);
|
|
REQUIRE(row.GetValue<int64_t>(2) == 94289);
|
|
REQUIRE(row.GetValue<double>(2) == 94289);
|
|
|
|
REQUIRE(row.GetValue<int>(3) == 9842);
|
|
REQUIRE(row.GetValue<int64_t>(3) == 9842);
|
|
REQUIRE(row.GetValue<double>(3) == 9842);
|
|
|
|
REQUIRE(row.GetValue<int>(4) == 4982412);
|
|
REQUIRE(row.GetValue<int64_t>(4) == 4982412);
|
|
REQUIRE(row.GetValue<double>(4) == 4982412);
|
|
REQUIRE(row.GetValue<string>(4) == "4982412");
|
|
|
|
REQUIRE(row.GetValue<int>(5) == 17);
|
|
REQUIRE(row.GetValue<int64_t>(5) == 17);
|
|
REQUIRE(row.GetValue<double>(5) == 17.3);
|
|
|
|
row_count++;
|
|
}
|
|
REQUIRE(row_count == 1);
|
|
}
|
|
|
|
TEST_CASE("Test dates/times/timestamps", "[api]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
REQUIRE_NO_FAIL(con.Query("CREATE TABLE data(i DATE, j TIME, k TIMESTAMP)"));
|
|
REQUIRE_NO_FAIL(
|
|
con.Query("INSERT INTO data VALUES (DATE '1992-01-01', TIME '13:00:17', TIMESTAMP '1993-01-01 14:00:17')"));
|
|
|
|
idx_t row_count = 0;
|
|
auto result = con.Query("SELECT * FROM data;");
|
|
for (auto &row : *result) {
|
|
int32_t year, month, day;
|
|
int32_t hour, minute, second, millisecond;
|
|
|
|
auto date = row.GetValue<date_t>(0);
|
|
auto time = row.GetValue<dtime_t>(1);
|
|
auto timestamp = row.GetValue<timestamp_t>(2);
|
|
Date::Convert(date, year, month, day);
|
|
REQUIRE(year == 1992);
|
|
REQUIRE(month == 1);
|
|
REQUIRE(day == 1);
|
|
|
|
Time::Convert(time, hour, minute, second, millisecond);
|
|
REQUIRE(hour == 13);
|
|
REQUIRE(minute == 0);
|
|
REQUIRE(second == 17);
|
|
REQUIRE(millisecond == 0);
|
|
|
|
Timestamp::Convert(timestamp, date, time);
|
|
Date::Convert(date, year, month, day);
|
|
Time::Convert(time, hour, minute, second, millisecond);
|
|
|
|
REQUIRE(year == 1993);
|
|
REQUIRE(month == 1);
|
|
REQUIRE(day == 1);
|
|
REQUIRE(hour == 14);
|
|
REQUIRE(minute == 0);
|
|
REQUIRE(second == 17);
|
|
REQUIRE(millisecond == 0);
|
|
|
|
row_count++;
|
|
}
|
|
REQUIRE(row_count == 1);
|
|
}
|
|
|
|
TEST_CASE("Error in streaming result after initial query", "[api][.]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
// create a big table with strings that are numbers
|
|
REQUIRE_NO_FAIL(con.Query("CREATE TABLE strings(v VARCHAR)"));
|
|
for (size_t i = 0; i < STANDARD_VECTOR_SIZE * 2 - 1; i++) {
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO strings VALUES ('" + to_string(i) + "')"));
|
|
}
|
|
// now insert one non-numeric value
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO strings VALUES ('hello')"));
|
|
|
|
// now create a streaming result
|
|
auto result = con.SendQuery("SELECT CAST(v AS INTEGER) FROM strings");
|
|
REQUIRE_FAIL(result);
|
|
}
|
|
|
|
TEST_CASE("Test UUID", "[api][uuid]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
REQUIRE_NO_FAIL(con.Query("CREATE TABLE uuids (u uuid)"));
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO uuids VALUES ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'), "
|
|
"('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11');"));
|
|
REQUIRE_FAIL(con.Query("INSERT INTO uuids VALUES ('');"));
|
|
REQUIRE_FAIL(con.Query("INSERT INTO uuids VALUES ('a0eebc99');"));
|
|
REQUIRE_FAIL(con.Query("INSERT INTO uuids VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380z11');"));
|
|
|
|
idx_t row_count = 0;
|
|
auto result = con.Query("SELECT * FROM uuids");
|
|
for (auto &row : *result) {
|
|
auto uuid = row.GetValue<string>(0);
|
|
REQUIRE(uuid == "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
row_count++;
|
|
}
|
|
REQUIRE(row_count == 2);
|
|
}
|
|
|
|
TEST_CASE("Test ARRAY_AGG with ORDER BY", "[api][array_agg]") {
|
|
DuckDB db(nullptr);
|
|
Connection con(db);
|
|
|
|
REQUIRE_NO_FAIL(con.Query("CREATE TABLE t2 (a INT, b INT, c INT)"));
|
|
REQUIRE_NO_FAIL(con.Query("INSERT INTO t2 VALUES (1,1,1), (1,2,2), (2,1,3), (2,2,4)"));
|
|
|
|
auto result = con.Query("select a, array_agg(c ORDER BY b) from t2 GROUP BY a");
|
|
REQUIRE(!result->HasError());
|
|
REQUIRE(result->names[1] == "array_agg(c ORDER BY b)");
|
|
}
|
|
|
|
TEST_CASE("Issue #9417", "[api][.]") {
|
|
DBConfig config;
|
|
config.options.allow_unsigned_extensions = true;
|
|
|
|
DuckDB db(TestCreatePath("issue_replication.db"), &config);
|
|
Connection con(db);
|
|
auto result = con.SendQuery("with max_period as ("
|
|
" select max(reporting_date) as max_record\n"
|
|
" from \"data/parquet-testing/issue9417.parquet\"\n"
|
|
" )\n"
|
|
" select\n"
|
|
" *\n"
|
|
" from \"data/parquet-testing/issue9417.parquet\" e\n"
|
|
" inner join max_period\n"
|
|
" on e.reporting_date = max_period.max_record\n"
|
|
" where e.record_date between '2012-01-31' and '2023-06-30'");
|
|
idx_t count = 0;
|
|
while (true) {
|
|
auto chunk = result->Fetch();
|
|
if (chunk) {
|
|
REQUIRE(count + chunk->size() <= 46);
|
|
count += chunk->size();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
REQUIRE(count == 46);
|
|
}
|