Skip to content

Commit c8b5f5a

Browse files
Added numeric casting
1 parent c78bdaf commit c8b5f5a

2 files changed

Lines changed: 101 additions & 8 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#ifndef SQLGEN_DUCKDB_CASTDUCKDBTYPE_HPP_
2+
#define SQLGEN_DUCKDB_CASTDUCKDBTYPE_HPP_
3+
4+
#include <duckdb.h>
5+
6+
#include <rfl.hpp>
7+
#include <type_traits>
8+
9+
#include "../Ref.hpp"
10+
#include "../Result.hpp"
11+
12+
namespace sqlgen::duckdb {
13+
14+
template <class T, class U>
15+
Ref<std::vector<T>> cast_as_vector(const size_t _size, U* _ptr) {
16+
auto vec = Ref<std::vector<T>>::make(_size);
17+
for (size_t i = 0; i < _size; ++i) {
18+
(*vec)[i] = static_cast<T>(_ptr[i]);
19+
}
20+
return vec;
21+
}
22+
23+
template <class T>
24+
Result<Ref<std::vector<T>>> cast_duckdb_type(const duckdb_type _type,
25+
const size_t _size,
26+
void* _raw_ptr) {
27+
if constexpr (!std::is_floating_point_v<T> && !std::is_integral_v<T>) {
28+
return error("Could not cast");
29+
30+
} else {
31+
if (_type == DUCKDB_TYPE_TINYINT) {
32+
return cast_as_vector<T>(_size, static_cast<int8_t*>(_raw_ptr));
33+
34+
} else if (_type == DUCKDB_TYPE_UTINYINT) {
35+
return cast_as_vector<T>(_size, static_cast<uint8_t*>(_raw_ptr));
36+
37+
} else if (_type == DUCKDB_TYPE_SMALLINT) {
38+
return cast_as_vector<T>(_size, static_cast<int16_t*>(_raw_ptr));
39+
40+
} else if (_type == DUCKDB_TYPE_USMALLINT) {
41+
return cast_as_vector<T>(_size, static_cast<uint16_t*>(_raw_ptr));
42+
43+
} else if (_type == DUCKDB_TYPE_INTEGER) {
44+
return cast_as_vector<T>(_size, static_cast<int32_t*>(_raw_ptr));
45+
46+
} else if (_type == DUCKDB_TYPE_UINTEGER) {
47+
return cast_as_vector<T>(_size, static_cast<uint32_t*>(_raw_ptr));
48+
49+
} else if (_type == DUCKDB_TYPE_BIGINT) {
50+
return cast_as_vector<T>(_size, static_cast<int64_t*>(_raw_ptr));
51+
52+
} else if (_type == DUCKDB_TYPE_UBIGINT) {
53+
return cast_as_vector<T>(_size, static_cast<uint64_t*>(_raw_ptr));
54+
55+
} else if (_type == DUCKDB_TYPE_FLOAT) {
56+
return cast_as_vector<T>(_size, static_cast<float*>(_raw_ptr));
57+
58+
} else if (_type == DUCKDB_TYPE_DOUBLE) {
59+
return cast_as_vector<T>(_size, static_cast<double*>(_raw_ptr));
60+
61+
} else {
62+
return error("Could not cast");
63+
}
64+
}
65+
}
66+
67+
} // namespace sqlgen::duckdb
68+
69+
#endif

include/sqlgen/duckdb/make_chunk_ptrs.hpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../Ref.hpp"
1212
#include "ColumnData.hpp"
1313
#include "DuckDBResult.hpp"
14+
#include "cast_duckdb_type.hpp"
1415
#include "chunk_ptrs_t.hpp"
1516
#include "get_duckdb_type.hpp"
1617

@@ -36,17 +37,40 @@ struct MakeChunkPtrs<rfl::Tuple<ColumnData<Ts, ColNames>...>> {
3637
template <class T, class ColName, int _i>
3738
static auto make_column_data(const Ref<DuckDBResult>& _res,
3839
duckdb_data_chunk _chunk) {
39-
if (duckdb_column_type(&_res->res(), _i) != get_duckdb_type<T>()) {
40+
const auto actual_duckdb_type = duckdb_column_type(&_res->res(), _i);
41+
42+
auto vec = duckdb_data_chunk_get_vector(_chunk, _i);
43+
44+
if (actual_duckdb_type == get_duckdb_type<T>()) {
45+
return ColumnData<T, ColName>{
46+
.vec = vec,
47+
.data = static_cast<T*>(duckdb_vector_get_data(vec)),
48+
.validity = duckdb_vector_get_validity(vec)};
49+
}
50+
51+
if constexpr (std::is_same_v<T, bool>) {
4052
throw std::runtime_error(
41-
"Wrong type in field " + std::to_string(_i) + ". Expected " +
53+
"Wrong type in field '" + ColName().str() + "'. Expected " +
4254
rfl::enum_to_string(get_duckdb_type<T>()) + ", got " +
43-
rfl::enum_to_string(duckdb_column_type(&_res->res(), _i)) + ".");
55+
rfl::enum_to_string(actual_duckdb_type) + ".");
56+
57+
} else {
58+
const auto ptr_res = cast_duckdb_type<T>(
59+
actual_duckdb_type, duckdb_data_chunk_get_size(_chunk),
60+
duckdb_vector_get_data(vec));
61+
62+
if (!ptr_res) {
63+
throw std::runtime_error(
64+
"Wrong type in field '" + ColName().str() + "'. Expected " +
65+
rfl::enum_to_string(get_duckdb_type<T>()) + ", got " +
66+
rfl::enum_to_string(actual_duckdb_type) + ".");
67+
}
68+
69+
return ColumnData<T, ColName>{.vec = vec,
70+
.data = (*ptr_res)->data(),
71+
.validity = duckdb_vector_get_validity(vec),
72+
.ptr = ptr_res->ptr()};
4473
}
45-
auto vec = duckdb_data_chunk_get_vector(_chunk, _i);
46-
return ColumnData<T, ColName>{
47-
.vec = vec,
48-
.data = static_cast<T*>(duckdb_vector_get_data(vec)),
49-
.validity = duckdb_vector_get_validity(vec)};
5074
}
5175
};
5276

0 commit comments

Comments
 (0)