Updated Branches: refs/heads/trunk f61d88488 -> 769fe895a
Update CQL pseudo-maps to real maps patch by xedin; reviewed by slebresne for CASSANDRA-4497 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/769fe895 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/769fe895 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/769fe895 Branch: refs/heads/trunk Commit: 769fe895a36868c47101f681f5fdd721bee1ad62 Parents: 3bfe5fb Author: Sylvain Lebresne <[email protected]> Authored: Tue Sep 4 19:41:33 2012 +0200 Committer: Sylvain Lebresne <[email protected]> Committed: Tue Sep 4 19:41:33 2012 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + NEWS.txt | 10 ++- .../org/apache/cassandra/config/CFMetaData.java | 3 +- src/java/org/apache/cassandra/cql3/CFPropDefs.java | 59 +++++++++------ src/java/org/apache/cassandra/cql3/Cql.g | 41 ++++++++--- .../cql3/statements/AlterTableStatement.java | 6 +- .../statements/CreateColumnFamilyStatement.java | 7 +-- .../cql3/statements/CreateKeyspaceStatement.java | 31 +++++--- 8 files changed, 103 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 256d5ec..d6b40ba 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -46,6 +46,7 @@ * (cql3) fix defining more than one PK to be invalid (CASSANDRA-4477) * remove schema agreement checking from all external APIs (Thrift, CQL and CQL3) (CASSANDRA-4487) * add Murmur3Partitioner and make it default for new installations (CASSANDRA-3772) + * (cql3) update pseudo-map syntax to use map syntax (CASSANDRA-4497) 1.1.5 http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/NEWS.txt ---------------------------------------------------------------------- diff --git a/NEWS.txt b/NEWS.txt index 56bb1dc..731040a 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -31,7 +31,7 @@ Upgrading remove nodes in this way with a mixed 1.1 (or lower) / 1.2 cluster, is not supported. - The somewhat ill-concieved CollatingOrderPreservingPartitioner - has been removed. Use RandomPartitioner (recommended) or + has been removed. Use Murmur3Partitioner (recommended) or ByteOrderedPartitioner instead. - Global option hinted_handoff_throttle_delay_in_ms has been removed. hinted_handoff_throttle_in_kb has been added instead. @@ -41,6 +41,14 @@ Upgrading - The default partitioner was changed from RandomPartitioner to Murmur3Partitioner which provides faster hashing as well as improved performance with secondary indexes. + - CQL3 is now considered final in this release. Compared to the beta + version that is part of 1.1, this final version has a few additions + (collections), but also some changes in the syntax for the options of the + create/alter keyspace/table statements. Typically, the syntax to create a + keyspace is now: + CREATE KEYSPACE ks WITH replication = { 'class' : 'CompactionStrategy', + 'replication_faction' : 2 }; + Please refer to the CQL3 documentation for details. Features -------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/config/CFMetaData.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java index bb9a5a6..dbe0c6f 100644 --- a/src/java/org/apache/cassandra/config/CFMetaData.java +++ b/src/java/org/apache/cassandra/config/CFMetaData.java @@ -149,8 +149,7 @@ public final class CFMetaData + "mutation blob," + "PRIMARY KEY (target_id, hint_id, message_version)" + ") WITH COMPACT STORAGE " - + "AND COMPACTION_STRATEGY_OPTIONS:MIN_COMPACTION_THRESHOLD=0 " - + "AND COMPACTION_STRATEGY_OPTIONS:MAX_COMPACTION_THRESHOLD=0 " + + "AND COMPACTION={'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 0, 'max_threshold' : 0} " + "AND COMMENT='hints awaiting delivery'"); public static final CFMetaData PeersCf = compile(12, "CREATE TABLE " + SystemTable.PEERS_CF + " (" http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/CFPropDefs.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/CFPropDefs.java b/src/java/org/apache/cassandra/cql3/CFPropDefs.java index db85522..b7207fe 100644 --- a/src/java/org/apache/cassandra/cql3/CFPropDefs.java +++ b/src/java/org/apache/cassandra/cql3/CFPropDefs.java @@ -20,8 +20,8 @@ package org.apache.cassandra.cql3; import com.google.common.collect.Sets; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ConfigurationException; -import org.apache.cassandra.io.compress.CompressionParameters; import org.apache.cassandra.db.compaction.AbstractCompactionStrategy; +import org.apache.cassandra.io.compress.CompressionParameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,10 +38,10 @@ public class CFPropDefs public static final String KW_READREPAIRCHANCE = "read_repair_chance"; public static final String KW_DCLOCALREADREPAIRCHANCE = "dclocal_read_repair_chance"; public static final String KW_GCGRACESECONDS = "gc_grace_seconds"; - public static final String KW_MINCOMPACTIONTHRESHOLD = "min_compaction_threshold"; - public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_compaction_threshold"; + public static final String KW_MINCOMPACTIONTHRESHOLD = "min_threshold"; + public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_threshold"; public static final String KW_REPLICATEONWRITE = "replicate_on_write"; - public static final String KW_COMPACTION_STRATEGY_CLASS = "compaction_strategy_class"; + public static final String KW_COMPACTION_STRATEGY_CLASS = "class"; public static final String KW_CACHING = "caching"; public static final String KW_BF_FP_CHANCE = "bloom_filter_fp_chance"; @@ -50,8 +50,8 @@ public class CFPropDefs public static final Set<String> obsoleteKeywords = new HashSet<String>(); public static final Set<String> allowedKeywords = new HashSet<String>(); - public static final String COMPACTION_OPTIONS_PREFIX = "compaction_strategy_options"; - public static final String COMPRESSION_PARAMETERS_PREFIX = "compression_parameters"; + public static final String COMPACTION_PARAMETERS = "compaction"; + public static final String COMPRESSION_PARAMETERS = "compression"; static { @@ -60,10 +60,16 @@ public class CFPropDefs keywords.add(KW_DCLOCALREADREPAIRCHANCE); keywords.add(KW_GCGRACESECONDS); keywords.add(KW_REPLICATEONWRITE); - keywords.add(KW_COMPACTION_STRATEGY_CLASS); keywords.add(KW_CACHING); keywords.add(KW_BF_FP_CHANCE); + obsoleteKeywords.add("compaction_strategy_class"); + obsoleteKeywords.add("compaction_strategy_options"); + obsoleteKeywords.add("min_compaction_threshold"); + obsoleteKeywords.add("max_compaction_threshold"); + obsoleteKeywords.add("compaction_parameters"); + obsoleteKeywords.add("compression_parameters"); + allowedKeywords.addAll(keywords); allowedKeywords.addAll(obsoleteKeywords); } @@ -85,31 +91,38 @@ public class CFPropDefs for (String obsolete : Sets.intersection(properties.keySet(), obsoleteKeywords)) logger.warn("Ignoring obsolete property {}", obsolete); - if (properties.containsKey(KW_COMPACTION_STRATEGY_CLASS)) + if (!compactionStrategyOptions.isEmpty()) { - compactionStrategyClass = CFMetaData.createCompactionStrategy(properties.get(KW_COMPACTION_STRATEGY_CLASS)); - compactionStrategyOptions.remove(KW_COMPACTION_STRATEGY_CLASS); + if (compactionStrategyOptions.containsKey(KW_COMPACTION_STRATEGY_CLASS)) + { + compactionStrategyClass = CFMetaData.createCompactionStrategy(compactionStrategyOptions.get(KW_COMPACTION_STRATEGY_CLASS)); + compactionStrategyOptions.remove(KW_COMPACTION_STRATEGY_CLASS); + } + else + { + throw new ConfigurationException("Missing sub-option '" + KW_COMPACTION_STRATEGY_CLASS + "' for the '" + COMPACTION_PARAMETERS + "' option."); + } } } /** Map a keyword to the corresponding value */ public void addProperty(String name, String value) { - String[] composite = name.split(":"); - if (composite.length > 1) + properties.put(name, value); + } + + public void addProperty(String name, Map<String, String> value) + { + if (name.equalsIgnoreCase(COMPACTION_PARAMETERS)) { - if (composite[0].equals(COMPACTION_OPTIONS_PREFIX)) - { - compactionStrategyOptions.put(composite[1], value); - return; - } - else if (composite[0].equals(COMPRESSION_PARAMETERS_PREFIX)) - { - compressionParameters.put(composite[1], value); - return; - } + for (Map.Entry<String, String> entry : value.entrySet()) + compactionStrategyOptions.put(entry.getKey().toLowerCase(), entry.getValue()); + } + else if (name.equalsIgnoreCase(COMPRESSION_PARAMETERS)) + { + for (Map.Entry<String, String> entry : value.entrySet()) + compressionParameters.put(entry.getKey().toLowerCase(), entry.getValue()); } - properties.put(name, value); } public void addAll(Map<String, String> propertyMap) http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/Cql.g ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g index 5a67820..8c43851 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -76,6 +76,26 @@ options { if (op == null && (value.isBindMarker() || Long.parseLong(value.getText()) > 0)) throw new MissingTokenException(102, stream, value); } + + public Map<String, String> convertMap(Map<Term, Term> terms) + { + if (terms == null || terms.isEmpty()) + return Collections.<String, String>emptyMap(); + + Map<String, String> res = new HashMap<String, String>(terms.size()); + + for (Map.Entry<Term, Term> entry : terms.entrySet()) + { + // Because the parser tries to be smart and recover on error (to + // allow displaying more than one error I suppose), we have null + // entries in there. Just skip those, a proper error will be thrown in the end. + if (entry.getKey() == null || entry.getValue() == null) + break; + res.put(entry.getKey().getText(), entry.getValue().getText()); + } + + return res; + } } @lexer::header { @@ -349,7 +369,7 @@ batchStatementObjective returns [ModificationStatement statement] */ createKeyspaceStatement returns [CreateKeyspaceStatement expr] : K_CREATE K_KEYSPACE ks=keyspaceName - K_WITH props=properties { $expr = new CreateKeyspaceStatement(ks, props); } + K_WITH props=mapProperties { $expr = new CreateKeyspaceStatement(ks, props); } ; /** @@ -380,7 +400,7 @@ pkDef[CreateColumnFamilyStatement.RawStatement expr] ; cfamProperty[CreateColumnFamilyStatement.RawStatement expr] - : k=property '=' v=propertyValue { $expr.addProperty(k, v); } + : property[expr.properties] | K_COMPACT K_STORAGE { $expr.setCompactStorage(); } | K_CLUSTERING K_ORDER K_BY '(' cfamOrdering[expr] (',' cfamOrdering[expr])* ')' ; @@ -407,13 +427,14 @@ 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 (property[props] + ( K_AND property[props] )* { type = AlterTableStatement.Type.OPTS; }) ) { $expr = new AlterTableStatement(cf, type, id, v, props); @@ -553,9 +574,9 @@ operation returns [Operation op] | '+' ml=map_literal { $op = MapOperation.Put(ml); } ; -property returns [String str] - @init{ StringBuilder sb = new StringBuilder(); } - : c1=cident { sb.append(c1); } ( ':' cn=cident { sb.append(':').append(cn); } )* { $str = sb.toString(); } +property[CFPropDefs props] + : k=cident '=' (simple=propertyValue { $props.addProperty(k.toString(), simple); } + | map=map_literal { $props.addProperty(k.toString(), convertMap(map)); }) ; propertyValue returns [String str] @@ -563,9 +584,9 @@ 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); } )* +mapProperties returns [Map<String, Map<String, String>> props] + @init { $props = new HashMap<String, Map<String, String>>(); } + : k=cident '=' v=map_literal { $props.put(k.toString(), convertMap(v)); } (K_AND kn=cident '=' vn=map_literal { $props.put(kn.toString(), convertMap(vn)); } )* ; // Either a string or a list of terms http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java index ff24945..c9d4f45 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java @@ -42,15 +42,15 @@ public class AlterTableStatement extends SchemaAlteringStatement public final Type oType; public final ParsedType validator; public final ColumnIdentifier columnName; - private final CFPropDefs cfProps = new CFPropDefs(); + private final CFPropDefs cfProps; - public AlterTableStatement(CFName name, Type type, ColumnIdentifier columnName, ParsedType validator, Map<String, String> propertyMap) + public AlterTableStatement(CFName name, Type type, ColumnIdentifier columnName, ParsedType validator, CFPropDefs cfProps) { super(name); this.oType = type; this.columnName = columnName; this.validator = validator; // used only for ADD/ALTER commands - this.cfProps.addAll(propertyMap); + this.cfProps = cfProps; } public void announceMigration() throws InvalidRequestException, ConfigurationException http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java index b8618b0..3c97f90 100644 --- a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java @@ -131,7 +131,7 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement public static class RawStatement extends CFStatement { private final Map<ColumnIdentifier, ParsedType> definitions = new HashMap<ColumnIdentifier, ParsedType>(); - private final CFPropDefs properties = new CFPropDefs(); + public final CFPropDefs properties = new CFPropDefs(); private final List<List<ColumnIdentifier>> keyAliases = new ArrayList<List<ColumnIdentifier>>(); private final List<ColumnIdentifier> columnAliases = new ArrayList<ColumnIdentifier>(); @@ -334,11 +334,6 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement columnAliases.add(alias); } - public void addProperty(String name, String value) - { - properties.addProperty(name, value); - } - public void setOrdering(ColumnIdentifier alias, boolean reversed) { definedOrdering.put(alias, reversed); http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java index 262c6aa..0c426b3 100644 --- a/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java @@ -34,8 +34,11 @@ import org.apache.cassandra.thrift.ThriftValidation; /** A <code>CREATE KEYSPACE</code> statement parsed from a CQL query. */ public class CreateKeyspaceStatement extends SchemaAlteringStatement { + private static String REPLICATION_PARAMETERS_PREFIX = "replication"; + private static String REPLICATION_STRATEGY_CLASS_KEY = "class"; + private final String name; - private final Map<String, String> attrs; + private final Map<String, Map<String, String>> attrs; private String strategyClass; private final Map<String, String> strategyOptions = new HashMap<String, String>(); @@ -46,7 +49,7 @@ public class CreateKeyspaceStatement extends SchemaAlteringStatement * @param name the name of the keyspace to create * @param attrs map of the raw keyword arguments that followed the <code>WITH</code> keyword. */ - public CreateKeyspaceStatement(String name, Map<String, String> attrs) + public CreateKeyspaceStatement(String name, Map<String, Map<String, String>> attrs) { super(); this.name = name; @@ -72,15 +75,23 @@ public class CreateKeyspaceStatement extends SchemaAlteringStatement if (name.length() > Schema.NAME_LENGTH) throw new InvalidRequestException(String.format("Keyspace names shouldn't be more than %s characters long (got \"%s\")", Schema.NAME_LENGTH, name)); - // required - if (!attrs.containsKey("strategy_class")) - throw new InvalidRequestException("missing required argument \"strategy_class\""); - strategyClass = attrs.get("strategy_class"); + if (!attrs.containsKey(REPLICATION_PARAMETERS_PREFIX)) + throw new InvalidRequestException("missing required argument '" + REPLICATION_PARAMETERS_PREFIX + "'"); + + Map<String, String> replication_parameters = attrs.get(REPLICATION_PARAMETERS_PREFIX); + + strategyClass = replication_parameters.get(REPLICATION_STRATEGY_CLASS_KEY); + + if (strategyClass == null) + throw new InvalidRequestException("missing required field '" + REPLICATION_STRATEGY_CLASS_KEY + "' for '" + REPLICATION_PARAMETERS_PREFIX + "' option"); - // optional - for (String key : attrs.keySet()) - if ((key.contains(":")) && (key.startsWith("strategy_options"))) - strategyOptions.put(key.split(":")[1], attrs.get(key)); + for (Map.Entry<String, String> entry : replication_parameters.entrySet()) + { + if (entry.getKey().equals(REPLICATION_STRATEGY_CLASS_KEY)) + continue; + + strategyOptions.put(entry.getKey(), entry.getValue()); + } // trial run to let ARS validate class + per-class options try
