[2/3] PHOENIX-167 Support semi/anti-joins

2014-10-06 Thread maryannxue
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

2014-10-06 Thread maryannxue
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