Node.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * https://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include <cmath>
  19. #include "Node.hh"
  20. namespace avro {
  21. using std::string;
  22. Node::~Node() = default;
  23. Name::Name(const std::string &name) {
  24. fullname(name);
  25. }
  26. string Name::fullname() const {
  27. return (ns_.empty()) ? simpleName_ : ns_ + "." + simpleName_;
  28. }
  29. void Name::fullname(const string &name) {
  30. string::size_type n = name.find_last_of('.');
  31. if (n == string::npos) {
  32. simpleName_ = name;
  33. ns_.clear();
  34. } else {
  35. ns_ = name.substr(0, n);
  36. simpleName_ = name.substr(n + 1);
  37. }
  38. check();
  39. }
  40. bool Name::operator<(const Name &n) const {
  41. return (ns_ < n.ns_) || (!(n.ns_ < ns_) && (simpleName_ < n.simpleName_));
  42. }
  43. static bool invalidChar1(char c) {
  44. return !isalnum(c) && c != '_' && c != '.' && c != '$';
  45. }
  46. static bool invalidChar2(char c) {
  47. return !isalnum(c) && c != '_';
  48. }
  49. void Name::check() const {
  50. if (!ns_.empty() && (ns_[0] == '.' || ns_[ns_.size() - 1] == '.' || std::find_if(ns_.begin(), ns_.end(), invalidChar1) != ns_.end())) {
  51. throw Exception("Invalid namespace: " + ns_);
  52. }
  53. if (simpleName_.empty()
  54. || std::find_if(simpleName_.begin(), simpleName_.end(), invalidChar2) != simpleName_.end()) {
  55. throw Exception("Invalid name: " + simpleName_);
  56. }
  57. }
  58. bool Name::operator==(const Name &n) const {
  59. return ns_ == n.ns_ && simpleName_ == n.simpleName_;
  60. }
  61. void Node::setLogicalType(LogicalType logicalType) {
  62. checkLock();
  63. // Check that the logical type is applicable to the node type.
  64. switch (logicalType.type()) {
  65. case LogicalType::NONE: break;
  66. case LogicalType::DECIMAL: {
  67. if (type_ != AVRO_BYTES && type_ != AVRO_FIXED) {
  68. throw Exception("DECIMAL logical type can annotate "
  69. "only BYTES or FIXED type");
  70. }
  71. if (type_ == AVRO_FIXED) {
  72. // Max precision that can be supported by the current size of
  73. // the FIXED type.
  74. long maxPrecision = floor(log10(2.0) * (8.0 * fixedSize() - 1));
  75. if (logicalType.precision() > maxPrecision) {
  76. throw Exception(
  77. boost::format(
  78. "DECIMAL precision %1% is too large for the "
  79. "FIXED type of size %2%, precision cannot be "
  80. "larger than %3%")
  81. % logicalType.precision() % fixedSize() % maxPrecision);
  82. }
  83. }
  84. if (logicalType.scale() > logicalType.precision()) {
  85. throw Exception("DECIMAL scale cannot exceed precision");
  86. }
  87. break;
  88. }
  89. case LogicalType::DATE:
  90. if (type_ != AVRO_INT) {
  91. throw Exception("DATE logical type can only annotate INT type");
  92. }
  93. break;
  94. case LogicalType::TIME_MILLIS:
  95. if (type_ != AVRO_INT) {
  96. throw Exception("TIME-MILLIS logical type can only annotate "
  97. "INT type");
  98. }
  99. break;
  100. case LogicalType::TIME_MICROS:
  101. if (type_ != AVRO_LONG) {
  102. throw Exception("TIME-MICROS logical type can only annotate "
  103. "LONG type");
  104. }
  105. break;
  106. case LogicalType::TIMESTAMP_MILLIS:
  107. if (type_ != AVRO_LONG) {
  108. throw Exception("TIMESTAMP-MILLIS logical type can only annotate "
  109. "LONG type");
  110. }
  111. break;
  112. case LogicalType::TIMESTAMP_MICROS:
  113. if (type_ != AVRO_LONG) {
  114. throw Exception("TIMESTAMP-MICROS logical type can only annotate "
  115. "LONG type");
  116. }
  117. break;
  118. case LogicalType::DURATION:
  119. if (type_ != AVRO_FIXED || fixedSize() != 12) {
  120. throw Exception("DURATION logical type can only annotate "
  121. "FIXED type of size 12");
  122. }
  123. break;
  124. case LogicalType::UUID:
  125. if (type_ != AVRO_STRING) {
  126. throw Exception("UUID logical type can only annotate "
  127. "STRING type");
  128. }
  129. break;
  130. }
  131. logicalType_ = logicalType;
  132. }
  133. } // namespace avro