Preserve quoted reserved keyword column names in MV creation

Patch by Carl Yeksigian; reviewed by Alex Petrov for CASSANDRA-11803
This commit is contained in:
Carl Yeksigian 2016-10-14 10:12:14 -04:00
parent a889852706
commit 153583be55
6 changed files with 145 additions and 3 deletions

View File

@ -1,4 +1,5 @@
3.0.10
* Preserve quoted reserved keyword column names in MV creation (CASSANDRA-11803)
* nodetool stopdaemon errors out (CASSANDRA-12646)
* Split materialized view mutations on build to prevent OOM (CASSANDRA-12268)
* mx4j does not work in 3.0.8 (CASSANDRA-12274)

View File

@ -362,8 +362,9 @@ public class ColumnIdentifier extends Selectable implements IMeasurableMemory, C
public static String maybeQuote(String text)
{
if (UNQUOTED_IDENTIFIER.matcher(text).matches())
if (UNQUOTED_IDENTIFIER.matcher(text).matches() && !ReservedKeywords.isReserved(text))
return text;
return '"' + PATTERN_DOUBLE_QUOTE.matcher(text).replaceAll(Matcher.quoteReplacement("\"\"")) + '"';
}
}

View File

@ -1634,6 +1634,8 @@ basic_unreserved_keyword returns [String str]
;
// Case-insensitive keywords
// When adding a new reserved keyword, add entry to o.a.c.cql3.ReservedKeywords as well
// When adding a new unreserved keyword, add entry to list above
K_SELECT: S E L E C T;
K_FROM: F R O M;
K_AS: A S;

View File

@ -0,0 +1,118 @@
/*
* 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.Set;
import com.google.common.collect.ImmutableSet;
class ReservedKeywords
{
private static final String[] reservedKeywords = new String[]
{
"SELECT",
"FROM",
"WHERE",
"AND",
"KEY",
"ENTRIES",
"FULL",
"INSERT",
"UPDATE",
"WITH",
"LIMIT",
"USING",
"USE",
"COUNT",
"SET",
"BEGIN",
"UNLOGGED",
"BATCH",
"APPLY",
"TRUNCATE",
"DELETE",
"IN",
"CREATE",
"KEYSPACE",
"SCHEMA",
"COLUMNFAMILY",
"TABLE",
"MATERIALIZED",
"VIEW",
"INDEX",
"ON",
"TO",
"DROP",
"PRIMARY",
"INTO",
"TIMESTAMP",
"TTL",
"ALTER",
"RENAME",
"ADD",
"ORDER",
"BY",
"ASC",
"DESC",
"ALLOW",
"IF",
"IS",
"GRANT",
"OF",
"REVOKE",
"MODIFY",
"AUTHORIZE",
"DESCRIBE",
"EXECUTE",
"NORECURSIVE",
"ASCII",
"BIGINT",
"BLOB",
"BOOLEAN",
"COUNTER",
"DECIMAL",
"DOUBLE",
"FLOAT",
"INET",
"INT",
"SMALLINT",
"TINYINT",
"TEXT",
"UUID",
"VARCHAR",
"VARINT",
"TIMEUUID",
"TOKEN",
"WRITETIME",
"DATE",
"TIME",
"NULL",
"NOT",
"NAN",
"INFINITY",
"OR",
"REPLACE" };
private static final Set<String> reservedSet = ImmutableSet.copyOf(reservedKeywords);
static boolean isReserved(String text)
{
return reservedSet.contains(text.toUpperCase());
}
}

View File

@ -1137,4 +1137,24 @@ public class ViewTest extends CQLTester
assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1, null, "rab"));
assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv"));
}
@Test
public void testReservedKeywordsInMV() throws Throwable
{
createTable("CREATE TABLE %s (\"token\" int PRIMARY KEY, \"keyspace\" int)");
executeNet(protocolVersion, "USE " + keyspace());
createView("mv",
"CREATE MATERIALIZED VIEW %s AS" +
" SELECT \"keyspace\", \"token\"" +
" FROM %%s" +
" WHERE \"keyspace\" IS NOT NULL AND \"token\" IS NOT NULL" +
" PRIMARY KEY (\"keyspace\", \"token\")");
execute("INSERT INTO %s (\"token\", \"keyspace\") VALUES (?, ?)", 0, 1);
assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1));
assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv"), row(1, 0));
}
}

View File

@ -635,10 +635,10 @@ public class ColumnFamilyStoreCQLHelperTest extends CQLTester
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, true).startsWith(
"CREATE TABLE IF NOT EXISTS " + DYNAMIC_COMPOSITE + "." + DYNAMIC_COMPOSITE + " (\n" +
"\tkey ascii,\n" +
"\t\"key\" ascii,\n" +
"\tcols 'org.apache.cassandra.db.marshal.DynamicCompositeType(a=>org.apache.cassandra.db.marshal.BytesType,b=>org.apache.cassandra.db.marshal.BytesType,c=>org.apache.cassandra.db.marshal.BytesType)',\n" +
"\tval ascii,\n" +
"\tPRIMARY KEY (key, cols))\n" +
"\tPRIMARY KEY (\"key\", cols))\n" +
"\tWITH ID = " + cfs.metadata.cfId + "\n" +
"\tAND COMPACT STORAGE"));
}