pg_async
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
protocol_io_traits.hpp
Go to the documentation of this file.
1 
8 #ifndef TIP_DB_PG_PROTOCOL_IO_TRAITS_HPP_
9 #define TIP_DB_PG_PROTOCOL_IO_TRAITS_HPP_
10 
11 #include <string>
12 
13 #include <istream>
14 #include <ostream>
15 #include <sstream>
16 
17 #include <type_traits>
18 #include <boost/optional.hpp>
19 
20 #include <tip/db/pg/common.hpp>
21 #include <tip/db/pg/pg_types.hpp>
22 #include <tip/util/streambuf.hpp>
23 
24 namespace tip {
25 namespace db {
26 namespace pg {
27 namespace io {
28 
36 };
37 
38 namespace detail {
42 typedef std::integral_constant< protocol_binary_type, OTHER > other_binary_type;
46 typedef std::integral_constant< protocol_binary_type, INTEGRAL > integral_binary_type;
51 typedef std::integral_constant< protocol_binary_type, FLOATING_POINT > floating_point_binary_type;
52 
56 template < typename T >
59 
67 
69 
73 
74 } // namespace detail
75 
76 template < typename T, protocol_data_format >
78 
79 template < typename T, protocol_data_format >
81 
87 template < typename T, protocol_data_format F >
89  typedef tip::util::input_iterator_buffer input_buffer_type;
92 };
93 
103 template < protocol_data_format F, typename T >
106 {
107  return typename protocol_io_traits< T, F >::parser_type(value);
108 }
109 
125 template < protocol_data_format F, typename T, typename InputIterator >
126 InputIterator
127 protocol_read(InputIterator begin, InputIterator end, T& value)
128 {
129  return typename protocol_io_traits< T, F >::parser_type(value)(begin, end);
130 }
131 
141 template < protocol_data_format F, typename T >
142 typename protocol_io_traits< T, F >::formatter_type
143 protocol_writer(T const& value)
144 {
145  return typename protocol_io_traits< T, F >::formatter_type(value);
146 }
147 
160 template < protocol_data_format F, typename T >
161 bool
162 protocol_write(std::vector<byte>& buffer, T const& value)
163 {
164  return protocol_writer<F>(value)(buffer);
165 }
166 
177 template < protocol_data_format F, typename T, typename OutputIterator >
178 bool
179 protocol_write(OutputIterator out, T const& value)
180 {
181  return protocol_writer<F>(value)(out);
182 }
183 
184 namespace detail {
185 
190 template < typename T >
191 struct parser_base {
192  typedef typename std::decay< T >::type value_type;
194 
195  parser_base(value_type& val) : value(val) {}
196 };
197 
202 template < typename T >
204  typedef typename std::decay< T >::type value_type;
206 
207  formatter_base(value_type const& val) : value(val) {}
208 };
209 
216 template < typename T, protocol_binary_type TYPE >
218 
226 template < typename T >
230 
234  size_t
235  size() const
236  {
237  return sizeof(T);
238  }
239 
241 
242  template < typename InputIterator >
243  InputIterator
244  operator()( InputIterator begin, InputIterator end );
245 };
246 
247 template < typename T >
248 struct binary_data_parser < T, OTHER >;
249 
256 template < typename T, protocol_binary_type TYPE >
258 
266 template < typename T >
270 
271  size_t
272  size() const
273  {
274  return sizeof(T);
275  }
276 
278 
279  bool
280  operator()(std::vector<byte>& buffer);
281 
282  template < typename OutputIterator >
283  bool
284  operator()(OutputIterator);
285 };
286 
291 template < oids::type::oid_type TypeOid, typename T >
293  static constexpr oids::type::oid_type type_oid = TypeOid;
294  typedef typename std::decay<T>::type type;
295 };
296 
297 } // namespace detail
298 
299 namespace traits {
300 
306 void
308 
314 bool
316 
321 template < oids::type::oid_type TypeOid >
322 struct pgcpp_data_mapping : detail::data_mapping_base< TypeOid, std::string > {};
323 
331 template < typename T >
332 struct cpppg_data_mapping : detail::data_mapping_base < oids::type::unknown, T > {};
333 
335 
336 template <typename T>
338 private:
339  static void test(...);
340  template < typename U > static bool test(U&);
341  static std::istream& is;
342  static T& val;
343 public:
344  static constexpr bool value = std::is_same<
345  decltype( test( std::declval< std::istream& >() >> std::declval< T& >()) ),
346  bool
347  >::type::value;
348 };
349 
350 template <typename T>
352 private:
353  static void test(...);
354  template < typename U > static bool test(U&);
355 public:
356  static constexpr bool value = std::is_same<
357  decltype( test( std::declval< std::ostream& >() << std::declval< T >() ) ),
358  bool
359  >::type::value;
360 };
361 
362 template < typename T, protocol_data_format format >
363 struct has_parser : std::false_type {};
364 template < typename T >
366  : std::integral_constant< bool, has_input_operator< T >::value > {};
367 template < > struct has_parser< smallint, BINARY_DATA_FORMAT > : std::true_type {};
368 template < > struct has_parser< integer, BINARY_DATA_FORMAT > : std::true_type {};
369 template < > struct has_parser< bigint, BINARY_DATA_FORMAT > : std::true_type {};
370 
371 template < typename T, protocol_data_format format >
372 struct has_formatter : std::false_type {};
373 template < typename T >
375  : std::integral_constant< bool, has_output_operator< T >::value > {};
376 template < > struct has_formatter< smallint, BINARY_DATA_FORMAT > : std::true_type {};
377 template < > struct has_formatter< integer, BINARY_DATA_FORMAT > : std::true_type {};
378 template < > struct has_formatter< bigint, BINARY_DATA_FORMAT > : std::true_type {};
380 
384 
388 template < typename T >
389 struct best_parser {
390 private:
391  static constexpr bool has_binary_parser = has_parser<T, BINARY_DATA_FORMAT>::value;
392 public:
393  static constexpr protocol_data_format value = has_binary_parser ? BINARY_DATA_FORMAT : TEXT_DATA_FORMAT;
395 };
396 
400 template < typename T >
402 private:
403  static constexpr bool has_binary_formatter = has_formatter< T, BINARY_DATA_FORMAT >::value;
404 public:
405  static constexpr protocol_data_format value = has_binary_formatter ? BINARY_DATA_FORMAT : TEXT_DATA_FORMAT;
407 };
408 
410 
412  "Text format parser for smallint");
414  "Binary format parser for smallint");
416  "Best parser for smallint is binary");
417 
419  "Text format writer for smallint");
421  "Binary format writer for smallint");
423  "Best writer for smallint is binary");
424 
426  "Text format parser for integer");
428  "Binary format parser for integer");
430  "Best parser for integer is binary");
431 
433  "Text format writer for integer");
435  "Binary format writer for integer");
437  "Best writer for integer is binary");
438 
440  "Text format parser for bigint");
442  "Binary format parser for bigint");
444  "Best parser for bigint is binary");
445 
447  "Text format writer for bigint");
449  "Binary format writer for bigint");
451  "Best writer for bigint is binary");
453 
454 
456  "Text format parser for float");
457 // @todo implement binary parser for floats
458 //static_assert(has_parser<float, BINARY_DATA_FORMAT>::value,
459 // "Binary format parser for float");
461  "Best parser for float is text");
462 
464  "Text format writer for float");
465 // @todo implement binary formatter for floats
466 //static_assert(has_formatter<float, BINARY_DATA_FORMAT>::value,
467 // "Binary format writer for float");
469  "Best writer for float is text");
470 
472  "Text format parser for double");
473 // @todo implement binary parser for doubles
474 //static_assert(has_parser<double, BINARY_DATA_FORMAT>::value,
475 // "Binary format parser for double");
477  "Best parser for double is text");
478 
480  "Text format writer for double");
481 // @todo implement binary formatter for doubles
482 //static_assert(has_formatter<double, BINARY_DATA_FORMAT>::value,
483 // "Binary format writer for double");
485  "Best writer for double is text");
487 
488 } // namespace traits
489 
493 template < typename T >
497 
499 
500  size_t
501  size() const
502  {
503  std::ostringstream os;
504  os << base_type::value;
505  return os.str().size();
506  }
507  bool
508  operator()(std::vector<char>& buffer)
509  {
510  std::ostringstream os;
511  os << base_type::value;
512  auto str = os.str();
513  std::copy(str.begin(), str.end(), std::back_inserter(buffer));
514  return true;
515  }
516 };
517 
521 template < typename T >
525 
526  typedef tip::util::input_iterator_buffer buffer_type;
527 
529 
530  size_t
531  size() const
532  {
533  return sizeof(T);
534  }
535 
536  template < typename InputIterator >
537  InputIterator
538  operator()(InputIterator begin, InputIterator end);
539 };
540 
541 template < typename T >
544  detail::protocol_binary_selector< typename std::decay<T>::type >::value > {
545 
548  typedef typename formatter_base::value_type value_type;
549 
551 };
552 
553 template < typename T >
556  detail::protocol_binary_selector< typename std::decay<T>::type >::value > {
557 
558  typedef detail::binary_data_parser< T,
560  typedef typename parser_base::value_type value_type;
561 
563 };
564 
568 template < >
570  detail::parser_base< std::string > {
572  typedef base_type::value_type value_type;
573 
575 
576  size_t
577  size() const
578  {
579  return base_type::value.size();
580  }
581 
582  template < typename InputIterator >
583  InputIterator
584  operator()(InputIterator begin, InputIterator end);
585 };
586 
587 namespace traits {
588 static_assert(has_parser<std::string, TEXT_DATA_FORMAT>::value,
589  "Text data parser for std::string");
590 static_assert(!has_parser<std::string, BINARY_DATA_FORMAT>::value,
591  "No binary data parser for std::string");
592 static_assert(best_parser<std::string>::value == TEXT_DATA_FORMAT,
593  "Best parser for std::string is binary");
594 } // namespace traits
595 
596 template < >
598  detail::formatter_base< std::string > {
600  typedef base_type::value_type value_type;
601 
603 
604  size_t
605  size() const
606  {
607  return base_type::value.size();
608  }
609  bool
610  operator()(std::ostream& out)
611  {
612  out << base_type::value;
613  return out.good();
614  }
615  bool
616  operator()(std::vector<char>& buffer)
617  {
618  auto iter = std::copy(base_type::value.begin(), base_type::value.end(),
619  std::back_inserter(buffer));
620  return true;
621  }
622 
623 };
624 
625 namespace traits {
626 static_assert(has_formatter<std::string, TEXT_DATA_FORMAT>::value,
627  "Text data parser for std::string");
628 static_assert(!has_formatter<std::string, BINARY_DATA_FORMAT>::value,
629  "No binary data parser for std::string");
630 static_assert(best_formatter<std::string>::value == TEXT_DATA_FORMAT,
631  "Best parser for std::string is binary");
632 } // namespace traits
633 
637 template < >
639  detail::parser_base< bool > {
641  typedef base_type::value_type value_type;
642 
643  typedef tip::util::input_iterator_buffer buffer_type;
644 
646 
647  size_t
648  size() const
649  {
650  return sizeof(bool);
651  }
652  bool
653  use_literal(std::string const& l);
654 
655  template < typename InputIterator >
656  InputIterator
657  operator()(InputIterator begin, InputIterator end);
658 
659 };
660 
664 template < >
666  detail::parser_base< bool > {
669  typedef tip::util::input_iterator_buffer buffer_type;
670 
672  size_t
673  size() const
674  {
675  return sizeof(bool);
676  }
677  template < typename InputIterator >
678  InputIterator
679  operator()( InputIterator begin, InputIterator end );
680 };
681 
682 namespace traits {
683 template < > struct has_parser< bool, BINARY_DATA_FORMAT > : std::true_type {};
685  "Text data parser for bool");
687  "Binary data parser for bool");
689  "Best parser for bool is binary");
690 } // namespace traits
691 
695 template < typename T >
696 struct protocol_parser< boost::optional< T >, TEXT_DATA_FORMAT > :
697  detail::parser_base< boost::optional< T > > {
700 
701  typedef T element_type;
702  typedef tip::util::input_iterator_buffer buffer_type;
703 
705 
706  bool
707  operator() (std::istream& in)
708  {
709  element_type tmp;
710  if (query_parse(tmp)(in)) {
711  base_type::value = value_type(tmp);
712  } else {
713  base_type::value = value_type();
714  }
715  return true;
716  }
717 
718  bool
719  operator() (buffer_type& buffer)
720  {
721  element_type tmp;
722  if (query_parse(tmp)(buffer)) {
723  base_type::value = value_type(tmp);
724  } else {
725  base_type::value = value_type();
726  }
727  return true;
728  }
729 
730  template < typename InputIterator >
731  InputIterator
732  operator()(InputIterator begin, InputIterator end);
733 };
734 
738 template < typename T >
739 struct protocol_parser< boost::optional< T >, BINARY_DATA_FORMAT > :
740  detail::parser_base< boost::optional< T > > {
742  typedef typename base_type::value_type value_type;
743 
744  typedef T element_type;
746  typedef tip::util::input_iterator_buffer buffer_type;
747 
749 
750  size_t
751  size() const
752  {
753  if (base_type::value)
754  return element_parser(*base_type::value).size();
755  return 0;
756  }
757 
758  template < typename InputIterator >
759  InputIterator
760  operator()( InputIterator begin, InputIterator end )
761  {
762  T tmp;
763  InputIterator c = protocol_read< BINARY_DATA_FORMAT >(begin, end, tmp);
764  if (c != begin) {
765  base_type::value = value_type(tmp);
766  } else {
767  base_type::value = value_type();
768  }
769  return c;
770  }
771 };
772 
776 template <>
778  detail::parser_base< bytea > {
781  typedef tip::util::input_iterator_buffer buffer_type;
782 
784 
785  size_t
786  size() const
787  {
788  return base_type::value.data.size();
789  }
790  bool
791  operator() (std::istream& in);
792 
793  bool
794  operator() (buffer_type& buffer);
795 
796  template < typename InputIterator >
797  InputIterator
798  operator()( InputIterator begin, InputIterator end );
799 };
800 
804 template <>
806  detail::parser_base< bytea > {
808  typedef base_type::value_type value_type;
809 
811  size_t
812  size() const
813  {
814  return base_type::value.data.size();
815  }
816  template < typename InputIterator >
817  InputIterator
818  operator()( InputIterator begin, InputIterator end );
819 };
820 
821 } // namespace io
822 } // namespace pg
823 } // namespace db
824 } // namespace tip
825 
828 
829 #endif /* TIP_DB_PG_PROTOCOL_IO_TRAITS_HPP_ */
detail::binary_data_parser< T, detail::protocol_binary_selector< typename std::decay< T >::type >::value > parser_base
boost::int_t< 64 >::exact bigint
8-byte integer, to match PostgreSQL bigint and bigserial types
Definition: common.hpp:170
Base structure for a binary data formatter. Has no definition.
FLOATING_POINT Floating point types, requiring endianness conversion.
Template for specifying mapping between a C++ type and PostgreSQL type oid.
OTHER Other types, require specialization.
std::integral_constant< protocol_binary_type, INTEGRAL > integral_binary_type
Integral datatypes. Selects binary parser specialization with network byte order conversion.
InputIterator protocol_read(InputIterator begin, InputIterator end, T &value)
Read value from input buffer.
protocol_data_format
Definition: common.hpp:283
static constexpr protocol_data_format value
InputIterator operator()(InputIterator begin, InputIterator end)
static constexpr protocol_data_format value
boost::int_t< 32 >::exact integer
4-byte integer, to match PostgreSQL integer and serial types
Definition: common.hpp:162
tip::util::input_iterator_buffer input_buffer_type
boost::uint_t< 64 >::exact ubigint
8-byte unsigned integer
Definition: common.hpp:174
Base structure for a binary data parser. Has no definition.
protocol_binary_type
Enumeration for binary parser/formatter template selection.
boost::uint_t< 16 >::exact usmallint
2-byte unsigned integer
Definition: common.hpp:158
Base template struct for a data parser.
protocol_formatter< T, F > formatter_type
detail::binary_data_formatter< T, detail::protocol_binary_selector< typename std::decay< T >::type >::value > formatter_base
std::integral_constant< protocol_binary_type, FLOATING_POINT > floating_point_binary_type
Floating point datatypes. Binary parser is not implemented yet.
std::integral_constant< protocol_binary_type, OTHER > other_binary_type
Types other then integral or floating point. Require explicit specialization of a binary data parser...
boost::uint_t< 32 >::exact uinteger
4-byte unsigned integer
Definition: common.hpp:166
Binary data, matches PostgreSQL bytea type.
Definition: common.hpp:196
Base template struct for a data formatter.
Base structure for specifying mapping between C++ data type and PostgreSQL type oid.
boost::int_t< 16 >::exact smallint
2-byte integer, to match PostgreSQL smallint and smallserial types
Definition: common.hpp:154
BINARY_DATA_FORMAT.
Definition: common.hpp:285
void register_binary_parser(oids::type::oid_type id)
Mark a type oid that it has a binary parser, so that pg_async can request data in binary format...
static constexpr oids::type::oid_type type_oid
bool protocol_write(std::vector< byte > &buffer, T const &value)
Write value to a buffer.
TEXT_DATA_FORMAT.
Definition: common.hpp:284
bool has_binary_parser(oids::type::oid_type id)
Check if there is a binary parser for the specified oid.
protocol_io_traits< T, F >::parser_type protocol_reader(T &value)
Helper function to create a protocol parser.
protocol_io_traits< T, F >::formatter_type protocol_writer(T const &value)
Helper function to create a protocol formatter.
Metafunction for specifying binary procotocol type.
INTEGRAL Integral types, requiring endianness conversion.