YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ptree/pt_dml_write_property.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
#include "yb/yql/cql/ql/ptree/pt_dml_write_property.h"
14
15
#include <set>
16
17
#include "yb/client/schema.h"
18
#include "yb/util/string_case.h"
19
#include "yb/yql/cql/ql/ptree/pt_expr.h"
20
#include "yb/yql/cql/ql/ptree/sem_context.h"
21
#include "yb/yql/cql/ql/ptree/yb_location.h"
22
23
namespace yb {
24
namespace ql {
25
26
using strings::Substitute;
27
using client::YBColumnSchema;
28
29
// These property names need to be lowercase, since identifiers are converted to lowercase by the
30
// scanner phase and as a result if we're doing string matching everything should be lowercase.
31
const std::map<std::string, PTDmlWriteProperty::KVProperty> PTDmlWriteProperty::kPropertyDataTypes
32
    = {
33
    {"options", KVProperty::kOptions}
34
};
35
36
PTDmlWriteProperty::PTDmlWriteProperty(MemoryContext *memctx,
37
                                 YBLocation::SharedPtr loc,
38
                                 const MCSharedPtr<MCString>& lhs,
39
                                 const PTExprPtr& rhs)
40
    : PTProperty(memctx, loc, lhs, rhs),
41
56
      property_type_(DmlWritePropertyType::kDmlWriteProperty) {}
42
43
PTDmlWriteProperty::PTDmlWriteProperty(MemoryContext *memctx,
44
                                 YBLocation::SharedPtr loc)
45
56
    : PTProperty(memctx, loc) {
46
56
}
47
48
64
PTDmlWriteProperty::~PTDmlWriteProperty() {
49
64
}
50
51
0
CHECKED_STATUS PTDmlWriteProperty::Analyze(SemContext *sem_context) {
52
53
  // Verify we have a valid property name in the lhs.
54
0
  const auto& update_property_name = lhs_->c_str();
55
0
  auto iterator = kPropertyDataTypes.find(update_property_name);
56
0
  if (iterator == kPropertyDataTypes.end()) {
57
0
    return sem_context->Error(this, Substitute("Unknown property '$0'", lhs_->c_str()).c_str(),
58
0
                              ErrorCode::INVALID_UPDATE_PROPERTY);
59
0
  }
60
61
0
  if (iterator->second == KVProperty::kOptions) {
62
0
    return sem_context->Error(this,
63
0
                            Substitute("Invalid value for property '$0'. Value must be a map",
64
0
                                        update_property_name).c_str(),
65
0
                            ErrorCode::DATATYPE_MISMATCH);
66
0
  }
67
68
0
  return Status::OK();
69
0
}
70
71
0
std::ostream& operator<<(ostream& os, const DmlWritePropertyType& property_type) {
72
0
  switch(property_type) {
73
0
    case DmlWritePropertyType::kDmlWriteProperty:
74
0
      os << "kDmlWriteProperty";
75
0
      break;
76
0
    case DmlWritePropertyType::kDmlWritePropertyMap:
77
0
      os << "kDmlWritePropertyMap";
78
0
      break;
79
0
  }
80
0
  return os;
81
0
}
82
83
0
void PTDmlWriteProperty::PrintSemanticAnalysisResult(SemContext *sem_context) {
84
0
  VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail";
85
0
}
86
87
54
CHECKED_STATUS PTDmlWritePropertyListNode::Analyze(SemContext *sem_context) {
88
  // Set to ensure we don't have duplicate update properties.
89
54
  std::set<string> update_properties;
90
54
  std::unordered_map<string, PTDmlWriteProperty::SharedPtr> order_tnodes;
91
54
  vector<string> order_columns;
92
56
  for (PTDmlWriteProperty::SharedPtr tnode : node_list()) {
93
56
    if (tnode == nullptr) {
94
      // This shouldn't happen because AppendList ignores null nodes.
95
0
      LOG(ERROR) << "Invalid null property";
96
0
      continue;
97
0
    }
98
56
    switch(tnode->property_type()) {
99
0
      case DmlWritePropertyType::kDmlWriteProperty: FALLTHROUGH_INTENDED;
100
56
      case DmlWritePropertyType::kDmlWritePropertyMap: {
101
56
        string update_property_name = tnode->lhs()->c_str();
102
56
        if (update_properties.find(update_property_name) != update_properties.end()) {
103
2
          return sem_context->Error(this, ErrorCode::DUPLICATE_UPDATE_PROPERTY);
104
2
        }
105
54
        RETURN_NOT_OK(tnode->Analyze(sem_context));
106
52
        update_properties.insert(update_property_name);
107
52
        break;
108
54
      }
109
56
    }
110
56
  }
111
112
50
  return Status::OK();
113
54
}
114
115
220
bool PTDmlWritePropertyListNode::ignore_null_jsonb_attributes() {
116
220
  for (PTDmlWriteProperty::SharedPtr tnode : node_list()) {
117
220
    if (
tnode->property_type() == DmlWritePropertyType::kDmlWritePropertyMap219
) {
118
220
      string update_property_name = tnode->lhs()->c_str();
119
220
      if (update_property_name == "options") {
120
220
        return \
121
220
          (std::static_pointer_cast<PTDmlWritePropertyMap>(tnode))->ignore_null_jsonb_attributes();
122
220
      }
123
220
    }
124
219
  }
125
0
  return false; // the default
126
220
}
127
128
const std::map<string, PTDmlWritePropertyMap::PropertyMapType> \
129
  PTDmlWritePropertyMap::kPropertyDataTypes
130
    = {
131
    {"options", PTDmlWritePropertyMap::PropertyMapType::kOptions}
132
};
133
134
PTDmlWritePropertyMap::PTDmlWritePropertyMap(MemoryContext *memctx,
135
                                       YBLocation::SharedPtr loc)
136
56
    : PTDmlWriteProperty(memctx, loc) {
137
56
  property_type_ = DmlWritePropertyType::kDmlWritePropertyMap;
138
56
  map_elements_ = TreeListNode<PTDmlWriteProperty>::MakeShared(memctx, loc);
139
56
}
140
141
32
PTDmlWritePropertyMap::~PTDmlWritePropertyMap() {
142
32
}
143
144
54
CHECKED_STATUS PTDmlWritePropertyMap::Analyze(SemContext *sem_context) {
145
  // Verify we have a valid property name in the lhs.
146
54
  const auto &property_name = lhs_->c_str();
147
54
  auto iterator = kPropertyDataTypes.find(property_name);
148
54
  if (iterator == kPropertyDataTypes.end()) {
149
0
    if (IsValidProperty(property_name)) {
150
0
      return sem_context->Error(this, Substitute("Invalid map value for property '$0'",
151
0
                                                 property_name).c_str(),
152
0
                                ErrorCode::DATATYPE_MISMATCH);
153
0
    }
154
0
    return sem_context->Error(this, Substitute("Unknown property '$0'", property_name).c_str(),
155
0
                              ErrorCode::INVALID_UPDATE_PROPERTY);
156
0
  }
157
158
54
  const auto &property_type = iterator->second;
159
160
54
  switch (property_type) {
161
54
    case PropertyMapType::kOptions:
162
54
      RETURN_SEM_CONTEXT_ERROR_NOT_OK(AnalyzeOptions(sem_context));
163
52
      break;
164
54
  }
165
52
  return Status::OK();
166
54
}
167
168
0
void PTDmlWritePropertyMap::PrintSemanticAnalysisResult(SemContext *sem_context) {
169
0
  VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail";
170
0
}
171
172
56
Status PTDmlWritePropertyMap::AnalyzeOptions(SemContext *sem_context) {
173
56
  for (const auto& subproperty : map_elements_->node_list()) {
174
56
    string subproperty_name;
175
56
    ToLowerCase(subproperty->lhs()->c_str(), &subproperty_name);
176
56
    auto iter = Options::kSubpropertyDataTypes.find(subproperty_name);
177
56
    if (iter == Options::kSubpropertyDataTypes.end()) {
178
4
      return STATUS(InvalidArgument, Substitute("Unknown options property $0",
179
4
                                                subproperty_name));
180
4
    }
181
182
52
    bool bool_val;
183
52
    switch(iter->second) {
184
52
      case Options::Subproperty::kIgnoreNullJsonbAttributes:
185
52
        RETURN_NOT_OK(GetBoolValueFromExpr(subproperty->rhs(), subproperty_name, &bool_val));
186
52
        break;
187
52
    }
188
52
  }
189
52
  return Status::OK();
190
56
}
191
192
220
bool PTDmlWritePropertyMap::ignore_null_jsonb_attributes() {
193
220
  for (const auto& subproperty : map_elements_->node_list()) {
194
220
    string subproperty_name;
195
220
    ToLowerCase(subproperty->lhs()->c_str(), &subproperty_name);
196
220
    auto iter = Options::kSubpropertyDataTypes.find(subproperty_name);
197
220
    if (iter != Options::kSubpropertyDataTypes.end() &&
198
220
        iter->second == Options::Subproperty::kIgnoreNullJsonbAttributes) {
199
220
      return std::dynamic_pointer_cast<PTConstBool>(subproperty->rhs())->Eval();
200
220
    }
201
220
  }
202
0
  return false; // Default if the property isn't specified
203
220
}
204
205
const std::map<std::string, Options::Subproperty>
206
Options::kSubpropertyDataTypes = {
207
    {"ignore_null_jsonb_attributes", Options::Subproperty::kIgnoreNullJsonbAttributes}
208
};
209
210
} // namespace ql
211
} // namespace yb