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 if (logger.isDebugEnabled()) {
148 logger.debug("Coming inside genCreateTableQuery method " + this.getKeyspaceName());
149 logger.debug("Coming inside genCreateTableQuery method " + this.getTableName());
152 String primaryKey = null;
153 String partitionKey = this.getPartitionKey();
154 String clusterKey = this.getClusteringKey();
155 String filteringKey = this.getFilteringKey();
156 if (filteringKey != null) {
157 clusterKey = clusterKey + "," + filteringKey;
159 primaryKey = this.getPrimaryKey(); // get primaryKey if available
161 PreparedQueryObject queryObject = new PreparedQueryObject();
162 // first read the information about the table fields
163 Map<String, String> fields = this.getFields();
164 if (fields == null) {
165 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
166 .setError("Create Table Error: No fields in request").toMap()).build();*/
167 throw new MusicQueryException(
168 "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode());
170 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
172 for (Map.Entry<String, String> entry : fields.entrySet()) {
173 if (entry.getKey().equals("PRIMARY KEY")) {
174 primaryKey = entry.getValue(); // replaces primaryKey
175 primaryKey = primaryKey.trim();
177 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
178 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
181 if (counter != (fields.size() - 1) ) {
182 counter = counter + 1;
185 if((primaryKey != null) && (partitionKey == null)) {
186 primaryKey = primaryKey.trim();
187 int count1 = StringUtils.countMatches(primaryKey, ')');
188 int count2 = StringUtils.countMatches(primaryKey, '(');
189 if (count1 != count2) {
190 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
191 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
193 throw new MusicQueryException(
194 "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey,
195 Status.BAD_REQUEST.getStatusCode());
198 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
199 if (primaryKey.contains(",") ) {
200 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
201 partitionKey=partitionKey.replaceAll("[\\(]+","");
202 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
203 clusterKey=clusterKey.replaceAll("[)]+", "");
205 partitionKey=primaryKey;
206 partitionKey=partitionKey.replaceAll("[\\)]+","");
207 partitionKey=partitionKey.replaceAll("[\\(]+","");
210 } else { // not null and has ) before the last char
211 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
212 partitionKey=partitionKey.replaceAll("[\\(]+","");
213 partitionKey = partitionKey.trim();
214 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
215 clusterKey=clusterKey.replaceAll("[\\(]+","");
216 clusterKey=clusterKey.replaceAll("[\\)]+","");
217 clusterKey = clusterKey.trim();
218 if (clusterKey.indexOf(',') == 0) {
219 clusterKey=clusterKey.substring(1);
221 clusterKey = clusterKey.trim();
222 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
225 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
226 && (partitionKey.equalsIgnoreCase(clusterKey) ||
227 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
228 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
229 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
230 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
231 + " primary key=" + primaryKey)
233 throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey
234 + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key="
235 + primaryKey, Status.BAD_REQUEST.getStatusCode());
239 if (partitionKey.isEmpty() ) primaryKey="";
240 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
241 else primaryKey=" (" + partitionKey + ")," + clusterKey;
244 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
246 } else { // end of length > 0
248 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
249 && (partitionKey.equalsIgnoreCase(clusterKey) ||
250 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
251 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
252 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
253 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
255 throw new MusicQueryException(
256 "Create Table primary key error: clusterKey(" + clusterKey
257 + ") equals/contains/overlaps partitionKey(" + partitionKey + ")",
258 Status.BAD_REQUEST.getStatusCode());
261 if (partitionKey.isEmpty() ) primaryKey="";
262 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
263 else primaryKey=" (" + partitionKey + ")," + clusterKey;
265 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
267 fieldsString.append(")");
269 } // end of last field check
272 // information about the name-value style properties
273 Map<String, Object> propertiesMap = this.getProperties();
274 StringBuilder propertiesString = new StringBuilder();
275 if (propertiesMap != null) {
277 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
278 Object ot = entry.getValue();
279 String value = ot + "";
280 if (ot instanceof String) {
281 value = "'" + value + "'";
282 } else if (ot instanceof Map) {
283 @SuppressWarnings("unchecked")
284 Map<String, Object> otMap = (Map<String, Object>) ot;
286 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
287 } catch (Exception e) {
288 throw new MusicQueryException(e.getMessage(),
289 Status.BAD_REQUEST.getStatusCode());
293 propertiesString.append(entry.getKey() + "=" + value + "");
294 if (counter != propertiesMap.size() - 1)
295 propertiesString.append(" AND ");
297 counter = counter + 1;
301 String clusteringOrder = this.getClusteringOrder();
303 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
304 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
306 for (int i = 0; i < arrayClusterOrder.length; i++) {
307 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
308 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
311 /*return response.status(Status.BAD_REQUEST)
312 .entity(new JsonResponse(ResultType.FAILURE)
313 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
316 throw new MusicQueryException(
317 "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"
318 + clusteringOrder + ".",
319 Status.BAD_REQUEST.getStatusCode());
321 // add validation for column names in cluster key
324 if (!(clusterKey.isEmpty())) {
325 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
326 //cjc check if propertiesString.length() >0 instead propertiesMap
327 if (propertiesMap != null) {
328 propertiesString.append(" AND "+ clusteringOrder);
330 propertiesString.append(clusteringOrder);
333 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
337 queryObject.appendQueryString(
338 "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString);
341 if (propertiesString != null && propertiesString.length()>0 )
342 queryObject.appendQueryString(" WITH " + propertiesString);
343 queryObject.appendQueryString(";");
352 public PreparedQueryObject genCreateShadowLockingTableQuery() {
353 if (logger.isDebugEnabled()) {
354 logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getKeyspaceName());
355 logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getTableName());
358 String tableName = "unsyncedKeys_" + this.getTableName();
359 String tabQuery = "CREATE TABLE IF NOT EXISTS " + this.getKeyspaceName() + "." + tableName
360 + " ( key text,PRIMARY KEY (key) );";
361 PreparedQueryObject queryObject = new PreparedQueryObject();
362 queryObject.appendQueryString(tabQuery);
370 * @return PreparedQueryObject
372 public PreparedQueryObject genDropTableQuery() {
373 if (logger.isDebugEnabled()) {
374 logger.debug("Coming inside genDropTableQuery method " + this.getKeyspaceName());
375 logger.debug("Coming inside genDropTableQuery method " + this.getTableName());
378 PreparedQueryObject query = new PreparedQueryObject();
379 query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";");
380 logger.info("Delete Query ::::: " + query.getQuery());