Prevent inefficient queries (CQL3) patch by slebresne; reviewed by jbellis for CASSANDRA-4915
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6fb75124 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6fb75124 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6fb75124 Branch: refs/heads/trunk Commit: 6fb751240013799a13890282e1af1f7dc85d9e8d Parents: 9fb5779 Author: Sylvain Lebresne <[email protected]> Authored: Fri Nov 23 10:04:56 2012 +0100 Committer: Sylvain Lebresne <[email protected]> Committed: Fri Nov 23 10:04:56 2012 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + src/java/org/apache/cassandra/cql3/Cql.g | 8 ++++- .../cassandra/cql3/statements/SelectStatement.java | 24 ++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6fb75124/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 90b6537..4ea42c1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -21,6 +21,7 @@ * Fix CQL3 LIMIT (CASSANDRA-4877) * Fix Stress for CQL3 (CASSANDRA-4979) * Remove cassandra specific exceptions from JMX interface (CASSANDRA-4893) + * (CQL3) Force using ALLOW FILTERING on potentially inefficient queries (CASSANDRA-4915) Merged from 1.1: * add basic authentication support for Pig CassandraStorage (CASSANDRA-3042) * fix CQL2 ALTER TABLE compaction_strategy_class altering (CASSANDRA-4965) http://git-wip-us.apache.org/repos/asf/cassandra/blob/6fb75124/src/java/org/apache/cassandra/cql3/Cql.g ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g index 9c3f77b..d814434 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -190,16 +190,19 @@ selectStatement returns [SelectStatement.RawStatement expr] boolean isCount = false; 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_FROM cf=columnFamilyName ( K_WHERE wclause=whereClause )? ( K_ORDER K_BY orderByClause[orderings] ( ',' orderByClause[orderings] )* )? ( K_LIMIT rows=INTEGER { limit = Integer.parseInt($rows.text); } )? + ( K_ALLOW K_FILTERING { allowFiltering = true; } )? { SelectStatement.Parameters params = new SelectStatement.Parameters(limit, orderings, - isCount); + isCount, + allowFiltering); $expr = new SelectStatement.RawStatement(cf, params, sclause, wclause); } ; @@ -754,6 +757,7 @@ unreserved_keyword returns [String str] | K_WRITETIME | K_MAP | K_LIST + | K_FILTERING ) { $str = $k.text; } | t=native_type { $str = t.toString(); } ; @@ -822,6 +826,8 @@ K_DESCRIBE: D E S C R I B E; K_FOR: F O R; K_FULL_ACCESS: F U L L '_' A C C E S S; K_NO_ACCESS: N O '_' A C C E S S; +K_ALLOW: A L L O W; +K_FILTERING: F I L T E R I N G; K_CLUSTERING: C L U S T E R I N G; http://git-wip-us.apache.org/repos/asf/cassandra/blob/6fb75124/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java index 4ae2b55..4e61a7b 100644 --- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java @@ -957,6 +957,16 @@ public class SelectStatement implements CQLStatement return name.type instanceof ReversedType; } + private boolean columnFilterIsIdentity() + { + for (Restriction r : columnRestrictions) + { + if (r != null) + return false; + } + return true; + } + public static class RawStatement extends CFStatement { private final Parameters parameters; @@ -1247,6 +1257,16 @@ public class SelectStatement implements CQLStatement stmt.isReversed = isReversed; } + // Make sure this queries is allowed (note: only key range can involve filtering underneath) + if (!parameters.allowFiltering && stmt.isKeyRange) + { + // We will potentially filter data if either: + // - Have more than one IndexExpression + // - Have no index expression and the column filter is not the identity + if (stmt.metadataRestrictions.size() > 1 || (stmt.metadataRestrictions.isEmpty() && !stmt.columnFilterIsIdentity())) + throw new InvalidRequestException("Cannot execute this query as it might involve data filtering and thus may have impredictible performance. " + + "If you want to execute this query despite the performance impredictibility, use ALLOW FILTERING"); + } return new ParsedStatement.Prepared(stmt, Arrays.<ColumnSpecification>asList(names)); } @@ -1432,12 +1452,14 @@ public class SelectStatement implements CQLStatement private final int limit; private final Map<ColumnIdentifier, Boolean> orderings; private final boolean isCount; + private final boolean allowFiltering; - public Parameters(int limit, Map<ColumnIdentifier, Boolean> orderings, boolean isCount) + public Parameters(int limit, Map<ColumnIdentifier, Boolean> orderings, boolean isCount, boolean allowFiltering) { this.limit = limit; this.orderings = orderings; this.isCount = isCount; + this.allowFiltering = allowFiltering; } }
