/
Literal.java
171 lines (140 loc) · 5.07 KB
/
Literal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.expression;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.expression.gen.script.Params;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
import org.elasticsearch.xpack.sql.type.DataTypes;
import java.util.List;
import java.util.Objects;
import static java.util.Collections.emptyList;
/**
* SQL Literal or constant.
*/
public class Literal extends NamedExpression {
public static final Literal TRUE = Literal.of(Location.EMPTY, Boolean.TRUE);
public static final Literal FALSE = Literal.of(Location.EMPTY, Boolean.FALSE);
public static final Literal NULL = Literal.of(Location.EMPTY, null);
private final Object value;
private final DataType dataType;
public Literal(Location location, Object value, DataType dataType) {
this(location, null, value, dataType);
}
public Literal(Location location, String name, Object value, DataType dataType) {
super(location, name == null ? String.valueOf(value) : name, emptyList(), null);
this.dataType = dataType;
this.value = DataTypeConversion.convert(value, dataType);
}
@Override
protected NodeInfo<Literal> info() {
return NodeInfo.create(this, Literal::new, value, dataType);
}
public Object value() {
return value;
}
@Override
public boolean foldable() {
return true;
}
@Override
public boolean nullable() {
return value == null;
}
@Override
public DataType dataType() {
return dataType;
}
@Override
public boolean resolved() {
return true;
}
@Override
public Object fold() {
return value;
}
@Override
public Attribute toAttribute() {
return new LiteralAttribute(location(), name(), null, false, id(), false, dataType, this);
}
@Override
public ScriptTemplate asScript() {
return new ScriptTemplate(String.valueOf(value), Params.EMPTY, dataType);
}
@Override
public Expression replaceChildren(List<Expression> newChildren) {
throw new UnsupportedOperationException("this type of node doesn't have any children to replace");
}
@Override
public AttributeSet references() {
return AttributeSet.EMPTY;
}
@Override
protected Expression canonicalize() {
String s = String.valueOf(value);
return name().equals(s) ? this : Literal.of(location(), value);
}
@Override
public int hashCode() {
return Objects.hash(value, dataType);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Literal other = (Literal) obj;
return Objects.equals(value, other.value)
&& Objects.equals(dataType, other.dataType);
}
@Override
public String toString() {
String s = String.valueOf(value);
return name().equals(s) ? s : name() + "=" + value;
}
/**
* Utility method for creating 'in-line' Literals (out of values instead of expressions).
*/
public static Literal of(Location loc, Object value) {
if (value instanceof Literal) {
return (Literal) value;
}
return new Literal(loc, value, DataTypes.fromJava(value));
}
/**
* Utility method for creating a literal out of a foldable expression.
* Throws an exception if the expression is not foldable.
*/
public static Literal of(Expression foldable) {
return of((String) null, foldable);
}
public static Literal of(String name, Expression foldable) {
if (!foldable.foldable()) {
throw new SqlIllegalArgumentException("Foldable expression required for Literal creation; received unfoldable " + foldable);
}
if (foldable instanceof Literal) {
Literal l = (Literal) foldable;
if (name == null || l.name().equals(name)) {
return l;
}
}
Object fold = foldable.fold();
if (name == null) {
name = foldable instanceof NamedExpression ? ((NamedExpression) foldable).name() : String.valueOf(fold);
}
return new Literal(foldable.location(), name, fold, foldable.dataType());
}
public static Literal of(Expression source, Object value) {
String name = source instanceof NamedExpression ? ((NamedExpression) source).name() : String.valueOf(value);
return new Literal(source.location(), name, value, source.dataType());
}
}