column-info.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // Copyright (C) 2016 Maciej Sobczak
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef SOCI_COLUMN_INFO_H_INCLUDED
  8. #define SOCI_COLUMN_INFO_H_INCLUDED
  9. #include "soci/soci-backend.h"
  10. #include "soci/type-conversion.h"
  11. #include "soci/values.h"
  12. #include <cstdint>
  13. namespace soci
  14. {
  15. struct SOCI_DECL column_info
  16. {
  17. std::string name;
  18. // DEPRECATED. USE dataType INSTEAD.
  19. data_type type;
  20. db_type dataType;
  21. std::size_t length; // meaningful for text columns only
  22. std::size_t precision;
  23. std::size_t scale;
  24. bool nullable;
  25. };
  26. template <>
  27. struct type_conversion<column_info>
  28. {
  29. typedef values base_type;
  30. static std::size_t get_numeric_value(const values & v,
  31. const std::string & field_name)
  32. {
  33. db_type dt = v.get_properties(field_name).get_db_type();
  34. switch (dt)
  35. {
  36. case db_double:
  37. return static_cast<std::size_t>(
  38. v.get<double>(field_name, 0.0));
  39. case db_int8:
  40. return static_cast<std::size_t>(
  41. v.get<int8_t>(field_name, 0));
  42. case db_uint8:
  43. return static_cast<std::size_t>(
  44. v.get<uint8_t>(field_name, 0));
  45. case db_int16:
  46. return static_cast<std::size_t>(
  47. v.get<int16_t>(field_name, 0));
  48. case db_uint16:
  49. return static_cast<std::size_t>(
  50. v.get<uint16_t>(field_name, 0));
  51. case db_int32:
  52. return static_cast<std::size_t>(
  53. v.get<int32_t>(field_name, 0));
  54. case db_uint32:
  55. return static_cast<std::size_t>(
  56. v.get<uint32_t>(field_name, 0));
  57. case db_int64:
  58. return static_cast<std::size_t>(
  59. v.get<int64_t>(field_name, 0ll));
  60. case db_uint64:
  61. return static_cast<std::size_t>(
  62. v.get<uint64_t>(field_name, 0ull));
  63. default:
  64. return 0u;
  65. }
  66. }
  67. static void from_base(values const & v, indicator /* ind */, column_info & ci)
  68. {
  69. ci.name = v.get<std::string>("COLUMN_NAME");
  70. ci.length = get_numeric_value(v, "CHARACTER_MAXIMUM_LENGTH");
  71. ci.precision = get_numeric_value(v, "NUMERIC_PRECISION");
  72. ci.scale = get_numeric_value(v, "NUMERIC_SCALE");
  73. const std::string & type_name = v.get<std::string>("DATA_TYPE");
  74. if (type_name == "text" || type_name == "TEXT" ||
  75. type_name == "clob" || type_name == "CLOB" ||
  76. type_name.find("char") != std::string::npos ||
  77. type_name.find("CHAR") != std::string::npos)
  78. {
  79. ci.type = dt_string;
  80. ci.dataType = db_string;
  81. }
  82. else if (type_name == "integer" || type_name == "INTEGER")
  83. {
  84. ci.type = dt_integer;
  85. ci.dataType = db_int32;
  86. }
  87. else if (type_name.find("number") != std::string::npos ||
  88. type_name.find("NUMBER") != std::string::npos ||
  89. type_name.find("numeric") != std::string::npos ||
  90. type_name.find("NUMERIC") != std::string::npos)
  91. {
  92. if (ci.scale != 0)
  93. {
  94. ci.type = dt_double;
  95. ci.dataType = db_double;
  96. }
  97. else
  98. {
  99. ci.type = dt_integer;
  100. ci.dataType = db_int32;
  101. }
  102. }
  103. else if (type_name.find("time") != std::string::npos ||
  104. type_name.find("TIME") != std::string::npos ||
  105. type_name.find("date") != std::string::npos ||
  106. type_name.find("DATE") != std::string::npos)
  107. {
  108. ci.type = dt_date;
  109. ci.dataType = db_date;
  110. }
  111. else if (type_name.find("blob") != std::string::npos ||
  112. type_name.find("BLOB") != std::string::npos ||
  113. type_name.find("oid") != std::string::npos ||
  114. type_name.find("OID") != std::string::npos)
  115. {
  116. ci.type = dt_blob;
  117. ci.dataType = db_blob;
  118. }
  119. else if (type_name.find("xml") != std::string::npos ||
  120. type_name.find("XML") != std::string::npos)
  121. {
  122. ci.type = dt_xml;
  123. ci.dataType = db_xml;
  124. }
  125. else
  126. {
  127. // this seems to be a safe default
  128. ci.type = dt_string;
  129. ci.dataType = db_string;
  130. }
  131. const std::string & nullable_s = v.get<std::string>("IS_NULLABLE");
  132. ci.nullable = (nullable_s == "YES");
  133. }
  134. };
  135. } // namespace soci
  136. #endif // SOCI_COLUMN_INFO_H_INCLUDED