Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
StringLiteral.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.io.IOException;
18 import java.io.StringReader;
19 import java.math.BigDecimal;
20 
21 import java_cup.runtime.Symbol;
22 
23 import org.apache.hadoop.hive.ql.parse.BaseSemanticAnalyzer;
24 
28 import com.cloudera.impala.thrift.TExprNode;
29 import com.cloudera.impala.thrift.TExprNodeType;
30 import com.cloudera.impala.thrift.TStringLiteral;
31 import com.google.common.base.Objects;
32 import com.google.common.base.Preconditions;
33 
34 public class StringLiteral extends LiteralExpr {
35  private final String value_;
36 
37  public StringLiteral(String value) {
38  this.value_ = value;
40  }
41 
42  public StringLiteral(String value, Type type) {
43  this.value_ = value;
44  type_ = type;
45  }
46 
50  protected StringLiteral(StringLiteral other) {
51  super(other);
52  value_ = other.value_;
53  }
54 
55  @Override
56  public boolean equals(Object obj) {
57  if (!super.equals(obj)) return false;
58  return ((StringLiteral) obj).value_.equals(value_);
59  }
60 
61  @Override
62  public String toSqlImpl() {
63  return "'" + value_ + "'";
64  }
65 
66  @Override
67  protected void toThrift(TExprNode msg) {
68  msg.node_type = TExprNodeType.STRING_LITERAL;
69  msg.string_literal = new TStringLiteral(getUnescapedValue());
70  }
71 
72  public String getValue() { return value_; }
73 
74  public String getUnescapedValue() {
75  // Unescape string exactly like Hive does. Hive's method assumes
76  // quotes so we add them here to reuse Hive's code.
77  return BaseSemanticAnalyzer.unescapeSQLString("'" + value_ + "'");
78  }
79 
80  @Override
81  public String getStringValue() {
82  return value_;
83  }
84 
85  @Override
86  public String debugString() {
87  return Objects.toStringHelper(this)
88  .add("value", value_)
89  .toString();
90  }
91 
92  @Override
93  protected Expr uncheckedCastTo(Type targetType) throws AnalysisException {
94  Preconditions.checkState(targetType.isNumericType() || targetType.isDateType()
95  || targetType.equals(this.type_) || targetType.isStringType());
96  if (targetType.equals(this.type_)) {
97  return this;
98  } else if (targetType.isStringType()) {
99  type_ = targetType;
100  } else if (targetType.isNumericType()) {
101  return convertToNumber();
102  } else if (targetType.isDateType()) {
103  // Let the BE do the cast so it is in Boost format
104  return new CastExpr(targetType, this);
105  }
106  return this;
107  }
108 
119  throws AnalysisException {
120  StringReader reader = new StringReader(value_);
121  SqlScanner scanner = new SqlScanner(reader);
122  // For distinguishing positive and negative numbers.
123  boolean negative = false;
124  Symbol sym;
125  try {
126  // We allow simple chaining of MINUS to recognize negative numbers.
127  // Currently we can't handle string literals containing full fledged expressions
128  // which are implicitly cast to a numeric literal.
129  // This would require invoking the parser.
130  sym = scanner.next_token();
131  while (sym.sym == SqlParserSymbols.SUBTRACT) {
132  negative = !negative;
133  sym = scanner.next_token();
134  }
135  } catch (IOException e) {
136  throw new AnalysisException("Failed to convert string literal to number.", e);
137  }
138  if (sym.sym == SqlParserSymbols.NUMERIC_OVERFLOW) {
139  throw new AnalysisException("Number too large: " + value_);
140  }
141  if (sym.sym == SqlParserSymbols.INTEGER_LITERAL) {
142  BigDecimal val = (BigDecimal) sym.value;
143  if (negative) val = val.negate();
144  return new NumericLiteral(val);
145  }
146  if (sym.sym == SqlParserSymbols.DECIMAL_LITERAL) {
147  BigDecimal val = (BigDecimal) sym.value;
148  if (negative) val = val.negate();
149  return new NumericLiteral(val);
150  }
151  // Symbol is not an integer or floating point literal.
152  throw new AnalysisException(
153  "Failed to convert string literal '" + value_ + "' to number.");
154  }
155 
156  @Override
157  public int compareTo(LiteralExpr o) {
158  int ret = super.compareTo(o);
159  if (ret != 0) return ret;
160  StringLiteral other = (StringLiteral) o;
161  return value_.compareTo(other.getStringValue());
162  }
163 
164  @Override
165  public Expr clone() { return new StringLiteral(this); }
166 }
static final ScalarType STRING
Definition: Type.java:53