View Javadoc

1   /*
2    * Copyright (c) 2011.  The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.expreval.expr.compare;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.expreval.client.NullColumnValueException;
26  import org.apache.expreval.client.ResultMissingColumnException;
27  import org.apache.expreval.expr.Operator;
28  import org.apache.expreval.expr.node.BooleanValue;
29  import org.apache.expreval.expr.node.GenericValue;
30  import org.apache.expreval.expr.var.DelegateColumn;
31  import org.apache.expreval.expr.var.GenericColumn;
32  import org.apache.hadoop.hbase.filter.CompareFilter;
33  import org.apache.hadoop.hbase.filter.Filter;
34  import org.apache.hadoop.hbase.hbql.client.HBqlException;
35  import org.apache.hadoop.hbase.hbql.filter.RecordFilterList;
36  import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
37  import org.apache.hadoop.hbase.hbql.impl.Utils;
38  import org.apache.hadoop.hbase.hbql.io.IO;
39  import org.apache.hadoop.hbase.hbql.mapping.FieldType;
40  import org.apache.hadoop.hbase.hbql.util.Lists;
41  
42  import java.io.DataInput;
43  import java.io.DataOutput;
44  import java.io.IOException;
45  import java.util.List;
46  
47  public class BooleanCompare extends GenericCompare implements BooleanValue {
48  
49      private static final Log LOG = LogFactory.getLog(BooleanCompare.class);
50  
51      public BooleanCompare(final GenericValue arg0, final Operator operator, final GenericValue arg1) {
52          super(arg0, operator, arg1);
53      }
54  
55      public Class<? extends GenericValue> validateTypes(final GenericValue parentExpr,
56                                                         final boolean allowCollections) throws HBqlException {
57          return this.validateType(BooleanValue.class);
58      }
59  
60      public Boolean getValue(final HConnectionImpl conn, final Object object) throws HBqlException,
61                                                                                      ResultMissingColumnException,
62                                                                                      NullColumnValueException {
63  
64          // Do not pre-evalute the OR or AND values. Should evaluate them in place
65          switch (this.getOperator()) {
66              case OR:
67                  return (Boolean)this.getValue(0, conn, object) || (Boolean)this.getValue(1, conn, object);
68              case AND:
69                  return (Boolean)this.getValue(0, conn, object) && (Boolean)this.getValue(1, conn, object);
70              case EQ: {
71                  boolean val0 = (Boolean)this.getValue(0, conn, object);
72                  boolean val1 = (Boolean)this.getValue(1, conn, object);
73                  return val0 == val1;
74              }
75              case NOTEQ: {
76                  boolean val0 = (Boolean)this.getValue(0, conn, object);
77                  boolean val1 = (Boolean)this.getValue(1, conn, object);
78                  return val0 != val1;
79              }
80              default:
81                  throw new HBqlException("Invalid operator: " + this.getOperator());
82          }
83      }
84  
85      public Filter getFilter() throws HBqlException {
86  
87          if (this.getOperator() == Operator.OR || this.getOperator() == Operator.AND) {
88  
89              final Filter filter0 = this.getExprArg(0).getFilter();
90              final Filter filter1 = this.getExprArg(1).getFilter();
91  
92              if (this.getOperator() == Operator.OR) {
93                  if (filter0 instanceof RecordFilterList) {
94                      if (((RecordFilterList)filter0).getOperator() == RecordFilterList.Operator.MUST_PASS_ONE) {
95                          ((RecordFilterList)filter0).addFilter(filter1);
96                          return filter0;
97                      }
98                  }
99  
100                 final List<Filter> filterList = Lists.newArrayList(filter0, filter1);
101                 return new RecordFilterList(RecordFilterList.Operator.MUST_PASS_ONE, filterList);
102             }
103             else {
104                 if (filter0 instanceof RecordFilterList) {
105                     if (((RecordFilterList)filter0).getOperator() == RecordFilterList.Operator.MUST_PASS_ALL) {
106                         ((RecordFilterList)filter0).addFilter(filter1);
107                         return filter0;
108                     }
109                 }
110 
111                 final List<Filter> filterList = Lists.newArrayList(filter0, filter1);
112                 return new RecordFilterList(RecordFilterList.Operator.MUST_PASS_ALL, filterList);
113             }
114         }
115 
116         if (this.getOperator() == Operator.EQ || this.getOperator() == Operator.NOTEQ) {
117 
118             this.validateArgsForCompareFilter();
119 
120             final GenericColumn<? extends GenericValue> column;
121             final Object constant;
122             final CompareFilter.CompareOp compareOp;
123 
124             if (this.getExprArg(0).isAColumnReference()) {
125                 column = ((DelegateColumn)this.getExprArg(0)).getTypedColumn();
126                 constant = this.getConstantValue(1);
127                 compareOp = this.getOperator().getCompareOpLeft();
128             }
129             else {
130                 column = ((DelegateColumn)this.getExprArg(1)).getTypedColumn();
131                 constant = this.getConstantValue(0);
132                 compareOp = this.getOperator().getCompareOpRight();
133             }
134 
135             return this.newSingleColumnValueFilter(column.getColumnAttrib(),
136                                                    compareOp,
137                                                    new BooleanComparable((Boolean)constant));
138         }
139 
140         throw new HBqlException("Invalid operator: " + this.getOperator());
141     }
142 
143     private static class BooleanComparable extends GenericComparable<Boolean> {
144 
145         public BooleanComparable() {
146         }
147 
148         public BooleanComparable(final Boolean value) {
149             this.setTypedValue(value);
150         }
151 
152         public int compareTo(final byte[] bytes) {
153 
154             if (this.equalValues(bytes))
155                 return 0;
156 
157             try {
158                 final Boolean columnValue = IO.getSerialization().getBooleanFromBytes(bytes);
159                 return (this.getTypedValue().compareTo(columnValue));
160             }
161             catch (HBqlException e) {
162                 e.printStackTrace();
163                 Utils.logException(LOG, e);
164                 return 1;
165             }
166         }
167 
168         public void write(final DataOutput dataOutput) throws IOException {
169             dataOutput.writeBoolean(this.getTypedValue());
170         }
171 
172         public void readFields(final DataInput dataInput) throws IOException {
173             this.setTypedValue(dataInput.readBoolean());
174 
175             this.setValueInBytes(FieldType.BooleanType, this.getTypedValue());
176         }
177     }
178 }