/src/java/org/apache/cassandra/cql/WhereClause.java

https://github.com/thepaul/cassandra · Java · 198 lines · 127 code · 24 blank · 47 comment · 21 complexity · b4c90471e7542d9ee58c888353c857ab MD5 · raw file

  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. * http://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. package org.apache.cassandra.cql;
  19. import java.nio.charset.CharacterCodingException;
  20. import java.util.ArrayList;
  21. import java.util.LinkedHashSet;
  22. import java.util.List;
  23. import java.util.Set;
  24. import org.apache.cassandra.config.CFMetaData;
  25. import org.apache.cassandra.utils.ByteBufferUtil;
  26. /**
  27. * WhereClauses encapsulate all of the predicates of a SELECT query.
  28. *
  29. */
  30. public class WhereClause
  31. {
  32. // all relations (except for `<key> IN (.., .., ..)` which can be directly interpreted) from parser
  33. // are stored into this array and are filtered to the keys/columns by extractKeysFromColumns(...)
  34. private final List<Relation> clauseRelations = new ArrayList<Relation>();
  35. private final List<Relation> columns = new ArrayList<Relation>();
  36. // added to either by the parser from an IN clause or by extractKeysFromColumns
  37. private final Set<Term> keys = new LinkedHashSet<Term>();
  38. private Term startKey, finishKey;
  39. private boolean includeStartKey = false, includeFinishKey = false, multiKey = false;
  40. // set by extractKeysFromColumns
  41. private String keyAlias = null;
  42. /**
  43. * Create a new WhereClause with the first parsed relation.
  44. *
  45. * @param firstRelation key or column relation
  46. */
  47. public WhereClause(Relation firstRelation)
  48. {
  49. and(firstRelation);
  50. }
  51. public WhereClause()
  52. {}
  53. /**
  54. * Add an additional relation to this WHERE clause.
  55. *
  56. * @param relation the relation to add.
  57. */
  58. public void and(Relation relation)
  59. {
  60. clauseRelations.add(relation);
  61. }
  62. /**
  63. * The same as KEY = <key> to avoid using Relation object
  64. * @param key key to include into clause
  65. */
  66. public void andKeyEquals(Term key)
  67. {
  68. keys.add(key);
  69. }
  70. public List<Relation> getColumnRelations()
  71. {
  72. return columns;
  73. }
  74. public boolean isKeyRange()
  75. {
  76. return startKey != null;
  77. }
  78. public Term getStartKey()
  79. {
  80. return startKey;
  81. }
  82. public Term getFinishKey()
  83. {
  84. return finishKey;
  85. }
  86. public Set<Term> getKeys()
  87. {
  88. return keys;
  89. }
  90. public boolean includeStartKey()
  91. {
  92. return includeStartKey;
  93. }
  94. public boolean includeFinishKey()
  95. {
  96. return includeFinishKey;
  97. }
  98. public void setKeyAlias(String alias)
  99. {
  100. keyAlias = alias.toUpperCase();
  101. }
  102. public boolean isMultiKey() {
  103. return multiKey;
  104. }
  105. public void setMultiKey(boolean multiKey)
  106. {
  107. this.multiKey = multiKey;
  108. }
  109. public String getKeyAlias()
  110. {
  111. // TODO fix special casing here, key alias should always be set post-extract
  112. // key alias as not related to keys in here, it can be unset when we have a query like
  113. // SELECT * FROM <CF> WHERE key = 1 and col > 2 and col < 3;
  114. // it will be always set when statement looks like this
  115. // SELECT * FROM <CF> WHERE <key> IN (.., .., ..);
  116. // key is NULL when KEY keyword is used or when key alias given by user was not recognized
  117. // validateKeyAlias will throw an exception for us in that case
  118. return keyAlias == null ? QueryProcessor.DEFAULT_KEY_NAME : keyAlias;
  119. }
  120. public void extractKeysFromColumns(CFMetaData cfm)
  121. {
  122. String realKeyAlias = null;
  123. try
  124. {
  125. // ThriftValidation ensures that key_alias is ascii
  126. realKeyAlias = ByteBufferUtil.string(cfm.getKeyName()).toUpperCase();
  127. }
  128. catch (CharacterCodingException e)
  129. {
  130. throw new RuntimeException(e);
  131. }
  132. if (!keys.isEmpty())
  133. return; // we already have key(s) set (<key> IN (.., ...) construction used)
  134. for (Relation relation : clauseRelations)
  135. {
  136. String name = relation.getEntity().getText().toUpperCase();
  137. if (name.equals(realKeyAlias))
  138. {
  139. if (keyAlias == null) // setting found key as an alias
  140. keyAlias = name;
  141. if (relation.operator() == RelationType.EQ)
  142. {
  143. keys.add(relation.getValue());
  144. }
  145. else if ((relation.operator() == RelationType.GT) || (relation.operator() == RelationType.GTE))
  146. {
  147. startKey = relation.getValue();
  148. includeStartKey = relation.operator() == RelationType.GTE;
  149. }
  150. else if ((relation.operator() == RelationType.LT) || (relation.operator() == RelationType.LTE))
  151. {
  152. finishKey = relation.getValue();
  153. includeFinishKey = relation.operator() == RelationType.LTE;
  154. }
  155. }
  156. else
  157. {
  158. columns.add(relation);
  159. }
  160. }
  161. }
  162. public String toString()
  163. {
  164. return String.format("WhereClause [keys=%s, startKey=%s, finishKey=%s, columns=%s, includeStartKey=%s, includeFinishKey=%s, multiKey=%s, keyAlias=%s]",
  165. keys,
  166. startKey,
  167. finishKey,
  168. columns,
  169. includeStartKey,
  170. includeFinishKey,
  171. multiKey,
  172. keyAlias);
  173. }
  174. }