You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2021/03/11 16:52:59 UTC
[cassandra] branch trunk updated: Fix the CQL generated for the
views.where_clause column when some identifiers require quoting
This is an automated email from the ASF dual-hosted git repository.
blerer pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new 92fe6a3 Fix the CQL generated for the views.where_clause column when some identifiers require quoting
92fe6a3 is described below
commit 92fe6a37fc79b9c545bccd75b93e5126fd1678e9
Author: Benjamin Lerer <b....@gmail.com>
AuthorDate: Fri Mar 5 17:44:17 2021 +0100
Fix the CQL generated for the views.where_clause column when some identifiers require quoting
patch by Benjamin Lerer; reviewed by Andrés de la Peña for CASSANDRA-16479
CASSANDRA-13426 changed the way the Materialized Views WHERE clause stored
in system_schema.views was generated. The code used to generate the WHERE
clause text was not relying on method quoting identifiers if needed.
The patch address this problem.
---
CHANGES.txt | 1 +
.../org/apache/cassandra/cql3/MultiColumnRelation.java | 4 ++--
src/java/org/apache/cassandra/cql3/QualifiedName.java | 12 ++++++++++++
src/java/org/apache/cassandra/cql3/Relation.java | 13 +++++++++++++
.../org/apache/cassandra/cql3/SingleColumnRelation.java | 4 ++--
src/java/org/apache/cassandra/cql3/TokenRelation.java | 4 ++--
src/java/org/apache/cassandra/cql3/WhereClause.java | 14 ++++++++++++--
.../cql3/restrictions/CustomIndexExpression.java | 7 ++++++-
.../org/apache/cassandra/schema/SchemaKeyspace.java | 2 +-
test/unit/org/apache/cassandra/cql3/ViewTest.java | 17 +++++++++++++++++
10 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 592c9c3..b470000 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0-beta5
+ * Fix the CQL generated for the views.where_clause column when some identifiers require quoting (CASSANDRA-16479)
* Send FAILED_SESSION_MSG on shutdown and on in-progress repairs during startup (CASSANDRA-16425)
* Reinstate removed ApplicationState padding (CASSANDRA-16484)
* Expose data dirs to ColumnFamilyStoreMBean (CASSANDRA-16335)
diff --git a/src/java/org/apache/cassandra/cql3/MultiColumnRelation.java b/src/java/org/apache/cassandra/cql3/MultiColumnRelation.java
index b61198b..e74b962 100644
--- a/src/java/org/apache/cassandra/cql3/MultiColumnRelation.java
+++ b/src/java/org/apache/cassandra/cql3/MultiColumnRelation.java
@@ -227,9 +227,9 @@ public class MultiColumnRelation extends Relation
}
@Override
- public String toString()
+ public String toCQLString()
{
- StringBuilder builder = new StringBuilder(Tuples.tupleToString(entities));
+ StringBuilder builder = new StringBuilder(Tuples.tupleToString(entities, ColumnIdentifier::toCQLString));
if (isIN())
{
return builder.append(" IN ")
diff --git a/src/java/org/apache/cassandra/cql3/QualifiedName.java b/src/java/org/apache/cassandra/cql3/QualifiedName.java
index fb2e110..a3f70d5 100644
--- a/src/java/org/apache/cassandra/cql3/QualifiedName.java
+++ b/src/java/org/apache/cassandra/cql3/QualifiedName.java
@@ -84,6 +84,18 @@ public class QualifiedName
: name;
}
+ /**
+ * Returns a string representation of the qualified name that is safe to use directly in CQL queries.
+ * If necessary, the string will be double-quoted, and any quotes inside the string will be escaped.
+ */
+ public String toCQLString()
+ {
+ String nameQuotedIfNeeded = ColumnIdentifier.maybeQuote(name);
+ return hasKeyspace()
+ ? String.format("%s.%s", ColumnIdentifier.maybeQuote(keyspace), nameQuotedIfNeeded)
+ : nameQuotedIfNeeded;
+ }
+
@Override
public int hashCode()
{
diff --git a/src/java/org/apache/cassandra/cql3/Relation.java b/src/java/org/apache/cassandra/cql3/Relation.java
index af70edd..f9f8214 100644
--- a/src/java/org/apache/cassandra/cql3/Relation.java
+++ b/src/java/org/apache/cassandra/cql3/Relation.java
@@ -257,4 +257,17 @@ public abstract class Relation
* a new Relation with "from" replaced by "to" is returned.
*/
public abstract Relation renameIdentifier(ColumnIdentifier from, ColumnIdentifier to);
+
+ /**
+ * Returns a CQL representation of this relation.
+ *
+ * @return a CQL representation of this relation
+ */
+ public abstract String toCQLString();
+
+ @Override
+ public String toString()
+ {
+ return toCQLString();
+ }
}
diff --git a/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java b/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
index ca87e10..9ff3f07 100644
--- a/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
+++ b/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
@@ -143,9 +143,9 @@ public final class SingleColumnRelation extends Relation
}
@Override
- public String toString()
+ public String toCQLString()
{
- String entityAsString = entity.toString();
+ String entityAsString = entity.toCQLString();
if (mapKey != null)
entityAsString = String.format("%s[%s]", entityAsString, mapKey);
diff --git a/src/java/org/apache/cassandra/cql3/TokenRelation.java b/src/java/org/apache/cassandra/cql3/TokenRelation.java
index be42143..139c55d 100644
--- a/src/java/org/apache/cassandra/cql3/TokenRelation.java
+++ b/src/java/org/apache/cassandra/cql3/TokenRelation.java
@@ -140,9 +140,9 @@ public final class TokenRelation extends Relation
}
@Override
- public String toString()
+ public String toCQLString()
{
- return String.format("token%s %s %s", Tuples.tupleToString(entities), relationType, value);
+ return String.format("token%s %s %s", Tuples.tupleToString(entities, ColumnIdentifier::toCQLString), relationType, value);
}
@Override
diff --git a/src/java/org/apache/cassandra/cql3/WhereClause.java b/src/java/org/apache/cassandra/cql3/WhereClause.java
index 060af35..16116a2 100644
--- a/src/java/org/apache/cassandra/cql3/WhereClause.java
+++ b/src/java/org/apache/cassandra/cql3/WhereClause.java
@@ -80,9 +80,19 @@ public final class WhereClause
@Override
public String toString()
{
+ return toCQLString();
+ }
+
+ /**
+ * Returns a CQL representation of this WHERE clause.
+ *
+ * @return a CQL representation of this WHERE clause
+ */
+ public String toCQLString()
+ {
return join(" AND ",
- concat(transform(relations, Relation::toString),
- transform(expressions, CustomIndexExpression::toString)));
+ concat(transform(relations, Relation::toCQLString),
+ transform(expressions, CustomIndexExpression::toCQLString)));
}
@Override
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/CustomIndexExpression.java b/src/java/org/apache/cassandra/cql3/restrictions/CustomIndexExpression.java
index 539715c..7a5fff6 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/CustomIndexExpression.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/CustomIndexExpression.java
@@ -55,10 +55,15 @@ public class CustomIndexExpression
value.bindAndGet(options));
}
+ public String toCQLString()
+ {
+ return String.format("expr(%s,%s)", targetIndex.toCQLString(), valueRaw.getText());
+ }
+
@Override
public String toString()
{
- return String.format("expr(%s,%s)", targetIndex, valueRaw);
+ return toCQLString();
}
@Override
diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 7c3bc23..6d85190 100644
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@ -740,7 +740,7 @@ public final class SchemaKeyspace
.add("include_all_columns", view.includeAllColumns)
.add("base_table_id", view.baseTableId.asUUID())
.add("base_table_name", view.baseTableName)
- .add("where_clause", view.whereClause.toString())
+ .add("where_clause", view.whereClause.toCQLString())
.add("id", table.id.asUUID());
addTableParamsToRowBuilder(table.params, rowBuilder);
diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java
index 29f2be5..b8939ce 100644
--- a/test/unit/org/apache/cassandra/cql3/ViewTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java
@@ -1442,4 +1442,21 @@ public class ViewTest extends CQLTester
DatabaseDescriptor.setEnableMaterializedViews(enableMaterializedViews);
}
}
+
+ @Test
+ public void testQuotedIdentifiersInWhereClause() throws Throwable
+ {
+ createTable("CREATE TABLE %s (\"theKey\" int, \"theClustering_1\" int, \"theClustering_2\" int, \"theValue\" int, PRIMARY KEY (\"theKey\", \"theClustering_1\", \"theClustering_2\"))");
+
+ executeNet(protocolVersion, "USE " + keyspace());
+
+ createView("view1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE \"theKey\" IS NOT NULL AND \"theClustering_1\" IS NOT NULL AND \"theClustering_2\" IS NOT NULL AND \"theValue\" IS NOT NULL PRIMARY KEY (\"theKey\", \"theClustering_1\", \"theClustering_2\");");
+ createView("view2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE \"theKey\" IS NOT NULL AND (\"theClustering_1\", \"theClustering_2\") = (1, 2) AND \"theValue\" IS NOT NULL PRIMARY KEY (\"theKey\", \"theClustering_1\", \"theClustering_2\");");
+ createView("view3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE token(\"theKey\") > token(1) AND \"theClustering_1\" = 1 AND \"theClustering_2\" > 2 AND \"theValue\" IS NOT NULL PRIMARY KEY (\"theKey\", \"theClustering_1\", \"theClustering_2\");");
+
+ assertRows(execute("SELECT where_clause FROM system_schema.views"),
+ row("\"theKey\" IS NOT NULL AND \"theClustering_1\" IS NOT NULL AND \"theClustering_2\" IS NOT NULL AND \"theValue\" IS NOT NULL"),
+ row("\"theKey\" IS NOT NULL AND (\"theClustering_1\", \"theClustering_2\") = (1, 2) AND \"theValue\" IS NOT NULL"),
+ row("token(\"theKey\") > token(1) AND \"theClustering_1\" = 1 AND \"theClustering_2\" > 2 AND \"theValue\" IS NOT NULL"));
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org