mirror of https://github.com/apache/cassandra
Updated CREATE CUSTOM INDEX syntax
patch by Aleksey Yeschenko; reviewed by Sylvain Lebresne for CASSANDRA-5639
This commit is contained in:
parent
e5c34d7c29
commit
2397bc8c33
|
|
@ -27,6 +27,7 @@
|
|||
* don't throw away initial causes exceptions for internode encryption issues (CASSANDRA-5644)
|
||||
* Fix message spelling errors for cql select statements (CASSANDRA-5647)
|
||||
* Suppress custom exceptions thru jmx (CASSANDRA-5652)
|
||||
* Update CREATE CUSTOM INDEX syntax (CASSANDRA-5639)
|
||||
Merged from 1.1:
|
||||
* Remove buggy thrift max message length option (CASSANDRA-5529)
|
||||
* Fix NPE in Pig's widerow mode (CASSANDRA-5488)
|
||||
|
|
|
|||
3
NEWS.txt
3
NEWS.txt
|
|
@ -17,6 +17,9 @@ Upgrading
|
|||
proportional to the number of nodes in the cluster (see
|
||||
https://issues.apache.org/jira/browse/CASSANDRA-5272).
|
||||
|
||||
- CQL3 syntax for CREATE CUSTOM INDEX has been updated. See CQL3
|
||||
documentation for details.
|
||||
|
||||
|
||||
1.2.5
|
||||
=====
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ exit 1
|
|||
from __future__ import with_statement
|
||||
|
||||
description = "CQL Shell for Apache Cassandra"
|
||||
version = "3.1.1"
|
||||
version = "3.1.2"
|
||||
|
||||
from StringIO import StringIO
|
||||
from itertools import groupby
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<link rel="StyleSheet" href="CQL.css" type="text/css" media="screen">
|
||||
|
||||
h1. Cassandra Query Language (CQL) v3.0.3
|
||||
h1. Cassandra Query Language (CQL) v3.0.4
|
||||
|
||||
|
||||
<span id="tableOfContents">
|
||||
|
|
@ -392,14 +392,14 @@ h3(#createIndexStmt). CREATE INDEX
|
|||
__Syntax:__
|
||||
|
||||
bc(syntax). <create-index-stmt> ::= CREATE ( CUSTOM )? INDEX <identifier>? ON <tablename> '(' <identifier> ')'
|
||||
( WITH <properties> )?
|
||||
( USING <string> )?
|
||||
|
||||
__Sample:__
|
||||
|
||||
bc(sample).
|
||||
CREATE INDEX userIndex ON NerdMovies (user);
|
||||
CREATE INDEX ON Mutants (abilityId);
|
||||
CREATE CUSTOM INDEX ON users (email) WITH options = {'class': 'path.to.the.IndexClass'};
|
||||
CREATE CUSTOM INDEX ON users (email) USING 'path.to.the.IndexClass';
|
||||
|
||||
The @CREATE INDEX@ statement is used to create a new (automatic) secondary index for a given (existing) column in a given table. A name for the index itself can be specified before the @ON@ keyword, if desired. If data already exists for the column, it will be indexed during the execution of this statement. After the index is created, new data for the column is indexed automatically at insertion time.
|
||||
|
||||
|
|
@ -1048,6 +1048,10 @@ h2(#changes). Changes
|
|||
|
||||
The following describes the addition/changes brought for each version of CQL.
|
||||
|
||||
h3. 3.0.4
|
||||
|
||||
* Updated the syntax for custom "secondary indexes":#createIndexStmt.
|
||||
|
||||
h3. 3.0.3
|
||||
|
||||
* Support for custom "secondary indexes":#createIndexStmt has been added.
|
||||
|
|
|
|||
|
|
@ -1204,7 +1204,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
|
|||
syntax_rules += r'''
|
||||
<createIndexStatement> ::= "CREATE" "CUSTOM"? "INDEX" indexname=<identifier>? "ON"
|
||||
cf=<columnFamilyName> "(" col=<cident> ")"
|
||||
( "WITH" "options = {'class': " <stringLiteral> "}" )?
|
||||
( "USING" <stringLiteral> )?
|
||||
;
|
||||
'''
|
||||
|
||||
|
|
|
|||
|
|
@ -451,16 +451,16 @@ cfamOrdering[CreateColumnFamilyStatement.RawStatement expr]
|
|||
;
|
||||
|
||||
/**
|
||||
* CREATE INDEX [indexName] ON columnFamily (columnName);
|
||||
* CREATE INDEX [indexName] ON <columnFamily> (<columnName>);
|
||||
* CREATE CUSTOM INDEX [indexName] ON <columnFamily> (<columnName>) USING <indexClass>;
|
||||
*/
|
||||
createIndexStatement returns [CreateIndexStatement expr]
|
||||
@init {
|
||||
boolean isCustom = false;
|
||||
IndexPropDefs props = new IndexPropDefs();
|
||||
}
|
||||
: K_CREATE (K_CUSTOM { isCustom = true; })? K_INDEX (idxName=IDENT)? K_ON cf=columnFamilyName '(' id=cident ')'
|
||||
( K_WITH properties[props] )?
|
||||
{ $expr = new CreateIndexStatement(cf, $idxName.text, id, isCustom, props); }
|
||||
( K_USING cls=STRING_LITERAL )?
|
||||
{ $expr = new CreateIndexStatement(cf, $idxName.text, id, isCustom, $cls.text); }
|
||||
;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,68 +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.cql3;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cassandra.db.index.SecondaryIndex;
|
||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||
import org.apache.cassandra.exceptions.RequestValidationException;
|
||||
import org.apache.cassandra.exceptions.SyntaxException;
|
||||
|
||||
public class IndexPropDefs extends PropertyDefinitions
|
||||
{
|
||||
public static final String KW_OPTIONS = "options";
|
||||
|
||||
public static final Set<String> keywords = new HashSet<String>();
|
||||
public static final Set<String> obsoleteKeywords = new HashSet<String>();
|
||||
|
||||
public static final String INDEX_CLASS_KEY = "class";
|
||||
|
||||
static
|
||||
{
|
||||
keywords.add(KW_OPTIONS);
|
||||
}
|
||||
|
||||
public void validate(boolean isCustom) throws RequestValidationException
|
||||
{
|
||||
validate(keywords, obsoleteKeywords);
|
||||
if (isCustom && !getOptions().containsKey(SecondaryIndex.CUSTOM_INDEX_OPTION_NAME))
|
||||
throw new InvalidRequestException(String.format("Custom index requires '%s' option to be specified", INDEX_CLASS_KEY));
|
||||
if (!isCustom && !getOptions().isEmpty())
|
||||
throw new InvalidRequestException(String.format("Only custom indexes can currently be parametrized"));
|
||||
}
|
||||
|
||||
public Map<String, String> getOptions() throws SyntaxException
|
||||
{
|
||||
Map<String, String> options = getMap(KW_OPTIONS);
|
||||
|
||||
if (options == null)
|
||||
return Collections.emptyMap();
|
||||
|
||||
if (!options.isEmpty() && options.containsKey(INDEX_CLASS_KEY))
|
||||
{
|
||||
options.put(SecondaryIndex.CUSTOM_INDEX_OPTION_NAME, options.get(INDEX_CLASS_KEY));
|
||||
options.remove(INDEX_CLASS_KEY);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ import org.apache.cassandra.utils.SemanticVersion;
|
|||
|
||||
public class QueryProcessor
|
||||
{
|
||||
public static final SemanticVersion CQL_VERSION = new SemanticVersion("3.0.3");
|
||||
public static final SemanticVersion CQL_VERSION = new SemanticVersion("3.0.4");
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(QueryProcessor.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,15 +47,15 @@ public class CreateIndexStatement extends SchemaAlteringStatement
|
|||
private final String indexName;
|
||||
private final ColumnIdentifier columnName;
|
||||
private final boolean isCustom;
|
||||
private final IndexPropDefs props;
|
||||
private final String indexClass;
|
||||
|
||||
public CreateIndexStatement(CFName name, String indexName, ColumnIdentifier columnName, boolean isCustom, IndexPropDefs props)
|
||||
public CreateIndexStatement(CFName name, String indexName, ColumnIdentifier columnName, boolean isCustom, String indexClass)
|
||||
{
|
||||
super(name);
|
||||
this.indexName = indexName;
|
||||
this.columnName = columnName;
|
||||
this.isCustom = isCustom;
|
||||
this.props = props;
|
||||
this.indexClass = indexClass;
|
||||
}
|
||||
|
||||
public void checkAccess(ClientState state) throws UnauthorizedException, InvalidRequestException
|
||||
|
|
@ -81,14 +81,14 @@ public class CreateIndexStatement extends SchemaAlteringStatement
|
|||
throw new InvalidRequestException(String.format("Cannot create index on column %s of compact CF", columnName));
|
||||
case COLUMN_METADATA:
|
||||
ColumnDefinition cd = cfm.getColumnDefinition(columnName.key);
|
||||
|
||||
if (cd.getIndexType() != null)
|
||||
throw new InvalidRequestException("Index already exists");
|
||||
|
||||
if (isCustom && indexClass == null)
|
||||
throw new InvalidRequestException("CUSTOM index requires specifiying the index class");
|
||||
if (!isCustom && indexClass != null)
|
||||
throw new InvalidRequestException("Cannot specify index class for a non-CUSTOM index");
|
||||
if (cd.getValidator().isCollection() && !isCustom)
|
||||
throw new InvalidRequestException("Indexes on collections are no yet supported");
|
||||
|
||||
props.validate(isCustom);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
|
|
@ -104,14 +104,7 @@ public class CreateIndexStatement extends SchemaAlteringStatement
|
|||
|
||||
if (isCustom)
|
||||
{
|
||||
try
|
||||
{
|
||||
cd.setIndexType(IndexType.CUSTOM, props.getOptions());
|
||||
}
|
||||
catch (SyntaxException e)
|
||||
{
|
||||
throw new AssertionError(); // can't happen after validation.
|
||||
}
|
||||
cd.setIndexType(IndexType.CUSTOM, Collections.singletonMap(SecondaryIndex.CUSTOM_INDEX_OPTION_NAME, indexClass));
|
||||
}
|
||||
else if (cfDef.isComposite)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue