You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2010/09/06 17:41:03 UTC
svn commit: r993074 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/compile/
testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: kahatlen
Date: Mon Sep 6 15:41:02 2010
New Revision: 993074
URL: http://svn.apache.org/viewvc?rev=993074&view=rev
Log:
DERBY-4791 (partial) LIKE operator optimizations and concatenation
Made ConcatenationOperatorNode capable of constant folding so that for
example 'ab' || '%' can be handled the same way as 'ab%'.
Added:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java (with props)
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ConcatenationOperatorNode.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ConcatenationOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ConcatenationOperatorNode.java?rev=993074&r1=993073&r2=993074&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ConcatenationOperatorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ConcatenationOperatorNode.java Mon Sep 6 15:41:02 2010
@@ -65,6 +65,34 @@ public class ConcatenationOperatorNode e
ClassName.ConcatableDataValue, ClassName.ConcatableDataValue);
}
+ /**
+ * Check if this node always evaluates to the same value. If so, return
+ * a constant node representing the known result.
+ *
+ * @return a constant node representing the result of this concatenation
+ * operation, or {@code this} if the result is not known up front
+ */
+ ValueNode evaluateConstantExpressions() throws StandardException {
+ if (leftOperand instanceof CharConstantNode &&
+ rightOperand instanceof CharConstantNode) {
+ CharConstantNode leftOp = (CharConstantNode) leftOperand;
+ CharConstantNode rightOp = (CharConstantNode) rightOperand;
+ StringDataValue leftValue = (StringDataValue) leftOp.getValue();
+ StringDataValue rightValue = (StringDataValue) rightOp.getValue();
+
+ StringDataValue resultValue =
+ (StringDataValue) getTypeServices().getNull();
+ resultValue.concatenate(leftValue, rightValue, resultValue);
+
+ return (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.CHAR_CONSTANT_NODE,
+ resultValue.getString(),
+ getContextManager());
+ }
+
+ return this;
+ }
+
/**
* overrides BindOperatorNode.bindExpression because concatenation has
* special requirements for parameter binding.
@@ -263,7 +291,9 @@ public class ConcatenationOperatorNode e
*/
this.setLeftRightInterfaceType(tc.interfaceName());
- return this;
+ // Finally, fold constants so that for example LIKE optimization is
+ // able to take advantage of concatenated literals like 'ab' || '%'.
+ return this.evaluateConstantExpressions();
}
/**
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java?rev=993074&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java Mon Sep 6 15:41:02 2010
@@ -0,0 +1,73 @@
+/*
+ * Class org.apache.derbyTesting.functionTests.tests.lang.LikeTest
+ *
+ * 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.derbyTesting.functionTests.tests.lang;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import junit.framework.Test;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.RuntimeStatisticsParser;
+import org.apache.derbyTesting.junit.SQLUtilities;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Tests for statements with a LIKE clause.
+ */
+public class LikeTest extends BaseJDBCTestCase {
+ public LikeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return TestConfiguration.defaultSuite(LikeTest.class);
+ }
+
+ /**
+ * Test that LIKE expressions are optimized and use indexes to limit the
+ * scan if the arguments are concatenated string literals. DERBY-4791.
+ */
+ public void testOptimizeConcatenatedStringLiterals() throws SQLException {
+ setAutoCommit(false);
+ Statement s = createStatement();
+ s.execute("create table t (x varchar(128) primary key, y int)");
+ s.execute("insert into t(x) values " +
+ "'abc', 'def', 'ghi', 'ab', 'de', 'gh'");
+ s.execute("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+
+ // Check that an optimizable LIKE predicate (one that doesn't begin
+ // with a wildcard) with a string literal picks an index scan.
+ String[][] expectedRows = { {"ab", null}, {"abc", null} };
+ JDBC.assertUnorderedResultSet(
+ s.executeQuery("select * from t where x like 'ab%'"),
+ expectedRows);
+ assertTrue(SQLUtilities.getRuntimeStatisticsParser(s).usedIndexScan());
+
+ // Now do the same test, but concatenate two string literals instead
+ // of using a single string literal. This should be optimized the
+ // same way.
+ JDBC.assertUnorderedResultSet(
+ s.executeQuery("select * from t where x like 'a'||'b'||'%'"),
+ expectedRows);
+ assertTrue(SQLUtilities.getRuntimeStatisticsParser(s).usedIndexScan());
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LikeTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=993074&r1=993073&r2=993074&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Mon Sep 6 15:41:02 2010
@@ -77,6 +77,7 @@ public class _Suite extends BaseTestCase
suite.addTest(InsertTest.suite());
suite.addTest(JoinTest.suite());
suite.addTest(LangScripts.suite());
+ suite.addTest(LikeTest.suite());
suite.addTest(LojReorderTest.suite());
suite.addTest(MathTrigFunctionsTest.suite());
suite.addTest(OuterJoinTest.suite());