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