You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by al...@apache.org on 2015/05/03 23:29:03 UTC
cassandra git commit: Fix invalidation of prepared statements on
function drops
Repository: cassandra
Updated Branches:
refs/heads/trunk e28860b40 -> d9836e0ef
Fix invalidation of prepared statements on function drops
patch by Sam Tunnicliffe; reviewed by Aleksey Yeschenko for
CASSANDRA-9166
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d9836e0e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d9836e0e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d9836e0e
Branch: refs/heads/trunk
Commit: d9836e0efe66c0cc0e33f32b605f6920893fa7a5
Parents: e28860b
Author: Sam Tunnicliffe <sa...@beobal.com>
Authored: Mon May 4 00:28:16 2015 +0300
Committer: Aleksey Yeschenko <al...@apache.org>
Committed: Mon May 4 00:28:16 2015 +0300
----------------------------------------------------------------------
.../org/apache/cassandra/cql3/Attributes.java | 6 -
.../org/apache/cassandra/cql3/CQLStatement.java | 9 +-
.../apache/cassandra/cql3/ColumnCondition.java | 13 ---
.../org/apache/cassandra/cql3/Operation.java | 5 -
.../apache/cassandra/cql3/QueryProcessor.java | 73 ++++++------
src/java/org/apache/cassandra/cql3/Term.java | 15 ---
.../org/apache/cassandra/cql3/UserTypes.java | 9 --
.../cql3/functions/AbstractFunction.java | 5 -
.../cassandra/cql3/functions/Function.java | 2 -
.../cassandra/cql3/functions/FunctionCall.java | 5 -
.../cassandra/cql3/functions/UDAggregate.java | 12 +-
.../cql3/restrictions/AbstractRestriction.java | 36 +-----
.../ForwardingPrimaryKeyRestrictions.java | 6 -
.../restrictions/MultiColumnRestriction.java | 25 ----
.../restrictions/PrimaryKeyRestrictionSet.java | 6 -
.../cql3/restrictions/Restriction.java | 10 +-
.../cql3/restrictions/RestrictionSet.java | 10 --
.../cql3/restrictions/Restrictions.java | 10 +-
.../restrictions/SingleColumnRestriction.java | 39 +------
.../restrictions/StatementRestrictions.java | 7 --
.../cql3/restrictions/TokenRestriction.java | 13 ---
.../selection/AbstractFunctionSelector.java | 5 -
.../cassandra/cql3/selection/Selection.java | 11 --
.../cassandra/cql3/selection/Selector.java | 5 -
.../cql3/selection/SelectorFactories.java | 8 --
.../cql3/statements/BatchStatement.java | 10 --
.../cql3/statements/ModificationStatement.java | 28 -----
.../cql3/statements/ParsedStatement.java | 7 +-
.../cql3/statements/SelectStatement.java | 9 --
.../org/apache/cassandra/cql3/CQLTester.java | 4 +-
.../cassandra/cql3/UFIdentificationTest.java | 2 +-
test/unit/org/apache/cassandra/cql3/UFTest.java | 117 +++++++++++++++++++
32 files changed, 180 insertions(+), 342 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/Attributes.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Attributes.java b/src/java/org/apache/cassandra/cql3/Attributes.java
index f3d298b..7b38e9f 100644
--- a/src/java/org/apache/cassandra/cql3/Attributes.java
+++ b/src/java/org/apache/cassandra/cql3/Attributes.java
@@ -50,12 +50,6 @@ public class Attributes
this.timeToLive = timeToLive;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return (timestamp != null && timestamp.usesFunction(ksName, functionName))
- || (timeToLive != null && timeToLive.usesFunction(ksName, functionName));
- }
-
public Iterable<Function> getFunctions()
{
if (timestamp != null && timeToLive != null)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/CQLStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQLStatement.java b/src/java/org/apache/cassandra/cql3/CQLStatement.java
index 80220a8..02292ad 100644
--- a/src/java/org/apache/cassandra/cql3/CQLStatement.java
+++ b/src/java/org/apache/cassandra/cql3/CQLStatement.java
@@ -54,13 +54,16 @@ public interface CQLStatement
public ResultMessage execute(QueryState state, QueryOptions options) throws RequestValidationException, RequestExecutionException;
/**
- * Variante of execute used for internal query against the system tables, and thus only query the local node.
+ * Variant of execute used for internal query against the system tables, and thus only query the local node.
*
* @param state the current query state
*/
public ResultMessage executeInternal(QueryState state, QueryOptions options) throws RequestValidationException, RequestExecutionException;
- boolean usesFunction(String ksName, String functionName);
-
+ /**
+ * Return an Iterable over all of the functions (both native and user-defined) used by any component
+ * of the statement
+ * @return functions all functions found (may contain duplicates)
+ */
public Iterable<Function> getFunctions();
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/ColumnCondition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/ColumnCondition.java b/src/java/org/apache/cassandra/cql3/ColumnCondition.java
index acebfe7..c7b5ddb 100644
--- a/src/java/org/apache/cassandra/cql3/ColumnCondition.java
+++ b/src/java/org/apache/cassandra/cql3/ColumnCondition.java
@@ -97,19 +97,6 @@ public class ColumnCondition
return new ColumnCondition(column, collectionElement, inMarker, null, Operator.IN);
}
- public boolean usesFunction(String ksName, String functionName)
- {
- if (collectionElement != null && collectionElement.usesFunction(ksName, functionName))
- return true;
- if (value != null && value.usesFunction(ksName, functionName))
- return true;
- if (inValues != null)
- for (Term value : inValues)
- if (value != null && value.usesFunction(ksName, functionName))
- return true;
- return false;
- }
-
public Iterable<Function> getFunctions()
{
Iterable<Function> iter = Collections.emptyList();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/Operation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Operation.java b/src/java/org/apache/cassandra/cql3/Operation.java
index d99a00d..4701a96 100644
--- a/src/java/org/apache/cassandra/cql3/Operation.java
+++ b/src/java/org/apache/cassandra/cql3/Operation.java
@@ -57,11 +57,6 @@ public abstract class Operation
this.t = t;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return t != null && t.usesFunction(ksName, functionName);
- }
-
public Iterable<Function> getFunctions()
{
return t != null ? t.getFunctions() : Collections.<Function>emptySet();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index f494436..2698a8f 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -18,52 +18,40 @@
package org.apache.cassandra.cql3;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.*;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
import com.google.common.primitives.Ints;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.EntryWeigher;
import com.googlecode.concurrentlinkedhashmap.EvictionListener;
-
import org.antlr.runtime.*;
-import org.apache.cassandra.exceptions.CassandraException;
-import org.apache.cassandra.service.MigrationListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.apache.cassandra.concurrent.ScheduledExecutors;
-import org.apache.cassandra.cql3.functions.*;
-
+import org.apache.cassandra.cql3.functions.Function;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.Functions;
import org.apache.cassandra.cql3.statements.*;
import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.composites.CType;
-import org.apache.cassandra.db.composites.CellName;
-import org.apache.cassandra.db.composites.CellNameType;
-import org.apache.cassandra.db.composites.Composite;
+import org.apache.cassandra.db.composites.*;
import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.RequestExecutionException;
-import org.apache.cassandra.exceptions.RequestValidationException;
-import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.metrics.CQLMetrics;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.MigrationManager;
-import org.apache.cassandra.service.QueryState;
+import org.apache.cassandra.service.*;
import org.apache.cassandra.service.pager.QueryPager;
import org.apache.cassandra.service.pager.QueryPagers;
import org.apache.cassandra.thrift.ThriftClientState;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.MD5Digest;
-import org.apache.cassandra.utils.SemanticVersion;
+import org.apache.cassandra.utils.*;
import org.github.jamm.MemoryMeter;
public class QueryProcessor implements QueryHandler
@@ -628,22 +616,37 @@ public class QueryProcessor implements QueryHandler
removeInvalidPreparedStatements(ksName, cfName);
}
- public void onDropFunction(String ksName, String functionName, List<AbstractType<?>> argTypes) {
+ public void onDropFunction(String ksName, String functionName, List<AbstractType<?>> argTypes)
+ {
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, functionName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, functionName);
}
+
public void onDropAggregate(String ksName, String aggregateName, List<AbstractType<?>> argTypes)
{
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, aggregateName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, aggregateName);
}
- private static void removeInvalidPreparedStatementsForFunction(Iterator<ParsedStatement.Prepared> iterator,
- String ksName, String functionName)
+ private static void removeInvalidPreparedStatementsForFunction(Iterator<ParsedStatement.Prepared> statements,
+ final String ksName,
+ final String functionName)
{
- while (iterator.hasNext())
- if (iterator.next().statement.usesFunction(ksName, functionName))
- iterator.remove();
+ final Predicate<Function> matchesFunction = new Predicate<Function>()
+ {
+ public boolean apply(Function f)
+ {
+ return ksName.equals(f.name().keyspace) && functionName.equals(f.name().name);
+ }
+ };
+
+ Iterators.removeIf(statements, new Predicate<ParsedStatement.Prepared>()
+ {
+ public boolean apply(ParsedStatement.Prepared statement)
+ {
+ return Iterables.any(statement.statement.getFunctions(), matchesFunction);
+ }
+ });
}
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/Term.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Term.java b/src/java/org/apache/cassandra/cql3/Term.java
index 6997f78..6fa0c76 100644
--- a/src/java/org/apache/cassandra/cql3/Term.java
+++ b/src/java/org/apache/cassandra/cql3/Term.java
@@ -70,8 +70,6 @@ public interface Term
*/
public abstract boolean containsBindMarker();
- boolean usesFunction(String ksName, String functionName);
-
Iterable<Function> getFunctions();
/**
@@ -122,11 +120,6 @@ public interface Term
public void collectMarkerSpecification(VariableSpecifications boundNames) {}
public Terminal bind(QueryOptions options) { return this; }
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
public Set<Function> getFunctions()
{
return Collections.emptySet();
@@ -168,14 +161,6 @@ public interface Term
*/
public abstract class NonTerminal implements Term
{
- // TODO - this is not necessarily false, yet isn't overridden in concrete classes
- // representing collection literals
- // e,g "UPDATE table SET map_col = { key_function() : val_function() }) WHERE ....
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
public ByteBuffer bindAndGet(QueryOptions options) throws InvalidRequestException
{
Terminal t = bind(options);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/UserTypes.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/UserTypes.java b/src/java/org/apache/cassandra/cql3/UserTypes.java
index b6d8521..de3f545 100644
--- a/src/java/org/apache/cassandra/cql3/UserTypes.java
+++ b/src/java/org/apache/cassandra/cql3/UserTypes.java
@@ -150,15 +150,6 @@ public abstract class UserTypes
this.values = values;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- if (values != null)
- for (Term value : values)
- if (value != null && value.usesFunction(ksName, functionName))
- return true;
- return false;
- }
-
public Iterable<Function> getFunctions()
{
return Terms.getFunctions(values);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java b/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
index 15ae757..1f5349e 100644
--- a/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
+++ b/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
@@ -67,11 +67,6 @@ public abstract class AbstractFunction implements Function
&& Objects.equal(this.returnType, that.returnType);
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return name.keyspace.equals(ksName) && name.name.equals(functionName);
- }
-
public Iterable<Function> getFunctions()
{
return ImmutableSet.<Function>of(this);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/functions/Function.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/Function.java b/src/java/org/apache/cassandra/cql3/functions/Function.java
index 3c2e5a7..6fb9ba2 100644
--- a/src/java/org/apache/cassandra/cql3/functions/Function.java
+++ b/src/java/org/apache/cassandra/cql3/functions/Function.java
@@ -50,8 +50,6 @@ public interface Function
*/
public boolean isAggregate();
- boolean usesFunction(String ksName, String functionName);
-
Iterable<Function> getFunctions();
boolean hasReferenceTo(Function function);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java b/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
index f42a093..689da5a 100644
--- a/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
+++ b/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
@@ -41,11 +41,6 @@ public class FunctionCall extends Term.NonTerminal
this.terms = terms;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return fun.usesFunction(ksName, functionName);
- }
-
public Iterable<Function> getFunctions()
{
return Iterables.concat(Terms.getFunctions(terms), fun.getFunctions());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
index 59f8daa..7eed4f0 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
@@ -98,16 +98,12 @@ public class UDAggregate extends AbstractFunction implements AggregateFunction
return stateFunction == function || finalFunction == function;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return super.usesFunction(ksName, functionName)
- || stateFunction != null && stateFunction.name().keyspace.equals(ksName) && stateFunction.name().name.equals(functionName)
- || finalFunction != null && finalFunction.name().keyspace.equals(ksName) && finalFunction.name().name.equals(functionName);
- }
-
public Iterable<Function> getFunctions()
{
- return ImmutableSet.of(this, stateFunction, finalFunction);
+ if (finalFunction != null)
+ return ImmutableSet.of(this, stateFunction, finalFunction);
+ else
+ return ImmutableSet.of(this, stateFunction);
}
public boolean isAggregate()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/AbstractRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/AbstractRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/AbstractRestriction.java
index d36162c..64c94f4 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/AbstractRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/AbstractRestriction.java
@@ -18,18 +18,16 @@
package org.apache.cassandra.cql3.restrictions;
import java.nio.ByteBuffer;
-import java.util.List;
import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.cql3.QueryOptions;
-import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.statements.Bound;
import org.apache.cassandra.db.composites.CompositesBuilder;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import static org.apache.cassandra.cql3.statements.RequestValidations.checkBindValueSet;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull;
-import static org.apache.cassandra.cql3.statements.RequestValidations.checkBindValueSet;
/**
* Base class for <code>Restriction</code>s
@@ -99,34 +97,4 @@ abstract class AbstractRestriction implements Restriction
checkFalse(value.remaining() > 0xFFFF, "Index expression values may not be larger than 64K");
return value;
}
-
- /**
- * Checks if the specified term is using the specified function.
- *
- * @param term the term to check
- * @param ksName the function keyspace name
- * @param functionName the function name
- * @return <code>true</code> if the specified term is using the specified function, <code>false</code> otherwise.
- */
- protected static final boolean usesFunction(Term term, String ksName, String functionName)
- {
- return term != null && term.usesFunction(ksName, functionName);
- }
-
- /**
- * Checks if one of the specified term is using the specified function.
- *
- * @param terms the terms to check
- * @param ksName the function keyspace name
- * @param functionName the function name
- * @return <code>true</code> if onee of the specified term is using the specified function, <code>false</code> otherwise.
- */
- protected static final boolean usesFunction(List<Term> terms, String ksName, String functionName)
- {
- if (terms != null)
- for (Term value : terms)
- if (usesFunction(value, ksName, functionName))
- return true;
- return false;
- }
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/ForwardingPrimaryKeyRestrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/ForwardingPrimaryKeyRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/ForwardingPrimaryKeyRestrictions.java
index fd40b7a..03c6cbc 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/ForwardingPrimaryKeyRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/ForwardingPrimaryKeyRestrictions.java
@@ -45,12 +45,6 @@ abstract class ForwardingPrimaryKeyRestrictions implements PrimaryKeyRestriction
protected abstract PrimaryKeyRestrictions getDelegate();
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return getDelegate().usesFunction(ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return getDelegate().getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
index 6d3ffab..c4bce4c 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
@@ -135,12 +135,6 @@ public abstract class MultiColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(value, ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return value.getFunctions();
@@ -270,12 +264,6 @@ public abstract class MultiColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(values, ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Terms.getFunctions(values);
@@ -315,12 +303,6 @@ public abstract class MultiColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Collections.emptySet();
@@ -395,13 +377,6 @@ public abstract class MultiColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return (slice.hasBound(Bound.START) && usesFunction(slice.bound(Bound.START), ksName, functionName))
- || (slice.hasBound(Bound.END) && usesFunction(slice.bound(Bound.END), ksName, functionName));
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return slice.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java b/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
index ab61628..b49d774 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
@@ -141,12 +141,6 @@ final class PrimaryKeyRestrictionSet extends AbstractPrimaryKeyRestrictions
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return restrictions.usesFunction(ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return restrictions.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/Restriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/Restriction.java b/src/java/org/apache/cassandra/cql3/restrictions/Restriction.java
index 71dc373..c115a3b 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/Restriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/Restriction.java
@@ -63,14 +63,10 @@ public interface Restriction
public Collection<ColumnDefinition> getColumnDefs();
/**
- * Returns <code>true</code> if one of the restrictions use the specified function.
- *
- * @param ksName the keyspace name
- * @param functionName the function name
- * @return <code>true</code> if one of the restrictions use the specified function, <code>false</code> otherwise.
+ * Return an Iterable over all of the functions (both native and user-defined) used by any component
+ * of the restriction
+ * @return functions all functions found (may contain duplicates)
*/
- public boolean usesFunction(String ksName, String functionName);
-
public Iterable<Function> getFunctions();
/**
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
index 3a236cc..6bf7666 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
@@ -81,16 +81,6 @@ final class RestrictionSet implements Restrictions, Iterable<Restriction>
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- for (Restriction restriction : restrictions.values())
- if (restriction.usesFunction(ksName, functionName))
- return true;
-
- return false;
- }
-
- @Override
public Iterable<Function> getFunctions()
{
com.google.common.base.Function<Restriction, Iterable<Function>> transform =
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
index 7487734..ab81bf7 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
@@ -39,14 +39,10 @@ interface Restrictions
public Collection<ColumnDefinition> getColumnDefs();
/**
- * Returns <code>true</code> if one of the restrictions use the specified function.
- *
- * @param ksName the keyspace name
- * @param functionName the function name
- * @return <code>true</code> if one of the restrictions use the specified function, <code>false</code> otherwise.
+ * Return an Iterable over all of the functions (both native and user-defined) used by any component
+ * of the restrictions
+ * @return functions all functions found (may contain duplicates)
*/
- public boolean usesFunction(String ksName, String functionName);
-
public Iterable<Function> getFunctions();
/**
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
index 69ef5d2..d32f585 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
@@ -23,12 +23,10 @@ import java.util.*;
import com.google.common.collect.Iterables;
import org.apache.cassandra.config.ColumnDefinition;
-
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.cql3.Term.Terminal;
import org.apache.cassandra.cql3.functions.Function;
import org.apache.cassandra.cql3.statements.Bound;
-
import org.apache.cassandra.db.IndexExpression;
import org.apache.cassandra.db.composites.CompositesBuilder;
import org.apache.cassandra.db.index.SecondaryIndex;
@@ -36,12 +34,11 @@ import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.exceptions.InvalidRequestException;
-import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull;
-
+import static org.apache.cassandra.cql3.statements.RequestValidations.checkBindValueSet;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
+import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
-import static org.apache.cassandra.cql3.statements.RequestValidations.checkBindValueSet;
public abstract class SingleColumnRestriction extends AbstractRestriction
{
@@ -111,12 +108,6 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(value, ksName, functionName);
- }
-
- @Override
public Iterable getFunctions()
{
return value.getFunctions();
@@ -225,12 +216,6 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(values, ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Terms.getFunctions(values);
@@ -263,12 +248,6 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Collections.emptySet();
@@ -302,13 +281,6 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return (slice.hasBound(Bound.START) && usesFunction(slice.bound(Bound.START), ksName, functionName))
- || (slice.hasBound(Bound.END) && usesFunction(slice.bound(Bound.END), ksName, functionName));
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return slice.getFunctions();
@@ -509,13 +481,6 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(values, ksName, functionName) || usesFunction(keys, ksName, functionName) ||
- usesFunction(entryKeys, ksName, functionName) || usesFunction(entryValues, ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Iterables.concat(Terms.getFunctions(values),
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index dcaad47..f848e2e 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@ -173,13 +173,6 @@ public final class StatementRestrictions
addSingleColumnRestriction((SingleColumnRestriction) restriction);
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return partitionKeyRestrictions.usesFunction(ksName, functionName)
- || clusteringColumnsRestrictions.usesFunction(ksName, functionName)
- || nonPrimaryKeyRestrictions.usesFunction(ksName, functionName);
- }
-
public Iterable<Function> getFunctions()
{
return Iterables.concat(partitionKeyRestrictions.getFunctions(),
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
index 5a00bd4..f8cd0dc 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
@@ -173,12 +173,6 @@ public abstract class TokenRestriction extends AbstractPrimaryKeyRestrictions
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return usesFunction(value, ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return value.getFunctions();
@@ -233,13 +227,6 @@ public abstract class TokenRestriction extends AbstractPrimaryKeyRestrictions
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return (slice.hasBound(Bound.START) && usesFunction(slice.bound(Bound.START), ksName, functionName))
- || (slice.hasBound(Bound.END) && usesFunction(slice.bound(Bound.END), ksName, functionName));
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return slice.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java b/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
index 11e7e48..1dd1903 100644
--- a/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
+++ b/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
@@ -68,11 +68,6 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
return fun.returnType();
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return fun.usesFunction(ksName, functionName);
- }
-
public Iterable<Function> getFunctions()
{
return Iterables.concat(fun.getFunctions(), factories.getFunctions());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/selection/Selection.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/Selection.java b/src/java/org/apache/cassandra/cql3/selection/Selection.java
index 25bce78..9c990ce 100644
--- a/src/java/org/apache/cassandra/cql3/selection/Selection.java
+++ b/src/java/org/apache/cassandra/cql3/selection/Selection.java
@@ -174,11 +174,6 @@ public abstract class Selection
return columns.size() - 1;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
public Iterable<Function> getFunctions()
{
return Collections.emptySet();
@@ -483,12 +478,6 @@ public abstract class Selection
}
@Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return factories.usesFunction(ksName, functionName);
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return factories.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/selection/Selector.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/Selector.java b/src/java/org/apache/cassandra/cql3/selection/Selector.java
index 8c1e6b8..2d345de 100644
--- a/src/java/org/apache/cassandra/cql3/selection/Selector.java
+++ b/src/java/org/apache/cassandra/cql3/selection/Selector.java
@@ -42,11 +42,6 @@ public abstract class Selector implements AssignmentTestable
*/
public static abstract class Factory
{
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
public Iterable<Function> getFunctions()
{
return Collections.emptySet();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/selection/SelectorFactories.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/SelectorFactories.java b/src/java/org/apache/cassandra/cql3/selection/SelectorFactories.java
index 6de766a..beb7399 100644
--- a/src/java/org/apache/cassandra/cql3/selection/SelectorFactories.java
+++ b/src/java/org/apache/cassandra/cql3/selection/SelectorFactories.java
@@ -89,14 +89,6 @@ final class SelectorFactories implements Iterable<Selector.Factory>
}
}
- public boolean usesFunction(String ksName, String functionName)
- {
- for (Factory factory : factories)
- if (factory != null && factory.usesFunction(ksName, functionName))
- return true;
- return false;
- }
-
public Iterable<Function> getFunctions()
{
Iterable<Function> functions = Collections.emptySet();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
index 27a6ffb..465b2d9 100644
--- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
@@ -76,16 +76,6 @@ public class BatchStatement implements CQLStatement
this.hasConditions = hasConditions;
}
- public boolean usesFunction(String ksName, String functionName)
- {
- if (attrs.usesFunction(ksName, functionName))
- return true;
- for (ModificationStatement statement : statements)
- if (statement.usesFunction(ksName, functionName))
- return true;
- return false;
- }
-
public Iterable<org.apache.cassandra.cql3.functions.Function> getFunctions()
{
Iterable<org.apache.cassandra.cql3.functions.Function> functions = attrs.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index e7a1a20..0862a9f 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -20,7 +20,6 @@ package org.apache.cassandra.cql3.statements;
import java.nio.ByteBuffer;
import java.util.*;
-import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -95,33 +94,6 @@ public abstract class ModificationStatement implements CQLStatement
this.attrs = attrs;
}
- public boolean usesFunction(String ksName, final String functionName)
- {
- if (attrs.usesFunction(ksName, functionName))
- return true;
-
- for (Restriction restriction : processedKeys.values())
- if (restriction.usesFunction(ksName, functionName))
- return true;
-
- if (columnOperations != null)
- for (Operation operation : columnOperations)
- if (operation.usesFunction(ksName, functionName))
- return true;
-
- if (columnConditions != null)
- for (ColumnCondition condition : columnConditions)
- if (condition.usesFunction(ksName, functionName))
- return true;
-
- if (staticConditions != null)
- for (ColumnCondition condition : staticConditions)
- if (condition.usesFunction(ksName, functionName))
- return true;
-
- return false;
- }
-
public Iterable<Function> getFunctions()
{
Iterable<Function> functions = attrs.getFunctions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java b/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
index b848df4..539a957 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
@@ -65,12 +65,7 @@ public abstract class ParsedStatement
}
}
- public boolean usesFunction(String ksName, String functionName)
- {
- return false;
- }
-
- public List<Function> getFunctions()
+ public Iterable<Function> getFunctions()
{
return Collections.emptyList();
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 8f7f75e..fe473aa 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -106,15 +106,6 @@ public class SelectStatement implements CQLStatement
this.limit = limit;
}
- @Override
- public boolean usesFunction(String ksName, String functionName)
- {
- return selection.usesFunction(ksName, functionName)
- || restrictions.usesFunction(ksName, functionName)
- || (limit != null && limit.usesFunction(ksName, functionName));
- }
-
- @Override
public Iterable<Function> getFunctions()
{
return Iterables.concat(selection.getFunctions(),
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/test/unit/org/apache/cassandra/cql3/CQLTester.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java
index b2135aa..c318717 100644
--- a/test/unit/org/apache/cassandra/cql3/CQLTester.java
+++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java
@@ -303,7 +303,9 @@ public abstract class CQLTester
private static boolean containsAny(String filename, List<String> tables)
{
for (int i = 0, m = tables.size(); i < m; i++)
- if (filename.contains(tables.get(i)))
+ // don't accidentally delete in-use directories with the
+ // same prefix as a table to delete, i.e. table_1 & table_11
+ if (filename.contains(tables.get(i) + "-"))
return true;
return false;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java b/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
index cfa42b3..044c98b 100644
--- a/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
@@ -158,7 +158,7 @@ public class UFIdentificationTest extends CQLTester
@Test @Ignore
// Technically, attributes like timestamp and ttl are Terms so could potentially
- // resolve to function calls (& so you can call usesFunction & getFunctions on them)
+ // resolve to function calls (& so you can call getFunctions on them)
// However, this is currently disallowed by CQL syntax
public void testModificationStatementWithAttributesFromFunction() throws Throwable
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d9836e0e/test/unit/org/apache/cassandra/cql3/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UFTest.java b/test/unit/org/apache/cassandra/cql3/UFTest.java
index 3c6baf8..42bddf3 100644
--- a/test/unit/org/apache/cassandra/cql3/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFTest.java
@@ -29,6 +29,7 @@ import com.datastax.driver.core.*;
import org.apache.cassandra.cql3.functions.FunctionName;
import org.apache.cassandra.cql3.functions.Functions;
import org.apache.cassandra.cql3.functions.UDFunction;
+import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.exceptions.FunctionExecutionException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.service.ClientState;
@@ -176,6 +177,122 @@ public class UFTest extends CQLTester
}
@Test
+ public void testDropFunctionDropsPreparedStatementsWithDelayedValues() throws Throwable
+ {
+ // test that dropping a function removes stmts which use
+ // it to provide a DelayedValue collection from the
+ // cache in QueryProcessor
+ checkDelayedValuesCorrectlyIdentifyFunctionsInUse(false);
+ }
+
+ @Test
+ public void testDropKeyspaceContainingFunctionDropsPreparedStatementsWithDelayedValues() throws Throwable
+ {
+ // test that dropping a function removes stmts which use
+ // it to provide a DelayedValue collection from the
+ // cache in QueryProcessor
+ checkDelayedValuesCorrectlyIdentifyFunctionsInUse(true);
+ }
+
+ private ResultMessage.Prepared prepareStatementWithDelayedValue(CollectionType.Kind kind, String function)
+ {
+ String collectionType;
+ String literalArgs;
+ switch (kind)
+ {
+ case LIST:
+ collectionType = "list<double>";
+ literalArgs = String.format("[%s(0.0)]", function);
+ break;
+ case SET:
+ collectionType = "set<double>";
+ literalArgs = String.format("{%s(0.0)}", function);
+ break;
+ case MAP:
+ collectionType = "map<double, double>";
+ literalArgs = String.format("{%s(0.0):0.0}", function);
+ break;
+ default:
+ Assert.fail("Unsupported collection type " + kind);
+ collectionType = null;
+ literalArgs = null;
+ }
+
+ createTable("CREATE TABLE %s (" +
+ " key int PRIMARY KEY," +
+ " val " + collectionType + ")");
+
+ ResultMessage.Prepared prepared = QueryProcessor.prepare(
+ String.format("INSERT INTO %s.%s (key, val) VALUES (?, %s)",
+ KEYSPACE,
+ currentTable(),
+ literalArgs),
+ ClientState.forInternalCalls(), false);
+ Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId));
+ return prepared;
+ }
+
+ private ResultMessage.Prepared prepareStatementWithDelayedValueTuple(String function)
+ {
+ createTable("CREATE TABLE %s (" +
+ " key int PRIMARY KEY," +
+ " val tuple<double> )");
+
+ ResultMessage.Prepared prepared = QueryProcessor.prepare(
+ String.format("INSERT INTO %s.%s (key, val) VALUES (?, (%s(0.0)))",
+ KEYSPACE,
+ currentTable(),
+ function),
+ ClientState.forInternalCalls(), false);
+ Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId));
+ return prepared;
+ }
+
+ public void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
+ {
+ // prepare a statement which doesn't use any function for a control
+ createTable("CREATE TABLE %s (" +
+ " key int PRIMARY KEY," +
+ " val double)");
+ ResultMessage.Prepared control = QueryProcessor.prepare(
+ String.format("INSERT INTO %s.%s (key, val) VALUES (?, ?)",
+ KEYSPACE,
+ currentTable()),
+ ClientState.forInternalCalls(), false);
+ Assert.assertNotNull(QueryProcessor.instance.getPrepared(control.statementId));
+
+ // a function that we'll drop and verify that statements which use it to
+ // provide a DelayedValue are removed from the cache in QueryProcessor
+ String function = createFunction(KEYSPACE_PER_TEST, "double",
+ "CREATE FUNCTION %s ( input double ) " +
+ "RETURNS double " +
+ "LANGUAGE javascript " +
+ "AS 'input'");
+ Assert.assertEquals(1, Functions.find(parseFunctionName(function)).size());
+
+ List<ResultMessage.Prepared> prepared = new ArrayList<>();
+ // prepare statements which use the function to provide a DelayedValue
+ prepared.add(prepareStatementWithDelayedValue(CollectionType.Kind.LIST, function));
+ prepared.add(prepareStatementWithDelayedValue(CollectionType.Kind.SET, function));
+ prepared.add(prepareStatementWithDelayedValue(CollectionType.Kind.MAP, function));
+ prepared.add(prepareStatementWithDelayedValueTuple(function));
+
+ // what to drop - the function is scoped to the per-test keyspace, but the prepared statements
+ // select from the per-fixture keyspace. So if we drop the per-test keyspace, the function
+ // should be removed along with the statements that reference it. The control statement should
+ // remain present in the cache. Likewise, if we actually drop the function itself the control
+ // statement should not be removed, but the others should be
+ if (dropKeyspace)
+ dropPerTestKeyspace();
+ else
+ execute("DROP FUNCTION " + function);
+
+ Assert.assertNotNull(QueryProcessor.instance.getPrepared(control.statementId));
+ for (ResultMessage.Prepared removed : prepared)
+ Assert.assertNull(QueryProcessor.instance.getPrepared(removed.statementId));
+ }
+
+ @Test
public void testFunctionCreationAndDrop() throws Throwable
{
createTable("CREATE TABLE %s (key int PRIMARY KEY, d double)");