File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\index\LinkedIndex.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.index;
8
9 import java.sql.PreparedStatement;
10 import java.sql.ResultSet;
11 import java.util.ArrayList;
12 import org.h2.engine.Constants;
13 import org.h2.engine.Session;
14 import org.h2.message.DbException;
15 import org.h2.result.Row;
16 import org.h2.result.SearchRow;
17 import org.h2.table.Column;
18 import org.h2.table.IndexColumn;
19 import org.h2.table.TableLink;
20 import org.h2.util.New;
21 import org.h2.util.StatementBuilder;
22 import org.h2.value.Value;
23 import org.h2.value.ValueNull;
24
25 /**
26 * A linked index is a index for a linked (remote) table.
27 * It is backed by an index on the remote table which is accessed over JDBC.
28 */
29 public class LinkedIndex extends BaseIndex {
30
31 private final TableLink link;
32 private final String targetTableName;
33 private long rowCount;
34
35 public LinkedIndex(TableLink table, int id, IndexColumn[] columns, IndexType indexType) {
36 initBaseIndex(table, id, null, columns, indexType);
37 link = table;
38 targetTableName = link.getQualifiedTable();
39 }
40
41 public String getCreateSQL() {
42 return null;
43 }
44
45 public void close(Session session) {
46 // nothing to do
47 }
48
49 private static boolean isNull(Value v) {
50 return v == null || v == ValueNull.INSTANCE;
51 }
52
53 public void add(Session session, Row row) {
54 ArrayList<Value> params = New.arrayList();
55 StatementBuilder buff = new StatementBuilder("INSERT INTO ");
56 buff.append(targetTableName).append(" VALUES(");
57 for (int i = 0; i < row.getColumnCount(); i++) {
58 Value v = row.getValue(i);
59 buff.appendExceptFirst(", ");
60 if (v == null) {
61 buff.append("DEFAULT");
62 } else if (isNull(v)) {
63 buff.append("NULL");
64 } else {
65 buff.append('?');
66 params.add(v);
67 }
68 }
69 buff.append(')');
70 String sql = buff.toString();
71 try {
72 link.execute(sql, params, true);
73 rowCount++;
74 } catch (Exception e) {
75 throw TableLink.wrapException(sql, e);
76 }
77 }
78
79 public Cursor find(Session session, SearchRow first, SearchRow last) {
80 ArrayList<Value> params = New.arrayList();
81 StatementBuilder buff = new StatementBuilder("SELECT * FROM ");
82 buff.append(targetTableName).append(" T");
83 for (int i = 0; first != null && i < first.getColumnCount(); i++) {
84 Value v = first.getValue(i);
85 if (v != null) {
86 buff.appendOnlyFirst(" WHERE ");
87 buff.appendExceptFirst(" AND ");
88 Column col = table.getColumn(i);
89 buff.append(col.getSQL());
90 if (v == ValueNull.INSTANCE) {
91 buff.append(" IS NULL");
92 } else {
93 buff.append(">=");
94 addParameter(buff, col);
95 params.add(v);
96 }
97 }
98 }
99 for (int i = 0; last != null && i < last.getColumnCount(); i++) {
100 Value v = last.getValue(i);
101 if (v != null) {
102 buff.appendOnlyFirst(" WHERE ");
103 buff.appendExceptFirst(" AND ");
104 Column col = table.getColumn(i);
105 buff.append(col.getSQL());
106 if (v == ValueNull.INSTANCE) {
107 buff.append(" IS NULL");
108 } else {
109 buff.append("<=");
110 addParameter(buff, col);
111 params.add(v);
112 }
113 }
114 }
115 String sql = buff.toString();
116 try {
117 PreparedStatement prep = link.execute(sql, params, false);
118 ResultSet rs = prep.getResultSet();
119 return new LinkedCursor(link, rs, session, sql, prep);
120 } catch (Exception e) {
121 throw TableLink.wrapException(sql, e);
122 }
123 }
124
125 private void addParameter(StatementBuilder buff, Column col) {
126 if (col.getType() == Value.STRING_FIXED && link.isOracle()) {
127 // workaround for Oracle
128 // create table test(id int primary key, name char(15));
129 // insert into test values(1, 'Hello')
130 // select * from test where name = ? -- where ? = "Hello" > no rows
131 buff.append("CAST(? AS CHAR(").append(col.getPrecision()).append("))");
132 } else {
133 buff.append('?');
134 }
135 }
136
137 public double getCost(Session session, int[] masks) {
138 return 100 + getCostRangeIndex(masks, rowCount + Constants.COST_ROW_OFFSET);
139 }
140
141 public void remove(Session session) {
142 // nothing to do
143 }
144
145 public void truncate(Session session) {
146 // nothing to do
147 }
148
149 public void checkRename() {
150 throw DbException.getUnsupportedException("LINKED");
151 }
152
153 public boolean needRebuild() {
154 return false;
155 }
156
157 public boolean canGetFirstOrLast() {
158 return false;
159 }
160
161 public Cursor findFirstOrLast(Session session, boolean first) {
162 // TODO optimization: could get the first or last value (in any case;
163 // maybe not optimized)
164 throw DbException.getUnsupportedException("LINKED");
165 }
166
167 public void remove(Session session, Row row) {
168 ArrayList<Value> params = New.arrayList();
169 StatementBuilder buff = new StatementBuilder("DELETE FROM ");
170 buff.append(targetTableName).append(" WHERE ");
171 for (int i = 0; i < row.getColumnCount(); i++) {
172 buff.appendExceptFirst("AND ");
173 Column col = table.getColumn(i);
174 buff.append(col.getSQL());
175 Value v = row.getValue(i);
176 if (isNull(v)) {
177 buff.append(" IS NULL ");
178 } else {
179 buff.append('=');
180 addParameter(buff, col);
181 params.add(v);
182 buff.append(' ');
183 }
184 }
185 String sql = buff.toString();
186 try {
187 PreparedStatement prep = link.execute(sql, params, false);
188 int count = prep.executeUpdate();
189 link.reusePreparedStatement(prep, sql);
190 rowCount -= count;
191 } catch (Exception e) {
192 throw TableLink.wrapException(sql, e);
193 }
194 }
195
196 /**
197 * Update a row using a UPDATE statement. This method is to be called if the
198 * emit updates option is enabled.
199 *
200 * @param oldRow the old data
201 * @param newRow the new data
202 */
203 public void update(Row oldRow, Row newRow) {
204 ArrayList<Value> params = New.arrayList();
205 StatementBuilder buff = new StatementBuilder("UPDATE ");
206 buff.append(targetTableName).append(" SET ");
207 for (int i = 0; i < newRow.getColumnCount(); i++) {
208 buff.appendExceptFirst(", ");
209 buff.append(table.getColumn(i).getSQL()).append('=');
210 Value v = newRow.getValue(i);
211 if (v == null) {
212 buff.append("DEFAULT");
213 } else {
214 buff.append('?');
215 params.add(v);
216 }
217 }
218 buff.append(" WHERE ");
219 buff.resetCount();
220 for (int i = 0; i < oldRow.getColumnCount(); i++) {
221 Column col = table.getColumn(i);
222 buff.appendExceptFirst(" AND ");
223 buff.append(col.getSQL());
224 Value v = oldRow.getValue(i);
225 if (isNull(v)) {
226 buff.append(" IS NULL");
227 } else {
228 buff.append('=');
229 params.add(v);
230 addParameter(buff, col);
231 }
232 }
233 String sql = buff.toString();
234 try {
235 link.execute(sql, params, true);
236 } catch (Exception e) {
237 throw TableLink.wrapException(sql, e);
238 }
239 }
240
241 public long getRowCount(Session session) {
242 return rowCount;
243 }
244
245 public long getRowCountApproximation() {
246 return rowCount;
247 }
248
249 }
250