View Javadoc
1   /*
2    * Copyright 2021 TiKV Project Authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package org.tikv.common.expression;
19  
20  import com.google.common.collect.ImmutableList;
21  import com.google.common.primitives.UnsignedLong;
22  import java.math.BigDecimal;
23  import java.sql.Date;
24  import java.sql.Timestamp;
25  import java.util.List;
26  import java.util.Objects;
27  import org.joda.time.DateTime;
28  import org.tikv.common.exception.TiExpressionException;
29  import org.tikv.common.types.*;
30  
31  // Refactor needed.
32  // Refer to https://github.com/pingcap/tipb/blob/master/go-tipb/expression.pb.go
33  // TODO: This might need a refactor to accept an DataType?
34  public class Constant extends Expression {
35    private final Object value;
36    private final BigDecimal UNSIGNED_LONG_MAX =
37        new BigDecimal(UnsignedLong.fromLongBits(-1).toString());
38  
39    public Constant(Object value, DataType type) {
40      this.value = value;
41      this.dataType = (type == null && value != null) ? getDefaultType(value) : type;
42      this.resolved = true;
43    }
44  
45    public static Constant create(Object value, DataType type) {
46      return new Constant(value, type);
47    }
48  
49    @Deprecated
50    public static Constant create(Object value) {
51      return new Constant(value, null);
52    }
53  
54    protected static boolean isIntegerType(Object value) {
55      return value instanceof Long
56          || value instanceof Integer
57          || value instanceof Short
58          || value instanceof Byte;
59    }
60  
61    private static DataType getDefaultType(Object value) {
62      if (value == null) {
63        throw new TiExpressionException("NULL constant has no type");
64      } else if (isIntegerType(value)) {
65        return IntegerType.BIGINT;
66      } else if (value instanceof String) {
67        return StringType.VARCHAR;
68      } else if (value instanceof Float) {
69        return RealType.FLOAT;
70      } else if (value instanceof Double) {
71        return RealType.DOUBLE;
72      } else if (value instanceof BigDecimal) {
73        int prec = ((BigDecimal) value).precision();
74        int frac = ((BigDecimal) value).scale();
75        return new DecimalType(prec, frac);
76      } else if (value instanceof DateTime) {
77        return DateTimeType.DATETIME;
78      } else if (value instanceof Date) {
79        return DateType.DATE;
80      } else if (value instanceof Timestamp) {
81        return TimestampType.TIMESTAMP;
82      } else if (value instanceof byte[]) {
83        return BytesType.TEXT;
84      } else {
85        throw new TiExpressionException(
86            "Constant type not supported:" + value.getClass().getSimpleName());
87      }
88    }
89  
90    public void setType(DataType type) {
91      this.dataType = type;
92    }
93  
94    public Object getValue() {
95      return value;
96    }
97  
98    @Override
99    public String toString() {
100     if (value == null) {
101       return "null";
102     }
103     if (value instanceof String) {
104       return String.format("\"%s\"", value);
105     }
106     return value.toString();
107   }
108 
109   @Override
110   public boolean equals(Object other) {
111     if (other instanceof Constant) {
112       return Objects.equals(value, ((Constant) other).value);
113     }
114     return false;
115   }
116 
117   @Override
118   public int hashCode() {
119     return Objects.hashCode(value);
120   }
121 
122   @Override
123   public List<Expression> getChildren() {
124     return ImmutableList.of();
125   }
126 
127   @Override
128   public <R, C> R accept(Visitor<R, C> visitor, C context) {
129     return visitor.visit(this, context);
130   }
131 
132   public boolean isOverflowed() {
133     if (this.dataType instanceof IntegerType) {
134       if (((IntegerType) this.dataType).isUnsignedLong()) {
135         return ((BigDecimal) value).min(UNSIGNED_LONG_MAX).signum() > 0
136             || ((BigDecimal) value).signum() < 0;
137       }
138     }
139     return false;
140   }
141 }