Skip to content

Commit 9d2d17b

Browse files
Added type checks
1 parent a8ed2d1 commit 9d2d17b

File tree

5 files changed

+112
-23
lines changed

5 files changed

+112
-23
lines changed

include/sqlgen/duckdb/Iterator.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class Iterator {
7373
return Ref<std::vector<Result<T>>>::make();
7474
}
7575
const idx_t row_count = duckdb_data_chunk_get_size(chunk);
76-
return make_chunk_ptrs<T>(chunk)
76+
return make_chunk_ptrs<T>(_res, chunk)
7777
.transform([&](auto&& _chunk_ptrs) {
7878
auto batch = Ref<std::vector<Result<T>>>::make();
7979
for (idx_t i = 0; i < row_count; ++i) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#ifndef SQLGEN_DUCKDB_GETDUCKDBTYPE_HPP_
2+
#define SQLGEN_DUCKDB_GETDUCKDBTYPE_HPP_
3+
4+
#include <duckdb.h>
5+
6+
#include <rfl.hpp>
7+
#include <type_traits>
8+
9+
#include "../Result.hpp"
10+
11+
namespace sqlgen::duckdb {
12+
13+
template <class T>
14+
duckdb_type get_duckdb_type() {
15+
using Type = std::remove_cvref_t<T>;
16+
17+
if constexpr (std::is_same_v<Type, bool>) {
18+
return DUCKDB_TYPE_BOOLEAN;
19+
20+
} else if constexpr (std::is_same_v<Type, char> ||
21+
std::is_same_v<Type, int8_t>) {
22+
return DUCKDB_TYPE_TINYINT;
23+
24+
} else if constexpr (std::is_same_v<Type, uint8_t>) {
25+
return DUCKDB_TYPE_UTINYINT;
26+
27+
} else if constexpr (std::is_same_v<Type, int16_t>) {
28+
return DUCKDB_TYPE_SMALLINT;
29+
30+
} else if constexpr (std::is_same_v<Type, uint16_t>) {
31+
return DUCKDB_TYPE_USMALLINT;
32+
33+
} else if constexpr (std::is_same_v<Type, int32_t>) {
34+
return DUCKDB_TYPE_INTEGER;
35+
36+
} else if constexpr (std::is_same_v<Type, uint32_t>) {
37+
return DUCKDB_TYPE_UINTEGER;
38+
39+
} else if constexpr (std::is_same_v<Type, int64_t>) {
40+
return DUCKDB_TYPE_BIGINT;
41+
42+
} else if constexpr (std::is_same_v<Type, uint64_t>) {
43+
return DUCKDB_TYPE_UBIGINT;
44+
45+
} else if constexpr (std::is_same_v<Type, float>) {
46+
return DUCKDB_TYPE_FLOAT;
47+
48+
} else if constexpr (std::is_same_v<Type, double>) {
49+
return DUCKDB_TYPE_DOUBLE;
50+
51+
} else if constexpr (std::is_same_v<Type, duckdb_string_t>) {
52+
return DUCKDB_TYPE_VARCHAR;
53+
54+
} else {
55+
static_assert(rfl::always_false_v<T>, "Unsupported type.");
56+
}
57+
}
58+
59+
} // namespace sqlgen::duckdb
60+
61+
#endif

include/sqlgen/duckdb/make_chunk_ptrs.hpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
#include <duckdb.h>
55

66
#include <rfl.hpp>
7+
#include <rfl/enums.hpp>
78
#include <type_traits>
89
#include <utility>
910

11+
#include "./parsing/Parser.hpp"
1012
#include "ColumnData.hpp"
1113
#include "chunk_ptrs_t.hpp"
14+
#include "get_duckdb_type.hpp"
1215

1316
namespace sqlgen::duckdb {
1417

@@ -17,16 +20,27 @@ struct MakeChunkPtrs;
1720

1821
template <class... Ts>
1922
struct MakeChunkPtrs<rfl::Tuple<ColumnData<Ts>...>> {
20-
Result<rfl::Tuple<ColumnData<Ts>...>> operator()(duckdb_data_chunk _chunk) {
21-
// TODO: Runtime type checking
22-
return [&]<int... _is>(std::integer_sequence<int, _is...>) {
23-
return rfl::Tuple<ColumnData<Ts>...>(
24-
make_column_data<Ts, _is>(_chunk)...);
25-
}(std::make_integer_sequence<int, sizeof...(Ts)>());
23+
Result<rfl::Tuple<ColumnData<Ts>...>> operator()(
24+
const Ref<duckdb_result>& _res, duckdb_data_chunk _chunk) {
25+
try {
26+
return [&]<int... _is>(std::integer_sequence<int, _is...>) {
27+
return rfl::Tuple<ColumnData<Ts>...>(
28+
make_column_data<Ts, _is>(_res, _chunk)...);
29+
}(std::make_integer_sequence<int, sizeof...(Ts)>());
30+
} catch (const std::exception& e) {
31+
return error(e.what());
32+
}
2633
}
2734

2835
template <class T, int _i>
29-
static auto make_column_data(duckdb_data_chunk _chunk) {
36+
static auto make_column_data(const Ref<duckdb_result>& _res,
37+
duckdb_data_chunk _chunk) {
38+
if (duckdb_column_type(_res.get(), _i) != get_duckdb_type<T>()) {
39+
throw std::runtime_error(
40+
"Wrong type in field " + std::to_string(_i) + ". Expected " +
41+
rfl::enum_to_string(get_duckdb_type<T>()) + ", got " +
42+
rfl::enum_to_string(duckdb_column_type(_res.get(), _i)) + ".");
43+
}
3044
auto vec = duckdb_data_chunk_get_vector(_chunk, _i);
3145
return ColumnData<T>{.vec = vec,
3246
.data = static_cast<T*>(duckdb_vector_get_data(vec)),
@@ -36,8 +50,8 @@ struct MakeChunkPtrs<rfl::Tuple<ColumnData<Ts>...>> {
3650

3751
template <class T>
3852
struct MakeChunkPtrs {
39-
auto operator()(duckdb_data_chunk _chunk) {
40-
return MakeChunkPtrs<chunk_ptrs_t<T>>{}(_chunk);
53+
auto operator()(const Ref<duckdb_result>& _res, duckdb_data_chunk _chunk) {
54+
return MakeChunkPtrs<chunk_ptrs_t<T>>{}(_res, _chunk);
4155
}
4256
};
4357

include/sqlgen/duckdb/parsing/Parser_reflection_type.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ template <class T>
1616
requires transpilation::has_reflection_method<std::remove_cvref_t<T>>
1717
struct Parser<T> {
1818
using Type = std::remove_cvref_t<T>;
19-
using ResultingType =
20-
typename Parser<typename Type::ReflectionType>::ResultingType;
19+
using ResultingType = typename Parser<
20+
std::remove_cvref_t<typename Type::ReflectionType>>::ResultingType;
2121

2222
static Result<T> read(const ResultingType* _r) noexcept {
2323
return Parser<std::remove_cvref_t<typename Type::ReflectionType>>::read(_r)

src/sqlgen/duckdb/to_sql.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -811,24 +811,38 @@ std::string type_to_sql(const dynamic::Type& _type) noexcept {
811811
} else if constexpr (std::is_same_v<T, dynamic::types::Dynamic>) {
812812
return _t.type_name;
813813

814-
} else if constexpr (std::is_same_v<T, dynamic::types::Int8> ||
815-
std::is_same_v<T, dynamic::types::Int16> ||
816-
std::is_same_v<T, dynamic::types::UInt8> ||
817-
std::is_same_v<T, dynamic::types::UInt16>) {
814+
} else if constexpr (std::is_same_v<T, dynamic::types::Int8>) {
815+
return "TINYINT";
816+
817+
} else if constexpr (std::is_same_v<T, dynamic::types::UInt8>) {
818+
return "UTINYINT";
819+
820+
} else if constexpr (std::is_same_v<T, dynamic::types::Int16>) {
818821
return "SMALLINT";
819822

820-
} else if constexpr (std::is_same_v<T, dynamic::types::Int32> ||
821-
std::is_same_v<T, dynamic::types::UInt32>) {
823+
} else if constexpr (std::is_same_v<T, dynamic::types::UInt16>) {
824+
return "USMALLINT";
825+
826+
} else if constexpr (std::is_same_v<T, dynamic::types::Int32>) {
822827
return "INTEGER";
823828

824-
} else if constexpr (std::is_same_v<T, dynamic::types::Int64> ||
825-
std::is_same_v<T, dynamic::types::UInt64>) {
829+
} else if constexpr (std::is_same_v<T, dynamic::types::UInt32>) {
830+
return "UINTEGER";
831+
832+
} else if constexpr (std::is_same_v<T, dynamic::types::Int64>) {
826833
return "BIGINT";
834+
835+
} else if constexpr (std::is_same_v<T, dynamic::types::UInt64>) {
836+
return "UBIGINT";
837+
827838
} else if constexpr (std::is_same_v<T, dynamic::types::Enum>) {
828839
return _t.name;
829-
} else if constexpr (std::is_same_v<T, dynamic::types::Float32> ||
830-
std::is_same_v<T, dynamic::types::Float64>) {
831-
return "NUMERIC";
840+
841+
} else if constexpr (std::is_same_v<T, dynamic::types::Float32>) {
842+
return "FLOAT";
843+
844+
} else if constexpr (std::is_same_v<T, dynamic::types::Float64>) {
845+
return "DOUBLE";
832846

833847
} else if constexpr (std::is_same_v<T, dynamic::types::Text>) {
834848
return "TEXT";

0 commit comments

Comments
 (0)