File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\expression\ConditionInSelect.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.expression;
8
9 import org.h2.command.dml.Query;
10 import org.h2.constant.ErrorCode;
11 import org.h2.engine.Database;
12 import org.h2.engine.Session;
13 import org.h2.index.IndexCondition;
14 import org.h2.message.DbException;
15 import org.h2.result.LocalResult;
16 import org.h2.table.ColumnResolver;
17 import org.h2.table.TableFilter;
18 import org.h2.util.StringUtils;
19 import org.h2.value.Value;
20 import org.h2.value.ValueBoolean;
21 import org.h2.value.ValueNull;
22
23 /**
24 * An 'in' condition with a subquery, as in WHERE ID IN(SELECT ...)
25 */
26 public class ConditionInSelect extends Condition {
27
28 private final Database database;
29 private Expression left;
30 private final Query query;
31 private final boolean all;
32 private final int compareType;
33 private int queryLevel;
34
35 public ConditionInSelect(Database database, Expression left, Query query, boolean all, int compareType) {
36 this.database = database;
37 this.left = left;
38 this.query = query;
39 this.all = all;
40 this.compareType = compareType;
41 }
42
43 public Value getValue(Session session) {
44 query.setSession(session);
45 LocalResult rows = query.query(0);
46 session.addTemporaryResult(rows);
47 Value l = left.getValue(session);
48 if (rows.getRowCount() == 0) {
49 return ValueBoolean.get(all);
50 } else if (l == ValueNull.INSTANCE) {
51 return l;
52 }
53 if (!session.getDatabase().getSettings().optimizeInSelect) {
54 return getValueSlow(rows, l);
55 }
56 if (all || (compareType != Comparison.EQUAL && compareType != Comparison.EQUAL_NULL_SAFE)) {
57 return getValueSlow(rows, l);
58 }
59 int dataType = rows.getColumnType(0);
60 if (dataType == Value.NULL) {
61 return ValueBoolean.get(false);
62 }
63 l = l.convertTo(dataType);
64 if (rows.containsDistinct(new Value[] { l })) {
65 return ValueBoolean.get(true);
66 }
67 if (rows.containsDistinct(new Value[] { ValueNull.INSTANCE })) {
68 return ValueNull.INSTANCE;
69 }
70 return ValueBoolean.get(false);
71 }
72
73 private Value getValueSlow(LocalResult rows, Value l) {
74 // this only returns the correct result if the result has at least one
75 // row, and if l is not null
76 boolean hasNull = false;
77 boolean result = all;
78 while (rows.next()) {
79 boolean value;
80 Value r = rows.currentRow()[0];
81 if (r == ValueNull.INSTANCE) {
82 value = false;
83 hasNull = true;
84 } else {
85 value = Comparison.compareNotNull(database, l, r, compareType);
86 }
87 if (!value && all) {
88 result = false;
89 break;
90 } else if (value && !all) {
91 result = true;
92 break;
93 }
94 }
95 if (!result && hasNull) {
96 return ValueNull.INSTANCE;
97 }
98 return ValueBoolean.get(result);
99 }
100
101 public void mapColumns(ColumnResolver resolver, int level) {
102 left.mapColumns(resolver, level);
103 query.mapColumns(resolver, level + 1);
104 this.queryLevel = Math.max(level, this.queryLevel);
105 }
106
107 public Expression optimize(Session session) {
108 left = left.optimize(session);
109 query.setRandomAccessResult(true);
110 query.prepare();
111 if (query.getColumnCount() != 1) {
112 throw DbException.get(ErrorCode.SUBQUERY_IS_NOT_SINGLE_COLUMN);
113 }
114 // Can not optimize: the data may change
115 return this;
116 }
117
118 public void setEvaluatable(TableFilter tableFilter, boolean b) {
119 left.setEvaluatable(tableFilter, b);
120 query.setEvaluatable(tableFilter, b);
121 }
122
123 public String getSQL() {
124 StringBuilder buff = new StringBuilder();
125 buff.append('(').append(left.getSQL()).append(' ');
126 if (all) {
127 buff.append(Comparison.getCompareOperator(compareType)).
128 append(" ALL");
129 } else {
130 buff.append("IN");
131 }
132 buff.append("(\n").append(StringUtils.indent(query.getPlanSQL(), 4, false)).
133 append("))");
134 return buff.toString();
135 }
136
137 public void updateAggregate(Session session) {
138 left.updateAggregate(session);
139 query.updateAggregate(session);
140 }
141
142 public boolean isEverything(ExpressionVisitor visitor) {
143 return left.isEverything(visitor) && query.isEverything(visitor);
144 }
145
146 public int getCost() {
147 return left.getCost() + query.getCostAsExpression();
148 }
149
150 public void createIndexConditions(Session session, TableFilter filter) {
151 if (!session.getDatabase().getSettings().optimizeInList) {
152 return;
153 }
154 if (!(left instanceof ExpressionColumn)) {
155 return;
156 }
157 ExpressionColumn l = (ExpressionColumn) left;
158 if (filter != l.getTableFilter()) {
159 return;
160 }
161 ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
162 if (!query.isEverything(visitor)) {
163 return;
164 }
165 filter.addIndexCondition(IndexCondition.getInQuery(l, query));
166 }
167
168 }
169