1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sqlfederation.resultset;
19
20 import com.cedarsoftware.util.CaseInsensitiveMap;
21 import org.apache.calcite.linq4j.Enumerator;
22 import org.apache.calcite.rel.type.RelDataType;
23 import org.apache.calcite.schema.Schema;
24 import org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
25 import org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
26 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
27 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
28 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.driver.jdbc.type.util.ResultSetUtils;
29 import org.apache.shardingsphere.sqlfederation.resultset.converter.SQLFederationColumnTypeConverter;
30
31 import java.io.InputStream;
32 import java.io.Reader;
33 import java.math.BigDecimal;
34 import java.net.URL;
35 import java.sql.Array;
36 import java.sql.Blob;
37 import java.sql.Clob;
38 import java.sql.Date;
39 import java.sql.ResultSetMetaData;
40 import java.sql.SQLException;
41 import java.sql.SQLFeatureNotSupportedException;
42 import java.sql.SQLWarning;
43 import java.sql.SQLXML;
44 import java.sql.Statement;
45 import java.sql.Time;
46 import java.sql.Timestamp;
47 import java.util.Arrays;
48 import java.util.Calendar;
49 import java.util.Collection;
50 import java.util.HashSet;
51 import java.util.List;
52 import java.util.Map;
53
54
55
56
57 public final class SQLFederationResultSet extends AbstractUnsupportedOperationSQLFederationResultSet {
58
59 private static final String ASCII = "Ascii";
60
61 private static final String UNICODE = "Unicode";
62
63 private static final String BINARY = "Binary";
64
65 private static final Collection<Class<?>> INVALID_FEDERATION_TYPES = new HashSet<>(Arrays.asList(Blob.class, Clob.class, Reader.class, InputStream.class, SQLXML.class));
66
67 private final Enumerator<?> enumerator;
68
69 private final Map<String, Integer> columnLabelAndIndexes;
70
71 private final SQLFederationResultSetMetaData resultSetMetaData;
72
73 private final SQLFederationColumnTypeConverter columnTypeConverter;
74
75 private Object[] currentRows;
76
77 private boolean wasNull;
78
79 private boolean closed;
80
81 public SQLFederationResultSet(final Enumerator<?> enumerator, final Schema sqlFederationSchema, final List<Projection> expandProjections, final DatabaseType databaseType,
82 final RelDataType resultColumnType) {
83 this.enumerator = enumerator;
84 columnTypeConverter = DatabaseTypedSPILoader.getService(SQLFederationColumnTypeConverter.class, databaseType);
85 columnLabelAndIndexes = new CaseInsensitiveMap<>(expandProjections.size(), 1F);
86 Map<Integer, String> indexAndColumnLabels = new CaseInsensitiveMap<>(expandProjections.size(), 1F);
87 handleColumnLabelAndIndex(columnLabelAndIndexes, indexAndColumnLabels, expandProjections);
88 resultSetMetaData = new SQLFederationResultSetMetaData(sqlFederationSchema, expandProjections, databaseType, resultColumnType, indexAndColumnLabels, columnTypeConverter);
89 }
90
91 private void handleColumnLabelAndIndex(final Map<String, Integer> columnLabelAndIndexes, final Map<Integer, String> indexAndColumnLabels, final List<Projection> expandProjections) {
92 for (int columnIndex = 1; columnIndex <= expandProjections.size(); columnIndex++) {
93 Projection projection = expandProjections.get(columnIndex - 1);
94 String columnLabel = projection.getColumnLabel();
95 columnLabelAndIndexes.put(columnLabel, columnIndex);
96 indexAndColumnLabels.put(columnIndex, columnLabel);
97 }
98 }
99
100 @Override
101 public boolean next() {
102 boolean result = enumerator.moveNext();
103 if (result) {
104 Object current = enumerator.current();
105 currentRows = null == current ? new Object[]{null} : getCurrentRows(current);
106 } else {
107 currentRows = new Object[]{null};
108 }
109 return result;
110 }
111
112 private Object[] getCurrentRows(final Object current) {
113 return current.getClass().isArray() && !(current instanceof byte[]) ? (Object[]) current : new Object[]{current};
114 }
115
116 @Override
117 public void close() {
118 closed = true;
119 enumerator.close();
120 currentRows = null;
121 }
122
123 @Override
124 public boolean wasNull() {
125 return wasNull;
126 }
127
128 @Override
129 public String getString(final int columnIndex) throws SQLException {
130 return (String) ResultSetUtils.convertValue(getValue(columnIndex, String.class), String.class);
131 }
132
133 @Override
134 public String getString(final String columnLabel) throws SQLException {
135 return getString(getIndexFromColumnLabelAndIndexMap(columnLabel));
136 }
137
138 @Override
139 public boolean getBoolean(final int columnIndex) throws SQLException {
140 return (boolean) ResultSetUtils.convertValue(getValue(columnIndex, boolean.class), boolean.class);
141 }
142
143 @Override
144 public boolean getBoolean(final String columnLabel) throws SQLException {
145 return getBoolean(getIndexFromColumnLabelAndIndexMap(columnLabel));
146 }
147
148 @Override
149 public byte getByte(final int columnIndex) throws SQLException {
150 return (byte) ResultSetUtils.convertValue(getValue(columnIndex, byte.class), byte.class);
151 }
152
153 @Override
154 public byte getByte(final String columnLabel) throws SQLException {
155 return getByte(getIndexFromColumnLabelAndIndexMap(columnLabel));
156 }
157
158 @Override
159 public short getShort(final int columnIndex) throws SQLException {
160 return (short) ResultSetUtils.convertValue(getValue(columnIndex, short.class), short.class);
161 }
162
163 @Override
164 public short getShort(final String columnLabel) throws SQLException {
165 return getShort(getIndexFromColumnLabelAndIndexMap(columnLabel));
166 }
167
168 @Override
169 public int getInt(final int columnIndex) throws SQLException {
170 return (int) ResultSetUtils.convertValue(getValue(columnIndex, int.class), int.class);
171 }
172
173 @Override
174 public int getInt(final String columnLabel) throws SQLException {
175 return getInt(getIndexFromColumnLabelAndIndexMap(columnLabel));
176 }
177
178 @Override
179 public long getLong(final int columnIndex) throws SQLException {
180 return (long) ResultSetUtils.convertValue(getValue(columnIndex, long.class), long.class);
181 }
182
183 @Override
184 public long getLong(final String columnLabel) throws SQLException {
185 return getLong(getIndexFromColumnLabelAndIndexMap(columnLabel));
186 }
187
188 @Override
189 public float getFloat(final int columnIndex) throws SQLException {
190 return (float) ResultSetUtils.convertValue(getValue(columnIndex, float.class), float.class);
191 }
192
193 @Override
194 public float getFloat(final String columnLabel) throws SQLException {
195 return getFloat(getIndexFromColumnLabelAndIndexMap(columnLabel));
196 }
197
198 @Override
199 public double getDouble(final int columnIndex) throws SQLException {
200 return (double) ResultSetUtils.convertValue(getValue(columnIndex, double.class), double.class);
201 }
202
203 @Override
204 public double getDouble(final String columnLabel) throws SQLException {
205 return getDouble(getIndexFromColumnLabelAndIndexMap(columnLabel));
206 }
207
208 @Override
209 public BigDecimal getBigDecimal(final int columnIndex, final int scale) throws SQLException {
210 return (BigDecimal) ResultSetUtils.convertValue(getValue(columnIndex, BigDecimal.class), BigDecimal.class);
211 }
212
213 @Override
214 public BigDecimal getBigDecimal(final String columnLabel, final int scale) throws SQLException {
215 return getBigDecimal(getIndexFromColumnLabelAndIndexMap(columnLabel));
216 }
217
218 @Override
219 public BigDecimal getBigDecimal(final int columnIndex) throws SQLException {
220 return (BigDecimal) ResultSetUtils.convertValue(getValue(columnIndex, BigDecimal.class), BigDecimal.class);
221 }
222
223 @Override
224 public BigDecimal getBigDecimal(final String columnLabel) throws SQLException {
225 return getBigDecimal(getIndexFromColumnLabelAndIndexMap(columnLabel));
226 }
227
228 @Override
229 public byte[] getBytes(final int columnIndex) throws SQLException {
230 return (byte[]) ResultSetUtils.convertValue(getValue(columnIndex, byte[].class), byte[].class);
231 }
232
233 @Override
234 public byte[] getBytes(final String columnLabel) throws SQLException {
235 return getBytes(getIndexFromColumnLabelAndIndexMap(columnLabel));
236 }
237
238 @Override
239 public Date getDate(final int columnIndex) throws SQLException {
240 return (Date) ResultSetUtils.convertValue(getValue(columnIndex, Date.class), Date.class);
241 }
242
243 @Override
244 public Date getDate(final String columnLabel) throws SQLException {
245 return getDate(getIndexFromColumnLabelAndIndexMap(columnLabel));
246 }
247
248 @Override
249 public Date getDate(final int columnIndex, final Calendar cal) throws SQLException {
250 return (Date) ResultSetUtils.convertValue(getCalendarValue(columnIndex), Date.class);
251 }
252
253 @Override
254 public Date getDate(final String columnLabel, final Calendar cal) throws SQLException {
255 return getDate(getIndexFromColumnLabelAndIndexMap(columnLabel), cal);
256 }
257
258 @Override
259 public Time getTime(final int columnIndex) throws SQLException {
260 return (Time) ResultSetUtils.convertValue(getValue(columnIndex, Time.class), Time.class);
261 }
262
263 @Override
264 public Time getTime(final String columnLabel) throws SQLException {
265 return getTime(getIndexFromColumnLabelAndIndexMap(columnLabel));
266 }
267
268 @Override
269 public Time getTime(final int columnIndex, final Calendar cal) throws SQLException {
270 return (Time) ResultSetUtils.convertValue(getCalendarValue(columnIndex), Time.class);
271 }
272
273 @Override
274 public Time getTime(final String columnLabel, final Calendar cal) throws SQLException {
275 return getTime(getIndexFromColumnLabelAndIndexMap(columnLabel), cal);
276 }
277
278 @Override
279 public Timestamp getTimestamp(final int columnIndex) throws SQLException {
280 return (Timestamp) ResultSetUtils.convertValue(getValue(columnIndex, Timestamp.class), Timestamp.class);
281 }
282
283 @Override
284 public Timestamp getTimestamp(final String columnLabel) throws SQLException {
285 return getTimestamp(getIndexFromColumnLabelAndIndexMap(columnLabel));
286 }
287
288 @Override
289 public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException {
290 return (Timestamp) ResultSetUtils.convertValue(getCalendarValue(columnIndex), Timestamp.class);
291 }
292
293 @Override
294 public Timestamp getTimestamp(final String columnLabel, final Calendar cal) throws SQLException {
295 return getTimestamp(getIndexFromColumnLabelAndIndexMap(columnLabel), cal);
296 }
297
298 @Override
299 public InputStream getAsciiStream(final int columnIndex) throws SQLException {
300 return getInputStream(ASCII);
301 }
302
303 @Override
304 public InputStream getAsciiStream(final String columnLabel) throws SQLException {
305 return getAsciiStream(getIndexFromColumnLabelAndIndexMap(columnLabel));
306 }
307
308 @Override
309 public InputStream getUnicodeStream(final int columnIndex) throws SQLException {
310 return getInputStream(UNICODE);
311 }
312
313 @Override
314 public InputStream getUnicodeStream(final String columnLabel) throws SQLException {
315 return getUnicodeStream(getIndexFromColumnLabelAndIndexMap(columnLabel));
316 }
317
318 @Override
319 public InputStream getBinaryStream(final int columnIndex) throws SQLException {
320 return getInputStream(BINARY);
321 }
322
323 @Override
324 public InputStream getBinaryStream(final String columnLabel) throws SQLException {
325 return getBinaryStream(getIndexFromColumnLabelAndIndexMap(columnLabel));
326 }
327
328 @Override
329 public SQLWarning getWarnings() {
330 return null;
331 }
332
333 @Override
334 public void clearWarnings() {
335 }
336
337 @Override
338 public ResultSetMetaData getMetaData() {
339 return resultSetMetaData;
340 }
341
342 @Override
343 public Object getObject(final int columnIndex) throws SQLException {
344 return getValue(columnIndex, Object.class);
345 }
346
347 @Override
348 public Object getObject(final String columnLabel) throws SQLException {
349 return getObject(getIndexFromColumnLabelAndIndexMap(columnLabel));
350 }
351
352 @Override
353 public int findColumn(final String columnLabel) throws SQLException {
354 return getIndexFromColumnLabelAndIndexMap(columnLabel);
355 }
356
357 @Override
358 public Reader getCharacterStream(final int columnIndex) throws SQLException {
359 return (Reader) getValue(columnIndex, Reader.class);
360 }
361
362 @Override
363 public Reader getCharacterStream(final String columnLabel) throws SQLException {
364 return getCharacterStream(getIndexFromColumnLabelAndIndexMap(columnLabel));
365 }
366
367 @Override
368 public void setFetchDirection(final int direction) {
369 }
370
371 @Override
372 public int getFetchDirection() {
373 return FETCH_FORWARD;
374 }
375
376 @Override
377 public void setFetchSize(final int rows) {
378 }
379
380 @Override
381 public int getFetchSize() {
382 return 0;
383 }
384
385 @Override
386 public int getType() {
387 return TYPE_FORWARD_ONLY;
388 }
389
390 @Override
391 public int getConcurrency() {
392 return CONCUR_READ_ONLY;
393 }
394
395 @Override
396 public Statement getStatement() {
397 return null;
398 }
399
400 @Override
401 public Blob getBlob(final int columnIndex) throws SQLException {
402 return (Blob) getValue(columnIndex, Blob.class);
403 }
404
405 @Override
406 public Blob getBlob(final String columnLabel) throws SQLException {
407 return getBlob(getIndexFromColumnLabelAndIndexMap(columnLabel));
408 }
409
410 @Override
411 public Clob getClob(final int columnIndex) throws SQLException {
412 return (Clob) getValue(columnIndex, Clob.class);
413 }
414
415 @Override
416 public Clob getClob(final String columnLabel) throws SQLException {
417 return getClob(getIndexFromColumnLabelAndIndexMap(columnLabel));
418 }
419
420 @Override
421 public Array getArray(final int columnIndex) throws SQLException {
422 return (Array) getValue(columnIndex, Array.class);
423 }
424
425 @Override
426 public Array getArray(final String columnLabel) throws SQLException {
427 return getArray(getIndexFromColumnLabelAndIndexMap(columnLabel));
428 }
429
430 @Override
431 public URL getURL(final int columnIndex) throws SQLException {
432 return (URL) getValue(columnIndex, URL.class);
433 }
434
435 @Override
436 public URL getURL(final String columnLabel) throws SQLException {
437 return getURL(getIndexFromColumnLabelAndIndexMap(columnLabel));
438 }
439
440 @Override
441 public boolean isClosed() {
442 return closed;
443 }
444
445 @Override
446 public SQLXML getSQLXML(final int columnIndex) throws SQLException {
447 return (SQLXML) getValue(columnIndex, SQLXML.class);
448 }
449
450 @Override
451 public SQLXML getSQLXML(final String columnLabel) throws SQLException {
452 return getSQLXML(getIndexFromColumnLabelAndIndexMap(columnLabel));
453 }
454
455 @Override
456 public String getNString(final int columnIndex) throws SQLException {
457 return getString(columnIndex);
458 }
459
460 @Override
461 public String getNString(final String columnLabel) throws SQLException {
462 return getString(columnLabel);
463 }
464
465 private Integer getIndexFromColumnLabelAndIndexMap(final String columnLabel) throws SQLException {
466 Integer result = columnLabelAndIndexes.get(columnLabel);
467 ShardingSpherePreconditions.checkNotNull(result, () -> new SQLFeatureNotSupportedException(String.format("can not get index from column label `%s`", columnLabel)));
468 return result;
469 }
470
471 private Object getValue(final int columnIndex, final Class<?> type) throws SQLException {
472 ShardingSpherePreconditions.checkNotContains(INVALID_FEDERATION_TYPES, type, () -> new SQLFeatureNotSupportedException(String.format("Get value from `%s`", type.getName())));
473 Object result = currentRows[columnIndex - 1];
474 wasNull = null == result;
475 return columnTypeConverter.convertColumnValue(result);
476 }
477
478 private Object getCalendarValue(final int columnIndex) {
479
480 Object result = currentRows[columnIndex - 1];
481 wasNull = null == result;
482 return result;
483 }
484
485 private InputStream getInputStream(final String type) throws SQLException {
486 throw new SQLFeatureNotSupportedException(String.format("Get input stream from `%s`", type));
487 }
488 }