77#pragma once
88
99#include < cstddef>
10+ #include < limits>
1011#include < string_view>
1112#include < vector>
1213
@@ -182,13 +183,8 @@ template<> struct string_traits<pgvector::SparseVector> {
182183 throw conversion_error{" Malformed sparsevec literal" };
183184 }
184185
186+ std::unordered_map<int , float > map;
185187 int dimensions = pqxx::from_string<int >(text.substr (n + 2 ), c);
186- if (dimensions < 0 ) {
187- throw conversion_error{" Dimensions cannot be negative" };
188- }
189-
190- std::vector<int > indices;
191- std::vector<float > values;
192188
193189 if (n > 1 ) {
194190 auto add_element = [&](std::string_view substr) {
@@ -200,12 +196,12 @@ template<> struct string_traits<pgvector::SparseVector> {
200196 int index = pqxx::from_string<int >(substr.substr (0 , ne), c);
201197 float value = pqxx::from_string<float >(substr.substr (ne + 1 ), c);
202198
203- if (index < 1 || index > dimensions) {
204- throw conversion_error{" Index out of bounds" };
199+ // check to avoid undefined behavior
200+ if (index > std::numeric_limits<int >::min ()) {
201+ index -= 1 ;
205202 }
206203
207- indices.push_back (index - 1 );
208- values.push_back (value);
204+ map.insert ({index, value});
209205 };
210206
211207 std::string_view inner = text.substr (1 , n - 1 );
@@ -219,7 +215,11 @@ template<> struct string_traits<pgvector::SparseVector> {
219215 add_element (inner.substr (start));
220216 }
221217
222- return pgvector::SparseVector{dimensions, std::move (indices), std::move (values)};
218+ try {
219+ return pgvector::SparseVector{map, dimensions};
220+ } catch (const std::invalid_argument& e) {
221+ throw conversion_error{e.what ()};
222+ }
223223 }
224224
225225 static std::string_view to_buf (std::span<char > buf, const pgvector::SparseVector& value, ctx c = {}) {
0 commit comments