Permalink
Browse files

Add alias support to SELECT statement

patch by Aleksey Yeschenko; reviewed by Sylvain Lebresne for
CASSANDRA-5075
  • Loading branch information...
1 parent df723af commit 08df0b8604cd34c4f1fb384f9f6eaba86203d116 @iamaleksey iamaleksey committed May 6, 2013
View
@@ -40,6 +40,7 @@
* Reenable ALTER TABLE DROP with new semantics (CASSANDRA-3919)
* Add binary protocol versioning (CASSANDRA-5436)
* Swap THshaServer for TThreadedSelectorServer (CASSANDRA-5530)
+ * Add alias support to SELECT statement (CASSANDRA-5075)
1.2.5
View
@@ -55,6 +55,11 @@ Operations
- CAS uses gc_grace_seconds to determine how long to keep unused paxos
state around for, or a minimum of three hours.
+Features
+--------
+ - Alias support has been added to CQL3 SELECT statement. Refer to
+ CQL3 documentation (http://cassandra.apache.org/doc/cql3/CQL.html) for details.
+
1.2.5
=====
View
@@ -32,7 +32,7 @@ exit 1
from __future__ import with_statement
description = "CQL Shell for Apache Cassandra"
-version = "3.0.1"
+version = "3.0.2"
from StringIO import StringIO
from itertools import groupby
View
@@ -580,9 +580,9 @@ bc(syntax)..
( ALLOW FILTERING )?
<select-clause> ::= <selection-list>
- | COUNT '(' ( '*' | '1' ) ')'
+ | COUNT '(' ( '*' | '1' ) ')' (AS <identifier>)?
-<selection-list> ::= <selector> ( ',' <selector> )*
+<selection-list> ::= <selector> (AS <identifier>)? ( ',' <selector> (AS <identifier>)? )*
| '*'
<selector> ::= <identifier>
@@ -604,13 +604,18 @@ __Sample:__
bc(sample)..
SELECT name, occupation FROM users WHERE userid IN (199, 200, 207);
+SELECT name AS user_name, occupation AS user_occupation FROM users;
+
SELECT time, value
FROM events
WHERE event_type = 'myEvent'
AND time > 2011-02-03
AND time <= 2012-01-01
SELECT COUNT(*) FROM users;
+
+SELECT COUNT(*) AS user_count FROM users;
+
p.
The @SELECT@ statements reads one or more columns for one or more rows in a table. It returns a result-set of rows, where each row contains the collection of columns corresponding to the query.
@@ -620,6 +625,8 @@ The @<select-clause>@ determines which columns needs to be queried and returned
A @<selector>@ is either a column name to retrieve, or a @<function>@ of one or multiple column names. The functions allows are the same that for @<term>@ and are describe in the "function section":#function. In addition to these generic functions, the @WRITETIME@ (resp. @TTL@) function allows to select the timestamp of when the column was inserted (resp. the time to live (in seconds) for the column (or null if the column has no expiration set)).
+Any @<selector>@ can be aliased using @AS@ keyword (see examples). Please note that @<where-clause>@ and @<order-by>@ clause should refer to the columns by their original names and not by their aliases.
+
The @COUNT@ keyword can be used with parenthesis enclosing @*@. If so, the query will return a single result: the number of rows matching the query. Note that @COUNT(1)@ is supported as an alias.
h4(#selectWhere). @<where-clause>@
@@ -966,6 +973,7 @@ CQL distinguishes between _reserved_ and _non-reserved_ keywords. Reserved keywo
| @AND@ | yes |
| @ANY@ | yes |
| @APPLY@ | yes |
+| @AS@ | no |
| @ASC@ | yes |
| @ASCII@ | no |
| @AUTHORIZE@ | yes |
@@ -1051,6 +1059,7 @@ The following describes the addition/changes brought for each version of CQL.
h3. 3.1.0
* "ALTER TABLE":#alterTableStmt @DROP@ option has been reenabled for CQL3 tables and has new semantics now: the space formerly used by dropped columns will now be eventually reclaimed (post-compaction). You should not readd previously dropped columns unless you use timestamps with microsecond precision (see "CASSANDRA-3919":https://issues.apache.org/jira/browse/CASSANDRA-3919 for more details).
+* SELECT statement now supports aliases in select clause. Aliases in WHERE and ORDER BY clauses are not supported. See the "section on select"#selectStmt for details.
h3. 3.0.3
@@ -758,9 +758,9 @@ def working_on_keyspace(ctxt):
")" ("=" | "<" | ">" | "<=" | ">=") <tokenDefinition>
| [rel_lhs]=<cident> "IN" "(" <term> ( "," <term> )* ")"
;
-<selectClause> ::= <selector> ("," <selector>)*
+<selectClause> ::= <selector> ("AS" <cident>)? ("," <selector> ("AS" <cident>)?)*
| "*"
- | "COUNT" "(" star=( "*" | "1" ) ")"
+ | "COUNT" "(" star=( "*" | "1" ) ")" ("AS" <cident>)?
;
<selector> ::= [colname]=<cident>
| "WRITETIME" "(" [colname]=<cident> ")"
@@ -20,15 +20,14 @@
import java.util.Locale;
import java.nio.ByteBuffer;
+import org.apache.cassandra.cql3.statements.Selectable;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.cassandra.cql3.statements.RawSelector;
-
/**
* Represents an identifer for a CQL column definition.
*/
-public class ColumnIdentifier implements RawSelector, Comparable<ColumnIdentifier>
+public class ColumnIdentifier implements Selectable, Comparable<ColumnIdentifier>
{
public final ByteBuffer key;
private final String text;
@@ -211,11 +211,13 @@ useStatement returns [UseStatement stmt]
selectStatement returns [SelectStatement.RawStatement expr]
@init {
boolean isCount = false;
+ ColumnIdentifier countAlias = null;
int limit = Integer.MAX_VALUE;
Map<ColumnIdentifier, Boolean> orderings = new LinkedHashMap<ColumnIdentifier, Boolean>();
boolean allowFiltering = false;
}
- : K_SELECT ( sclause=selectClause | (K_COUNT '(' sclause=selectCountClause ')' { isCount = true; }) )
+ : K_SELECT ( sclause=selectClause
+ | (K_COUNT '(' sclause=selectCountClause ')' { isCount = true; } (K_AS c=cident { countAlias = c; })?) )
K_FROM cf=columnFamilyName
( K_WHERE wclause=whereClause )?
( K_ORDER K_BY orderByClause[orderings] ( ',' orderByClause[orderings] )* )?
@@ -225,6 +227,7 @@ selectStatement returns [SelectStatement.RawStatement expr]
SelectStatement.Parameters params = new SelectStatement.Parameters(limit,
orderings,
isCount,
+ countAlias,
allowFiltering);
$expr = new SelectStatement.RawStatement(cf, params, sclause, wclause);
}
@@ -235,18 +238,23 @@ selectClause returns [List<RawSelector> expr]
| '\*' { $expr = Collections.<RawSelector>emptyList();}
;
-selectionFunctionArgs returns [List<RawSelector> a]
- : '(' ')' { $a = Collections.emptyList(); }
- | '(' s1=selector { List<RawSelector> args = new ArrayList<RawSelector>(); args.add(s1); }
- ( ',' sn=selector { args.add(sn); } )*
- ')' { $a = args; }
+selector returns [RawSelector s]
+ @init{ ColumnIdentifier alias = null; }
+ : us=unaliasedSelector (K_AS c=cident { alias = c; })? { $s = new RawSelector(us, alias); }
;
-selector returns [RawSelector s]
+unaliasedSelector returns [Selectable s]
: c=cident { $s = c; }
- | K_WRITETIME '(' c=cident ')' { $s = new RawSelector.WritetimeOrTTL(c, true); }
- | K_TTL '(' c=cident ')' { $s = new RawSelector.WritetimeOrTTL(c, false); }
- | f=functionName args=selectionFunctionArgs { $s = new RawSelector.WithFunction(f, args); }
+ | K_WRITETIME '(' c=cident ')' { $s = new Selectable.WritetimeOrTTL(c, true); }
+ | K_TTL '(' c=cident ')' { $s = new Selectable.WritetimeOrTTL(c, false); }
+ | f=functionName args=selectionFunctionArgs { $s = new Selectable.WithFunction(f, args); }
+ ;
+
+selectionFunctionArgs returns [List<Selectable> a]
+ : '(' ')' { $a = Collections.emptyList(); }
+ | '(' s1=unaliasedSelector { List<Selectable> args = new ArrayList<Selectable>(); args.add(s1); }
+ ( ',' sn=unaliasedSelector { args.add(sn); } )*
+ ')' { $a = args; }
;
selectCountClause returns [List<RawSelector> expr]
@@ -878,6 +886,7 @@ unreserved_keyword returns [String str]
unreserved_function_keyword returns [String str]
: k=( K_KEY
+ | K_AS
| K_CLUSTERING
| K_COMPACT
| K_STORAGE
@@ -905,6 +914,7 @@ unreserved_function_keyword returns [String str]
// Case-insensitive keywords
K_SELECT: S E L E C T;
K_FROM: F R O M;
+K_AS: A S;
K_WHERE: W H E R E;
K_AND: A N D;
K_KEY: K E Y;
@@ -92,13 +92,14 @@ public void trim(int limit)
}
}
- public ResultSet makeCountResult()
+ public ResultSet makeCountResult(ColumnIdentifier alias)
{
String ksName = metadata.names.get(0).ksName;
String cfName = metadata.names.get(0).cfName;
long count = rows.size();
- Metadata newMetadata = new Metadata(Collections.singletonList(new ColumnSpecification(ksName, cfName, COUNT_COLUMN, LongType.instance)));
+ ColumnSpecification spec = new ColumnSpecification(ksName, cfName, alias == null ? COUNT_COLUMN : alias, LongType.instance);
+ Metadata newMetadata = new Metadata(Collections.singletonList(spec));
List<List<ByteBuffer>> newRows = Collections.singletonList(Collections.singletonList(ByteBufferUtil.bytes(count)));
return new ResultSet(newMetadata, newRows);
@@ -18,52 +18,16 @@
*/
package org.apache.cassandra.cql3.statements;
-import java.util.List;
-
import org.apache.cassandra.cql3.ColumnIdentifier;
-public interface RawSelector
+public class RawSelector
{
- public static class WritetimeOrTTL implements RawSelector
- {
- public final ColumnIdentifier id;
- public final boolean isWritetime;
+ public final Selectable selectable;
+ public final ColumnIdentifier alias;
- public WritetimeOrTTL(ColumnIdentifier id, boolean isWritetime)
- {
- this.id = id;
- this.isWritetime = isWritetime;
- }
-
- @Override
- public String toString()
- {
- return (isWritetime ? "writetime" : "ttl") + "(" + id + ")";
- }
- }
-
- public static class WithFunction implements RawSelector
+ public RawSelector(Selectable selectable, ColumnIdentifier alias)
{
- public final String functionName;
- public final List<RawSelector> args;
-
- public WithFunction(String functionName, List<RawSelector> args)
- {
- this.functionName = functionName;
- this.args = args;
- }
-
- @Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append(functionName).append("(");
- for (int i = 0; i < args.size(); i++)
- {
- if (i > 0) sb.append(", ");
- sb.append(args.get(i));
- }
- return sb.append(")").toString();
- }
+ this.selectable = selectable;
+ this.alias = alias;
}
}
Oops, something went wrong.

0 comments on commit 08df0b8

Please sign in to comment.