Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
LiteralExpr.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.math.BigDecimal;
18 import java.math.BigInteger;
19 
26 import com.cloudera.impala.thrift.TColumnValue;
27 import com.cloudera.impala.thrift.TExprNode;
28 import com.cloudera.impala.thrift.TQueryCtx;
29 import com.google.common.base.Preconditions;
30 
35 public abstract class LiteralExpr extends Expr implements Comparable<LiteralExpr> {
36 
37  public LiteralExpr() {
39  }
40 
44  protected LiteralExpr(LiteralExpr other) {
45  super(other);
46  }
47 
51  public static LiteralExpr create(String value, Type type) throws AnalysisException {
52  Preconditions.checkArgument(type.isValid());
53  LiteralExpr e = null;
54  switch (type.getPrimitiveType()) {
55  case NULL_TYPE:
56  e = new NullLiteral();
57  break;
58  case BOOLEAN:
59  e = new BoolLiteral(value);
60  break;
61  case TINYINT:
62  case SMALLINT:
63  case INT:
64  case BIGINT:
65  case FLOAT:
66  case DOUBLE:
67  case DECIMAL:
68  e = new NumericLiteral(value, type);
69  break;
70  case STRING:
71  case VARCHAR:
72  case CHAR:
73  e = new StringLiteral(value);
74  break;
75  case DATE:
76  case DATETIME:
77  case TIMESTAMP:
78  // TODO: we support TIMESTAMP but no way to specify it in SQL.
79  throw new AnalysisException(
80  "DATE/DATETIME/TIMESTAMP literals not supported: " + value);
81  default:
82  Preconditions.checkState(false,
83  String.format("Literals of type '%s' not supported.", type.toSql()));
84  }
85  e.analyze(null);
86  // Need to cast since we cannot infer the type from the value. e.g. value
87  // can be parsed as tinyint but we need a bigint.
88  return (LiteralExpr) e.uncheckedCastTo(type);
89  }
90 
94  public static LiteralExpr fromThrift(TExprNode exprNode, Type colType) {
95  try {
96  LiteralExpr result = null;
97  switch (exprNode.node_type) {
98  case FLOAT_LITERAL:
99  result = LiteralExpr.create(
100  Double.toString(exprNode.float_literal.value), colType);
101  break;
102  case DECIMAL_LITERAL:
103  byte[] bytes = exprNode.decimal_literal.getValue();
104  BigDecimal val = new BigDecimal(new BigInteger(bytes));
105  ScalarType decimalType = (ScalarType) colType;
106  // We store the decimal as the unscaled bytes. Need to adjust for the scale.
107  val = val.movePointLeft(decimalType.decimalScale());
108  result = new NumericLiteral(val, colType);
109  break;
110  case INT_LITERAL:
111  result = LiteralExpr.create(
112  Long.toString(exprNode.int_literal.value), colType);
113  break;
114  case STRING_LITERAL:
115  result = LiteralExpr.create(exprNode.string_literal.value, colType);
116  break;
117  case BOOL_LITERAL:
118  result = LiteralExpr.create(
119  Boolean.toString(exprNode.bool_literal.value), colType);
120  break;
121  case NULL_LITERAL:
122  return NullLiteral.create(colType);
123  default:
124  throw new UnsupportedOperationException("Unsupported partition key type: " +
125  exprNode.node_type);
126  }
127  Preconditions.checkNotNull(result);
128  result.analyze(null);
129  return result;
130  } catch (Exception e) {
131  throw new IllegalStateException("Error creating LiteralExpr: ", e);
132  }
133  }
134 
135  // Returns the string representation of the literal's value. Used when passing
136  // literal values to the metastore rather than to Impala backends. This is similar to
137  // the toSql() method, but does not perform any formatting of the string values. Neither
138  // method unescapes string values.
139  public abstract String getStringValue();
140 
141  // Swaps the sign of numeric literals.
142  // Throws for non-numeric literals.
143  public void swapSign() throws NotImplementedException {
144  throw new NotImplementedException("swapSign() only implemented for numeric" +
145  "literals");
146  }
147 
153  public static LiteralExpr create(Expr constExpr, TQueryCtx queryCtx)
154  throws AnalysisException {
155  Preconditions.checkState(constExpr.isConstant());
156  Preconditions.checkState(constExpr.getType().isValid());
157  if (constExpr instanceof LiteralExpr) return (LiteralExpr) constExpr;
158 
159  TColumnValue val = null;
160  try {
161  val = FeSupport.EvalConstExpr(constExpr, queryCtx);
162  } catch (InternalException e) {
163  throw new AnalysisException(String.format("Failed to evaluate expr '%s'",
164  constExpr.toSql()), e);
165  }
166 
167  LiteralExpr result = null;
168  switch (constExpr.getType().getPrimitiveType()) {
169  case NULL_TYPE:
170  result = new NullLiteral();
171  break;
172  case BOOLEAN:
173  if (val.isBool_val()) result = new BoolLiteral(val.bool_val);
174  break;
175  case TINYINT:
176  if (val.isSetByte_val()) {
177  result = new NumericLiteral(BigDecimal.valueOf(val.byte_val));
178  }
179  break;
180  case SMALLINT:
181  if (val.isSetShort_val()) {
182  result = new NumericLiteral(BigDecimal.valueOf(val.short_val));
183  }
184  break;
185  case INT:
186  if (val.isSetInt_val()) {
187  result = new NumericLiteral(BigDecimal.valueOf(val.int_val));
188  }
189  break;
190  case BIGINT:
191  if (val.isSetLong_val()) {
192  result = new NumericLiteral(BigDecimal.valueOf(val.long_val));
193  }
194  break;
195  case FLOAT:
196  case DOUBLE:
197  if (val.isSetDouble_val()) {
198  result =
199  new NumericLiteral(new BigDecimal(val.double_val), constExpr.getType());
200  }
201  break;
202  case DECIMAL:
203  if (val.isSetString_val()) {
204  result =
205  new NumericLiteral(new BigDecimal(val.string_val), constExpr.getType());
206  }
207  break;
208  case STRING:
209  case VARCHAR:
210  case CHAR:
211  if (val.isSetString_val()) result = new StringLiteral(val.string_val);
212  break;
213  case DATE:
214  case DATETIME:
215  case TIMESTAMP:
216  throw new AnalysisException(
217  "DATE/DATETIME/TIMESTAMP literals not supported: " + constExpr.toSql());
218  default:
219  Preconditions.checkState(false,
220  String.format("Literals of type '%s' not supported.",
221  constExpr.getType().toSql()));
222  }
223  // None of the fields in the thrift struct were set indicating a NULL.
224  if (result == null) result = new NullLiteral();
225 
226  result.analyze(null);
227  return (LiteralExpr)result;
228  }
229 
230  // Order NullLiterals based on the SQL ORDER BY default behavior: NULLS LAST.
231  @Override
232  public int compareTo(LiteralExpr other) {
233  if (this instanceof NullLiteral && other instanceof NullLiteral) return 0;
234  if (this instanceof NullLiteral) return -1;
235  if (other instanceof NullLiteral) return 1;
236  if (getClass() != other.getClass()) return -1;
237  return 0;
238  }
239 }
static LiteralExpr create(String value, Type type)
static LiteralExpr create(Expr constExpr, TQueryCtx queryCtx)
static LiteralExpr fromThrift(TExprNode exprNode, Type colType)