1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.expression; |
7 | |
8 | import org.h2.api.ErrorCode; |
9 | import org.h2.engine.Session; |
10 | import org.h2.message.DbException; |
11 | import org.h2.table.Column; |
12 | import org.h2.table.ColumnResolver; |
13 | import org.h2.table.TableFilter; |
14 | import org.h2.value.Value; |
15 | import org.h2.value.ValueBoolean; |
16 | import org.h2.value.ValueNull; |
17 | |
18 | /** |
19 | * A parameter of a prepared statement. |
20 | */ |
21 | public class Parameter extends Expression implements ParameterInterface { |
22 | |
23 | private Value value; |
24 | private Column column; |
25 | private final int index; |
26 | |
27 | public Parameter(int index) { |
28 | this.index = index; |
29 | } |
30 | |
31 | @Override |
32 | public String getSQL() { |
33 | return "?" + (index + 1); |
34 | } |
35 | |
36 | @Override |
37 | public void setValue(Value v, boolean closeOld) { |
38 | // don't need to close the old value as temporary files are anyway |
39 | // removed |
40 | this.value = v; |
41 | } |
42 | |
43 | public void setValue(Value v) { |
44 | this.value = v; |
45 | } |
46 | |
47 | @Override |
48 | public Value getParamValue() { |
49 | if (value == null) { |
50 | // to allow parameters in function tables |
51 | return ValueNull.INSTANCE; |
52 | } |
53 | return value; |
54 | } |
55 | |
56 | @Override |
57 | public Value getValue(Session session) { |
58 | return getParamValue(); |
59 | } |
60 | |
61 | @Override |
62 | public int getType() { |
63 | if (value != null) { |
64 | return value.getType(); |
65 | } |
66 | if (column != null) { |
67 | return column.getType(); |
68 | } |
69 | return Value.UNKNOWN; |
70 | } |
71 | |
72 | @Override |
73 | public void mapColumns(ColumnResolver resolver, int level) { |
74 | // can't map |
75 | } |
76 | |
77 | @Override |
78 | public void checkSet() { |
79 | if (value == null) { |
80 | throw DbException.get(ErrorCode.PARAMETER_NOT_SET_1, "#" + (index + 1)); |
81 | } |
82 | } |
83 | |
84 | @Override |
85 | public Expression optimize(Session session) { |
86 | return this; |
87 | } |
88 | |
89 | @Override |
90 | public boolean isConstant() { |
91 | return false; |
92 | } |
93 | |
94 | @Override |
95 | public boolean isValueSet() { |
96 | return value != null; |
97 | } |
98 | |
99 | @Override |
100 | public void setEvaluatable(TableFilter tableFilter, boolean b) { |
101 | // not bound |
102 | } |
103 | |
104 | @Override |
105 | public int getScale() { |
106 | if (value != null) { |
107 | return value.getScale(); |
108 | } |
109 | if (column != null) { |
110 | return column.getScale(); |
111 | } |
112 | return 0; |
113 | } |
114 | |
115 | @Override |
116 | public long getPrecision() { |
117 | if (value != null) { |
118 | return value.getPrecision(); |
119 | } |
120 | if (column != null) { |
121 | return column.getPrecision(); |
122 | } |
123 | return 0; |
124 | } |
125 | |
126 | @Override |
127 | public int getDisplaySize() { |
128 | if (value != null) { |
129 | return value.getDisplaySize(); |
130 | } |
131 | if (column != null) { |
132 | return column.getDisplaySize(); |
133 | } |
134 | return 0; |
135 | } |
136 | |
137 | @Override |
138 | public void updateAggregate(Session session) { |
139 | // nothing to do |
140 | } |
141 | |
142 | @Override |
143 | public boolean isEverything(ExpressionVisitor visitor) { |
144 | switch(visitor.getType()) { |
145 | case ExpressionVisitor.EVALUATABLE: |
146 | // the parameter _will_be_ evaluatable at execute time |
147 | case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: |
148 | // it is checked independently if the value is the same as the last |
149 | // time |
150 | case ExpressionVisitor.NOT_FROM_RESOLVER: |
151 | case ExpressionVisitor.QUERY_COMPARABLE: |
152 | case ExpressionVisitor.GET_DEPENDENCIES: |
153 | case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL: |
154 | case ExpressionVisitor.DETERMINISTIC: |
155 | case ExpressionVisitor.READONLY: |
156 | case ExpressionVisitor.GET_COLUMNS: |
157 | return true; |
158 | case ExpressionVisitor.INDEPENDENT: |
159 | return value != null; |
160 | default: |
161 | throw DbException.throwInternalError("type="+visitor.getType()); |
162 | } |
163 | } |
164 | |
165 | @Override |
166 | public int getCost() { |
167 | return 0; |
168 | } |
169 | |
170 | @Override |
171 | public Expression getNotIfPossible(Session session) { |
172 | return new Comparison(session, Comparison.EQUAL, this, |
173 | ValueExpression.get(ValueBoolean.get(false))); |
174 | } |
175 | |
176 | public void setColumn(Column column) { |
177 | this.column = column; |
178 | } |
179 | |
180 | public int getIndex() { |
181 | return index; |
182 | } |
183 | |
184 | } |