Author: eevans Date: Mon Dec 19 16:50:35 2011 New Revision: 1220840 URL: http://svn.apache.org/viewvc?rev=1220840&view=rev Log: index bind markers using parser
Patch by eevans; reviewed by Rick Shaw for CASSANDRA-2475 Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/CQLStatement.java 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/Term.java Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/CQLStatement.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/CQLStatement.java?rev=1220840&r1=1220839&r2=1220840&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cql/CQLStatement.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cql/CQLStatement.java Mon Dec 19 16:50:35 2011 @@ -26,9 +26,10 @@ public class CQLStatement public Object statement; public int boundTerms = 0; - public CQLStatement(StatementType type, Object statement) + public CQLStatement(StatementType type, Object statement, int lastMarker) { this.type = type; this.statement = statement; + this.boundTerms = lastMarker + 1; } } 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=1220840&r1=1220839&r2=1220840&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g Mon Dec 19 16:50:35 2011 @@ -42,6 +42,7 @@ options { @members { private List<String> recognitionErrors = new ArrayList<String>(); + private int currentBindMarkerIdx = -1; public void displayRecognitionError(String[] tokenNames, RecognitionException e) { @@ -111,20 +112,20 @@ options { } query returns [CQLStatement stmnt] - : selectStatement { $stmnt = new CQLStatement(StatementType.SELECT, $selectStatement.expr); } - | insertStatement endStmnt { $stmnt = new CQLStatement(StatementType.INSERT, $insertStatement.expr); } - | updateStatement endStmnt { $stmnt = new CQLStatement(StatementType.UPDATE, $updateStatement.expr); } - | batchStatement { $stmnt = new CQLStatement(StatementType.BATCH, $batchStatement.expr); } - | useStatement { $stmnt = new CQLStatement(StatementType.USE, $useStatement.keyspace); } - | truncateStatement { $stmnt = new CQLStatement(StatementType.TRUNCATE, $truncateStatement.cf); } - | deleteStatement endStmnt { $stmnt = new CQLStatement(StatementType.DELETE, $deleteStatement.expr); } - | createKeyspaceStatement { $stmnt = new CQLStatement(StatementType.CREATE_KEYSPACE, $createKeyspaceStatement.expr); } - | createColumnFamilyStatement { $stmnt = new CQLStatement(StatementType.CREATE_COLUMNFAMILY, $createColumnFamilyStatement.expr); } - | createIndexStatement { $stmnt = new CQLStatement(StatementType.CREATE_INDEX, $createIndexStatement.expr); } - | dropIndexStatement { $stmnt = new CQLStatement(StatementType.DROP_INDEX, $dropIndexStatement.expr); } - | dropKeyspaceStatement { $stmnt = new CQLStatement(StatementType.DROP_KEYSPACE, $dropKeyspaceStatement.ksp); } - | dropColumnFamilyStatement { $stmnt = new CQLStatement(StatementType.DROP_COLUMNFAMILY, $dropColumnFamilyStatement.cfam); } - | alterTableStatement { $stmnt = new CQLStatement(StatementType.ALTER_TABLE, $alterTableStatement.expr); } + : selectStatement { $stmnt = new CQLStatement(StatementType.SELECT, $selectStatement.expr, currentBindMarkerIdx); } + | insertStatement endStmnt { $stmnt = new CQLStatement(StatementType.INSERT, $insertStatement.expr, currentBindMarkerIdx); } + | updateStatement endStmnt { $stmnt = new CQLStatement(StatementType.UPDATE, $updateStatement.expr, currentBindMarkerIdx); } + | batchStatement { $stmnt = new CQLStatement(StatementType.BATCH, $batchStatement.expr, currentBindMarkerIdx); } + | useStatement { $stmnt = new CQLStatement(StatementType.USE, $useStatement.keyspace, currentBindMarkerIdx); } + | truncateStatement { $stmnt = new CQLStatement(StatementType.TRUNCATE, $truncateStatement.cf, currentBindMarkerIdx); } + | deleteStatement endStmnt { $stmnt = new CQLStatement(StatementType.DELETE, $deleteStatement.expr, currentBindMarkerIdx); } + | createKeyspaceStatement { $stmnt = new CQLStatement(StatementType.CREATE_KEYSPACE, $createKeyspaceStatement.expr, currentBindMarkerIdx); } + | createColumnFamilyStatement { $stmnt = new CQLStatement(StatementType.CREATE_COLUMNFAMILY, $createColumnFamilyStatement.expr, currentBindMarkerIdx); } + | createIndexStatement { $stmnt = new CQLStatement(StatementType.CREATE_INDEX, $createIndexStatement.expr, currentBindMarkerIdx); } + | dropIndexStatement { $stmnt = new CQLStatement(StatementType.DROP_INDEX, $dropIndexStatement.expr, currentBindMarkerIdx); } + | dropKeyspaceStatement { $stmnt = new CQLStatement(StatementType.DROP_KEYSPACE, $dropKeyspaceStatement.ksp, currentBindMarkerIdx); } + | dropColumnFamilyStatement { $stmnt = new CQLStatement(StatementType.DROP_COLUMNFAMILY, $dropColumnFamilyStatement.cfam, currentBindMarkerIdx); } + | alterTableStatement { $stmnt = new CQLStatement(StatementType.ALTER_TABLE, $alterTableStatement.expr, currentBindMarkerIdx); } ; // USE <KEYSPACE>; @@ -450,7 +451,9 @@ comparatorType ; term returns [Term item] - : ( t=K_KEY | t=STRING_LITERAL | t=INTEGER | t=UUID | t=IDENT | t=FLOAT | t=QMARK) { $item = new Term($t.text, $t.type); } + : (( t=K_KEY | t=STRING_LITERAL | t=INTEGER | t=UUID | t=IDENT | t=FLOAT ) { $item = new Term($t.text, $t.type); } + | t=QMARK { $item = new Term($t.text, $t.type, ++currentBindMarkerIdx); } + ) ; termList returns [List<Term> items] 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=1220840&r1=1220839&r2=1220840&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java Mon Dec 19 16:50:35 2011 @@ -494,120 +494,6 @@ public class QueryProcessor Predicates.not(Predicates.equalTo(StorageProxy.UNREACHABLE))); } - - private final static void maybeAddBoundTerm(CQLStatement statement, Term term) throws InvalidRequestException - { - if (term != null && term.isBindMarker()) - term.setBindIndex(statement.boundTerms++); - } - - private static void discoverBoundTerms(CQLStatement statement) throws InvalidRequestException - { - switch (statement.type) - { - case SELECT: - SelectStatement select = (SelectStatement)statement.statement; - if (logger.isTraceEnabled()) logger.trace(select.toString()); - - // handle the select expression first - if (!select.isColumnRange()) - { - for (Term term : select.getColumnNames()) - maybeAddBoundTerm(statement,term); - } - else - { - maybeAddBoundTerm(statement, select.getColumnStart()); - maybeAddBoundTerm(statement, select.getColumnFinish()); - } - - // next handle the WHERE clause NB order is VERY important - - // first check for a multi-key (IN) list - - if (select.isMultiKey()) - { - for (Term term : select.getKeys()) maybeAddBoundTerm(statement, term); - } - else if (!select.getColumnRelations().isEmpty()) - { - if (select.isKeyRange()) - { - maybeAddBoundTerm(statement, select.getKeyStart()); - maybeAddBoundTerm(statement, select.getKeyFinish()); - } - - for (Relation relation : select.getColumnRelations()) - { - maybeAddBoundTerm(statement, relation.getEntity()); - maybeAddBoundTerm(statement, relation.getValue()); - } - } - else - { - // maybe its empty or just a simple term - for (Term term : select.getKeys()) maybeAddBoundTerm(statement, term); - } - - break; - - case UPDATE: - UpdateStatement update = (UpdateStatement)statement.statement; - if (logger.isTraceEnabled()) logger.trace(update.toString()); - - // first handle the SET clause values that come in pairs for UPDATE. NB the order of the markers (?) - for (Map.Entry<Term, Operation> column : update.getColumns().entrySet()) - { - maybeAddBoundTerm(statement, column.getKey()); - maybeAddBoundTerm(statement, column.getValue().a); - } - - // now handle the key(s) in the WHERE clause - - for (Term term : update.getKeys()) maybeAddBoundTerm(statement, term); - break; - - case INSERT: // insert uses UpdateStatement but with different marker ordering - UpdateStatement insert = (UpdateStatement)statement.statement; - if (logger.isTraceEnabled()) logger.trace(insert.toString()); - - // first handle the INTO..VALUES clause values that are grouped in order for INSERT. NB the order of the markers (?) - for (Term term : insert.getColumnNames()) maybeAddBoundTerm(statement, term); - for (Term term : insert.getColumnValues()) maybeAddBoundTerm(statement, term); - - // now handle the key(s) in the VALUES clause - for (Term term : insert.getKeys()) maybeAddBoundTerm(statement, term); - break; - - case DELETE: - DeleteStatement delete = (DeleteStatement)statement.statement; - if (logger.isTraceEnabled()) logger.trace(delete.toString()); - - // first handle the columns list for DELETE. NB the order of the markers (?) - for (Term term : delete.getColumns()) maybeAddBoundTerm(statement, term); - - // now handle the key(s) in the WHERE clause - for (Term term : delete.getKeys()) maybeAddBoundTerm(statement, term); - break; - - case CREATE_COLUMNFAMILY: - CreateColumnFamilyStatement createCf = (CreateColumnFamilyStatement)statement.statement; - - // handle the left hand Terms. Not terribly useful but included for completeness - for (Term term : createCf.getColumns().keySet()) maybeAddBoundTerm(statement, term); - break; - - case CREATE_INDEX: - CreateIndexStatement createIdx = (CreateIndexStatement)statement.statement; - - // handle the column name Term. Not terribly useful but included for completeness - maybeAddBoundTerm(statement, createIdx.getColumnName()); - break; - - default: // all other statement types are a NOOP. - } - } - public static CqlResult processStatement(CQLStatement statement,ClientState clientState, List<String> variables ) throws UnavailableException, InvalidRequestException, TimedOutException, SchemaDisagreementException { @@ -1101,15 +987,12 @@ public class QueryProcessor CQLStatement statement = getStatement(queryString); int statementId = makeStatementId(queryString); - - discoverBoundTerms(statement); - if (logger.isTraceEnabled()) logger.trace("Discovered "+ statement.boundTerms + " bound variables."); + logger.trace("Discovered "+ statement.boundTerms + " bound variables."); clientState.getPrepared().put(statementId, statement); - if (logger.isTraceEnabled()) - logger.trace(String.format("Stored prepared statement #%d with %d bind markers", - statementId, - statement.boundTerms)); + logger.trace(String.format("Stored prepared statement #%d with %d bind markers", + statementId, + statement.boundTerms)); return new CqlPreparedResult(statementId, statement.boundTerms); } @@ -1121,13 +1004,15 @@ public class QueryProcessor if (!(variables.isEmpty() && (statement.boundTerms == 0))) { if (variables.size() != statement.boundTerms) - throw new InvalidRequestException(String.format("there were %d markers(?) in CQL but %d bound variables", - statement.boundTerms, variables.size())); + throw new InvalidRequestException(String.format("there were %d markers(?) in CQL but %d bound variables", + statement.boundTerms, + variables.size())); // at this point there is a match in count between markers and variables that is non-zero if (logger.isTraceEnabled()) - for (int i = 0; i < variables.size(); i++) logger.trace("[{}] '{}'", i+1, variables.get(i)); + for (int i = 0; i < variables.size(); i++) + logger.trace("[{}] '{}'", i+1, variables.get(i)); } return processStatement(statement, clientState, variables); Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/Term.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/Term.java?rev=1220840&r1=1220839&r2=1220840&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cql/Term.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cql/Term.java Mon Dec 19 16:50:35 2011 @@ -33,11 +33,10 @@ import org.apache.cassandra.thrift.Inval /** A term parsed from a CQL statement. */ public class Term -{ +{ private final String text; private final TermType type; - - private Integer bindIndex; + private Integer bindIndex = -1; /** * Create new Term instance from a string, and an integer that corresponds @@ -70,9 +69,10 @@ public class Term this.type = TermType.STRING; } - public void setBindIndex(int bindIndex) + public Term(String text, int type, int index) { - this.bindIndex = bindIndex; + this(text, type); + this.bindIndex = index; } /**