[2/3] PHOENIX-167 Support semi/anti-joins
http://git-wip-us.apache.org/repos/asf/phoenix/blob/909d9759/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java -- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java new file mode 100644 index 000..3aecd29 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java @@ -0,0 +1,810 @@ +/* + * 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.phoenix.end2end; + +import static org.apache.phoenix.util.TestUtil.JOIN_COITEM_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_COITEM_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_SCHEMA; +import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.sql.Connection; +import java.sql.Date; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.schema.TableAlreadyExistsException; +import org.apache.phoenix.util.MetaDataUtil; +import org.apache.phoenix.util.PropertiesUtil; +import org.apache.phoenix.util.QueryUtil; +import org.apache.phoenix.util.ReadOnlyProps; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +@Category(HBaseManagedTimeTest.class) +@RunWith(Parameterized.class) +public class SubqueryIT extends BaseHBaseManagedTimeIT { + +private SimpleDateFormat format = new SimpleDateFormat(-MM-dd HH:mm:ss); +private String[] indexDDL; +private String[] plans; + +public SubqueryIT(String[] indexDDL, String[] plans) { +this.indexDDL = indexDDL; +this.plans = plans; +} + +@BeforeClass +@Shadower(classBeingShadowed = BaseHBaseManagedTimeIT.class) +public static void doSetup() throws Exception { +MapString,String props = Maps.newHashMapWithExpectedSize(3); +// Forces server cache to be used +props.put(QueryServices.INDEX_MUTATE_BATCH_SIZE_THRESHOLD_ATTRIB, Integer.toString(2)); +// Must update config before starting server +setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator())); +} + +@Before +public void initTable() throws Exception { +initTableValues(); +if (indexDDL != null indexDDL.length 0) { +Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); +Connection conn = DriverManager.getConnection(getUrl(), props); +for (String ddl : indexDDL) { +try { +conn.createStatement().execute(ddl); +} catch (TableAlreadyExistsException e) { +} +} +conn.close(); +} +} + +@Parameters +public static CollectionObject data() { +ListObject testCases = Lists.newArrayList(); +testCases.add(new String[][] { +{}, { +CLIENT
[2/3] PHOENIX-167 Support semi/anti-joins
http://git-wip-us.apache.org/repos/asf/phoenix/blob/5effbbca/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java -- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java index 075e420..4e882d1 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java @@ -51,6 +51,7 @@ import org.apache.phoenix.parse.ComparisonParseNode; import org.apache.phoenix.parse.DerivedTableNode; import org.apache.phoenix.parse.EqualParseNode; import org.apache.phoenix.parse.HintNode; +import org.apache.phoenix.parse.StatelessTraverseAllParseNodeVisitor; import org.apache.phoenix.parse.HintNode.Hint; import org.apache.phoenix.parse.JoinTableNode; import org.apache.phoenix.parse.JoinTableNode.JoinType; @@ -59,7 +60,6 @@ import org.apache.phoenix.parse.OrderByNode; import org.apache.phoenix.parse.ParseNode; import org.apache.phoenix.parse.ParseNodeFactory; import org.apache.phoenix.parse.SelectStatement; -import org.apache.phoenix.parse.StatelessTraverseAllParseNodeVisitor; import org.apache.phoenix.parse.TableName; import org.apache.phoenix.parse.TableNode; import org.apache.phoenix.parse.TableNodeVisitor; @@ -82,6 +82,7 @@ import org.apache.phoenix.util.SchemaUtil; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class JoinCompiler { @@ -122,9 +123,9 @@ public class JoinCompiler { joinTable.addFilter(select.getWhere()); } -ColumnParseNodeVisitor generalRefVisitor = new ColumnParseNodeVisitor(resolver); -ColumnParseNodeVisitor joinLocalRefVisitor = new ColumnParseNodeVisitor(resolver); -ColumnParseNodeVisitor prefilterRefVisitor = new ColumnParseNodeVisitor(resolver); +ColumnRefParseNodeVisitor generalRefVisitor = new ColumnRefParseNodeVisitor(resolver); +ColumnRefParseNodeVisitor joinLocalRefVisitor = new ColumnRefParseNodeVisitor(resolver); +ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver); joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor); @@ -256,7 +257,7 @@ public class JoinCompiler { this.prefilterAcceptedTables = new ArrayListJoinTable(); for (int i = lastRightJoinIndex == -1 ? 0 : lastRightJoinIndex; i joinSpecs.size(); i++) { JoinSpec joinSpec = joinSpecs.get(i); -if (joinSpec.getType() != JoinType.Left) { +if (joinSpec.getType() != JoinType.Left joinSpec.getType() != JoinType.Anti) { prefilterAcceptedTables.add(joinSpec.getJoinTable()); } } @@ -306,9 +307,9 @@ public class JoinCompiler { filter.accept(visitor); } -public void pushDownColumnRefVisitors(ColumnParseNodeVisitor generalRefVisitor, -ColumnParseNodeVisitor joinLocalRefVisitor, -ColumnParseNodeVisitor prefilterRefVisitor) throws SQLException { +public void pushDownColumnRefVisitors(ColumnRefParseNodeVisitor generalRefVisitor, +ColumnRefParseNodeVisitor joinLocalRefVisitor, +ColumnRefParseNodeVisitor prefilterRefVisitor) throws SQLException { for (ParseNode node : table.getPreFilters()) { node.accept(prefilterRefVisitor); } @@ -359,14 +360,18 @@ public class JoinCompiler { if (!table.isFlat() || (!useStarJoin count 1 - joinSpecs.get(count - 1).getType() != JoinType.Left)) + joinSpecs.get(count - 1).getType() != JoinType.Left + joinSpecs.get(count - 1).getType() != JoinType.Semi + joinSpecs.get(count - 1).getType() != JoinType.Anti)) return null; boolean[] vector = new boolean[count]; for (int i = 0; i count; i++) { JoinSpec joinSpec = joinSpecs.get(i); if (joinSpec.getType() != JoinType.Left - joinSpec.getType() != JoinType.Inner) + joinSpec.getType() != JoinType.Inner + joinSpec.getType() != JoinType.Semi + joinSpec.getType() != JoinType.Anti) return null; vector[i] = true; IteratorTableRef iter = joinSpec.getDependencies().iterator(); @@ -787,22 +792,22 @@ public class JoinCompiler { } private static class