32 #include "sqlTraits.hpp"
43 return Traits<T>::verifyType(
m_res, column);
45 template bool Fastcgipp::SQL::Results_base::verifyColumn<bool>(
47 template bool Fastcgipp::SQL::Results_base::verifyColumn<int16_t>(
49 template bool Fastcgipp::SQL::Results_base::verifyColumn<int32_t>(
51 template bool Fastcgipp::SQL::Results_base::verifyColumn<int64_t>(
53 template bool Fastcgipp::SQL::Results_base::verifyColumn<float>(
55 template bool Fastcgipp::SQL::Results_base::verifyColumn<double>(
58 Fastcgipp::SQL::Results_base::verifyColumn<std::chrono::time_point<std::chrono::system_clock>>(
60 template bool Fastcgipp::SQL::Results_base::verifyColumn<Fastcgipp::Address>(
62 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::string>(
64 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::wstring>(
66 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<char>>(
68 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<int16_t>>(
70 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<int32_t>>(
72 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<int64_t>>(
74 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<float>>(
76 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<double>>(
78 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<std::string>>(
80 template bool Fastcgipp::SQL::Results_base::verifyColumn<std::vector<std::wstring>>(
91 std::is_integral<Numeric>::value ||
92 std::is_floating_point<Numeric>::value,
93 "Numeric must be a numeric type.");
95 PQgetvalue(
reinterpret_cast<const PGresult*
>(m_res), row, column));
97 template void Fastcgipp::SQL::Results_base::field<int16_t>(
100 int16_t& value)
const;
101 template void Fastcgipp::SQL::Results_base::field<int32_t>(
104 int32_t& value)
const;
105 template void Fastcgipp::SQL::Results_base::field<int64_t>(
108 int64_t& value)
const;
109 template void Fastcgipp::SQL::Results_base::field<float>(
113 template void Fastcgipp::SQL::Results_base::field<double>(
116 double& value)
const;
120 template<>
void Fastcgipp::SQL::Results_base::field<bool>(
125 value =
static_cast<bool>(
126 *PQgetvalue(
reinterpret_cast<const PGresult*
>(m_res), row, column));
129 template<>
void Fastcgipp::SQL::Results_base::field<std::string>(
132 std::string& value)
const
135 PQgetvalue(
reinterpret_cast<const PGresult*
>(m_res), row, column),
136 PQgetlength(
reinterpret_cast<const PGresult*
>(m_res), row, column));
139 template<>
void Fastcgipp::SQL::Results_base::field<std::wstring>(
142 std::wstring& value)
const
144 std::wstring_convert<std::codecvt_utf8<wchar_t>,
wchar_t> converter;
145 const char*
const start = PQgetvalue(
146 reinterpret_cast<const PGresult*
>(m_res),
149 const char*
const end = start+PQgetlength(
150 reinterpret_cast<const PGresult*
>(m_res),
155 value = converter.from_bytes(start, end);
157 catch(
const std::range_error& e)
159 WARNING_LOG(
"Error in code conversion from utf8 in SQL result")
164 std::chrono::time_point<std::chrono::system_clock>>(
167 std::chrono::time_point<std::chrono::system_clock>& value)
const
170 PQgetvalue(
reinterpret_cast<const PGresult*
>(m_res), row, column));
172 const std::chrono::duration<int64_t, std::micro> duration(count);
174 value = std::chrono::time_point<std::chrono::system_clock>(
175 std::chrono::duration_cast<std::chrono::system_clock::duration>(
176 duration)+std::chrono::seconds(946684800));
179 template<>
void Fastcgipp::SQL::Results_base::field<Fastcgipp::Address>(
182 Address& value)
const
184 char* address_p =
reinterpret_cast<char*
>(&value);
185 const char*
const data = PQgetvalue(
186 reinterpret_cast<const PGresult*
>(m_res),
190 switch(PQgetlength(
reinterpret_cast<const PGresult*
>(m_res), row, column))
194 address_p = std::fill_n(address_p, 10,
char(0));
195 address_p = std::fill_n(address_p, 2,
char(-1));
212 template<
typename Numeric>
216 std::vector<Numeric>& value)
const
219 std::is_integral<Numeric>::value ||
220 std::is_floating_point<Numeric>::value,
221 "Numeric must be a numeric type.");
222 const char*
const start = PQgetvalue(
223 reinterpret_cast<const PGresult*
>(m_res),
228 start+0*
sizeof(int32_t)));
231 WARNING_LOG(
"SQL result array type for std::vector<Numeric> has "\
237 start+1*
sizeof(int32_t)));
240 WARNING_LOG(
"SQL result array type for std::vector<Numeric> has "\
246 start+2*
sizeof(int32_t)));
247 if(elementType != Traits<Numeric>::oid)
249 WARNING_LOG(
"SQL result array type for std::vector<Numeric> has "\
250 "the wrong element type");
255 start+3*
sizeof(int32_t)));
259 for(
int i=0; i<size; ++i)
261 const int32_t length(
263 start + 5*
sizeof(int32_t)
264 + i*(
sizeof(int32_t) +
sizeof(Numeric))));
265 if(length !=
sizeof(Numeric))
267 WARNING_LOG(
"SQL result array for Numeric has element of wrong size");
272 start + 6*
sizeof(int32_t)
273 + i*(
sizeof(int32_t) +
sizeof(Numeric))));
276 template void Fastcgipp::SQL::Results_base::field<int16_t>(
279 std::vector<int16_t>& value)
const;
280 template void Fastcgipp::SQL::Results_base::field<int32_t>(
283 std::vector<int32_t>& value)
const;
284 template void Fastcgipp::SQL::Results_base::field<int64_t>(
287 std::vector<int64_t>& value)
const;
288 template void Fastcgipp::SQL::Results_base::field<float>(
291 std::vector<float>& value)
const;
292 template void Fastcgipp::SQL::Results_base::field<double>(
295 std::vector<double>& value)
const;
297 template<>
void Fastcgipp::SQL::Results_base::field<char>(
300 std::vector<char>& value)
const
302 const unsigned size = PQgetlength(
303 reinterpret_cast<const PGresult*
>(m_res),
306 const char*
const start = PQgetvalue(
307 reinterpret_cast<const PGresult*
>(m_res),
310 const char*
const end = start+size;
313 value.assign(start, end);
317 void Fastcgipp::SQL::Results_base::field<std::string>(
320 std::vector<std::string>& value)
const
322 const char* ptr = PQgetvalue(
323 reinterpret_cast<const PGresult*
>(m_res),
328 ptr +=
sizeof(int32_t);
331 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
337 ptr +=
sizeof(int32_t);
340 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
345 const int32_t elementType(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
346 ptr +=
sizeof(int32_t);
347 if(elementType != Traits<std::string>::oid)
349 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
350 "the wrong element type");
354 const int32_t size(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
355 ptr += 2*
sizeof(int32_t);
359 for(
int i=0; i<size; ++i)
361 const int32_t length(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
362 ptr +=
sizeof(int32_t);
364 value.emplace_back(ptr, length);
370 void Fastcgipp::SQL::Results_base::field<std::wstring>(
373 std::vector<std::wstring>& value)
const
375 const char* ptr = PQgetvalue(
376 reinterpret_cast<const PGresult*
>(m_res),
380 const int32_t ndim(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
381 ptr +=
sizeof(int32_t);
384 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
389 const int32_t hasNull(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
390 ptr +=
sizeof(int32_t);
393 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
398 const int32_t elementType(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
399 ptr +=
sizeof(int32_t);
400 if(elementType != Traits<std::string>::oid)
402 WARNING_LOG(
"SQL result array type for std::vector<std::string> has "\
403 "the wrong element type");
407 const int32_t size(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
408 ptr += 2*
sizeof(int32_t);
412 std::wstring_convert<std::codecvt_utf8<wchar_t>,
wchar_t> converter;
415 for(
int i=0; i<size; ++i)
417 const int32_t length(*
reinterpret_cast<const BigEndian<int32_t>*
>(ptr));
418 ptr +=
sizeof(int32_t);
420 value.emplace_back(std::move(
421 converter.from_bytes(ptr, ptr+length)));
425 catch(
const std::range_error& e)
427 WARNING_LOG(
"Error in array code conversion to utf8 in SQL parameter")
435 if(
reinterpret_cast<const PGresult*
>(m_res) ==
nullptr)
438 switch(PQresultStatus(
reinterpret_cast<const PGresult*
>(m_res)))
440 case PGRES_EMPTY_QUERY:
442 case PGRES_COMMAND_OK:
444 case PGRES_TUPLES_OK:
450 case PGRES_BAD_RESPONSE:
452 case PGRES_NONFATAL_ERROR:
454 case PGRES_COPY_BOTH:
456 case PGRES_SINGLE_TUPLE:
465 return std::atoi(PQcmdTuples(
reinterpret_cast<PGresult*
>(m_res)));
471 PQclear(
reinterpret_cast<PGresult*
>(m_res));
476 return PQresultErrorMessage(
reinterpret_cast<const PGresult*
>(m_res));
481 return PQntuples(
reinterpret_cast<const PGresult*
>(m_res));
486 return static_cast<bool>(PQgetisnull(
487 reinterpret_cast<const PGresult*
>(m_res),
494 return PQnfields(
reinterpret_cast<const PGresult*
>(m_res));
504 return "Empty Query";
514 return "Bad Response";
516 return "Non-fatal Error";
520 return "Single Tuple";
523 return "Fatal Error";