2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (C) 2019 IBM
8 * ===================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.datastore.jsonobjects;
29 import javax.ws.rs.core.Response.Status;
31 import org.apache.commons.lang3.StringUtils;
32 import org.onap.music.datastore.PreparedQueryObject;
33 import org.onap.music.eelf.logging.EELFLoggerDelegate;
34 import org.onap.music.exceptions.MusicQueryException;
35 import org.onap.music.main.MusicUtil;
37 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
39 import io.swagger.annotations.ApiModel;
40 import io.swagger.annotations.ApiModelProperty;
42 @ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.")
43 @JsonIgnoreProperties(ignoreUnknown = true)
44 public class JsonTable {
45 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonTable.class);
47 private String keyspaceName;
48 private String tableName;
50 private Map<String, String> fields;
51 private Map<String, Object> properties;
52 private String primaryKey;
53 private String partitionKey;
54 private String clusteringKey;
55 private String filteringKey;
56 private String clusteringOrder;
57 private Map<String, String> consistencyInfo;
59 @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
60 public Map<String, String> getConsistencyInfo() {
61 return consistencyInfo;
64 public void setConsistencyInfo(Map<String, String> consistencyInfo) {
65 this.consistencyInfo = consistencyInfo;
68 @ApiModelProperty(value = "Properties")
69 public Map<String, Object> getProperties() {
73 public void setProperties(Map<String, Object> properties) {
74 this.properties = properties;
77 @ApiModelProperty(value = "Fields")
78 public Map<String, String> getFields() {
82 public void setFields(Map<String, String> fields) {
86 @ApiModelProperty(value = "KeySpace Name")
87 public String getKeyspaceName() {
91 public void setKeyspaceName(String keyspaceName) {
92 this.keyspaceName = keyspaceName;
95 @ApiModelProperty(value = "Table Name")
96 public String getTableName() {
100 public void setTableName(String tableName) {
101 this.tableName = tableName;
104 @ApiModelProperty(value = "Clustering Order", notes = "")
105 public String getClusteringOrder() {
106 return clusteringOrder;
109 public void setClusteringOrder(String clusteringOrder) {
110 this.clusteringOrder = clusteringOrder;
113 @ApiModelProperty(value = "Primary Key")
114 public String getPrimaryKey() {
118 public void setPrimaryKey(String primaryKey) {
119 this.primaryKey = primaryKey;
122 public String getClusteringKey() {
123 return clusteringKey;
126 public void setClusteringKey(String clusteringKey) {
127 this.clusteringKey = clusteringKey;
130 public String getFilteringKey() {
134 public void setFilteringKey(String filteringKey) {
135 this.filteringKey = filteringKey;
138 public String getPartitionKey() {
142 public void setPartitionKey(String partitionKey) {
143 this.partitionKey = partitionKey;
146 public PreparedQueryObject genCreateTableQuery() throws MusicQueryException {
147 String primaryKey = null;
148 String partitionKey = this.getPartitionKey();
149 String clusterKey = this.getClusteringKey();
150 String filteringKey = this.getFilteringKey();
151 if (filteringKey != null) {
152 clusterKey = clusterKey + "," + filteringKey;
154 primaryKey = this.getPrimaryKey(); // get primaryKey if available
156 PreparedQueryObject queryObject = new PreparedQueryObject();
157 // first read the information about the table fields
158 Map<String, String> fields = this.getFields();
159 if (fields == null) {
160 throw new MusicQueryException(
161 "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode());
163 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
165 for (Map.Entry<String, String> entry : fields.entrySet()) {
166 if (entry.getKey().equals("PRIMARY KEY")) {
167 primaryKey = entry.getValue(); // replaces primaryKey
168 primaryKey = primaryKey.trim();
172 fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
173 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
176 if (counter != (fields.size() - 1) ) {
177 counter = counter + 1;
180 if((primaryKey != null) && (partitionKey == null)) {
181 primaryKey = primaryKey.trim();
182 int count1 = StringUtils.countMatches(primaryKey, ')');
183 int count2 = StringUtils.countMatches(primaryKey, '(');
184 if (count1 != count2) {
185 throw new MusicQueryException(
186 "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey,
187 Status.BAD_REQUEST.getStatusCode());
190 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
191 if (primaryKey.contains(",") ) {
192 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
193 partitionKey=partitionKey.replaceAll("[\\(]+","");
194 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
195 clusterKey=clusterKey.replaceAll("[)]+", "");
197 partitionKey=primaryKey;
198 partitionKey=partitionKey.replaceAll("[\\)]+","");
199 partitionKey=partitionKey.replaceAll("[\\(]+","");
202 } else { // not null and has ) before the last char
203 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
204 partitionKey=partitionKey.replaceAll("[\\(]+","");
205 partitionKey = partitionKey.trim();
206 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
207 clusterKey=clusterKey.replaceAll("[\\(]+","");
208 clusterKey=clusterKey.replaceAll("[\\)]+","");
209 clusterKey = clusterKey.trim();
210 if (clusterKey.indexOf(',') == 0) {
211 clusterKey=clusterKey.substring(1);
213 clusterKey = clusterKey.trim();
214 if (clusterKey.equals(",") )
215 clusterKey=""; // print error if needed ( ... ),)
218 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
219 && (partitionKey.equalsIgnoreCase(clusterKey) ||
220 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
221 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
222 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
223 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
224 + " primary key=" + primaryKey)
226 throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey
227 + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key="
228 + primaryKey, Status.BAD_REQUEST.getStatusCode());
232 if (partitionKey.isEmpty() )
234 else if (clusterKey.isEmpty() )
235 primaryKey=" (" + partitionKey + ")";
237 primaryKey=" (" + partitionKey + ")," + clusterKey;
240 if (primaryKey != null)
241 fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
243 } else { // end of length > 0
245 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
246 && (partitionKey.equalsIgnoreCase(clusterKey) ||
247 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
248 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
249 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
250 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
252 throw new MusicQueryException(
253 "Create Table primary key error: clusterKey(" + clusterKey
254 + ") equals/contains/overlaps partitionKey(" + partitionKey + ")",
255 Status.BAD_REQUEST.getStatusCode());
258 if (partitionKey.isEmpty() )
260 else if (clusterKey.isEmpty() )
261 primaryKey=" (" + partitionKey + ")";
263 primaryKey=" (" + partitionKey + ")," + clusterKey;
265 if (primaryKey != null)
266 fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
268 fieldsString.append(")");
270 } // end of last field check
273 // information about the name-value style properties
274 Map<String, Object> propertiesMap = this.getProperties();
275 StringBuilder propertiesString = new StringBuilder();
276 if (propertiesMap != null) {
278 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
279 Object ot = entry.getValue();
280 String value = ot + "";
281 if (ot instanceof String) {
282 value = "'" + value + "'";
283 } else if (ot instanceof Map) {
284 @SuppressWarnings("unchecked")
285 Map<String, Object> otMap = (Map<String, Object>) ot;
287 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
288 } catch (Exception e) {
289 throw new MusicQueryException(e.getMessage(),
290 Status.BAD_REQUEST.getStatusCode());
294 propertiesString.append(entry.getKey() + "=" + value + "");
295 if (counter != propertiesMap.size() - 1)
296 propertiesString.append(" AND ");
298 counter = counter + 1;
302 String clusteringOrder = this.getClusteringOrder();
304 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
305 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
307 for (int i = 0; i < arrayClusterOrder.length; i++) {
308 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
309 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
312 /*return response.status(Status.BAD_REQUEST)
313 .entity(new JsonResponse(ResultType.FAILURE)
314 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
317 throw new MusicQueryException(
318 "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"
319 + clusteringOrder + ".",
320 Status.BAD_REQUEST.getStatusCode());
322 // add validation for column names in cluster key
325 if (!(clusterKey.isEmpty())) {
326 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
327 //cjc check if propertiesString.length() >0 instead propertiesMap
328 if (propertiesMap != null) {
329 propertiesString.append(" AND "+ clusteringOrder);
331 propertiesString.append(clusteringOrder);
334 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
338 queryObject.appendQueryString(
339 "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString);
342 if (propertiesString != null && propertiesString.length()>0 )
343 queryObject.appendQueryString(" WITH " + propertiesString);
344 queryObject.appendQueryString(";");
352 * @return PreparedQueryObject
354 public PreparedQueryObject genDropTableQuery() {
355 PreparedQueryObject query = new PreparedQueryObject();
356 query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";");
357 logger.info("Delete Query ::::: " + query.getQuery());