Metadata.java
/*
* 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.functions.types;
import org.apache.cassandra.cql3.ColumnIdentifier;
/**
* Keeps metadata on the connected cluster, including known nodes and schema definitions.
*/
public class Metadata
{
/*
* Deal with case sensitivity for a given element id (keyspace, table, column, etc.)
*
* This method is used to convert identifiers provided by the client (through methods such as getKeyspace(String)),
* to the format used internally by the driver.
*
* We expect client-facing APIs to behave like cqlsh, that is:
* - identifiers that are mixed-case or contain special characters should be quoted.
* - unquoted identifiers will be lowercased: getKeyspace("Foo") will look for a keyspace named "foo"
*/
static String handleId(String id)
{
// Shouldn't really happen for this method, but no reason to fail here
if (id == null) return null;
boolean isAlphanumericLowCase = true;
boolean isAlphanumeric = true;
for (int i = 0; i < id.length(); i++)
{
char c = id.charAt(i);
if (c >= 65 && c <= 90)
{ // A-Z
isAlphanumericLowCase = false;
}
else if (!((c >= 48 && c <= 57) // 0-9
|| (c == 95) // _ (underscore)
|| (c >= 97 && c <= 122) // a-z
))
{
isAlphanumeric = false;
isAlphanumericLowCase = false;
break;
}
}
if (isAlphanumericLowCase)
{
return id;
}
if (isAlphanumeric)
{
return id.toLowerCase();
}
// Check if it's enclosed in quotes. If it is, remove them and unescape internal double quotes
return ParseUtils.unDoubleQuote(id);
}
/**
* Quotes a CQL identifier if necessary.
*
* <p>This is similar to {@link #quote(String)}, except that it won't quote the input string if it
* can safely be used as-is. For example:
*
* <ul>
* <li>{@code quoteIfNecessary("foo").equals("foo")} (no need to quote).
* <li>{@code quoteIfNecessary("Foo").equals("\"Foo\"")} (identifier is mixed case so case
* sensitivity is required)
* <li>{@code quoteIfNecessary("foo bar").equals("\"foo bar\"")} (identifier contains special
* characters)
* <li>{@code quoteIfNecessary("table").equals("\"table\"")} (identifier is a reserved CQL
* keyword)
* </ul>
*
* @param id the "internal" form of the identifier. That is, the identifier as it would appear in
* Cassandra system tables (such as {@code system_schema.tables}, {@code
* system_schema.columns}, etc.)
* @return the identifier as it would appear in a CQL query string. This is also how you need to
* pass it to public driver methods, such as {@code #getKeyspace(String)}.
*/
static String quoteIfNecessary(String id)
{
return ColumnIdentifier.maybeQuote(id);
}
/**
* Quote a keyspace, table or column identifier to make it case sensitive.
*
* <p>CQL identifiers, including keyspace, table and column ones, are case insensitive by default.
* Case sensitive identifiers can however be provided by enclosing the identifier in double quotes
* (see the <a href="http://cassandra.apache.org/doc/cql3/CQL.html#identifiers">CQL
* documentation</a> for details). If you are using case sensitive identifiers, this method can be
* used to enclose such identifiers in double quotes, making them case sensitive.
*
* <p>Note that <a
* href="https://docs.datastax.com/en/cql/3.0/cql/cql_reference/keywords_r.html">reserved CQL
* keywords</a> should also be quoted. You can check if a given identifier is a reserved keyword
* by calling {@code #isReservedCqlKeyword(String)}.
*
* @param id the keyspace or table identifier.
* @return {@code id} enclosed in double-quotes, for use in methods like {@code #getReplicas},
* {@code #getKeyspace}, {@code KeyspaceMetadata#getTable} or even {@code
* Cluster#connect(String)}.
*/
public static String quote(String id)
{
return ParseUtils.doubleQuote(id);
}
}