You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by al...@apache.org on 2014/02/20 20:39:07 UTC
[2/4] Remove CQL2
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/QueryProcessor.java b/src/java/org/apache/cassandra/cql/QueryProcessor.java
deleted file mode 100644
index 3d5c3f1..0000000
--- a/src/java/org/apache/cassandra/cql/QueryProcessor.java
+++ /dev/null
@@ -1,913 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.TimeoutException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.config.*;
-import org.apache.cassandra.cli.CliUtils;
-import org.apache.cassandra.cql.hooks.ExecutionContext;
-import org.apache.cassandra.cql.hooks.PostPreparationHook;
-import org.apache.cassandra.cql.hooks.PreExecutionHook;
-import org.apache.cassandra.cql.hooks.PreparationContext;
-import org.apache.cassandra.db.CounterCell;
-import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.composites.CellName;
-import org.apache.cassandra.db.composites.CellNameType;
-import org.apache.cassandra.db.composites.Composite;
-import org.apache.cassandra.db.context.CounterContext;
-import org.apache.cassandra.db.filter.*;
-import org.apache.cassandra.db.index.SecondaryIndexManager;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.AsciiType;
-import org.apache.cassandra.db.marshal.TypeParser;
-import org.apache.cassandra.dht.*;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.serializers.MarshalException;
-import org.apache.cassandra.service.StorageProxy;
-import org.apache.cassandra.service.StorageService;
-import org.apache.cassandra.service.MigrationManager;
-import org.apache.cassandra.thrift.Column;
-import org.apache.cassandra.thrift.CqlMetadata;
-import org.apache.cassandra.thrift.CqlResult;
-import org.apache.cassandra.thrift.CqlResultType;
-import org.apache.cassandra.thrift.CqlRow;
-import org.apache.cassandra.thrift.CqlPreparedResult;
-import org.apache.cassandra.thrift.ThriftValidation;
-import org.apache.cassandra.thrift.ThriftClientState;
-import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.Pair;
-import org.apache.cassandra.utils.SemanticVersion;
-import org.antlr.runtime.*;
-
-
-import static org.apache.cassandra.thrift.ThriftValidation.validateColumnFamily;
-
-public class QueryProcessor
-{
- public static final SemanticVersion CQL_VERSION = new SemanticVersion("2.0.0");
-
- private static final Logger logger = LoggerFactory.getLogger(QueryProcessor.class);
-
- public static final String DEFAULT_KEY_NAME = CFMetaData.DEFAULT_KEY_ALIAS.toUpperCase();
-
- private static final List<PreExecutionHook> preExecutionHooks = new CopyOnWriteArrayList<>();
- private static final List<PostPreparationHook> postPreparationHooks = new CopyOnWriteArrayList<>();
-
- public static void addPreExecutionHook(PreExecutionHook hook)
- {
- preExecutionHooks.add(hook);
- }
-
- public static void removePreExecutionHook(PreExecutionHook hook)
- {
- preExecutionHooks.remove(hook);
- }
-
- public static void addPostPreparationHook(PostPreparationHook hook)
- {
- postPreparationHooks.add(hook);
- }
-
- public static void removePostPreparationHook(PostPreparationHook hook)
- {
- postPreparationHooks.remove(hook);
- }
-
- private static List<org.apache.cassandra.db.Row> getSlice(CFMetaData metadata, SelectStatement select, List<ByteBuffer> variables, long now)
- throws InvalidRequestException, ReadTimeoutException, UnavailableException, IsBootstrappingException
- {
- List<ReadCommand> commands = new ArrayList<ReadCommand>();
-
- // ...of a list of column names
- if (!select.isColumnRange())
- {
- SortedSet<CellName> columnNames = getColumnNames(select, metadata, variables);
- validateColumnNames(columnNames);
-
- for (Term rawKey: select.getKeys())
- {
- ByteBuffer key = rawKey.getByteBuffer(metadata.getKeyValidator(),variables);
-
- validateKey(key);
- commands.add(new SliceByNamesReadCommand(metadata.ksName, key, select.getColumnFamily(), now, new NamesQueryFilter(columnNames)));
- }
- }
- // ...a range (slice) of column names
- else
- {
- AbstractType<?> at = metadata.comparator.asAbstractType();
- Composite start = metadata.comparator.fromByteBuffer(select.getColumnStart().getByteBuffer(at,variables));
- Composite finish = metadata.comparator.fromByteBuffer(select.getColumnFinish().getByteBuffer(at,variables));
-
- for (Term rawKey : select.getKeys())
- {
- ByteBuffer key = rawKey.getByteBuffer(metadata.getKeyValidator(),variables);
-
- validateKey(key);
- validateSliceFilter(metadata, start, finish, select.isColumnsReversed());
- commands.add(new SliceFromReadCommand(metadata.ksName,
- key,
- select.getColumnFamily(),
- now,
- new SliceQueryFilter(start, finish, select.isColumnsReversed(), select.getColumnsLimit())));
- }
- }
-
- return StorageProxy.read(commands, select.getConsistencyLevel());
- }
-
- private static SortedSet<CellName> getColumnNames(SelectStatement select, CFMetaData metadata, List<ByteBuffer> variables)
- throws InvalidRequestException
- {
- String keyString = metadata.getCQL2KeyName();
- List<Term> selectColumnNames = select.getColumnNames();
- SortedSet<CellName> columnNames = new TreeSet<>(metadata.comparator);
- for (Term column : selectColumnNames)
- {
- // skip the key for the slice op; we'll add it to the resultset in extractThriftColumns
- if (!column.getText().equalsIgnoreCase(keyString))
- columnNames.add(metadata.comparator.cellFromByteBuffer(column.getByteBuffer(metadata.comparator.asAbstractType(),variables)));
- }
- return columnNames;
- }
-
- private static List<org.apache.cassandra.db.Row> multiRangeSlice(CFMetaData metadata, SelectStatement select, List<ByteBuffer> variables, long now)
- throws ReadTimeoutException, UnavailableException, InvalidRequestException
- {
- IPartitioner<?> p = StorageService.getPartitioner();
-
- AbstractType<?> keyType = Schema.instance.getCFMetaData(metadata.ksName, select.getColumnFamily()).getKeyValidator();
-
- ByteBuffer startKeyBytes = (select.getKeyStart() != null)
- ? select.getKeyStart().getByteBuffer(keyType,variables)
- : null;
-
- ByteBuffer finishKeyBytes = (select.getKeyFinish() != null)
- ? select.getKeyFinish().getByteBuffer(keyType,variables)
- : null;
-
- RowPosition startKey = RowPosition.forKey(startKeyBytes, p), finishKey = RowPosition.forKey(finishKeyBytes, p);
- if (startKey.compareTo(finishKey) > 0 && !finishKey.isMinimum(p))
- {
- if (p instanceof RandomPartitioner)
- throw new InvalidRequestException("Start key sorts after end key. This is not allowed; you probably should not specify end key at all, under RandomPartitioner");
- else
- throw new InvalidRequestException("Start key must sort before (or equal to) finish key in your partitioner!");
- }
- AbstractBounds<RowPosition> bounds = new Bounds<RowPosition>(startKey, finishKey);
-
- IDiskAtomFilter columnFilter = filterFromSelect(select, metadata, variables);
- validateFilter(metadata, columnFilter);
-
- List<Relation> columnRelations = select.getColumnRelations();
- List<IndexExpression> expressions = new ArrayList<IndexExpression>(columnRelations.size());
- for (Relation columnRelation : columnRelations)
- {
- // Left and right side of relational expression encoded according to comparator/validator.
- ByteBuffer entity = columnRelation.getEntity().getByteBuffer(metadata.comparator.asAbstractType(), variables);
- ByteBuffer value = columnRelation.getValue().getByteBuffer(metadata.getValueValidatorForFullCellName(entity), variables);
-
- expressions.add(new IndexExpression(entity,
- IndexExpression.Operator.valueOf(columnRelation.operator().toString()),
- value));
- }
-
- int limit = select.isKeyRange() && select.getKeyStart() != null
- ? select.getNumRecords() + 1
- : select.getNumRecords();
-
- List<org.apache.cassandra.db.Row> rows = StorageProxy.getRangeSlice(new RangeSliceCommand(metadata.ksName,
- select.getColumnFamily(),
- now,
- columnFilter,
- bounds,
- expressions,
- limit),
- select.getConsistencyLevel());
-
- // if start key was set and relation was "greater than"
- if (select.getKeyStart() != null && !select.includeStartKey() && !rows.isEmpty())
- {
- if (rows.get(0).key.key.equals(startKeyBytes))
- rows.remove(0);
- }
-
- // if finish key was set and relation was "less than"
- if (select.getKeyFinish() != null && !select.includeFinishKey() && !rows.isEmpty())
- {
- int lastIndex = rows.size() - 1;
- if (rows.get(lastIndex).key.key.equals(finishKeyBytes))
- rows.remove(lastIndex);
- }
-
- return rows.subList(0, select.getNumRecords() < rows.size() ? select.getNumRecords() : rows.size());
- }
-
- private static IDiskAtomFilter filterFromSelect(SelectStatement select, CFMetaData metadata, List<ByteBuffer> variables)
- throws InvalidRequestException
- {
- if (select.isColumnRange() || select.getColumnNames().size() == 0)
- {
- AbstractType<?> comparator = metadata.comparator.asAbstractType();
- return new SliceQueryFilter(metadata.comparator.fromByteBuffer(select.getColumnStart().getByteBuffer(comparator, variables)),
- metadata.comparator.fromByteBuffer(select.getColumnFinish().getByteBuffer(comparator, variables)),
- select.isColumnsReversed(),
- select.getColumnsLimit());
- }
- else
- {
- return new NamesQueryFilter(getColumnNames(select, metadata, variables));
- }
- }
-
- /* Test for SELECT-specific taboos */
- private static void validateSelect(String keyspace, SelectStatement select, List<ByteBuffer> variables) throws InvalidRequestException
- {
- select.getConsistencyLevel().validateForRead(keyspace);
-
- // Finish key w/o start key (KEY < foo)
- if (!select.isKeyRange() && (select.getKeyFinish() != null))
- throw new InvalidRequestException("Key range clauses must include a start key (i.e. KEY > term)");
-
- // Key range and by-key(s) combined (KEY > foo AND KEY = bar)
- if (select.isKeyRange() && select.getKeys().size() > 0)
- throw new InvalidRequestException("You cannot combine key range and by-key clauses in a SELECT");
-
- // Start and finish keys, *and* column relations (KEY > foo AND KEY < bar and name1 = value1).
- if (select.isKeyRange() && (select.getKeyFinish() != null) && (select.getColumnRelations().size() > 0))
- throw new InvalidRequestException("You cannot combine key range and by-column clauses in a SELECT");
-
- // Can't use more than one KEY =
- if (!select.isMultiKey() && select.getKeys().size() > 1)
- throw new InvalidRequestException("You cannot use more than one KEY = in a SELECT");
-
- if (select.getColumnRelations().size() > 0)
- {
- ColumnFamilyStore cfstore = Keyspace.open(keyspace).getColumnFamilyStore(select.getColumnFamily());
- CellNameType comparator = cfstore.metadata.comparator;
- AbstractType<?> at = comparator.asAbstractType();
- SecondaryIndexManager idxManager = cfstore.indexManager;
- for (Relation relation : select.getColumnRelations())
- {
- ByteBuffer name = relation.getEntity().getByteBuffer(at, variables);
- if ((relation.operator() == RelationType.EQ) && idxManager.indexes(comparator.cellFromByteBuffer(name)))
- return;
- }
- throw new InvalidRequestException("No indexed columns present in by-columns clause with \"equals\" operator");
- }
- }
-
- public static void validateKey(ByteBuffer key) throws InvalidRequestException
- {
- if (key == null || key.remaining() == 0)
- {
- throw new InvalidRequestException("Key may not be empty");
- }
-
- // check that key can be handled by FBUtilities.writeShortByteArray
- if (key.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
- {
- throw new InvalidRequestException("Key length of " + key.remaining() +
- " is longer than maximum of " + FBUtilities.MAX_UNSIGNED_SHORT);
- }
- }
-
- public static void validateKeyAlias(CFMetaData cfm, String key) throws InvalidRequestException
- {
- assert key.toUpperCase().equals(key); // should always be uppercased by caller
- String realKeyAlias = cfm.getCQL2KeyName().toUpperCase();
- if (!realKeyAlias.equals(key))
- throw new InvalidRequestException(String.format("Expected key '%s' to be present in WHERE clause for '%s'", realKeyAlias, cfm.cfName));
- }
-
- private static void validateColumnNames(Iterable<CellName> columns)
- throws InvalidRequestException
- {
- for (CellName name : columns)
- {
- if (name.dataSize() > org.apache.cassandra.db.Cell.MAX_NAME_LENGTH)
- throw new InvalidRequestException(String.format("column name is too long (%s > %s)",
- name.dataSize(),
- org.apache.cassandra.db.Cell.MAX_NAME_LENGTH));
- if (name.isEmpty())
- throw new InvalidRequestException("zero-length column name");
- }
- }
-
- public static void validateColumnName(CellName column)
- throws InvalidRequestException
- {
- validateColumnNames(Arrays.asList(column));
- }
-
- public static void validateColumn(CFMetaData metadata, CellName name, ByteBuffer value)
- throws InvalidRequestException
- {
- validateColumnName(name);
- AbstractType<?> validator = metadata.getValueValidator(name);
-
- try
- {
- if (validator != null)
- validator.validate(value);
- }
- catch (MarshalException me)
- {
- throw new InvalidRequestException(String.format("Invalid column value for column (name=%s); %s",
- ByteBufferUtil.bytesToHex(name.toByteBuffer()),
- me.getMessage()));
- }
- }
-
- private static void validateFilter(CFMetaData metadata, IDiskAtomFilter filter)
- throws InvalidRequestException
- {
- if (filter instanceof SliceQueryFilter)
- validateSliceFilter(metadata, (SliceQueryFilter)filter);
- else
- validateColumnNames(((NamesQueryFilter)filter).columns);
- }
-
- private static void validateSliceFilter(CFMetaData metadata, SliceQueryFilter range)
- throws InvalidRequestException
- {
- validateSliceFilter(metadata, range.start(), range.finish(), range.reversed);
- }
-
- private static void validateSliceFilter(CFMetaData metadata, Composite start, Composite finish, boolean reversed)
- throws InvalidRequestException
- {
- CellNameType comparator = metadata.comparator;
- Comparator<Composite> orderedComparator = reversed ? comparator.reverseComparator(): comparator;
- if (!start.isEmpty() && !finish.isEmpty() && orderedComparator.compare(start, finish) > 0)
- throw new InvalidRequestException("range finish must come after start in traversal order");
- }
-
- public static CqlResult processStatement(CQLStatement statement, ExecutionContext context)
- throws RequestExecutionException, RequestValidationException
- {
- String keyspace = null;
- ThriftClientState clientState = context.clientState;
- List<ByteBuffer> variables = context.variables;
-
- // Some statements won't have (or don't need) a keyspace (think USE, or CREATE).
- if (statement.type != StatementType.SELECT && StatementType.REQUIRES_KEYSPACE.contains(statement.type))
- keyspace = clientState.getKeyspace();
-
- CqlResult result = new CqlResult();
-
- if (!preExecutionHooks.isEmpty())
- for (PreExecutionHook hook : preExecutionHooks)
- statement = hook.processStatement(statement, context);
-
- if (logger.isDebugEnabled()) logger.debug("CQL statement type: {}", statement.type.toString());
- CFMetaData metadata;
- switch (statement.type)
- {
- case SELECT:
- SelectStatement select = (SelectStatement)statement.statement;
-
- final String oldKeyspace = clientState.getRawKeyspace();
-
- if (select.isSetKeyspace())
- {
- keyspace = CliUtils.unescapeSQLString(select.getKeyspace());
- ThriftValidation.validateKeyspace(keyspace);
- }
- else if (oldKeyspace == null)
- throw new InvalidRequestException("no keyspace has been specified");
- else
- keyspace = oldKeyspace;
-
- clientState.hasColumnFamilyAccess(keyspace, select.getColumnFamily(), Permission.SELECT);
- metadata = validateColumnFamily(keyspace, select.getColumnFamily());
-
- // need to do this in here because we need a CFMD.getKeyName()
- select.extractKeyAliasFromColumns(metadata);
-
- if (select.getKeys().size() > 0)
- validateKeyAlias(metadata, select.getKeyAlias());
-
- validateSelect(keyspace, select, variables);
-
- List<org.apache.cassandra.db.Row> rows;
-
- long now = System.currentTimeMillis();
- // By-key
- if (!select.isKeyRange() && (select.getKeys().size() > 0))
- {
- rows = getSlice(metadata, select, variables, now);
- }
- else
- {
- rows = multiRangeSlice(metadata, select, variables, now);
- }
-
- // count resultset is a single column named "count"
- result.type = CqlResultType.ROWS;
- if (select.isCountOperation())
- {
- validateCountOperation(select);
-
- ByteBuffer countBytes = ByteBufferUtil.bytes("count");
- result.schema = new CqlMetadata(Collections.<ByteBuffer, String>emptyMap(),
- Collections.<ByteBuffer, String>emptyMap(),
- "AsciiType",
- "LongType");
- List<Column> columns = Collections.singletonList(new Column(countBytes).setValue(ByteBufferUtil.bytes((long) rows.size())));
- result.rows = Collections.singletonList(new CqlRow(countBytes, columns));
- return result;
- }
-
- // otherwise create resultset from query results
- result.schema = new CqlMetadata(new HashMap<ByteBuffer, String>(),
- new HashMap<ByteBuffer, String>(),
- TypeParser.getShortName(metadata.comparator.asAbstractType()),
- TypeParser.getShortName(metadata.getDefaultValidator()));
- List<CqlRow> cqlRows = new ArrayList<CqlRow>(rows.size());
- for (org.apache.cassandra.db.Row row : rows)
- {
- List<Column> thriftColumns = new ArrayList<Column>();
- if (select.isColumnRange())
- {
- if (select.isFullWildcard())
- {
- // prepend key
- ByteBuffer keyName = ByteBufferUtil.bytes(metadata.getCQL2KeyName());
- thriftColumns.add(new Column(keyName).setValue(row.key.key).setTimestamp(-1));
- result.schema.name_types.put(keyName, TypeParser.getShortName(AsciiType.instance));
- result.schema.value_types.put(keyName, TypeParser.getShortName(metadata.getKeyValidator()));
- }
-
- // preserve comparator order
- if (row.cf != null)
- {
- for (org.apache.cassandra.db.Cell c : row.cf.getSortedColumns())
- {
- if (c.isMarkedForDelete(now))
- continue;
-
- ColumnDefinition cd = metadata.getColumnDefinition(c.name());
- if (cd != null)
- result.schema.value_types.put(c.name().toByteBuffer(), TypeParser.getShortName(cd.type));
-
- thriftColumns.add(thriftify(c));
- }
- }
- }
- else
- {
- String keyString = metadata.getCQL2KeyName();
-
- // order columns in the order they were asked for
- for (Term term : select.getColumnNames())
- {
- if (term.getText().equalsIgnoreCase(keyString))
- {
- // preserve case of key as it was requested
- ByteBuffer requestedKey = ByteBufferUtil.bytes(term.getText());
- thriftColumns.add(new Column(requestedKey).setValue(row.key.key).setTimestamp(-1));
- result.schema.name_types.put(requestedKey, TypeParser.getShortName(AsciiType.instance));
- result.schema.value_types.put(requestedKey, TypeParser.getShortName(metadata.getKeyValidator()));
- continue;
- }
-
- if (row.cf == null)
- continue;
-
- ByteBuffer nameBytes;
- try
- {
- nameBytes = term.getByteBuffer(metadata.comparator.asAbstractType(), variables);
- }
- catch (InvalidRequestException e)
- {
- throw new AssertionError(e);
- }
-
- CellName name = metadata.comparator.cellFromByteBuffer(nameBytes);
- ColumnDefinition cd = metadata.getColumnDefinition(name);
- if (cd != null)
- result.schema.value_types.put(nameBytes, TypeParser.getShortName(cd.type));
- org.apache.cassandra.db.Cell c = row.cf.getColumn(name);
- if (c == null || c.isMarkedForDelete(System.currentTimeMillis()))
- thriftColumns.add(new Column().setName(nameBytes));
- else
- thriftColumns.add(thriftify(c));
- }
- }
-
- // Create a new row, add the columns to it, and then add it to the list of rows
- CqlRow cqlRow = new CqlRow();
- cqlRow.key = row.key.key;
- cqlRow.columns = thriftColumns;
- if (select.isColumnsReversed())
- Collections.reverse(cqlRow.columns);
- cqlRows.add(cqlRow);
- }
-
- result.rows = cqlRows;
- return result;
-
- case INSERT: // insert uses UpdateStatement
- case UPDATE:
- UpdateStatement update = (UpdateStatement)statement.statement;
- update.getConsistencyLevel().validateForWrite(keyspace);
-
- keyspace = update.keyspace == null ? clientState.getKeyspace() : update.keyspace;
- // permission is checked in prepareRowMutations()
- List<IMutation> rowMutations = update.prepareRowMutations(keyspace, clientState, variables);
-
- for (IMutation mutation : rowMutations)
- {
- validateKey(mutation.key());
- }
-
- StorageProxy.mutateWithTriggers(rowMutations, update.getConsistencyLevel(), false);
-
- result.type = CqlResultType.VOID;
- return result;
-
- case BATCH:
- BatchStatement batch = (BatchStatement) statement.statement;
- batch.getConsistencyLevel().validateForWrite(keyspace);
-
- if (batch.getTimeToLive() != 0)
- throw new InvalidRequestException("Global TTL on the BATCH statement is not supported.");
-
- for (AbstractModification up : batch.getStatements())
- {
- if (up.isSetConsistencyLevel())
- throw new InvalidRequestException(
- "Consistency level must be set on the BATCH, not individual statements");
-
- if (batch.isSetTimestamp() && up.isSetTimestamp())
- throw new InvalidRequestException(
- "Timestamp must be set either on BATCH or individual statements");
- }
-
- List<IMutation> mutations = batch.getMutations(keyspace, clientState, variables);
- for (IMutation mutation : mutations)
- {
- validateKey(mutation.key());
- }
-
- StorageProxy.mutateWithTriggers(mutations, batch.getConsistencyLevel(), false);
-
- result.type = CqlResultType.VOID;
- return result;
-
- case USE:
- clientState.validateLogin();
- clientState.setKeyspace(CliUtils.unescapeSQLString((String) statement.statement));
-
- result.type = CqlResultType.VOID;
- return result;
-
- case TRUNCATE:
- Pair<String, String> columnFamily = (Pair<String, String>)statement.statement;
- keyspace = columnFamily.left == null ? clientState.getKeyspace() : columnFamily.left;
-
- validateColumnFamily(keyspace, columnFamily.right);
- clientState.hasColumnFamilyAccess(keyspace, columnFamily.right, Permission.MODIFY);
-
- try
- {
- StorageProxy.truncateBlocking(keyspace, columnFamily.right);
- }
- catch (TimeoutException e)
- {
- throw new TruncateException(e);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case DELETE:
- DeleteStatement delete = (DeleteStatement)statement.statement;
-
- keyspace = delete.keyspace == null ? clientState.getKeyspace() : delete.keyspace;
- // permission is checked in prepareRowMutations()
- List<IMutation> deletions = delete.prepareRowMutations(keyspace, clientState, variables);
- for (IMutation deletion : deletions)
- {
- validateKey(deletion.key());
- }
-
- StorageProxy.mutateWithTriggers(deletions, delete.getConsistencyLevel(), false);
-
- result.type = CqlResultType.VOID;
- return result;
-
- case CREATE_KEYSPACE:
- CreateKeyspaceStatement create = (CreateKeyspaceStatement)statement.statement;
- create.validate();
- ThriftValidation.validateKeyspaceNotSystem(create.getName());
- clientState.hasAllKeyspacesAccess(Permission.CREATE);
-
- try
- {
- KSMetaData ksm = KSMetaData.newKeyspace(create.getName(),
- create.getStrategyClass(),
- create.getStrategyOptions(),
- true);
- ThriftValidation.validateKeyspaceNotYetExisting(ksm.name);
- MigrationManager.announceNewKeyspace(ksm);
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case CREATE_COLUMNFAMILY:
- CreateColumnFamilyStatement createCf = (CreateColumnFamilyStatement)statement.statement;
- clientState.hasKeyspaceAccess(keyspace, Permission.CREATE);
-
- try
- {
- MigrationManager.announceNewColumnFamily(createCf.getCFMetaData(keyspace, variables));
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.toString());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case CREATE_INDEX:
- CreateIndexStatement createIdx = (CreateIndexStatement)statement.statement;
- clientState.hasColumnFamilyAccess(keyspace, createIdx.getColumnFamily(), Permission.ALTER);
- CFMetaData oldCfm = Schema.instance.getCFMetaData(keyspace, createIdx.getColumnFamily());
- if (oldCfm == null)
- throw new InvalidRequestException("No such column family: " + createIdx.getColumnFamily());
-
- boolean columnExists = false;
- ByteBuffer columnName = createIdx.getColumnName().getByteBuffer();
- // mutating oldCfm directly would be bad, but mutating a copy is fine.
- CFMetaData cfm = oldCfm.clone();
- for (ColumnDefinition cd : cfm.regularColumns())
- {
- if (cd.name.bytes.equals(columnName))
- {
- if (cd.getIndexType() != null)
- throw new InvalidRequestException("Index already exists");
- if (logger.isDebugEnabled())
- logger.debug("Updating column {} definition for index {}", cfm.comparator.getString(cfm.comparator.fromByteBuffer(columnName)), createIdx.getIndexName());
- cd.setIndexType(IndexType.KEYS, Collections.<String, String>emptyMap());
- cd.setIndexName(createIdx.getIndexName());
- columnExists = true;
- break;
- }
- }
- if (!columnExists)
- throw new InvalidRequestException("No column definition found for column " + oldCfm.comparator.getString(cfm.comparator.fromByteBuffer(columnName)));
-
- try
- {
- cfm.addDefaultIndexNames();
- MigrationManager.announceColumnFamilyUpdate(cfm, true); // As far as metadata are concerned, CQL2 == thrift
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.toString());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case DROP_INDEX:
- DropIndexStatement dropIdx = (DropIndexStatement)statement.statement;
- keyspace = clientState.getKeyspace();
- dropIdx.setKeyspace(keyspace);
- clientState.hasColumnFamilyAccess(keyspace, dropIdx.getColumnFamily(), Permission.ALTER);
-
- try
- {
- CFMetaData updatedCF = dropIdx.generateCFMetadataUpdate();
- MigrationManager.announceColumnFamilyUpdate(updatedCF, true); // As far as metadata are concerned, CQL2 == thrift
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.toString());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case DROP_KEYSPACE:
- String deleteKeyspace = (String)statement.statement;
- ThriftValidation.validateKeyspaceNotSystem(deleteKeyspace);
- clientState.hasKeyspaceAccess(deleteKeyspace, Permission.DROP);
-
- try
- {
- MigrationManager.announceKeyspaceDrop(deleteKeyspace);
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case DROP_COLUMNFAMILY:
- String deleteColumnFamily = (String)statement.statement;
- clientState.hasColumnFamilyAccess(keyspace, deleteColumnFamily, Permission.DROP);
-
- try
- {
- MigrationManager.announceColumnFamilyDrop(keyspace, deleteColumnFamily);
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
-
- case ALTER_TABLE:
- AlterTableStatement alterTable = (AlterTableStatement) statement.statement;
-
- validateColumnFamily(keyspace, alterTable.columnFamily);
- clientState.hasColumnFamilyAccess(keyspace, alterTable.columnFamily, Permission.ALTER);
-
- try
- {
- MigrationManager.announceColumnFamilyUpdate(alterTable.getCFMetaData(keyspace), true); // As far as metadata are concerned, CQL2 == thrift
- }
- catch (ConfigurationException e)
- {
- InvalidRequestException ex = new InvalidRequestException(e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- result.type = CqlResultType.VOID;
- return result;
- }
- return null; // We should never get here.
- }
-
- public static CqlResult process(String queryString, ThriftClientState clientState)
- throws RequestValidationException, RequestExecutionException
- {
- logger.trace("CQL QUERY: {}", queryString);
- return processStatement(getStatement(queryString),
- new ExecutionContext(clientState, queryString, Collections.<ByteBuffer>emptyList()));
- }
-
- public static CqlPreparedResult prepare(String queryString, ThriftClientState clientState)
- throws RequestValidationException
- {
- logger.trace("CQL QUERY: {}", queryString);
-
- CQLStatement statement = getStatement(queryString);
- int statementId = makeStatementId(queryString);
- logger.trace("Discovered "+ statement.boundTerms + " bound variables.");
-
- clientState.getPrepared().put(statementId, statement);
- logger.trace(String.format("Stored prepared statement #%d with %d bind markers",
- statementId,
- statement.boundTerms));
-
- if (!postPreparationHooks.isEmpty())
- {
- PreparationContext context = new PreparationContext(clientState, queryString, statement);
- for (PostPreparationHook hook : postPreparationHooks)
- hook.processStatement(statement, context);
- }
-
- return new CqlPreparedResult(statementId, statement.boundTerms);
- }
-
- public static CqlResult processPrepared(CQLStatement statement, ThriftClientState clientState, List<ByteBuffer> variables)
- throws RequestValidationException, RequestExecutionException
- {
- // Check to see if there are any bound variables to verify
- 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()));
-
- // 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));
- }
-
- return processStatement(statement, new ExecutionContext(clientState, null, variables));
- }
-
- private static final int makeStatementId(String cql)
- {
- // use the hash of the string till something better is provided
- return cql.hashCode();
- }
-
- private static Column thriftify(org.apache.cassandra.db.Cell c)
- {
- ByteBuffer value = (c instanceof CounterCell)
- ? ByteBufferUtil.bytes(CounterContext.instance().total(c.value()))
- : c.value();
- return new Column(c.name().toByteBuffer()).setValue(value).setTimestamp(c.timestamp());
- }
-
- private static CQLStatement getStatement(String queryStr) throws SyntaxException
- {
- try
- {
- // Lexer and parser
- CharStream stream = new ANTLRStringStream(queryStr);
- CqlLexer lexer = new CqlLexer(stream);
- TokenStream tokenStream = new CommonTokenStream(lexer);
- CqlParser parser = new CqlParser(tokenStream);
-
- // Parse the query string to a statement instance
- CQLStatement statement = parser.query();
-
- // The lexer and parser queue up any errors they may have encountered
- // along the way, if necessary, we turn them into exceptions here.
- lexer.throwLastRecognitionError();
- parser.throwLastRecognitionError();
-
- return statement;
- }
- catch (RuntimeException re)
- {
- SyntaxException ire = new SyntaxException("Failed parsing statement: [" + queryStr + "] reason: " + re.getClass().getSimpleName() + " " + re.getMessage());
- throw ire;
- }
- catch (RecognitionException e)
- {
- SyntaxException ire = new SyntaxException("Invalid or malformed CQL query string: " + e.getMessage());
- throw ire;
- }
- }
-
- private static void validateCountOperation(SelectStatement select) throws InvalidRequestException
- {
- if (select.isWildcard())
- return; // valid count(*)
-
- if (!select.isColumnRange())
- {
- List<Term> columnNames = select.getColumnNames();
- String firstColumn = columnNames.get(0).getText();
-
- if (columnNames.size() == 1 && (firstColumn.equals("*") || firstColumn.equals("1")))
- return; // valid count(*) || count(1)
- }
-
- throw new InvalidRequestException("Only COUNT(*) and COUNT(1) operations are currently supported.");
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/Relation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/Relation.java b/src/java/org/apache/cassandra/cql/Relation.java
deleted file mode 100644
index 669c5f2..0000000
--- a/src/java/org/apache/cassandra/cql/Relation.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-/**
- * Relations encapsulate the relationship between an entity of some kind, and
- * a value (term). For example, <key> > "start" or "colname1" = "somevalue".
- *
- */
-public class Relation
-{
- private final Term entity;
- private final RelationType relationType;
- private final Term value;
-
- /**
- * Creates a new relation.
- *
- * @param entity the kind of relation this is; what the term is being compared to.
- * @param type the type that describes how this entity relates to the value.
- * @param value the value being compared.
- */
- public Relation(Term entity, String type, Term value)
- {
- this.entity = entity;
- this.relationType = RelationType.forString(type);
- this.value = value;
- }
-
- public RelationType operator()
- {
- return relationType;
- }
-
- public Term getEntity()
- {
- return entity;
- }
-
- public Term getValue()
- {
- return value;
- }
-
- @Override
- public String toString()
- {
- return String.format("Relation(%s, %s, %s)", entity, relationType, value);
- }
-}
-
-enum RelationType
-{
- EQ, LT, LTE, GTE, GT;
-
- public static RelationType forString(String s)
- {
- if (s.equals("="))
- return EQ;
- else if (s.equals("<"))
- return LT;
- else if (s.equals("<="))
- return LTE;
- else if (s.equals(">="))
- return GTE;
- else if (s.equals(">"))
- return GT;
-
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/SelectExpression.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/SelectExpression.java b/src/java/org/apache/cassandra/cql/SelectExpression.java
deleted file mode 100644
index 4d3cb2f..0000000
--- a/src/java/org/apache/cassandra/cql/SelectExpression.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 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.
- *
- * See: doc/cql/CQL.html#SpecifyingColumns
- */
-public class SelectExpression
-{
- public static final int MAX_COLUMNS_DEFAULT = 10000;
-
- private int numColumns = MAX_COLUMNS_DEFAULT;
- private boolean reverseColumns = false;
- private final boolean hasFirstSet;
- private final boolean wildcard;
- private final Term start, finish;
- private final 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
- * @param wildcard determines weather this statement is wildcard
- * @param firstSet determines weather "FIRST" keyword was set
- */
- public SelectExpression(Term start, Term finish, int count, boolean reverse, boolean wildcard, boolean firstSet)
- {
- this.start = start;
- this.finish = finish;
- numColumns = count;
- reverseColumns = reverse;
- this.wildcard = wildcard;
- hasFirstSet = firstSet;
- this.columns = null;
- }
-
- /**
- * 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
- * @param firstSet determines weather "FIRST" keyword was set
- */
- public SelectExpression(Term first, int count, boolean reverse, boolean firstSet)
- {
- wildcard = false;
- columns = new ArrayList<Term>();
- columns.add(first);
- numColumns = count;
- reverseColumns = reverse;
- hasFirstSet = firstSet;
- start = null;
- finish = null;
- }
-
- /**
- * Add an additional column name to a SelectExpression.
- *
- * @param addTerm
- */
- public void and(Term addTerm)
- {
- assert !isColumnRange(); // Not possible when invoked by parser
- columns.add(addTerm);
- }
-
- public boolean isColumnRange()
- {
- return (start != null);
- }
-
- public boolean isColumnList()
- {
- return !isColumnRange();
- }
- public int getColumnsLimit()
- {
- return numColumns;
- }
-
- public boolean isColumnsReversed()
- {
- return reverseColumns;
- }
-
- public void setColumnsReversed(boolean reversed)
- {
- reverseColumns = reversed;
- }
-
- public void setColumnsLimit(int limit)
- {
- numColumns = limit;
- }
-
- /**
- * @return weather expression includes "FIRST" keyword
- */
- public boolean hasFirstSet()
- {
- return hasFirstSet;
- }
-
- public Term getStart()
- {
- return start;
- }
-
- public Term getFinish()
- {
- return finish;
- }
-
- public List<Term> getColumns()
- {
- return columns;
- }
-
- public boolean isWildcard()
- {
- return wildcard;
- }
-
- public String toString()
- {
- return String.format("SelectExpression [numColumns=%s, reverseColumns=%s, hasFirstSet=%s, wildcard=%s, start=%s, finish=%s, columns=%s]",
- numColumns,
- reverseColumns,
- hasFirstSet,
- wildcard,
- start,
- finish,
- columns);
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/SelectStatement.java b/src/java/org/apache/cassandra/cql/SelectStatement.java
deleted file mode 100644
index b4ccd56..0000000
--- a/src/java/org/apache/cassandra/cql/SelectStatement.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.db.ConsistencyLevel;
-
-/**
- * Encapsulates a completely parsed SELECT query, including the target
- * column family, expression, result count, and ordering clause.
- *
- */
-public class SelectStatement
-{
- private final SelectExpression expression;
- private final boolean isCountOper;
- private final String columnFamily;
- private final String keyspace;
- private final ConsistencyLevel cLevel;
- private final WhereClause clause;
- private final int numRecords;
-
- public SelectStatement(SelectExpression expression, boolean isCountOper, String keyspace, String columnFamily,
- ConsistencyLevel cLevel, WhereClause clause, int numRecords)
- {
- this.expression = expression;
- this.isCountOper = isCountOper;
- this.keyspace = keyspace;
- this.columnFamily = columnFamily;
- this.cLevel = cLevel;
- this.clause = (clause != null) ? clause : new WhereClause();
- this.numRecords = numRecords;
- }
-
- public boolean isKeyRange()
- {
- return clause.isKeyRange();
- }
-
- public Set<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 boolean isWildcard()
- {
- return expression.isWildcard();
- }
- public boolean isFullWildcard()
- {
- return expression.isWildcard() && !expression.hasFirstSet();
- }
-
- public List<Term> getColumnNames()
- {
- return expression.getColumns();
- }
-
- public Term getColumnStart()
- {
- return expression.getStart();
- }
-
- public Term getColumnFinish()
- {
- return expression.getFinish();
- }
-
- public boolean isSetKeyspace()
- {
- return keyspace != null;
- }
-
- public String getKeyspace()
- {
- return keyspace;
- }
-
- public String getColumnFamily()
- {
- return columnFamily;
- }
-
- public boolean isColumnsReversed()
- {
- return expression.isColumnsReversed();
- }
-
- public ConsistencyLevel getConsistencyLevel()
- {
- return cLevel;
- }
-
- public int getNumRecords()
- {
- return numRecords;
- }
-
- public int getColumnsLimit()
- {
- return expression.getColumnsLimit();
- }
-
- public boolean isCountOperation()
- {
- return isCountOper;
- }
-
- public boolean includeStartKey()
- {
- return clause.includeStartKey();
- }
-
- public boolean includeFinishKey()
- {
- return clause.includeFinishKey();
- }
-
- public String getKeyAlias()
- {
- return clause.getKeyAlias();
- }
-
- public boolean isMultiKey()
- {
- return clause.isMultiKey();
- }
-
- public void extractKeyAliasFromColumns(CFMetaData cfm)
- {
- clause.extractKeysFromColumns(cfm);
- }
-
- public List<Relation> getClauseRelations()
- {
- return clause.getClauseRelations();
- }
-
- public String toString()
- {
- return String.format("SelectStatement [expression=%s, isCountOper=%s, columnFamily=%s, keyspace=%s, cLevel=%s, clause=%s, numRecords=%s]",
- expression,
- isCountOper,
- columnFamily,
- keyspace,
- cLevel,
- clause,
- numRecords);
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/StatementType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/StatementType.java b/src/java/org/apache/cassandra/cql/StatementType.java
deleted file mode 100644
index 94db6a3..0000000
--- a/src/java/org/apache/cassandra/cql/StatementType.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.util.EnumSet;
-
-public enum StatementType
-{
- SELECT, INSERT, UPDATE, BATCH, USE, TRUNCATE, DELETE, CREATE_KEYSPACE, CREATE_COLUMNFAMILY, CREATE_INDEX, DROP_INDEX,
- DROP_KEYSPACE, DROP_COLUMNFAMILY, ALTER_TABLE;
-
- /** Statement types that don't require a keyspace to be set */
- private static final EnumSet<StatementType> TOP_LEVEL = EnumSet.of(USE, CREATE_KEYSPACE, DROP_KEYSPACE);
-
- /** Statement types that require a keyspace to be set */
- public static final EnumSet<StatementType> REQUIRES_KEYSPACE = EnumSet.complementOf(TOP_LEVEL);
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/Term.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/Term.java b/src/java/org/apache/cassandra/cql/Term.java
deleted file mode 100644
index 6e47bfa..0000000
--- a/src/java/org/apache/cassandra/cql/Term.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.AsciiType;
-import org.apache.cassandra.db.marshal.FloatType;
-import org.apache.cassandra.db.marshal.IntegerType;
-import org.apache.cassandra.db.marshal.LexicalUUIDType;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.serializers.MarshalException;
-
-/** A term parsed from a CQL statement. */
-public class Term
-{
- private final String text;
- private final TermType type;
- private Integer bindIndex = -1;
-
- public Term(String text, TermType type)
- {
- this.text = text == null ? "" : text;
- this.type = type;
- }
-
- /**
- * Create new Term instance from a string, and an integer that corresponds
- * with the token ID from CQLParser.
- *
- * @param text the text representation of the term.
- * @param type the term's type as an integer token ID.
- */
- public Term(String text, int type)
- {
- this(text == null ? "" : text, TermType.forInt(type));
- }
-
- public Term(long value, TermType type)
- {
- this(String.valueOf(value), type);
- }
-
- protected Term()
- {
- this("", TermType.STRING);
- }
-
- public Term(String text, int type, int index)
- {
- this(text, type);
- this.bindIndex = index;
- }
-
- /**
- * Returns the text parsed to create this term.
- *
- * @return the string term acquired from a CQL statement.
- */
- public String getText()
- {
- return text;
- }
-
- /**
- * Returns the typed value, serialized to a ByteBuffer according to a
- * comparator/validator.
- *
- * @return a ByteBuffer of the value.
- * @throws InvalidRequestException if unable to coerce the string to its type.
- */
- public ByteBuffer getByteBuffer(AbstractType<?> validator, List<ByteBuffer> variables) throws InvalidRequestException
- {
- try
- {
- if (!isBindMarker()) return validator.fromStringCQL2(text);
-
- // must be a marker term so check for a CqlBindValue stored in the term
- if (bindIndex == null)
- throw new AssertionError("a marker Term was encountered with no index value");
-
- return variables.get(bindIndex);
- }
- catch (MarshalException e)
- {
- throw new InvalidRequestException(e.getMessage());
- }
- }
-
- /**
- * Returns the typed value, serialized to a ByteBuffer.
- *
- * @return a ByteBuffer of the value.
- * @throws InvalidRequestException if unable to coerce the string to its type.
- */
- public ByteBuffer getByteBuffer() throws InvalidRequestException
- {
- switch (type)
- {
- case STRING:
- return AsciiType.instance.fromString(text);
- case INTEGER:
- return IntegerType.instance.fromString(text);
- case UUID:
- // we specifically want the Lexical class here, not "UUIDType," because we're supposed to have
- // a uuid-shaped string here, and UUIDType also accepts integer or date strings (and turns them into version 1 uuids).
- return LexicalUUIDType.instance.fromString(text);
- case FLOAT:
- return FloatType.instance.fromString(text);
- }
-
- // FIXME: handle scenario that should never happen
- return null;
- }
-
- /**
- * Obtain the term's type.
- *
- * @return the type
- */
- public TermType getType()
- {
- return type;
- }
-
- public String toString()
- {
- return String.format("Term(%s, type=%s)", getText(), type);
- }
-
- public boolean isBindMarker()
- {
- return type==TermType.QMARK;
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((text == null) ? 0 : text.hashCode());
- result = prime * result + ((type == null) ? 0 : type.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Term other = (Term) obj;
- if (type==TermType.QMARK) return false; // markers are never equal
- if (text == null)
- {
- if (other.text != null)
- return false;
- } else if (!text.equals(other.text))
- return false;
- if (type != other.type)
- return false;
- return true;
- }
-
-
-}
-
-enum TermType
-{
- STRING, INTEGER, UUID, FLOAT, QMARK;
-
- static TermType forInt(int type)
- {
- if ((type == CqlParser.STRING_LITERAL) || (type == CqlParser.IDENT))
- return STRING;
- else if (type == CqlParser.INTEGER)
- return INTEGER;
- else if (type == CqlParser.UUID)
- return UUID;
- else if (type == CqlParser.FLOAT)
- return FLOAT;
- else if (type == CqlParser.QMARK)
- return QMARK;
-
- // FIXME: handled scenario that should never occur.
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/UpdateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/UpdateStatement.java b/src/java/org/apache/cassandra/cql/UpdateStatement.java
deleted file mode 100644
index 16a0d76..0000000
--- a/src/java/org/apache/cassandra/cql/UpdateStatement.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.nio.ByteBuffer;
-import java.util.*;
-
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.composites.CellName;
-import org.apache.cassandra.db.composites.CellNameType;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.thrift.ThriftClientState;
-
-import static org.apache.cassandra.cql.QueryProcessor.validateColumn;
-import static org.apache.cassandra.cql.QueryProcessor.validateKey;
-import static org.apache.cassandra.thrift.ThriftValidation.validateColumnFamily;
-
-/**
- * An <code>UPDATE</code> statement parsed from a CQL query statement.
- *
- */
-public class UpdateStatement extends AbstractModification
-{
- private Map<Term, Operation> columns;
- private List<Term> columnNames, columnValues;
- private final List<Term> keys;
-
- /**
- * Creates a new UpdateStatement from a column family name, columns map, consistency
- * level, and key term.
- *
- * @param keyspace Keyspace (optional)
- * @param columnFamily column family name
- * @param keyName alias key name
- * @param columns a map of column name/values pairs
- * @param keys the keys to update
- * @param attrs additional attributes for statement (CL, timestamp, timeToLive)
- */
- public UpdateStatement(String keyspace,
- String columnFamily,
- String keyName,
- Map<Term, Operation> columns,
- List<Term> keys,
- Attributes attrs)
- {
- super(keyspace, columnFamily, keyName, attrs);
-
- this.columns = columns;
- this.keys = keys;
- }
-
- /**
- * Creates a new UpdateStatement from a column family name, a consistency level,
- * key, and lists of column names and values. It is intended for use with the
- * alternate update format, <code>INSERT</code>.
- *
- * @param keyspace Keyspace (optional)
- * @param columnFamily column family name
- * @param keyName alias key name
- * @param columnNames list of column names
- * @param columnValues list of column values (corresponds to names)
- * @param keys the keys to update
- * @param attrs additional attributes for statement (CL, timestamp, timeToLive)
- */
- public UpdateStatement(String keyspace,
- String columnFamily,
- String keyName,
- List<Term> columnNames,
- List<Term> columnValues,
- List<Term> keys,
- Attributes attrs)
- {
- super(keyspace, columnFamily, keyName, attrs);
-
- this.columnNames = columnNames;
- this.columnValues = columnValues;
- this.keys = keys;
- }
-
- /**
- * Returns the consistency level of this <code>UPDATE</code> statement, either
- * one parsed from the CQL statement, or the default level otherwise.
- *
- * @return the consistency level as a Thrift enum.
- */
- public ConsistencyLevel getConsistencyLevel()
- {
- return (cLevel != null) ? cLevel : defaultConsistency;
- }
-
- /**
- * True if an explicit consistency level was parsed from the statement.
- *
- * @return true if a consistency was parsed, false otherwise.
- */
- public boolean isSetConsistencyLevel()
- {
- return (cLevel != null);
- }
-
- /** {@inheritDoc} */
- public List<IMutation> prepareRowMutations(String keyspace, ThriftClientState clientState, List<ByteBuffer> variables)
- throws InvalidRequestException, UnauthorizedException
- {
- return prepareRowMutations(keyspace, clientState, null, variables);
- }
-
- /** {@inheritDoc} */
- public List<IMutation> prepareRowMutations(String keyspace, ThriftClientState clientState, Long timestamp, List<ByteBuffer> variables)
- throws InvalidRequestException, UnauthorizedException
- {
- boolean hasCommutativeOperation = false;
-
- for (Map.Entry<Term, Operation> column : getColumns().entrySet())
- {
- if (!column.getValue().isUnary())
- hasCommutativeOperation = true;
-
- if (hasCommutativeOperation && column.getValue().isUnary())
- throw new InvalidRequestException("Mix of commutative and non-commutative operations is not allowed.");
- }
-
- CFMetaData metadata = validateColumnFamily(keyspace, columnFamily, hasCommutativeOperation);
- if (hasCommutativeOperation)
- getConsistencyLevel().validateCounterForWrite(metadata);
-
- QueryProcessor.validateKeyAlias(metadata, keyName);
-
- clientState.hasColumnFamilyAccess(keyspace, columnFamily, Permission.MODIFY);
-
- List<IMutation> mutations = new LinkedList<>();
-
- for (Term key: keys)
- mutations.add(mutationForKey(keyspace, key.getByteBuffer(getKeyType(keyspace),variables), metadata, timestamp, clientState, variables));
-
- return mutations;
- }
-
- /**
- * Compute a mutation for a single key
- *
- *
- * @param keyspace working keyspace
- * @param key key to change
- * @param metadata information about CF
- * @param timestamp global timestamp to use for every key mutation
- *
- * @param clientState
- * @return mutation
- *
- * @throws InvalidRequestException on the wrong request
- */
- private IMutation mutationForKey(String keyspace, ByteBuffer key, CFMetaData metadata, Long timestamp, ThriftClientState clientState, List<ByteBuffer> variables)
- throws InvalidRequestException
- {
- validateKey(key);
- CellNameType comparator = metadata.comparator;
- AbstractType<?> at = comparator.asAbstractType();
-
- // if true we need to wrap Mutation into CounterMutation
- boolean hasCounterColumn = false;
- Mutation mutation = new Mutation(keyspace, key);
-
- for (Map.Entry<Term, Operation> column : getColumns().entrySet())
- {
- CellName colName = comparator.cellFromByteBuffer(column.getKey().getByteBuffer(at, variables));
- Operation op = column.getValue();
-
- if (op.isUnary())
- {
- if (hasCounterColumn)
- throw new InvalidRequestException("Mix of commutative and non-commutative operations is not allowed.");
-
- ByteBuffer colValue = op.a.getByteBuffer(metadata.getValueValidator(colName),variables);
-
- validateColumn(metadata, colName, colValue);
- mutation.add(columnFamily,
- colName,
- colValue,
- (timestamp == null) ? getTimestamp(clientState) : timestamp,
- getTimeToLive());
- }
- else
- {
- hasCounterColumn = true;
-
- if (!column.getKey().getText().equals(op.a.getText()))
- throw new InvalidRequestException("Only expressions like X = X + <long> are supported.");
-
- long value;
-
- try
- {
- value = Long.parseLong(op.b.getText());
- }
- catch (NumberFormatException e)
- {
- throw new InvalidRequestException(String.format("'%s' is an invalid value, should be a long.",
- op.b.getText()));
- }
-
- mutation.addCounter(columnFamily, colName, value);
- }
- }
-
- return (hasCounterColumn) ? new CounterMutation(mutation, getConsistencyLevel()) : mutation;
- }
-
- public String getColumnFamily()
- {
- return columnFamily;
- }
-
- public List<Term> getKeys()
- {
- return keys;
- }
-
- public Map<Term, Operation> getColumns() throws InvalidRequestException
- {
- // Created from an UPDATE
- if (columns != null)
- return columns;
-
- // Created from an INSERT
-
- // Don't hate, validate.
- if (columnNames.size() != columnValues.size())
- throw new InvalidRequestException("unmatched column names/values");
- if (columnNames.size() < 1)
- throw new InvalidRequestException("no columns specified for INSERT");
-
- columns = new HashMap<Term, Operation>();
-
- for (int i = 0; i < columnNames.size(); i++)
- columns.put(columnNames.get(i), new Operation(columnValues.get(i)));
-
- return columns;
- }
-
- public String toString()
- {
- return String.format("UpdateStatement(keyspace=%s, columnFamily=%s, keys=%s, columns=%s, consistency=%s, timestamp=%s, timeToLive=%s)",
- keyspace,
- columnFamily,
- keys,
- columns,
- getConsistencyLevel(),
- timestamp,
- timeToLive);
- }
-
- public AbstractType<?> getKeyType(String keyspace)
- {
- return Schema.instance.getCFMetaData(keyspace, columnFamily).getKeyValidator();
- }
-
- public List<Term> getColumnNames()
- {
- return columnNames;
- }
-
- public List<Term> getColumnValues()
- {
- return columnValues;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/WhereClause.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/WhereClause.java b/src/java/org/apache/cassandra/cql/WhereClause.java
deleted file mode 100644
index 3df5102..0000000
--- a/src/java/org/apache/cassandra/cql/WhereClause.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql;
-
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.cassandra.config.CFMetaData;
-
-/**
- * WhereClauses encapsulate all of the predicates of a SELECT query.
- *
- */
-public class WhereClause
-{
- // all relations (except for `<key> IN (.., .., ..)` which can be directly interpreted) from parser
- // are stored into this array and are filtered to the keys/columns by extractKeysFromColumns(...)
- private final List<Relation> clauseRelations = new ArrayList<Relation>();
- private final List<Relation> columns = new ArrayList<Relation>();
-
- // added to either by the parser from an IN clause or by extractKeysFromColumns
- private final Set<Term> keys = new LinkedHashSet<Term>();
- private Term startKey, finishKey;
- private boolean includeStartKey = false, includeFinishKey = false, multiKey = false;
- // set by extractKeysFromColumns
- private String keyAlias = null;
-
- /**
- * 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)
- {
- clauseRelations.add(relation);
- }
-
- /**
- * The same as KEY = <key> to avoid using Relation object
- * @param key key to include into clause
- */
- public void andKeyEquals(Term key)
- {
- keys.add(key);
- }
-
- public List<Relation> getColumnRelations()
- {
- return columns;
- }
-
- public boolean isKeyRange()
- {
- return startKey != null;
- }
-
- public Term getStartKey()
- {
- return startKey;
- }
-
- public Term getFinishKey()
- {
- return finishKey;
- }
-
- public Set<Term> getKeys()
- {
- return keys;
- }
-
- public boolean includeStartKey()
- {
- return includeStartKey;
- }
-
- public boolean includeFinishKey()
- {
- return includeFinishKey;
- }
-
- public void setKeyAlias(String alias)
- {
- keyAlias = alias.toUpperCase();
- }
-
- public boolean isMultiKey() {
- return multiKey;
- }
-
- public void setMultiKey(boolean multiKey)
- {
- this.multiKey = multiKey;
- }
-
- public String getKeyAlias()
- {
- // TODO fix special casing here, key alias should always be set post-extract
- // key alias as not related to keys in here, it can be unset when we have a query like
- // SELECT * FROM <CF> WHERE key = 1 and col > 2 and col < 3;
- // it will be always set when statement looks like this
- // SELECT * FROM <CF> WHERE <key> IN (.., .., ..);
- // key is NULL when KEY keyword is used or when key alias given by user was not recognized
- // validateKeyAlias will throw an exception for us in that case
- return keyAlias == null ? QueryProcessor.DEFAULT_KEY_NAME : keyAlias;
- }
-
- public void extractKeysFromColumns(CFMetaData cfm)
- {
- String realKeyAlias = cfm.getCQL2KeyName();
-
- if (!keys.isEmpty())
- return; // we already have key(s) set (<key> IN (.., ...) construction used)
-
- for (Relation relation : clauseRelations)
- {
- String name = relation.getEntity().getText().toUpperCase();
- if (name.equals(realKeyAlias))
- {
- if (keyAlias == null) // setting found key as an alias
- keyAlias = name;
-
- if (relation.operator() == RelationType.EQ)
- {
- keys.add(relation.getValue());
- }
- else if ((relation.operator() == RelationType.GT) || (relation.operator() == RelationType.GTE))
- {
- startKey = relation.getValue();
- includeStartKey = relation.operator() == RelationType.GTE;
- }
- else if ((relation.operator() == RelationType.LT) || (relation.operator() == RelationType.LTE))
- {
- finishKey = relation.getValue();
- includeFinishKey = relation.operator() == RelationType.LTE;
- }
- }
- else
- {
- columns.add(relation);
- }
- }
- }
-
- public List<Relation> getClauseRelations()
- {
- return clauseRelations;
- }
-
- public String toString()
- {
- return String.format("WhereClause [keys=%s, startKey=%s, finishKey=%s, columns=%s, includeStartKey=%s, includeFinishKey=%s, multiKey=%s, keyAlias=%s]",
- keys,
- startKey,
- finishKey,
- columns,
- includeStartKey,
- includeFinishKey,
- multiKey,
- keyAlias);
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/hooks/ExecutionContext.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/hooks/ExecutionContext.java b/src/java/org/apache/cassandra/cql/hooks/ExecutionContext.java
deleted file mode 100644
index deb785c..0000000
--- a/src/java/org/apache/cassandra/cql/hooks/ExecutionContext.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql.hooks;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-
-import com.google.common.base.Optional;
-
-import org.apache.cassandra.thrift.ThriftClientState;
-
-/**
- * Contextual information about the execution of a CQLStatement.
- * Used by {@link org.apache.cassandra.cql.hooks.PreExecutionHook}
- *
- * The CQL string representing the statement being executed is optional
- * and is not present for prepared statements. Contexts created for the
- * execution of regular (i.e. non-prepared) statements will always
- * contain a CQL string.
- */
-public class ExecutionContext
-{
- public final ThriftClientState clientState;
- public final Optional<String> queryString;
- public final List<ByteBuffer> variables;
-
- public ExecutionContext(ThriftClientState clientState, String queryString, List<ByteBuffer> variables)
- {
- this.clientState = clientState;
- this.queryString = Optional.fromNullable(queryString);
- this.variables = variables;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26217071/src/java/org/apache/cassandra/cql/hooks/PostPreparationHook.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/hooks/PostPreparationHook.java b/src/java/org/apache/cassandra/cql/hooks/PostPreparationHook.java
deleted file mode 100644
index 1de9c70..0000000
--- a/src/java/org/apache/cassandra/cql/hooks/PostPreparationHook.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-package org.apache.cassandra.cql.hooks;
-
-import org.apache.cassandra.cql.CQLStatement;
-import org.apache.cassandra.exceptions.RequestValidationException;
-
-/**
- * Run directly after a CQL Statement is prepared in
- * {@link org.apache.cassandra.cql.QueryProcessor}.
- */
-public interface PostPreparationHook
-{
- /**
- * Called in QueryProcessor, once a CQL statement has been prepared.
- *
- * @param statement the statement to perform additional processing on
- * @param context preparation context containing additional info
- * about the operation and statement
- * @throws RequestValidationException
- */
- void processStatement(CQLStatement statement, PreparationContext context) throws RequestValidationException;
-}