/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ptree/pt_keyspace_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 | | |
14 | | #include <set> |
15 | | #include "yb/client/schema.h" |
16 | | #include "yb/yql/cql/ql/ptree/pt_keyspace_property.h" |
17 | | #include "yb/yql/cql/ql/ptree/sem_context.h" |
18 | | #include "yb/yql/cql/ql/ptree/yb_location.h" |
19 | | |
20 | | #include "yb/util/logging.h" |
21 | | #include "yb/util/string_case.h" |
22 | | |
23 | | namespace yb { |
24 | | namespace ql { |
25 | | |
26 | | using strings::Substitute; |
27 | | using client::YBColumnSchema; |
28 | | |
29 | | PTKeyspaceProperty::PTKeyspaceProperty(MemoryContext *memctx, |
30 | | YBLocation::SharedPtr loc, |
31 | | const MCSharedPtr<MCString>& lhs, |
32 | | const PTExprPtr& rhs) |
33 | | : PTProperty(memctx, loc, lhs, rhs), |
34 | 374 | property_type_(KeyspacePropertyType::kKVProperty) { |
35 | 374 | } |
36 | | |
37 | | PTKeyspaceProperty::PTKeyspaceProperty(MemoryContext *memctx, |
38 | | YBLocation::SharedPtr loc) |
39 | 172 | : PTProperty(memctx, loc) { |
40 | 172 | } |
41 | | |
42 | 288 | PTKeyspaceProperty::~PTKeyspaceProperty() { |
43 | 288 | } |
44 | | |
45 | 0 | CHECKED_STATUS PTKeyspaceProperty::Analyze(SemContext *sem_context) { |
46 | 0 | return Status::OK(); |
47 | 0 | } |
48 | | |
49 | 0 | void PTKeyspaceProperty::PrintSemanticAnalysisResult(SemContext *sem_context) { |
50 | 0 | VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail"; |
51 | 0 | } |
52 | | |
53 | 171 | CHECKED_STATUS PTKeyspacePropertyListNode::Analyze(SemContext *sem_context) { |
54 | 171 | bool has_replication = false; |
55 | | |
56 | | // If the statement has properties, 'replication' property must be present. Check this before |
57 | | // checking anything else. |
58 | 171 | for (PTKeyspaceProperty::SharedPtr tnode : node_list()) { |
59 | 171 | const auto property_name = string(tnode->lhs()->c_str()); |
60 | 171 | if (property_name == "replication") { |
61 | 163 | has_replication = true; |
62 | 163 | break; |
63 | 163 | } |
64 | 171 | } |
65 | 171 | if (!has_replication) { |
66 | 8 | return sem_context->Error(this, "Missing mandatory replication strategy class", |
67 | 8 | ErrorCode::INVALID_ARGUMENTS); |
68 | 8 | } |
69 | | |
70 | 193 | for (PTKeyspaceProperty::SharedPtr tnode : node_list())163 { |
71 | 193 | const auto property_name = string(tnode->lhs()->c_str()); |
72 | 193 | if (property_name == "durable_writes") { |
73 | 30 | bool val = false; |
74 | 30 | RETURN_SEM_CONTEXT_ERROR_NOT_OK(PTProperty::GetBoolValueFromExpr(tnode->rhs(), |
75 | 30 | "durable_writes", &val)); |
76 | 163 | } else if (property_name == "replication") { |
77 | 163 | if (tnode->property_type() != KeyspacePropertyType::kPropertyMap) { |
78 | 0 | return sem_context->Error(this, |
79 | 0 | "Invalid value for property 'replication'. It should be a map", |
80 | 0 | ErrorCode::INVALID_ARGUMENTS); |
81 | 0 | } |
82 | 163 | RETURN_SEM_CONTEXT_ERROR_NOT_OK(tnode->Analyze(sem_context)); |
83 | 163 | } else { |
84 | 0 | return sem_context->Error(this, |
85 | 0 | Substitute("Invalid property $0", property_name).c_str(), |
86 | 0 | ErrorCode::INVALID_ARGUMENTS); |
87 | 0 | } |
88 | 193 | } |
89 | 128 | return Status::OK(); |
90 | 163 | } |
91 | | |
92 | | PTKeyspacePropertyMap::PTKeyspacePropertyMap(MemoryContext *memctx, |
93 | | YBLocation::SharedPtr loc) |
94 | 172 | : PTKeyspaceProperty(memctx, loc) { |
95 | 172 | property_type_ = KeyspacePropertyType::kPropertyMap; |
96 | 172 | map_elements_ = TreeListNode<PTKeyspaceProperty>::MakeShared(memctx, loc); |
97 | 172 | } |
98 | | |
99 | 86 | PTKeyspacePropertyMap::~PTKeyspacePropertyMap() { |
100 | 86 | } |
101 | | |
102 | 194 | CHECKED_STATUS PTKeyspacePropertyMap::Analyze(SemContext *sem_context) { |
103 | 194 | DCHECK_ONLY_NOTNULL(lhs_.get()); |
104 | | // Verify we have a valid property name in the lhs. |
105 | 194 | const auto property_name = string(lhs_->c_str()); |
106 | 194 | DCHECK_EQ(property_name, "replication"); |
107 | | // Find 'class' subproperty. |
108 | 194 | std::unique_ptr<string> class_name = nullptr; |
109 | 194 | std::unique_ptr<int64_t> replication_factor = nullptr; |
110 | 194 | vector<PTKeyspaceProperty::SharedPtr> other_subproperties; |
111 | | |
112 | 378 | for (const auto &map_element : map_elements_->node_list()) { |
113 | 378 | string subproperty_name; |
114 | 378 | ToLowerCase(map_element->lhs()->c_str(), &subproperty_name); |
115 | | |
116 | 378 | if (subproperty_name == "class") { |
117 | 194 | class_name.reset(new string()); |
118 | 194 | RETURN_NOT_OK(GetStringValueFromExpr(map_element->rhs(), false, "class", class_name.get())); |
119 | 194 | } else if (184 subproperty_name == "replication_factor"184 ) { |
120 | 164 | replication_factor.reset(new int64_t); |
121 | 164 | RETURN_NOT_OK(GetIntValueFromExpr(map_element->rhs(), "replication_factor", |
122 | 164 | replication_factor.get())); |
123 | 164 | } else { |
124 | 20 | other_subproperties.push_back(map_element); |
125 | 20 | } |
126 | 378 | } |
127 | | |
128 | 162 | if (class_name == nullptr) { |
129 | 0 | return sem_context->Error(this, "Missing mandatory replication strategy class", |
130 | 0 | ErrorCode::INVALID_ARGUMENTS); |
131 | 0 | } |
132 | | |
133 | 162 | if (*class_name != "SimpleStrategy" && *class_name != "NetworkTopologyStrategy"28 ) { |
134 | 10 | return sem_context->Error(this, |
135 | 10 | Substitute("Unable to find replication strategy class 'org.apache.cassandra.locator.$0", |
136 | 10 | *class_name).c_str(), |
137 | 10 | ErrorCode::INVALID_ARGUMENTS); |
138 | 10 | } |
139 | 152 | if (*class_name == "NetworkTopologyStrategy") { |
140 | 18 | if (replication_factor != nullptr) { |
141 | 8 | return sem_context->Error(this, |
142 | 8 | "replication_factor is an option for SimpleStrategy, not NetworkTopologyStrategy", |
143 | 8 | ErrorCode::INVALID_ARGUMENTS); |
144 | 8 | } |
145 | | |
146 | | // Verify that all subproperties have integer values. |
147 | 10 | int64_t val = 0; |
148 | 12 | for (const auto& subproperty : other_subproperties) { |
149 | 12 | RETURN_NOT_OK(GetIntValueFromExpr(subproperty->rhs(), subproperty->lhs()->c_str(), &val)); |
150 | 12 | } |
151 | 134 | } else { |
152 | 134 | if (!other_subproperties.empty()) { |
153 | 4 | return sem_context->Error(this, |
154 | 4 | Substitute( |
155 | 4 | "Unrecognized strategy option $0 passed to SimpleStrategy", |
156 | 4 | other_subproperties.front()->lhs()->c_str()).c_str(), |
157 | 4 | ErrorCode::INVALID_ARGUMENTS); |
158 | | |
159 | 4 | } |
160 | 130 | if (replication_factor == nullptr) { |
161 | 4 | return sem_context->Error(this, |
162 | 4 | "SimpleStrategy requires a replication_factor strategy option", |
163 | 4 | ErrorCode::INVALID_ARGUMENTS); |
164 | 4 | } |
165 | 130 | } |
166 | | |
167 | 132 | return Status::OK(); |
168 | 152 | } |
169 | | |
170 | 0 | void PTKeyspacePropertyMap::PrintSemanticAnalysisResult(SemContext *sem_context) { |
171 | 0 | VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail"; |
172 | 0 | } |
173 | | |
174 | | } // namespace ql |
175 | | } // namespace yb |