Skip to content

Commit 3a2fb74

Browse files
committed
Improved from_string function for SparseVector
1 parent 30c5a8b commit 3a2fb74

File tree

2 files changed

+79
-11
lines changed

2 files changed

+79
-11
lines changed

include/pgvector/pqxx.hpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,30 @@ template <> struct string_traits<pgvector::SparseVector> {
130130
throw conversion_error("Malformed sparsevec literal");
131131
}
132132

133+
int dimensions = std::stoi(std::string(text.substr(n + 2)));
134+
if (dimensions < 0) {
135+
throw conversion_error("Malformed sparsevec literal");
136+
}
137+
133138
std::vector<int> indices;
134139
std::vector<float> values;
135-
std::istringstream ss(std::string(text.substr(1, n)));
136-
while (ss.good()) {
137-
std::string substr;
138-
std::getline(ss, substr, ',');
139140

140-
size_t ne = substr.find(":");
141-
if (ne == std::string::npos) {
142-
throw conversion_error("Malformed sparsevec literal");
143-
}
141+
if (n > 1) {
142+
std::istringstream ss(std::string(text.substr(1, n)));
143+
while (ss.good()) {
144+
std::string substr;
145+
std::getline(ss, substr, ',');
146+
147+
size_t ne = substr.find(":");
148+
if (ne == std::string::npos) {
149+
throw conversion_error("Malformed sparsevec literal");
150+
}
144151

145-
indices.push_back(std::stoi(substr.substr(0, ne)) - 1);
146-
values.push_back(std::stof(substr.substr(ne + 1)));
152+
indices.push_back(std::stoi(substr.substr(0, ne)) - 1);
153+
values.push_back(std::stof(substr.substr(ne + 1)));
154+
}
147155
}
148156

149-
int dimensions = std::stoi(std::string(text.substr(n + 2)));
150157
return pgvector::SparseVector(dimensions, indices, values);
151158
}
152159

test/pqxx_test.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,67 @@ void test_sparsevec_to_string() {
225225

226226
void test_sparsevec_from_string() {
227227
assert(pqxx::from_string<pgvector::SparseVector>("{1:1,3:2,5:3}/6") == pgvector::SparseVector({1, 0, 2, 0, 3, 0}));
228+
assert(pqxx::from_string<pgvector::SparseVector>("{}/6") == pgvector::SparseVector({0, 0, 0, 0, 0, 0}));
229+
230+
try {
231+
auto unused = pqxx::from_string<pgvector::SparseVector>("");
232+
assert(false);
233+
} catch (const pqxx::conversion_error& e) {
234+
assert(std::string_view(e.what()) == "Malformed sparsevec literal");
235+
}
236+
237+
try {
238+
auto unused = pqxx::from_string<pgvector::SparseVector>("{");
239+
assert(false);
240+
} catch (const pqxx::conversion_error& e) {
241+
assert(std::string_view(e.what()) == "Malformed sparsevec literal");
242+
}
243+
244+
try {
245+
auto unused = pqxx::from_string<pgvector::SparseVector>("{}/-1");
246+
assert(false);
247+
} catch (const pqxx::conversion_error& e) {
248+
assert(std::string_view(e.what()) == "Malformed sparsevec literal");
249+
}
250+
251+
// TODO change to pqxx::conversion_error
252+
try {
253+
auto unused = pqxx::from_string<pgvector::SparseVector>("{:}/1");
254+
assert(false);
255+
} catch (const std::invalid_argument& e) {
256+
assert(true);
257+
}
258+
259+
try {
260+
auto unused = pqxx::from_string<pgvector::SparseVector>("{,}/1");
261+
assert(false);
262+
} catch (const pqxx::conversion_error& e) {
263+
assert(std::string_view(e.what()) == "Malformed sparsevec literal");
264+
}
265+
266+
// TODO change to pqxx::conversion_error
267+
try {
268+
auto unused = pqxx::from_string<pgvector::SparseVector>("{a:1}/1");
269+
assert(false);
270+
} catch (const std::invalid_argument& e) {
271+
assert(true);
272+
}
273+
274+
// TODO change to pqxx::conversion_error
275+
try {
276+
auto unused = pqxx::from_string<pgvector::SparseVector>("{1:a}/1");
277+
assert(false);
278+
} catch (const std::invalid_argument& e) {
279+
assert(true);
280+
}
281+
282+
// TODO change to pqxx::conversion_error
283+
try {
284+
auto unused = pqxx::from_string<pgvector::SparseVector>("{}/a");
285+
assert(false);
286+
} catch (const std::invalid_argument& e) {
287+
assert(true);
288+
}
228289
}
229290

230291
void test_pqxx() {

0 commit comments

Comments
 (0)