meta_check_context.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_DETAIL_TYPING_META_CHECK_CONTEXT_HPP
  8. #define BOOST_MYSQL_DETAIL_TYPING_META_CHECK_CONTEXT_HPP
  9. #include <boost/mysql/client_errc.hpp>
  10. #include <boost/mysql/column_type.hpp>
  11. #include <boost/mysql/diagnostics.hpp>
  12. #include <boost/mysql/error_code.hpp>
  13. #include <boost/mysql/metadata.hpp>
  14. #include <boost/mysql/metadata_collection_view.hpp>
  15. #include <boost/mysql/string_view.hpp>
  16. #include <boost/mysql/detail/access.hpp>
  17. #include <boost/mysql/detail/config.hpp>
  18. #include <boost/mysql/detail/typing/pos_map.hpp>
  19. #include <memory>
  20. #include <sstream>
  21. namespace boost {
  22. namespace mysql {
  23. namespace detail {
  24. inline const char* column_type_to_str(const metadata& meta) noexcept
  25. {
  26. switch (meta.type())
  27. {
  28. case column_type::tinyint: return meta.is_unsigned() ? "TINYINT UNSIGNED" : "TINYINT";
  29. case column_type::smallint: return meta.is_unsigned() ? "SMALLINT UNSIGNED" : "SMALLINT";
  30. case column_type::mediumint: return meta.is_unsigned() ? "MEDIUMINT UNSIGNED" : "MEDIUMINT";
  31. case column_type::int_: return meta.is_unsigned() ? "INT UNSIGNED" : "INT";
  32. case column_type::bigint: return meta.is_unsigned() ? "BIGINT UNSIGNED" : "BIGINT";
  33. case column_type::float_: return "FLOAT";
  34. case column_type::double_: return "DOUBLE";
  35. case column_type::decimal: return "DECIMAL";
  36. case column_type::bit: return "BIT";
  37. case column_type::year: return "YEAR";
  38. case column_type::time: return "TIME";
  39. case column_type::date: return "DATE";
  40. case column_type::datetime: return "DATETIME";
  41. case column_type::timestamp: return "TIMESTAMP";
  42. case column_type::char_: return "CHAR";
  43. case column_type::varchar: return "VARCHAR";
  44. case column_type::binary: return "BINARY";
  45. case column_type::varbinary: return "VARBINARY";
  46. case column_type::text: return "TEXT";
  47. case column_type::blob: return "BLOB";
  48. case column_type::enum_: return "ENUM";
  49. case column_type::set: return "SET";
  50. case column_type::json: return "JSON";
  51. case column_type::geometry: return "GEOMETRY";
  52. default: return "<unknown column type>";
  53. }
  54. }
  55. class meta_check_context
  56. {
  57. std::unique_ptr<std::ostringstream> errors_;
  58. std::size_t current_index_{};
  59. span<const std::size_t> pos_map_;
  60. name_table_t name_table_;
  61. metadata_collection_view meta_{};
  62. bool nullability_checked_{};
  63. std::ostringstream& add_error()
  64. {
  65. if (!errors_)
  66. errors_.reset(new std::ostringstream);
  67. else
  68. *errors_ << '\n';
  69. return *errors_;
  70. }
  71. void insert_field_name(std::ostringstream& os)
  72. {
  73. if (has_field_names(name_table_))
  74. os << "'" << name_table_[current_index_] << "'";
  75. else
  76. os << "in position " << current_index_;
  77. }
  78. public:
  79. meta_check_context(
  80. span<const std::size_t> pos_map,
  81. name_table_t name_table,
  82. metadata_collection_view meta
  83. ) noexcept
  84. : pos_map_(pos_map), name_table_(name_table), meta_(meta)
  85. {
  86. }
  87. // Accessors
  88. const metadata& current_meta() const noexcept { return map_metadata(pos_map_, current_index_, meta_); }
  89. bool is_current_field_absent() const noexcept { return pos_map_[current_index_] == pos_absent; }
  90. // Iteration
  91. void advance() noexcept
  92. {
  93. nullability_checked_ = false;
  94. ++current_index_;
  95. }
  96. // Nullability
  97. void set_nullability_checked() noexcept { nullability_checked_ = true; }
  98. bool nullability_checked() const noexcept { return nullability_checked_; }
  99. // Error reporting
  100. BOOST_MYSQL_DECL
  101. void add_field_absent_error();
  102. BOOST_MYSQL_DECL
  103. void add_type_mismatch_error(const char* cpp_type_name);
  104. BOOST_MYSQL_DECL
  105. void add_nullability_error();
  106. BOOST_MYSQL_DECL
  107. error_code check_errors(diagnostics& diag) const;
  108. };
  109. } // namespace detail
  110. } // namespace mysql
  111. } // namespace boost
  112. #ifdef BOOST_MYSQL_HEADER_ONLY
  113. #include <boost/mysql/impl/meta_check_context.ipp>
  114. #endif
  115. #endif