Skip to content

Commit 5e9c78c

Browse files
committed
Added support for libpqxx 8
1 parent 2a97d8e commit 5e9c78c

File tree

3 files changed

+35
-65
lines changed

3 files changed

+35
-65
lines changed

CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ include(GNUInstallDirs)
77
add_library(pgvector INTERFACE)
88
add_library(pgvector::pgvector ALIAS pgvector)
99

10-
target_compile_features(pgvector INTERFACE cxx_std_17)
10+
target_compile_features(pgvector INTERFACE cxx_std_20)
1111

1212
target_include_directories(
1313
pgvector
@@ -26,13 +26,13 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
2626
if(BUILD_TESTING)
2727
include(FetchContent)
2828

29-
FetchContent_Declare(libpqxx GIT_REPOSITORY https://github.com/jtv/libpqxx.git GIT_TAG 7.10.2)
29+
FetchContent_Declare(libpqxx GIT_REPOSITORY https://github.com/jtv/libpqxx.git GIT_TAG 8.0.0-rc1)
3030
FetchContent_MakeAvailable(libpqxx)
3131

3232
add_executable(test test/halfvec_test.cpp test/main.cpp test/pqxx_test.cpp test/sparsevec_test.cpp test/vector_test.cpp)
3333
target_link_libraries(test PRIVATE libpqxx::pqxx pgvector::pgvector)
3434
if(NOT MSVC)
35-
target_compile_options(test PRIVATE -Wall -Wextra -Wpedantic -Werror)
35+
target_compile_options(test PRIVATE -Wall -Wextra -Wpedantic -Werror -Wno-unused-parameter)
3636
endif()
3737
endif()
3838
endif()

include/pgvector/pqxx.hpp

Lines changed: 30 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,12 @@
2121
/// @cond
2222

2323
namespace pqxx {
24-
template <> inline std::string_view const type_name<pgvector::Vector>{"vector"};
24+
template <> inline constexpr std::string_view name_type<pgvector::Vector>() noexcept { return "vector"; };
2525

2626
template <> struct nullness<pgvector::Vector> : no_null<pgvector::Vector> {};
2727

2828
template <> struct string_traits<pgvector::Vector> {
29-
static constexpr bool converts_to_string{true};
30-
31-
static constexpr bool converts_from_string{true};
32-
33-
static pgvector::Vector from_string(std::string_view text) {
29+
static pgvector::Vector from_string(std::string_view text, ctx c = {}) {
3430
if (text.size() < 2 || text.front() != '[' || text.back() != ']') {
3531
throw conversion_error("Malformed vector literal");
3632
}
@@ -46,18 +42,12 @@ template <> struct string_traits<pgvector::Vector> {
4642
return pgvector::Vector(result);
4743
}
4844

49-
static zview to_buf(char* begin, char* end, const pgvector::Vector& value) {
50-
char *const next = into_buf(begin, end, value);
51-
return zview{begin, next - begin - 1};
52-
}
53-
54-
static char* into_buf(char* begin, char* end, const pgvector::Vector& value) {
55-
auto ret = string_traits<std::vector<float>>::into_buf(
56-
begin, end, static_cast<std::vector<float>>(value));
45+
static std::string_view to_buf(std::span<char> buf, const pgvector::Vector& value, ctx c = {}) {
46+
auto len = pqxx::into_buf(buf, static_cast<std::vector<float>>(value), c);
5747
// replace array brackets
58-
*begin = '[';
59-
*(ret - 2) = ']';
60-
return ret;
48+
buf[0] = '[';
49+
buf[len - 1] = ']';
50+
return {std::data(buf), len};
6151
}
6252

6353
static size_t size_buffer(const pgvector::Vector& value) noexcept {
@@ -66,16 +56,12 @@ template <> struct string_traits<pgvector::Vector> {
6656
}
6757
};
6858

69-
template <> inline std::string_view const type_name<pgvector::HalfVector>{"halfvec"};
59+
template <> inline constexpr std::string_view name_type<pgvector::HalfVector>() noexcept { return "halfvec"; };
7060

7161
template <> struct nullness<pgvector::HalfVector> : no_null<pgvector::HalfVector> {};
7262

7363
template <> struct string_traits<pgvector::HalfVector> {
74-
static constexpr bool converts_to_string{true};
75-
76-
static constexpr bool converts_from_string{true};
77-
78-
static pgvector::HalfVector from_string(std::string_view text) {
64+
static pgvector::HalfVector from_string(std::string_view text, ctx c = {}) {
7965
if (text.size() < 2 || text.front() != '[' || text.back() != ']') {
8066
throw conversion_error("Malformed halfvec literal");
8167
}
@@ -91,18 +77,12 @@ template <> struct string_traits<pgvector::HalfVector> {
9177
return pgvector::HalfVector(result);
9278
}
9379

94-
static zview to_buf(char* begin, char* end, const pgvector::HalfVector& value) {
95-
char *const next = into_buf(begin, end, value);
96-
return zview{begin, next - begin - 1};
97-
}
98-
99-
static char* into_buf(char* begin, char* end, const pgvector::HalfVector& value) {
100-
auto ret = string_traits<std::vector<float>>::into_buf(
101-
begin, end, static_cast<std::vector<float>>(value));
80+
static std::string_view to_buf(std::span<char> buf, const pgvector::HalfVector& value, ctx c = {}) {
81+
auto len = pqxx::into_buf(buf, static_cast<std::vector<float>>(value), c);
10282
// replace array brackets
103-
*begin = '[';
104-
*(ret - 2) = ']';
105-
return ret;
83+
buf[0] = '[';
84+
buf[len - 1] = ']';
85+
return {std::data(buf), len};
10686
}
10787

10888
static size_t size_buffer(const pgvector::HalfVector& value) noexcept {
@@ -111,16 +91,12 @@ template <> struct string_traits<pgvector::HalfVector> {
11191
}
11292
};
11393

114-
template <> inline std::string_view const type_name<pgvector::SparseVector>{"sparsevec"};
94+
template <> inline constexpr std::string_view name_type<pgvector::SparseVector>() noexcept { return "sparsevec"; };
11595

11696
template <> struct nullness<pgvector::SparseVector> : no_null<pgvector::SparseVector> {};
11797

11898
template <> struct string_traits<pgvector::SparseVector> {
119-
static constexpr bool converts_to_string{true};
120-
121-
static constexpr bool converts_from_string{true};
122-
123-
static pgvector::SparseVector from_string(std::string_view text) {
99+
static pgvector::SparseVector from_string(std::string_view text, ctx c = {}) {
124100
if (text.size() < 4 || text.front() != '{') {
125101
throw conversion_error("Malformed sparsevec literal");
126102
}
@@ -130,7 +106,7 @@ template <> struct string_traits<pgvector::SparseVector> {
130106
throw conversion_error("Malformed sparsevec literal");
131107
}
132108

133-
int dimensions = string_traits<int>::from_string(text.substr(n + 2));
109+
int dimensions = string_traits<int>::from_string(text.substr(n + 2), c);
134110
if (dimensions < 0) {
135111
throw conversion_error("Dimensions cannot be negative");
136112
}
@@ -149,8 +125,8 @@ template <> struct string_traits<pgvector::SparseVector> {
149125
throw conversion_error("Malformed sparsevec literal");
150126
}
151127

152-
int index = string_traits<int>::from_string(substr.substr(0, ne));
153-
float value = string_traits<float>::from_string(substr.substr(ne + 1));
128+
int index = string_traits<int>::from_string(substr.substr(0, ne), c);
129+
float value = string_traits<float>::from_string(substr.substr(ne + 1), c);
154130

155131
if (index < 1) {
156132
throw conversion_error("Index out of bounds");
@@ -164,12 +140,7 @@ template <> struct string_traits<pgvector::SparseVector> {
164140
return pgvector::SparseVector(dimensions, indices, values);
165141
}
166142

167-
static zview to_buf(char* begin, char* end, const pgvector::SparseVector& value) {
168-
char *const next = into_buf(begin, end, value);
169-
return zview{begin, next - begin - 1};
170-
}
171-
172-
static char* into_buf(char* begin, char* end, const pgvector::SparseVector& value) {
143+
static std::string_view to_buf(std::span<char> buf, const pgvector::SparseVector& value, ctx c = {}) {
173144
int dimensions = value.dimensions();
174145
auto indices = value.indices();
175146
auto values = value.values();
@@ -181,25 +152,24 @@ template <> struct string_traits<pgvector::SparseVector> {
181152
throw conversion_overrun{"sparsevec cannot have more than 16000 dimensions"};
182153
}
183154

184-
char *here = begin;
185-
*here++ = '{';
155+
size_t here = 0;
156+
buf[here++] = '{';
186157

187158
for (size_t i = 0; i < nnz; i++) {
188159
if (i != 0) {
189-
*here++ = ',';
160+
buf[here++] = ',';
190161
}
191162

192-
here = string_traits<int>::into_buf(here, end, indices[i] + 1) - 1;
193-
*here++ = ':';
194-
here = string_traits<float>::into_buf(here, end, values[i]) - 1;
163+
here += pqxx::into_buf(buf.subspan(here), indices[i] + 1, c);
164+
buf[here++] = ':';
165+
here += pqxx::into_buf(buf.subspan(here), values[i], c);
195166
}
196167

197-
*here++ = '}';
198-
*here++ = '/';
199-
here = string_traits<int>::into_buf(here, end, dimensions) - 1;
200-
*here++ = '\0';
168+
buf[here++] = '}';
169+
buf[here++] = '/';
170+
here += pqxx::into_buf(buf.subspan(here), dimensions, c);
201171

202-
return here;
172+
return {std::data(buf), here};
203173
}
204174

205175
static size_t size_buffer(const pgvector::SparseVector& value) noexcept {

test/pqxx_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ void test_stream_to(pqxx::connection &conn) {
116116

117117
pqxx::nontransaction tx(conn);
118118
auto stream = pqxx::stream_to::table(tx, {"items"}, {"embedding"});
119-
stream << pgvector::Vector({1, 2, 3});
120-
stream << pgvector::Vector({4, 5, 6});
119+
stream.write_values(pgvector::Vector({1, 2, 3}));
120+
stream.write_values(pgvector::Vector({4, 5, 6}));
121121
stream.complete();
122122
pqxx::result res = tx.exec("SELECT embedding FROM items ORDER BY id");
123123
assert(res[0][0].as<std::string>() == "[1,2,3]");

0 commit comments

Comments
 (0)