File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\result\ResultRemote.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.result;
8
9 import java.io.IOException;
10 import java.util.ArrayList;
11 import org.h2.constant.SysProperties;
12 import org.h2.engine.SessionRemote;
13 import org.h2.message.DbException;
14 import org.h2.message.Trace;
15 import org.h2.util.New;
16 import org.h2.value.Transfer;
17 import org.h2.value.Value;
18
19 /**
20 * The client side part of a result set that is kept on the server.
21 * In many cases, the complete data is kept on the client side,
22 * but for large results only a subset is in-memory.
23 */
24 public class ResultRemote implements ResultInterface {
25
26 private int fetchSize;
27 private SessionRemote session;
28 private Transfer transfer;
29 private int id;
30 private final ResultColumn[] columns;
31 private Value[] currentRow;
32 private final int rowCount;
33 private int rowId, rowOffset;
34 private ArrayList<Value[]> result;
35 private final Trace trace;
36
37 public ResultRemote(SessionRemote session, Transfer transfer, int id, int columnCount, int fetchSize)
38 throws IOException {
39 this.session = session;
40 trace = session.getTrace();
41 this.transfer = transfer;
42 this.id = id;
43 this.columns = new ResultColumn[columnCount];
44 rowCount = transfer.readInt();
45 for (int i = 0; i < columnCount; i++) {
46 columns[i] = new ResultColumn(transfer);
47 }
48 rowId = -1;
49 result = New.arrayList();
50 this.fetchSize = fetchSize;
51 fetchRows(false);
52 }
53
54 public String getAlias(int i) {
55 return columns[i].alias;
56 }
57
58 public String getSchemaName(int i) {
59 return columns[i].schemaName;
60 }
61
62 public String getTableName(int i) {
63 return columns[i].tableName;
64 }
65
66 public String getColumnName(int i) {
67 return columns[i].columnName;
68 }
69
70 public int getColumnType(int i) {
71 return columns[i].columnType;
72 }
73
74 public long getColumnPrecision(int i) {
75 return columns[i].precision;
76 }
77
78 public int getColumnScale(int i) {
79 return columns[i].scale;
80 }
81
82 public int getDisplaySize(int i) {
83 return columns[i].displaySize;
84 }
85
86 public boolean isAutoIncrement(int i) {
87 return columns[i].autoIncrement;
88 }
89
90 public int getNullable(int i) {
91 return columns[i].nullable;
92 }
93
94 public void reset() {
95 rowId = -1;
96 currentRow = null;
97 if (session == null) {
98 return;
99 }
100 synchronized (session) {
101 session.checkClosed();
102 try {
103 session.traceOperation("RESULT_RESET", id);
104 transfer.writeInt(SessionRemote.RESULT_RESET).writeInt(id).flush();
105 } catch (IOException e) {
106 throw DbException.convertIOException(e, null);
107 }
108 }
109 }
110
111 public Value[] currentRow() {
112 return currentRow;
113 }
114
115 public boolean next() {
116 if (rowId < rowCount) {
117 rowId++;
118 remapIfOld();
119 if (rowId < rowCount) {
120 if (rowId - rowOffset >= result.size()) {
121 fetchRows(true);
122 }
123 currentRow = result.get(rowId - rowOffset);
124 return true;
125 }
126 currentRow = null;
127 }
128 return false;
129 }
130
131 public int getRowId() {
132 return rowId;
133 }
134
135 public int getVisibleColumnCount() {
136 return columns.length;
137 }
138
139 public int getRowCount() {
140 return rowCount;
141 }
142
143 private void sendClose() {
144 if (session == null) {
145 return;
146 }
147 // TODO result sets: no reset possible for larger remote result sets
148 try {
149 synchronized (session) {
150 session.traceOperation("RESULT_CLOSE", id);
151 transfer.writeInt(SessionRemote.RESULT_CLOSE).writeInt(id);
152 }
153 } catch (IOException e) {
154 trace.error(e, "close");
155 } finally {
156 transfer = null;
157 session = null;
158 }
159 }
160
161 public void close() {
162 result = null;
163 sendClose();
164 }
165
166 private void remapIfOld() {
167 if (session == null) {
168 return;
169 }
170 try {
171 if (id <= session.getCurrentId() - SysProperties.SERVER_CACHED_OBJECTS / 2) {
172 // object is too old - we need to map it to a new id
173 int newId = session.getNextId();
174 session.traceOperation("CHANGE_ID", id);
175 transfer.writeInt(SessionRemote.CHANGE_ID).writeInt(id).writeInt(newId);
176 id = newId;
177 // TODO remote result set: very old result sets may be
178 // already removed on the server (theoretically) - how to
179 // solve this?
180 }
181 } catch (IOException e) {
182 throw DbException.convertIOException(e, null);
183 }
184 }
185
186 private void fetchRows(boolean sendFetch) {
187 synchronized (session) {
188 session.checkClosed();
189 try {
190 rowOffset += result.size();
191 result.clear();
192 int fetch = Math.min(fetchSize, rowCount - rowOffset);
193 if (sendFetch) {
194 session.traceOperation("RESULT_FETCH_ROWS", id);
195 transfer.writeInt(SessionRemote.RESULT_FETCH_ROWS).writeInt(id).writeInt(fetch);
196 session.done(transfer);
197 }
198 for (int r = 0; r < fetch; r++) {
199 boolean row = transfer.readBoolean();
200 if (!row) {
201 break;
202 }
203 int len = columns.length;
204 Value[] values = new Value[len];
205 for (int i = 0; i < len; i++) {
206 Value v = transfer.readValue();
207 values[i] = v;
208 }
209 result.add(values);
210 }
211 if (rowOffset + result.size() >= rowCount) {
212 sendClose();
213 }
214 } catch (IOException e) {
215 throw DbException.convertIOException(e, null);
216 }
217 }
218 }
219
220 public String toString() {
221 return "columns: " + columns.length + " rows: " + rowCount + " pos: " + rowId;
222 }
223
224 public int getFetchSize() {
225 return fetchSize;
226 }
227
228 public void setFetchSize(int fetchSize) {
229 this.fetchSize = fetchSize;
230 }
231
232 public boolean needToClose() {
233 return true;
234 }
235
236 }
237