|
21 | 21 | #pragma warning(disable : 4251) // for dll export |
22 | 22 | #endif |
23 | 23 |
|
24 | | -#include <string> |
| 24 | +#include <cassert> |
25 | 25 | #include <memory> |
26 | | -#include <vector> |
27 | | -#include <assert.h> |
28 | | -#include <unordered_map> |
29 | 26 | #include <ostream> |
30 | | -#include <boost/uuid/uuid.hpp> |
| 27 | +#include <string> |
| 28 | +#include <unordered_map> |
| 29 | +#include <vector> |
| 30 | + |
31 | 31 | #include <boost/endian/arithmetic.hpp> |
32 | 32 | #include <boost/endian/conversion.hpp> |
33 | 33 | #include <boost/optional.hpp> |
34 | 34 | #include <boost/uuid/nil_generator.hpp> |
| 35 | +#include <boost/uuid/uuid.hpp> |
35 | 36 |
|
36 | | -#include <hazelcast/client/query/paging_predicate.h> |
37 | 37 | #include "hazelcast/client/address.h" |
38 | | -#include "hazelcast/client/member.h" |
39 | | -#include "hazelcast/client/serialization/pimpl/data.h" |
40 | | -#include "hazelcast/client/map/data_entry_view.h" |
41 | | -#include "hazelcast/client/exception/protocol_exceptions.h" |
42 | 38 | #include "hazelcast/client/config/index_config.h" |
| 39 | +#include "hazelcast/client/exception/protocol_exceptions.h" |
| 40 | +#include "hazelcast/client/map/data_entry_view.h" |
| 41 | +#include "hazelcast/client/member.h" |
43 | 42 | #include "hazelcast/client/protocol/codec/ErrorCodec.h" |
| 43 | +#include "hazelcast/client/query/paging_predicate.h" |
| 44 | +#include "hazelcast/client/serialization/pimpl/data.h" |
| 45 | +#include "hazelcast/client/sql/impl/query_id.h" |
| 46 | +#include "hazelcast/client/sql/column_metadata.h" |
| 47 | +#include "hazelcast/client/sql/impl/page.h" |
| 48 | +#include "hazelcast/client/sql/impl/error.h" |
| 49 | +#include "hazelcast/client/sql/column_type.h" |
44 | 50 |
|
45 | 51 | namespace hazelcast { |
46 | 52 | namespace util { |
@@ -795,6 +801,121 @@ class HAZELCAST_API ClientMessage |
795 | 801 | return h; |
796 | 802 | } |
797 | 803 |
|
| 804 | + /** |
| 805 | + * Reads the header of the current frame. |
| 806 | + * The cursor must be at a frame's beginning. |
| 807 | + */ |
| 808 | + frame_header_t read_frame_header() |
| 809 | + { |
| 810 | + frame_header_t header{}; |
| 811 | + auto pos = rd_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS); |
| 812 | + std::memcpy(&header.frame_len, pos, sizeof(header.frame_len)); |
| 813 | + pos += sizeof(header.frame_len); |
| 814 | + std::memcpy(&header.flags, pos, sizeof(header.flags)); |
| 815 | + return header; |
| 816 | + } |
| 817 | + |
| 818 | + template<typename T> |
| 819 | + typename std::enable_if<std::is_same<T, sql::column_metadata>::value, |
| 820 | + T>::type |
| 821 | + get() |
| 822 | + { |
| 823 | + // skip begin frame |
| 824 | + skip_frame(); |
| 825 | + |
| 826 | + const frame_header_t header = read_frame_header(); |
| 827 | + |
| 828 | + auto type = static_cast<sql::column_type>(get<int32_t>()); |
| 829 | + |
| 830 | + bool nullable = true; |
| 831 | + int nullable_size = 0; |
| 832 | + if (header.frame_len - SIZE_OF_FRAME_LENGTH_AND_FLAGS >= |
| 833 | + INT32_SIZE + INT8_SIZE) { |
| 834 | + nullable = get<bool>(); |
| 835 | + nullable_size = INT8_SIZE; |
| 836 | + } |
| 837 | + |
| 838 | + // skip bytes in initial frame |
| 839 | + rd_ptr(static_cast<int32_t>(header.frame_len) - |
| 840 | + SIZE_OF_FRAME_LENGTH_AND_FLAGS - INT32_SIZE - nullable_size); |
| 841 | + |
| 842 | + std::string name = get<std::string>(); |
| 843 | + |
| 844 | + fast_forward_to_end_frame(); |
| 845 | + |
| 846 | + return sql::column_metadata(std::move(name), type, nullable); |
| 847 | + } |
| 848 | + |
| 849 | + template<typename T> |
| 850 | + typename std::enable_if<std::is_same<T, sql::impl::page>::value, T>::type |
| 851 | + get() |
| 852 | + { |
| 853 | + // begin frame |
| 854 | + skip_frame(); |
| 855 | + |
| 856 | + bool last = peek(SIZE_OF_FRAME_LENGTH_AND_FLAGS + |
| 857 | + 1)[SIZE_OF_FRAME_LENGTH_AND_FLAGS] == 1; |
| 858 | + skip_frame(); |
| 859 | + |
| 860 | + auto column_type_ids = get<std::vector<int32_t>>(); |
| 861 | + |
| 862 | + using column = std::vector<boost::optional<std::string>>; |
| 863 | + |
| 864 | + std::vector<column> columns; |
| 865 | + std::vector<sql::column_type> column_types; |
| 866 | + |
| 867 | + for (auto column_type_id : column_type_ids) { |
| 868 | + auto column_type = static_cast<sql::column_type>(column_type_id); |
| 869 | + column_types.push_back(column_type); |
| 870 | + |
| 871 | + switch (column_type) { |
| 872 | + case sql::column_type::varchar: |
| 873 | + columns.push_back( |
| 874 | + get<std::vector<boost::optional<std::string>>>()); |
| 875 | + break; |
| 876 | + default: |
| 877 | + assert(false); |
| 878 | + |
| 879 | + // TODO add others |
| 880 | + } |
| 881 | + } |
| 882 | + |
| 883 | + fast_forward_to_end_frame(); |
| 884 | + |
| 885 | + return sql::impl::page{ column_types, columns, last }; |
| 886 | + } |
| 887 | + |
| 888 | + template<typename T> |
| 889 | + typename std::enable_if<std::is_same<T, sql::impl::error>::value, T>::type |
| 890 | + get() |
| 891 | + { |
| 892 | + // begin frame |
| 893 | + skip_frame(); |
| 894 | + |
| 895 | + const auto header = read_frame_header(); |
| 896 | + |
| 897 | + auto code = get<int>(); |
| 898 | + auto originating_member_id = get<boost::uuids::uuid>(); |
| 899 | + |
| 900 | + // skip bytes in initial frame |
| 901 | + rd_ptr(static_cast<int32_t>(header.frame_len) - |
| 902 | + SIZE_OF_FRAME_LENGTH_AND_FLAGS - INT32_SIZE - UUID_SIZE); |
| 903 | + |
| 904 | + auto message = get_nullable<std::string>(); |
| 905 | + |
| 906 | + boost::optional<std::string> suggestion; |
| 907 | + if (!next_frame_is_data_structure_end_frame()) { |
| 908 | + suggestion = get_nullable<std::string>(); |
| 909 | + } |
| 910 | + |
| 911 | + fast_forward_to_end_frame(); |
| 912 | + |
| 913 | + return sql::impl::error{ code, |
| 914 | + std::move(message), |
| 915 | + originating_member_id, |
| 916 | + std::move(suggestion) }; |
| 917 | + } |
| 918 | + |
798 | 919 | template<typename T> |
799 | 920 | boost::optional<T> get_nullable() |
800 | 921 | { |
@@ -1075,6 +1196,30 @@ class HAZELCAST_API ClientMessage |
1075 | 1196 | h->flags |= IS_FINAL_FLAG; |
1076 | 1197 | } |
1077 | 1198 | } |
| 1199 | + |
| 1200 | + void set(const frame_header_t& header) |
| 1201 | + { |
| 1202 | + auto pos = wr_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS); |
| 1203 | + std::memcpy(pos, &header.frame_len, sizeof(header.frame_len)); |
| 1204 | + pos += sizeof(header.frame_len); |
| 1205 | + std::memcpy(pos, &header.flags, sizeof(header.flags)); |
| 1206 | + } |
| 1207 | + |
| 1208 | + void set(const sql::impl::query_id& query_id, bool is_final = false) |
| 1209 | + { |
| 1210 | + add_begin_frame(); |
| 1211 | + |
| 1212 | + set(frame_header_t{ SIZE_OF_FRAME_LENGTH_AND_FLAGS + 4 * INT64_SIZE, |
| 1213 | + DEFAULT_FLAGS }); |
| 1214 | + |
| 1215 | + set(query_id.member_id_high()); |
| 1216 | + set(query_id.member_id_low()); |
| 1217 | + set(query_id.local_id_high()); |
| 1218 | + set(query_id.local_id_low()); |
| 1219 | + |
| 1220 | + add_end_frame(is_final); |
| 1221 | + } |
| 1222 | + |
1078 | 1223 | //----- Setter methods end --------------------- |
1079 | 1224 |
|
1080 | 1225 | //----- utility methods ------------------- |
|
0 commit comments