1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.expreval.expr.function;
22
23 import org.apache.expreval.client.InternalErrorException;
24 import org.apache.expreval.client.NullColumnValueException;
25 import org.apache.expreval.client.ResultMissingColumnException;
26 import org.apache.expreval.expr.FunctionTypeSignature;
27 import org.apache.expreval.expr.GenericExpression;
28 import org.apache.expreval.expr.TypeSupport;
29 import org.apache.expreval.expr.node.BooleanValue;
30 import org.apache.expreval.expr.node.DateValue;
31 import org.apache.expreval.expr.node.DoubleValue;
32 import org.apache.expreval.expr.node.FloatValue;
33 import org.apache.expreval.expr.node.GenericValue;
34 import org.apache.expreval.expr.node.IntegerValue;
35 import org.apache.expreval.expr.node.LongValue;
36 import org.apache.expreval.expr.node.NumberValue;
37 import org.apache.expreval.expr.node.ShortValue;
38 import org.apache.expreval.expr.node.StringValue;
39 import org.apache.hadoop.hbase.hbql.client.HBqlException;
40 import org.apache.hadoop.hbase.hbql.impl.InvalidTypeException;
41
42 import java.util.List;
43 import java.util.Random;
44
45 public abstract class GenericFunction extends GenericExpression {
46
47 final static Random randomVal = new Random();
48
49 public static enum FunctionType {
50
51
52 DATEINTERVAL(new FunctionTypeSignature(DateValue.class, LongValue.class), false, true),
53 DATECONSTANT(new FunctionTypeSignature(DateValue.class), false, true),
54
55
56 DATE(new FunctionTypeSignature(DateValue.class, StringValue.class, StringValue.class), false, true),
57 LONGTODATE(new FunctionTypeSignature(DateValue.class, LongValue.class), false, true),
58 RANDOMDATE(new FunctionTypeSignature(DateValue.class), false, true),
59
60
61 TRIM(new FunctionTypeSignature(StringValue.class, StringValue.class), false, true),
62 LOWER(new FunctionTypeSignature(StringValue.class, StringValue.class), false, true),
63 UPPER(new FunctionTypeSignature(StringValue.class, StringValue.class), false, true),
64 CONCAT(new FunctionTypeSignature(StringValue.class, StringValue.class, StringValue.class), false, true),
65 REPLACE(new FunctionTypeSignature(StringValue.class, StringValue.class, StringValue.class, StringValue.class), false, true),
66 SUBSTRING(new FunctionTypeSignature(StringValue.class, StringValue.class, IntegerValue.class, IntegerValue.class), false, true),
67 ZEROPAD(new FunctionTypeSignature(StringValue.class, LongValue.class, IntegerValue.class), false, true),
68 REPEAT(new FunctionTypeSignature(StringValue.class, StringValue.class, IntegerValue.class), false, true),
69
70
71 LENGTH(new FunctionTypeSignature(IntegerValue.class, StringValue.class), false, true),
72 INDEXOF(new FunctionTypeSignature(IntegerValue.class, StringValue.class, StringValue.class), false, true),
73
74 DATETOLONG(new FunctionTypeSignature(LongValue.class, DateValue.class), false, true),
75
76 SHORT(new FunctionTypeSignature(ShortValue.class, StringValue.class), false, true),
77 INTEGER(new FunctionTypeSignature(IntegerValue.class, StringValue.class), false, true),
78 LONG(new FunctionTypeSignature(LongValue.class, StringValue.class), false, true),
79 FLOAT(new FunctionTypeSignature(FloatValue.class, StringValue.class), false, true),
80 DOUBLE(new FunctionTypeSignature(DoubleValue.class, StringValue.class), false, true),
81
82 COUNT(new FunctionTypeSignature(LongValue.class), true, false),
83 MIN(new FunctionTypeSignature(NumberValue.class, NumberValue.class), true, false),
84 MAX(new FunctionTypeSignature(NumberValue.class, NumberValue.class), true, false),
85
86 ABS(new FunctionTypeSignature(NumberValue.class, NumberValue.class), false, true),
87 LESSER(new FunctionTypeSignature(NumberValue.class, NumberValue.class, NumberValue.class), false, true),
88 GREATER(new FunctionTypeSignature(NumberValue.class, NumberValue.class, NumberValue.class), false, true),
89
90 RANDOMINTEGER(new FunctionTypeSignature(IntegerValue.class), false, false),
91 RANDOMLONG(new FunctionTypeSignature(LongValue.class), false, false),
92 RANDOMFLOAT(new FunctionTypeSignature(FloatValue.class), false, false),
93 RANDOMDOUBLE(new FunctionTypeSignature(DoubleValue.class), false, false),
94
95
96 RANDOMBOOLEAN(new FunctionTypeSignature(BooleanValue.class), false, false),
97 DEFINEDINROW(new FunctionTypeSignature(BooleanValue.class, GenericValue.class), false, false),
98 EVAL(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
99
100 MAPPINGEXISTS(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
101 FAMILYEXISTSFORTABLE(new FunctionTypeSignature(BooleanValue.class, StringValue.class, StringValue.class), false, false),
102 FAMILYEXISTSFORMAPPING(new FunctionTypeSignature(BooleanValue.class, StringValue.class, StringValue.class), false, false),
103 TABLEEXISTS(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
104 TABLEENABLED(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
105 TABLEAVAILABLE(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
106 INDEXEXISTSFORTABLE(new FunctionTypeSignature(BooleanValue.class, StringValue.class, StringValue.class), false, false),
107 INDEXEXISTSFORMAPPING(new FunctionTypeSignature(BooleanValue.class, StringValue.class, StringValue.class), false, false),
108 ASYNCEXECUTOREXISTS(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false),
109 QUERYEXECUTORPOOLEXISTS(new FunctionTypeSignature(BooleanValue.class, StringValue.class), false, false);
110
111 private final FunctionTypeSignature typeSignature;
112 private final boolean anAggregateValue;
113 private final boolean optimiziable;
114
115 private FunctionType(final FunctionTypeSignature typeSignature,
116 final boolean anAggregateValue,
117 final boolean optimiziable) {
118 this.typeSignature = typeSignature;
119 this.anAggregateValue = anAggregateValue;
120 this.optimiziable = optimiziable;
121 }
122
123 private FunctionTypeSignature getTypeSignature() {
124 return this.typeSignature;
125 }
126
127 public boolean isAnAggregateValue() {
128 return this.anAggregateValue;
129 }
130
131 public boolean isOptimiziable() {
132 return this.optimiziable;
133 }
134
135 public static GenericFunction getFunction(final String functionName, final List<GenericValue> exprList) {
136
137 final FunctionType type;
138
139 try {
140 type = FunctionType.valueOf(functionName.toUpperCase());
141 }
142 catch (IllegalArgumentException e) {
143 return null;
144 }
145
146 final Class<? extends GenericValue> returnType = type.getTypeSignature().getReturnType();
147
148 if (TypeSupport.isParentClass(BooleanValue.class, returnType))
149 return new BooleanFunction(type, exprList);
150 else if (TypeSupport.isParentClass(StringValue.class, returnType))
151 return new StringFunction(type, exprList);
152 else if (TypeSupport.isParentClass(NumberValue.class, returnType))
153 return new NumberFunction(type, exprList);
154 else if (TypeSupport.isParentClass(DateValue.class, returnType))
155 return new DateFunction(type, exprList);
156 else
157 return null;
158 }
159 }
160
161 private final FunctionType functionType;
162
163 public GenericFunction(final FunctionType functionType, final List<GenericValue> exprs) {
164 super(null, exprs);
165 this.functionType = functionType;
166 }
167
168 protected FunctionType getFunctionType() {
169 return this.functionType;
170 }
171
172 protected FunctionTypeSignature getTypeSignature() {
173 return this.getFunctionType().getTypeSignature();
174 }
175
176 protected boolean isIntervalDate() {
177 return this.getFunctionType() == FunctionType.DATEINTERVAL;
178 }
179
180 public boolean isAnAggregateValue() {
181 return this.getFunctionType().isAnAggregateValue();
182 }
183
184 protected boolean isConstantDate() {
185 return this.getFunctionType() == FunctionType.DATECONSTANT;
186 }
187
188 public boolean isAConstant() {
189 if (!this.getFunctionType().isOptimiziable())
190 return false;
191
192 return super.isAConstant();
193 }
194
195 public Class<? extends GenericValue> validateTypes(final GenericValue parentExpr,
196 final boolean allowCollections) throws HBqlException {
197
198 int i = 0;
199 if (this.getGenericValueList().size() != this.getTypeSignature().getArgCount())
200 throw new InvalidTypeException("Incorrect number of arguments in function " + this.getFunctionType().name()
201 + " in " + this.asString());
202
203 for (final Class<? extends GenericValue> clazz : this.getTypeSignature().getArgTypeList()) {
204 final Class<? extends GenericValue> type = this.getExprArg(i).validateTypes(this, false);
205 try {
206 this.validateParentClass(clazz, type);
207 }
208 catch (InvalidTypeException e) {
209
210 throw new InvalidTypeException("Invalid type " + type.getSimpleName() + " for arg " + i + " in function "
211 + this.getFunctionName() + " in "
212 + this.asString() + ". Expecting type " + clazz.getSimpleName() + ".");
213 }
214 i++;
215 }
216
217 return this.getTypeSignature().getReturnType();
218 }
219
220 protected String getFunctionName() {
221 return this.getFunctionType().name();
222 }
223
224 public GenericValue getOptimizedValue() throws HBqlException {
225 this.optimizeAllArgs();
226 if (!this.isAConstant())
227 return this;
228 else
229 try {
230 return this.getFunctionType().getTypeSignature().newLiteral(this.getValue(null, null));
231 }
232 catch (ResultMissingColumnException e) {
233 throw new InternalErrorException("Missing column: " + e.getMessage());
234 }
235 catch (NullColumnValueException e) {
236 throw new InternalErrorException("Null value: " + e.getMessage());
237 }
238 }
239
240 public String asString() {
241 return this.getFunctionName() + super.asString();
242 }
243 }