Skip to content

Commit

Permalink
Add AlterKeyspace statement to 1.1
Browse files Browse the repository at this point in the history
patch by slebresne; reviewed by xedin for CASSANDRA-4611
  • Loading branch information
Sylvain Lebresne committed Oct 4, 2012
1 parent 59a6a5d commit 2ce7b9b
Show file tree
Hide file tree
Showing 11 changed files with 387 additions and 153 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* Fix CQL3 'is reversed' logic (CASSANDRA-4716)
* (CQL3) Don't return ReversedType in result set metadata (CASSANDRA-4717)
* Pluggable Thrift transport factories for CLI (CASSANDRA-4609)
* Backport adding AlterKeyspace statement (CASSANDRA-4611)
Merged from 1.0:
* Switch from NBHM to CHM in MessagingService's callback map, which
prevents OOM in long-running instances (CASSANDRA-4708)
Expand Down
8 changes: 4 additions & 4 deletions src/java/org/apache/cassandra/config/KSMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ public final class KSMetaData
}

// For new user created keyspaces (through CQL)
public static KSMetaData newKeyspace(String name, String strategyName, Map<String, String> options) throws ConfigurationException
public static KSMetaData newKeyspace(String name, String strategyName, Map<String, String> options, boolean durableWrites) throws ConfigurationException
{
Class<? extends AbstractReplicationStrategy> cls = AbstractReplicationStrategy.getClass(strategyName);
if (cls.equals(LocalStrategy.class))
throw new ConfigurationException("Unable to use given strategy class: LocalStrategy is reserved for internal use.");

return newKeyspace(name, cls, options, Collections.<CFMetaData>emptyList());
return newKeyspace(name, cls, options, durableWrites, Collections.<CFMetaData>emptyList());
}

public static KSMetaData newKeyspace(String name, Class<? extends AbstractReplicationStrategy> strategyClass, Map<String, String> options, Iterable<CFMetaData> cfDefs)
public static KSMetaData newKeyspace(String name, Class<? extends AbstractReplicationStrategy> strategyClass, Map<String, String> options, boolean durablesWrites, Iterable<CFMetaData> cfDefs)
{
return new KSMetaData(name, strategyClass, options, true, cfDefs);
return new KSMetaData(name, strategyClass, options, durablesWrites, cfDefs);
}

public static KSMetaData cloneWith(KSMetaData ksm, Iterable<CFMetaData> cfDefs)
Expand Down
3 changes: 2 additions & 1 deletion src/java/org/apache/cassandra/cql/QueryProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,8 @@ else if (oldKeyspace == null)
{
KSMetaData ksm = KSMetaData.newKeyspace(create.getName(),
create.getStrategyClass(),
create.getStrategyOptions());
create.getStrategyOptions(),
true);
ThriftValidation.validateKeyspaceNotYetExisting(ksm.name);
MigrationManager.announceNewKeyspace(ksm);
validateSchemaIsSettled();
Expand Down
123 changes: 19 additions & 104 deletions src/java/org/apache/cassandra/cql3/CFPropDefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@
*/
package org.apache.cassandra.cql3;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ConfigurationException;
import org.apache.cassandra.db.compaction.AbstractCompactionStrategy;
Expand All @@ -29,12 +38,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class CFPropDefs
public class CFPropDefs extends PropertyDefinitions
{
private static Logger logger = LoggerFactory.getLogger(CFPropDefs.class);

Expand Down Expand Up @@ -89,7 +93,6 @@ public class CFPropDefs
allowedKeywords.addAll(obsoleteKeywords);
}

public final Map<String, String> properties = new HashMap<String, String>();
private Class<? extends AbstractCompactionStrategy> compactionStrategyClass = null;
public final Map<String, String> compactionStrategyOptions = new HashMap<String, String>();
public final Map<String, String> compressionParameters = new HashMap<String, String>()
Expand All @@ -115,18 +118,9 @@ public static AbstractType<?> parseType(String type) throws InvalidRequestExcept
}
}

/* If not comparator/validator is not specified, default to text (BytesType is the wrong default for CQL
* since it uses hex terms). If the value specified is not found in the comparators map, assume the user
* knows what they are doing (a custom comparator/validator for example), and pass it on as-is.
*/

public void validate() throws ConfigurationException
public void validate() throws ConfigurationException, InvalidRequestException
{
// Catch the case where someone passed a kwarg that is not recognized.
for (String bogus : Sets.difference(properties.keySet(), allowedKeywords))
throw new ConfigurationException(bogus + " is not a valid keyword argument for CREATE TABLE");
for (String obsolete : Sets.intersection(properties.keySet(), obsoleteKeywords))
logger.warn("Ignoring obsolete property {}", obsolete);
validate(keywords, obsoleteKeywords);

if (properties.containsKey(KW_COMPACTION_STRATEGY_CLASS))
{
Expand All @@ -135,8 +129,8 @@ public void validate() throws ConfigurationException
}
}

/** Map a keyword to the corresponding value */
public void addProperty(String name, String value)
@Override
public void addProperty(String name, String value) throws InvalidRequestException
{
String[] composite = name.split(":");
if (composite.length > 1)
Expand All @@ -152,24 +146,13 @@ else if (composite[0].equals(COMPRESSION_PARAMETERS_PREFIX))
return;
}
}
properties.put(name, value);
}

public void addAll(Map<String, String> propertyMap)
{
for (Map.Entry<String, String> entry : propertyMap.entrySet())
addProperty(entry.getKey(), entry.getValue());
}

public Boolean hasProperty(String name)
{
return properties.containsKey(name);
super.addProperty(name, value);
}

public void applyToCFMetadata(CFMetaData cfm) throws ConfigurationException
public void applyToCFMetadata(CFMetaData cfm) throws ConfigurationException, InvalidRequestException
{
if (hasProperty(KW_COMMENT))
cfm.comment(get(KW_COMMENT));
cfm.comment(getString(KW_COMMENT, ""));

cfm.readRepairChance(getDouble(KW_READREPAIRCHANCE, cfm.getReadRepairChance()));
cfm.dcLocalReadRepairChance(getDouble(KW_DCLOCALREADREPAIRCHANCE, cfm.getDcLocalReadRepair()));
Expand All @@ -181,80 +164,12 @@ public void applyToCFMetadata(CFMetaData cfm) throws ConfigurationException
cfm.bloomFilterFpChance(getDouble(KW_BF_FP_CHANCE, cfm.getBloomFilterFpChance()));

if (compactionStrategyClass != null)
{
cfm.compactionStrategyClass(compactionStrategyClass);

if (!compactionStrategyOptions.isEmpty())
cfm.compactionStrategyOptions(new HashMap<String, String>(compactionStrategyOptions));

if (!compressionParameters.isEmpty())
cfm.compressionParameters(CompressionParameters.create(compressionParameters));
}

public String get(String name)
{
return properties.get(name);
}

public String getString(String key, String defaultValue)
{
String value = properties.get(key);
return value != null ? value : defaultValue;
}

// Return a property value, typed as a Boolean
public Boolean getBoolean(String key, Boolean defaultValue)
{
String value = properties.get(key);
return (value == null) ? defaultValue : value.toLowerCase().matches("(1|true|yes)");
}

// Return a property value, typed as a Double
public Double getDouble(String key, Double defaultValue) throws ConfigurationException
{
Double result;
String value = properties.get(key);

if (value == null)
result = defaultValue;
else
{
try
{
result = Double.parseDouble(value);
}
catch (NumberFormatException e)
{
throw new ConfigurationException(String.format("%s not valid for \"%s\"", value, key));
}
}
return result;
}

// Return a property value, typed as an Integer
public Integer getInt(String key, Integer defaultValue) throws ConfigurationException
{
String value = properties.get(key);
return toInt(key, value, defaultValue);
}

public static Integer toInt(String key, String value, Integer defaultValue) throws ConfigurationException
{
Integer result;

if (value == null)
result = defaultValue;
else
{
try
{
result = Integer.parseInt(value);
}
catch (NumberFormatException e)
{
throw new ConfigurationException(String.format("%s not valid for \"%s\"", value, key));
}
}
return result;
cfm.compressionParameters(CompressionParameters.create(compressionParameters));
}

@Override
Expand Down
35 changes: 25 additions & 10 deletions src/java/org/apache/cassandra/cql3/Cql.g
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ cqlStatement returns [ParsedStatement stmt]
| st15=grantStatement { $stmt = st15; }
| st16=revokeStatement { $stmt = st16; }
| st17=listGrantsStatement { $stmt = st17; }
| st18=alterKeyspaceStatement { $stmt = st18; }
;

/*
Expand Down Expand Up @@ -341,8 +342,9 @@ batchStatementObjective returns [ModificationStatement statement]
* CREATE KEYSPACE <KEYSPACE> WITH attr1 = value1 AND attr2 = value2;
*/
createKeyspaceStatement returns [CreateKeyspaceStatement expr]
@init { KSPropDefs attrs = new KSPropDefs(); }
: K_CREATE K_KEYSPACE ks=keyspaceName
K_WITH props=properties { $expr = new CreateKeyspaceStatement(ks, props); }
K_WITH properties[attrs] { $expr = new CreateKeyspaceStatement(ks, attrs); }
;

/**
Expand All @@ -368,7 +370,7 @@ cfamColumns[CreateColumnFamilyStatement.RawStatement expr]
;

cfamProperty[CreateColumnFamilyStatement.RawStatement expr]
: k=property '=' v=propertyValue { $expr.addProperty(k, v); }
: k=propertyKey '=' v=propertyValue { try { $expr.addProperty(k, v); } catch (InvalidRequestException e) { addRecognitionError(e.getMessage()); } }
| K_COMPACT K_STORAGE { $expr.setCompactStorage(); }
| K_CLUSTERING K_ORDER K_BY '(' cfamOrdering[expr] (',' cfamOrdering[expr])* ')'
;
Expand All @@ -386,6 +388,16 @@ createIndexStatement returns [CreateIndexStatement expr]
{ $expr = new CreateIndexStatement(cf, $idxName.text, id); }
;

/**
* ALTER KEYSPACE <KS> WITH <property> = <value>;
*/
alterKeyspaceStatement returns [AlterKeyspaceStatement expr]
@init { KSPropDefs attrs = new KSPropDefs(); }
: K_ALTER K_KEYSPACE ks=keyspaceName
K_WITH properties[attrs] { $expr = new AlterKeyspaceStatement(ks, attrs); }
;


/**
* ALTER COLUMN FAMILY <CF> ALTER <column> TYPE <newtype>;
* ALTER COLUMN FAMILY <CF> ADD <column> <newtype>;
Expand All @@ -395,13 +407,13 @@ createIndexStatement returns [CreateIndexStatement expr]
alterTableStatement returns [AlterTableStatement expr]
@init {
AlterTableStatement.Type type = null;
props = new HashMap<String, String>();
CFPropDefs props = new CFPropDefs();
}
: K_ALTER K_COLUMNFAMILY cf=columnFamilyName
( K_ALTER id=cident K_TYPE v=comparatorType { type = AlterTableStatement.Type.ALTER; }
| K_ADD id=cident v=comparatorType { type = AlterTableStatement.Type.ADD; }
| K_DROP id=cident { type = AlterTableStatement.Type.DROP; }
| K_WITH props=properties { type = AlterTableStatement.Type.OPTS; }
| K_WITH properties[props] { type = AlterTableStatement.Type.OPTS; }
)
{
$expr = new AlterTableStatement(cf, type, id, v, props);
Expand Down Expand Up @@ -545,7 +557,15 @@ termPairWithOperation[Map<ColumnIdentifier, Operation> columns]
)
;

property returns [String str]
properties[PropertyDefinitions props]
: property[props] (K_AND property[props])*
;

property[PropertyDefinitions props]
: k=propertyKey '=' simple=propertyValue { try { $props.addProperty(k, simple); } catch (InvalidRequestException e) { addRecognitionError(e.getMessage()); } }
;

propertyKey returns [String str]
@init{ StringBuilder sb = new StringBuilder(); }
: c1=cident { sb.append(c1); } ( ':' cn=cident { sb.append(':').append(cn); } )* { $str = sb.toString(); }
;
Expand All @@ -555,11 +575,6 @@ propertyValue returns [String str]
| u=unreserved_keyword { $str = u; }
;

properties returns [Map<String, String> props]
@init{ $props = new HashMap<String, String>(); }
: k1=property '=' v1=propertyValue { $props.put(k1, v1); } (K_AND kn=property '=' vn=propertyValue { $props.put(kn, vn); } )*
;

relation returns [Relation rel]
: name=cident type=('=' | '<' | '<=' | '>=' | '>') t=term { $rel = new Relation($name.id, $type.text, $t.term); }
| K_TOKEN '(' name=cident ')' type=('=' |'<' | '<=' | '>=' | '>') t=extendedTerm { $rel = new Relation($name.id, $type.text, $t.term, true); }
Expand Down
Loading

0 comments on commit 2ce7b9b

Please sign in to comment.