cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From eev...@apache.org
Subject svn commit: r1034532 - in /cassandra/trunk: src/java/org/apache/cassandra/cql/ test/system/
Date Fri, 12 Nov 2010 19:32:33 GMT
Author: eevans
Date: Fri Nov 12 19:32:32 2010
New Revision: 1034532

URL: http://svn.apache.org/viewvc?rev=1034532&view=rev
Log:
refactor CQL SELECT to be more SQLish

Patch by eevans

Added:
    cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java
Modified:
    cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/Relation.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/SelectExpression.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
    cassandra/trunk/test/system/test_cql.py

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g Fri Nov 12 19:32:32 2010
@@ -65,30 +65,19 @@ useStatement returns [String keyspace]
 selectStatement returns [SelectStatement expr]
     : { 
           int numRecords = 10000;
-          int numColumns = 10000;
-          boolean reversed = false;
           ConsistencyLevel cLevel = ConsistencyLevel.ONE;
       }
-      K_SELECT K_FROM? IDENT
-          (K_USING K_CONSISTENCY '.' K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text);
})?
-          K_WHERE selectExpression
-          (limit=(K_ROWLIMIT | K_COLLIMIT) value=INTEGER
-              { 
-                  int count = Integer.parseInt($value.text);
-                  if ($limit.type == K_ROWLIMIT)
-                      numRecords = count;
-                  else
-                      numColumns = count;
-              }
-          )*
-          order=(K_ASC | K_DESC { reversed = true; })? endStmnt
+      K_SELECT selectExpression K_FROM columnFamily=IDENT
+          ( K_USING K_CONSISTENCY '.' K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text);
} )?
+          ( K_WHERE whereClause )?
+          ( K_LIMIT rows=INTEGER { numRecords = Integer.parseInt($rows.text); } )?
+          endStmnt
       {
-          return new SelectStatement($IDENT.text,
+          return new SelectStatement($selectExpression.expr,
+                                     $columnFamily.text,
                                      cLevel,
-                                     $selectExpression.expr,
-                                     numRecords,
-                                     numColumns,
-                                     reversed);
+                                     $whereClause.clause,
+                                     numRecords);
       }
     ;
 
@@ -116,16 +105,32 @@ term returns [Term item]
       { $item = new Term($t.text, $t.type); }
     ;
 
-// Note: slices are inclusive so >= and >, and < and <= all have the same semantics.
 
+// Note: ranges are inclusive so >= and >, and < and <= all have the same semantics.
 
 relation returns [Relation rel]
-    : kind=(K_KEY | K_COLUMN) type=('=' | '<' | '<=' | '>=' | '>') t=term
-      { return new Relation($kind.text, $type.text, $t.item); }
+    : { Term entity = new Term("KEY", STRING_LITERAL); }
+      (K_KEY | name=term { entity = $name.item; } ) type=('=' | '<' | '<=' | '>='
| '>') t=term
+      { return new Relation(entity, $type.text, $t.item); }
     ;
 
 // relation [[AND relation] ...]
+whereClause returns [WhereClause clause]
+    : first=relation { $clause = new WhereClause(first); } 
+          (K_AND next=relation { $clause.and(next); })*
+    ;
+
+// [FIRST n] [REVERSED] name1[[[,name2],nameN],...]
+// [FIRST n] [REVERSED] name1..nameN
 selectExpression returns [SelectExpression expr]
-    : first=relation { $expr = new SelectExpression(first); } 
-          (K_AND next=relation { $expr.and(next); })*
+    : {
+          int count = 10000;
+          boolean reversed = false;
+      }
+      ( K_FIRST cols=INTEGER { count = Integer.parseInt($cols.text); } )?
+      ( K_REVERSED { reversed = true; } )?
+      ( first=term { $expr = new SelectExpression(first, count, reversed); }
+            (',' next=term { $expr.and(next); })*
+      | start=term '..' finish=term { $expr = new SelectExpression(start, finish, count,
reversed); }
+      )
     ;
 
 columnDef returns [Column column]
@@ -151,14 +156,10 @@ K_COLUMN:      C O L (U M N)?;
 K_UPDATE:      U P D A T E;
 K_WITH:        W I T H;
 K_ROW:         R O W;
-K_ROWLIMIT:    R O W L I M I T;
-K_COLLIMIT:    C O L L I M I T;
-K_ASC:         A S C (E N D I N G)?;
-K_DESC:        D E S C (E N D I N G)?;
+K_LIMIT:       L I M I T;
 K_USING:       U S I N G;
 K_CONSISTENCY: C O N S I S T E N C Y;
-K_LEVEL:       ( Z E R O
-               | O N E 
+K_LEVEL:       ( O N E 
                | Q U O R U M 
                | A L L 
                | D C Q U O R U M 
@@ -166,6 +167,8 @@ K_LEVEL:       ( Z E R O
                )
                ;
 K_USE:         U S E;
+K_FIRST:       F I R S T;
+K_REVERSED:    R E V E R S E D;
 
 // Case-insensitive alpha characters
 fragment A: ('a'|'A');

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java Fri Nov 12 19:32:32
2010
@@ -65,38 +65,37 @@ public class QueryProcessor
 {
     private static final Logger logger = LoggerFactory.getLogger(QueryProcessor.class);
     
-    private static List<org.apache.cassandra.db.Row> multiSlice(String keyspace, SelectStatement
select)
+    private static List<org.apache.cassandra.db.Row> getSlice(String keyspace, SelectStatement
select)
     throws InvalidRequestException, TimedOutException, UnavailableException
     {
         List<org.apache.cassandra.db.Row> rows = null;
         QueryPath queryPath = new QueryPath(select.getColumnFamily());
         List<ReadCommand> commands = new ArrayList<ReadCommand>();
         
-        for (Term keyName : select.getKeyPredicates().getTerms())
+        assert select.getKeys().size() == 1;
+        
+        ByteBuffer key = select.getKeys().get(0).getByteBuffer();
+        validateKey(key);
+        
+        // ...of a list of column names
+        if (!select.isColumnRange())
         {
-            ByteBuffer key = keyName.getByteBuffer();
-            validateKey(key);
+            Collection<ByteBuffer> columnNames = new ArrayList<ByteBuffer>();
+            for (Term column : select.getColumnNames())
+                columnNames.add(column.getByteBuffer());
             
-            // ...of a list of column names
-            if ((!select.getColumnPredicates().isRange()) && select.getColumnPredicates().isInitialized())
-            {
-                Collection<ByteBuffer> columnNames = new ArrayList<ByteBuffer>();
-                for (Term column : select.getColumnPredicates().getTerms())
-                    columnNames.add(column.getByteBuffer());
-                
-                commands.add(new SliceByNamesReadCommand(keyspace, key, queryPath, columnNames));
-            }
-            // ...a range (slice) of column names
-            else
-            {
-                commands.add(new SliceFromReadCommand(keyspace,
-                                                      key,
-                                                      queryPath,
-                                                      select.getColumnPredicates().getStart().getByteBuffer(),
-                                                      select.getColumnPredicates().getFinish().getByteBuffer(),
-                                                      select.reversed(),
-                                                      select.getNumColumns()));
-            }
+            commands.add(new SliceByNamesReadCommand(keyspace, key, queryPath, columnNames));
+        }
+        // ...a range (slice) of column names
+        else
+        {
+            commands.add(new SliceFromReadCommand(keyspace,
+                                                  key,
+                                                  queryPath,
+                                                  select.getColumnStart().getByteBuffer(),
+                                                  select.getColumnFinish().getByteBuffer(),
+                                                  select.isColumnsReversed(),
+                                                  select.getColumnsLimit()));
         }
 
         try
@@ -135,24 +134,25 @@ public class QueryProcessor
         // FIXME: ranges can be open-ended, but a start must exist.  Assert so here.
         
         IPartitioner<?> p = StorageService.getPartitioner();
-        AbstractBounds bounds = new Bounds(p.getToken(select.getKeyPredicates().getStart().getByteBuffer()),
-                                           p.getToken(select.getKeyPredicates().getFinish().getByteBuffer()));
+        AbstractBounds bounds = new Bounds(p.getToken(select.getKeyStart().getByteBuffer()),
+                                           p.getToken(select.getKeyFinish().getByteBuffer()));
+        
         
         // XXX: Our use of Thrift structs internally makes me Sad. :(
         SlicePredicate thriftSlicePredicate = new SlicePredicate();
-        if (select.getColumnPredicates().isRange() || select.getColumnPredicates().getTerms().size()
== 0)
+        if (select.isColumnRange() || select.getColumnNames().size() == 0)
         {
             SliceRange sliceRange = new SliceRange();
-            sliceRange.start = select.getColumnPredicates().getStart().getByteBuffer();
-            sliceRange.finish = select.getColumnPredicates().getFinish().getByteBuffer();
+            sliceRange.start = select.getColumnStart().getByteBuffer();
+            sliceRange.finish = select.getColumnFinish().getByteBuffer();
             sliceRange.reversed = false;    // FIXME: hard-coded
-            sliceRange.count = select.getNumColumns();
+            sliceRange.count = select.getColumnsLimit();
             thriftSlicePredicate.slice_range = sliceRange;
         }
         else
         {
             List<ByteBuffer> columnNames = new ArrayList<ByteBuffer>();
-            for (Term column : select.getColumnPredicates().getTerms())
+            for (Term column : select.getColumnNames())
                 columnNames.add(column.getByteBuffer());
             thriftSlicePredicate.column_names = columnNames;
         }
@@ -204,10 +204,31 @@ public class QueryProcessor
                 avroResult.type = CqlResultType.ROWS;
                 List<org.apache.cassandra.db.Row> rows = null;
                 
-                if (!select.getKeyPredicates().isRange())
-                    rows = multiSlice(keyspace, select);
+                if (!select.isKeyRange() && (select.getKeys().size() > 0))
+                {
+                    // Multiple keys (aka "multiget") is not allowed( any longer).
+                    if (select.getKeys().size() > 1)
+                    {
+                        InvalidRequestException invalidRequest = new InvalidRequestException();
+                        invalidRequest.why = "SELECTs can contain only one by-key clause
(i.e. KEY = TERM)";
+                        throw invalidRequest;
+                    }
+                    
+                    rows = getSlice(keyspace, select);
+                }
                 else
+                {
+                    // Combining key ranges and column index queries is not currently allowed
+                    if (select.getColumnRelations().size() > 0)
+                    {
+                        InvalidRequestException invalidRequest = new InvalidRequestException();
+                        invalidRequest.why = "You cannot combine key ranges and by-column
clauses " +
+                        		"(i.e. \"name\" = \"value\") in a SELECT statement";
+                        throw invalidRequest;
+                    }
+                    
                     rows = multiRangeSlice(keyspace, select);
+                }
                 
                 // Create the result set
                 for (org.apache.cassandra.db.Row row : rows)

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/Relation.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/Relation.java?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/Relation.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/Relation.java Fri Nov 12 19:32:32 2010
@@ -22,14 +22,15 @@ package org.apache.cassandra.cql;
 
 /**
  * Relations encapsulate the relationship between an entity of some kind, and
- * a value (term). For example, KEY > 'start' or COLUMN = 1000L.
+ * a value (term). For example, KEY > "start" or "colname1" = "somevalue".
  *
  */
 public class Relation
 {
-    public Entity entity = Entity.COLUMN;
-    public RelationType type;
-    public Term value;
+    public EntityType entityType = EntityType.COLUMN;
+    public Term entity;
+    private RelationType relationType;
+    private Term value;
     
     /**
      * Creates a new relation.
@@ -38,27 +39,38 @@ public class Relation
      * @param type the type that describes how this entity relates to the value.
      * @param value the value being compared.
      */
-    public Relation(String entity, String type, Term value)
+    public Relation(Term entity, String type, Term value)
     {
-        if (entity.toUpperCase().equals("KEY"))
-            this.entity = Entity.KEY;
+        if (entity.getText().toUpperCase().equals("KEY"))
+            this.entityType = EntityType.KEY;
         
-        this.type = RelationType.forString(type);
+        this.entity = entity;
+        this.relationType = RelationType.forString(type);
         this.value = value;
     }
     
     public boolean isKey()
     {
-        return entity.equals(Entity.KEY);
+        return entityType.equals(EntityType.KEY);
     }
     
     public boolean isColumn()
     {
-        return entity.equals(Entity.COLUMN);
+        return entityType.equals(EntityType.COLUMN);
+    }
+    
+    public RelationType operator()
+    {
+        return relationType;
+    }
+    
+    public Term getValue()
+    {
+        return value;
     }
 }
 
-enum Entity
+enum EntityType
 {
     KEY, COLUMN;
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/SelectExpression.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/SelectExpression.java?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/SelectExpression.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/SelectExpression.java Fri Nov 12 19:32:32
2010
@@ -1,4 +1,3 @@
-package org.apache.cassandra.cql;
 /*
  * 
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,122 +18,111 @@ package org.apache.cassandra.cql;
  * under the License.
  * 
  */
-
+package org.apache.cassandra.cql;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * SelectExpressions encapsulate all of the predicates of a SELECT query.
+ * Select expressions are analogous to the projection in a SQL query. They
+ * determine which columns will appear in the result set.  SelectExpression
+ * instances encapsulate a parsed expression from a <code>SELECT</code>
+ * statement.
  * 
- * @author eevans
- *
+ * See: doc/cql/CQL.html#SpecifyingColumns
  */
 public class SelectExpression
 {
-    private Predicates keys = new Predicates();
-    private Predicates columns = new Predicates();
+    public static final int MAX_COLUMNS_DEFAULT = 10000;
     
-    public SelectExpression(Relation firstRelation)
+    private int numColumns = MAX_COLUMNS_DEFAULT;
+    private boolean reverseColumns = false;
+    private Term start, finish;
+    private List<Term> columns;
+    
+    /**
+     * Create a new SelectExpression for a range (slice) of columns.
+     * 
+     * @param start the starting column name
+     * @param finish the finishing column name
+     * @param count the number of columns to limit the results to
+     * @param reverse true to reverse column order
+     */
+    public SelectExpression(Term start, Term finish, int count, boolean reverse)
     {
-        and(firstRelation);
+        this.start = start;
+        this.finish = finish;
+        numColumns = count;
+        reverseColumns = reverse;
     }
     
-    public void and(Relation relation)
+    /**
+     * Create a new SelectExpression for a list of columns.
+     * 
+     * @param first the first (possibly only) column name to select on.
+     * @param count the number of columns to limit the results on
+     * @param reverse true to reverse column order
+     */
+    public SelectExpression(Term first, int count, boolean reverse)
     {
-        if (relation.isKey())
-        {
-            if (relation.type.equals(RelationType.EQ))
-                keys.addTerm(relation.value);
-            else if ((relation.type.equals(RelationType.GT) || relation.type.equals(RelationType.GTE)))
-                keys.setStart(relation.value);
-            else if ((relation.type.equals(RelationType.LT) || relation.type.equals(RelationType.LTE)))
-                keys.setFinish(relation.value);
-        }
-        else    // It's a column
-        {
-            if (relation.type.equals(RelationType.EQ))
-                columns.addTerm(relation.value);
-            else if ((relation.type.equals(RelationType.GT) || relation.type.equals(RelationType.GTE)))
-                columns.setStart(relation.value);
-            else if ((relation.type.equals(RelationType.LT) || relation.type.equals(RelationType.LTE)))
-                columns.setFinish(relation.value);
-        }
+        columns = new ArrayList<Term>();
+        columns.add(first);
+        numColumns = count;
+        reverseColumns = reverse;
     }
     
-    public Predicates getKeyPredicates()
+    /**
+     * Add an additional column name to a SelectExpression.
+     * 
+     * @param addTerm
+     */
+    public void and(Term addTerm)
     {
-        return keys;
+        assert !isColumnRange();    // Not possible when invoked by parser
+        columns.add(addTerm);
     }
     
-    public Predicates getColumnPredicates()
+    public boolean isColumnRange()
     {
-        return columns;
+        return (start != null);
     }
-}
-
-class Predicates
-{
-    private boolean initialized = false;
-    private List<Term> names = new ArrayList<Term>();
-    private Term start, finish;
-    private boolean isRange = false;
     
-    Term getStart()
+    public boolean isColumnList()
     {
-        return start == null ? new Term() : start;
+        return !isColumnRange();
     }
-    
-    void setStart(Term start)
+    public int getColumnsLimit()
     {
-        // FIXME: propagate a proper exception
-        if (initialized && (!isRange()))
-            throw new RuntimeException("You cannot combine discreet names and range operators.");
-        
-        initialized = true;
-        isRange = true;
-        this.start = start;
+        return numColumns;
     }
-    
-    Term getFinish()
+
+    public boolean isColumnsReversed()
     {
-        return finish == null ? new Term() : finish;
+        return reverseColumns;
     }
     
-    void setFinish(Term finish)
+    public void setColumnsReversed(boolean reversed)
     {
-        // FIXME: propagate a proper exception
-        if (initialized && (!isRange()))
-            throw new RuntimeException("You cannot combine discreet names and range operators.");
-        
-        initialized = true;
-        isRange = true;
-        this.finish = finish;
+        reverseColumns = reversed;
     }
     
-    List<Term> getTerms()
+    public void setColumnsLimit(int limit)
     {
-        return names;
+        numColumns = limit;
     }
-    
-    void addTerm(Term name)
+
+    public Term getStart()
     {
-        // FIXME: propagate a proper exception
-        if (initialized && (isRange()))
-            throw new RuntimeException("You cannot combine discreet names and range operators.");
-        
-        initialized = true;
-        isRange = false;
-        names.add(name);
+        return start;
     }
-    
-    boolean isRange()
+
+    public Term getFinish()
     {
-        return isRange;
+        return finish;
     }
 
-    boolean isInitialized()
+    public List<Term> getColumns()
     {
-        return initialized;
+        return columns;
     }
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java Fri Nov 12 19:32:32
2010
@@ -20,6 +20,8 @@
  */
 package org.apache.cassandra.cql;
 
+import java.util.List;
+
 import org.apache.cassandra.thrift.ConsistencyLevel;
 
 /**
@@ -29,32 +31,65 @@ import org.apache.cassandra.thrift.Consi
  */
 public class SelectStatement
 {
+    private final SelectExpression expression;
     private final String columnFamily;
     private final ConsistencyLevel cLevel;
-    private final SelectExpression expression;
+    private final WhereClause clause;
     private final int numRecords;
-    private final int numColumns;
-    private final boolean reverse;
     
-    public SelectStatement(String columnFamily, ConsistencyLevel cLevel, SelectExpression
expression,
-            int numRecords, int numColumns, boolean reverse)
+    public SelectStatement(SelectExpression expression, String columnFamily, ConsistencyLevel
cLevel,
+            WhereClause clause, int numRecords)
     {
+        this.expression = expression;
         this.columnFamily = columnFamily;
         this.cLevel = cLevel;
-        this.expression = expression;
+        this.clause = clause;
         this.numRecords = numRecords;
-        this.numColumns = numColumns;
-        this.reverse = reverse;
     }
     
-    public Predicates getKeyPredicates()
+    public boolean isKeyRange()
+    {
+        return clause.isKeyRange();
+    }
+    
+    public List<Term> getKeys()
+    {
+        return clause.getKeys();
+    }
+    
+    public Term getKeyStart()
+    {
+        return clause.getStartKey();
+    }
+    
+    public Term getKeyFinish()
+    {
+        return clause.getFinishKey();
+    }
+    
+    public List<Relation> getColumnRelations()
+    {
+        return clause.getColumnRelations();
+    }
+    
+    public boolean isColumnRange()
+    {
+        return expression.isColumnRange();
+    }
+    
+    public List<Term> getColumnNames()
+    {
+        return expression.getColumns();
+    }
+    
+    public Term getColumnStart()
     {
-        return expression.getKeyPredicates();
+        return expression.getStart();
     }
     
-    public Predicates getColumnPredicates()
+    public Term getColumnFinish()
     {
-        return expression.getColumnPredicates();
+        return expression.getFinish();
     }
     
     public String getColumnFamily()
@@ -62,9 +97,9 @@ public class SelectStatement
         return columnFamily;
     }
     
-    public boolean reversed()
+    public boolean isColumnsReversed()
     {
-        return reverse;
+        return expression.isColumnsReversed();
     }
     
     public ConsistencyLevel getConsistencyLevel()
@@ -77,8 +112,8 @@ public class SelectStatement
         return numRecords;
     }
 
-    public int getNumColumns()
+    public int getColumnsLimit()
     {
-        return numColumns;
+        return expression.getColumnsLimit();
     }
 }

Added: cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java?rev=1034532&view=auto
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java (added)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java Fri Nov 12 19:32:32
2010
@@ -0,0 +1,102 @@
+package org.apache.cassandra.cql;
+/*
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ */
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WhereClauses encapsulate all of the predicates of a SELECT query.
+ *
+ */
+public class WhereClause
+{
+    private List<Term> keys = new ArrayList<Term>();
+    private Term startKey, finishKey;
+    private List<Relation> columns = new ArrayList<Relation>();
+    
+    /**
+     * Create a new WhereClause with the first parsed relation.
+     * 
+     * @param firstRelation key or column relation
+     */
+    public WhereClause(Relation firstRelation)
+    {
+        and(firstRelation);
+    }
+    
+    public WhereClause()
+    {
+        
+    }
+    
+    /**
+     * Add an additional relation to this WHERE clause.
+     * 
+     * @param relation the relation to add.
+     */
+    public void and(Relation relation)
+    {
+        if (relation.isKey())
+        {
+            if (relation.operator().equals(RelationType.EQ))
+                keys.add(relation.getValue());
+            else if ((relation.operator().equals(RelationType.GT) || relation.operator().equals(RelationType.GTE)))
+                startKey = relation.getValue();
+            else if ((relation.operator().equals(RelationType.LT) || relation.operator().equals(RelationType.LTE)))
+                finishKey = relation.getValue();
+            
+        }
+        else
+            columns.add(relation);
+    }
+    
+    public List<Relation> getColumnRelations()
+    {
+        return columns;
+    }
+    
+    public boolean isKeyRange()
+    {
+        return startKey != null;
+    }
+    
+    public boolean isKeyList()
+    {
+        return !isKeyRange();
+    }
+    
+    public Term getStartKey()
+    {
+        return startKey;
+    }
+    
+    public Term getFinishKey()
+    {
+        return finishKey;
+    }
+    
+    public List<Term> getKeys()
+    {
+        return keys;
+    }
+}

Modified: cassandra/trunk/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/system/test_cql.py?rev=1034532&r1=1034531&r2=1034532&view=diff
==============================================================================
--- cassandra/trunk/test/system/test_cql.py (original)
+++ cassandra/trunk/test/system/test_cql.py Fri Nov 12 19:32:32 2010
@@ -39,7 +39,7 @@ class TestCql(AvroTester):
     def test_select_simple(self):
         "retrieve a column"
         conn = init()
-        r = conn.execute('SELECT FROM Standard1 WHERE KEY="ka" AND COL="ca1"')
+        r = conn.execute('SELECT "ca1" FROM Standard1 WHERE KEY="ka"')
         assert r[0]['key'] == 'ka'
         assert r[0]['columns'][0]['name'] == 'ca1'
         assert r[0]['columns'][0]['value'] == 'va1'
@@ -48,42 +48,14 @@ class TestCql(AvroTester):
         "retrieve multiple columns"
         conn = init()
         r = conn.execute("""
-            SELECT FROM Standard1 WHERE KEY = "kd" AND COLUMN = "cd1"
-                    AND COLUMN = "col"
+            SELECT "cd1", "col" FROM Standard1 WHERE KEY = "kd"
         """)
         assert "cd1" in [i['name'] for i in r[0]['columns']]
         assert "col" in [i['name'] for i in r[0]['columns']]
 
-    def test_select_rows_columns(self):
-        "fetch multiple rows and columns"
-        conn = init()
-        r = conn.execute("""
-            SELECT FROM
-                Standard1
-            WHERE
-                KEY = "ka" AND KEY = "kd" AND COLUMN = "col";
-        """)
-        for result in r:
-            assert result['key'] in ("ka", "kd")
-            assert result['columns'][0]['name'] == "col"
-            assert result['columns'][0]['value'] == "val"
-
-    def test_select_rows(self):
-        "fetch multiple rows, all columns"
-        conn = init()
-        r = conn.execute("""
-            SELECT FROM
-                Standard1
-            WHERE
-                KEY = "ka" AND KEY = "kd" AND KEY = "kb"
-        """)
-        for result in r:
-            assert result['key'] in ("ka", "kd", "kb")
-            assert len(result['columns']) == 2
-
     def test_select_row_range(self):
         "retrieve a range of rows with columns"
         conn = init()
         r = conn.execute("""
-            SELECT FROM StandardLong1 WHERE KEY > "ad" AND KEY < "ag";
+            SELECT "col1" FROM StandardLong1 WHERE KEY > "ad" AND KEY < "ag";
         """)



Mime
View raw message