001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2007-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap4j;
011
012import org.olap4j.OlapWrapper;
013
014import java.io.InputStream;
015import java.io.Reader;
016import java.math.BigDecimal;
017import java.net.URL;
018import java.sql.*;
019import java.sql.Date;
020import java.util.*;
021import javax.sql.rowset.RowSetMetaDataImpl;
022
023/**
024 * Implementation of {@link ResultSet} which returns 0 rows.
025 *
026 * <p>This class is used to implement {@link java.sql.DatabaseMetaData}
027 * methods for querying object types where those object types never have
028 * any instances for this particular driver.</p>
029 *
030 * <p>This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs;
031 * it is instantiated using {@link Factory#newEmptyResultSet}.</p>
032 *
033 * @author jhyde
034 * @since May 24, 2007
035 */
036abstract class EmptyResultSet implements ResultSet, OlapWrapper {
037    final MondrianOlap4jConnection olap4jConnection;
038    private final List<String> headerList;
039    private final List<List<Object>> rowList;
040    private int rowOrdinal = -1;
041    private final RowSetMetaDataImpl metaData = new RowSetMetaDataImpl();
042
043    EmptyResultSet(
044        MondrianOlap4jConnection olap4jConnection,
045        List<String> headerList,
046        List<List<Object>> rowList)
047    {
048        this.olap4jConnection = olap4jConnection;
049        this.headerList = headerList;
050        this.rowList = rowList;
051        try {
052            metaData.setColumnCount(headerList.size());
053            for (int i = 0; i < headerList.size(); i++) {
054                metaData.setColumnName(i + 1, headerList.get(i));
055                deduceType(rowList, i);
056            }
057        } catch (SQLException e) {
058            throw new RuntimeException(e);
059        }
060    }
061
062    protected void deduceType(List<List<Object>> rowList, int column)
063        throws SQLException
064    {
065        int nullability = ResultSetMetaData.columnNoNulls;
066        int type = Types.OTHER;
067        int maxLen = 0;
068        for (List<Object> objects : rowList) {
069            final Object o = objects.get(column);
070            if (o == null) {
071                nullability = ResultSetMetaData.columnNullable;
072            } else {
073                if (type == Types.OTHER) {
074                    type = deduceColumnType(o);
075                }
076                if (o instanceof String) {
077                    maxLen = Math.max(maxLen, ((String) o).length());
078                }
079            }
080        }
081        metaData.setNullable(column + 1, nullability);
082        metaData.setColumnType(column + 1, type);
083        if (maxLen > 0) {
084            metaData.setPrecision(column + 1, maxLen);
085        }
086    }
087
088    private int deduceColumnType(Object o) {
089        if (o instanceof String) {
090            return Types.VARCHAR;
091        } else if (o instanceof Integer) {
092            return Types.INTEGER;
093        } else if (o instanceof Long) {
094            return Types.BIGINT;
095        } else if (o instanceof Double) {
096            return Types.DOUBLE;
097        } else if (o instanceof Float) {
098            return Types.FLOAT;
099        } else if (o instanceof Boolean) {
100            return Types.BOOLEAN;
101        } else {
102            return Types.VARCHAR;
103        }
104    }
105
106    // helper methods
107
108    /**
109     * Returns the value of a given column
110     * @param columnOrdinal 0-based ordinal
111     * @return Value
112     */
113    private Object getColumn(int columnOrdinal) {
114        return rowList.get(rowOrdinal).get(columnOrdinal);
115    }
116
117    private Object getColumn(String columnLabel) throws SQLException {
118        int column = headerList.indexOf(columnLabel);
119        if (column < 0) {
120            throw new SQLException("Column not found: " + columnLabel);
121        }
122        return rowList.get(rowOrdinal).get(column);
123    }
124
125    // implement ResultSet
126
127    public boolean next() throws SQLException {
128        // note that if rowOrdinal == rowList.size - 1, we move but then return
129        // false
130        if (rowOrdinal < rowList.size()) {
131            ++rowOrdinal;
132        }
133        return rowOrdinal < rowList.size();
134    }
135
136    public void close() throws SQLException {
137    }
138
139    public boolean wasNull() throws SQLException {
140        throw new UnsupportedOperationException();
141    }
142
143    public String getString(int columnIndex) throws SQLException {
144        final Object result = getColumn(columnIndex - 1);
145        return result == null ? null : String.valueOf(result);
146    }
147
148    public boolean getBoolean(int columnIndex) throws SQLException {
149        Object o = getColumn(columnIndex - 1);
150        if (o instanceof Boolean) {
151            return (Boolean) o;
152        } else if (o instanceof String) {
153            return Boolean.valueOf((String) o);
154        } else {
155            return !o.equals(0);
156        }
157    }
158
159    public byte getByte(int columnIndex) throws SQLException {
160        Object o = getColumn(columnIndex - 1);
161        return ((Number) o).byteValue();
162    }
163
164    public short getShort(int columnIndex) throws SQLException {
165        Object o = getColumn(columnIndex - 1);
166        return ((Number) o).shortValue();
167    }
168
169    public int getInt(int columnIndex) throws SQLException {
170        Object o = getColumn(columnIndex - 1);
171        return ((Number) o).intValue();
172    }
173
174    public long getLong(int columnIndex) throws SQLException {
175        Object o = getColumn(columnIndex - 1);
176        return ((Number) o).longValue();
177    }
178
179    public float getFloat(int columnIndex) throws SQLException {
180        Object o = getColumn(columnIndex - 1);
181        return ((Number) o).floatValue();
182    }
183
184    public double getDouble(int columnIndex) throws SQLException {
185        Object o = getColumn(columnIndex - 1);
186        return ((Number) o).doubleValue();
187    }
188
189    public BigDecimal getBigDecimal(
190        int columnIndex, int scale) throws SQLException
191    {
192        throw new UnsupportedOperationException();
193    }
194
195    public byte[] getBytes(int columnIndex) throws SQLException {
196        Object o = getColumn(columnIndex - 1);
197        return (byte[]) o;
198    }
199
200    public Date getDate(int columnIndex) throws SQLException {
201        Object o = getColumn(columnIndex - 1);
202        return (Date) o;
203    }
204
205    public Time getTime(int columnIndex) throws SQLException {
206        Object o = getColumn(columnIndex - 1);
207        return (Time) o;
208    }
209
210    public Timestamp getTimestamp(int columnIndex) throws SQLException {
211        Object o = getColumn(columnIndex - 1);
212        return (Timestamp) o;
213    }
214
215    public InputStream getAsciiStream(int columnIndex) throws SQLException {
216        throw new UnsupportedOperationException();
217    }
218
219    public InputStream getUnicodeStream(int columnIndex) throws SQLException {
220        throw new UnsupportedOperationException();
221    }
222
223    public InputStream getBinaryStream(int columnIndex) throws SQLException {
224        throw new UnsupportedOperationException();
225    }
226
227    public String getString(String columnLabel) throws SQLException {
228        final Object result = getColumn(columnLabel);
229        return result == null ? null : String.valueOf(result);
230    }
231
232    public boolean getBoolean(String columnLabel) throws SQLException {
233        Object o = getColumn(columnLabel);
234        if (o instanceof Boolean) {
235            return (Boolean) o;
236        } else if (o instanceof String) {
237            return Boolean.valueOf((String) o);
238        } else {
239            return !o.equals(0);
240        }
241    }
242
243    public byte getByte(String columnLabel) throws SQLException {
244        Object o = getColumn(columnLabel);
245        return ((Number) o).byteValue();
246    }
247
248    public short getShort(String columnLabel) throws SQLException {
249        Object o = getColumn(columnLabel);
250        return ((Number) o).shortValue();
251    }
252
253    public int getInt(String columnLabel) throws SQLException {
254        Object o = getColumn(columnLabel);
255        return ((Number) o).intValue();
256    }
257
258    public long getLong(String columnLabel) throws SQLException {
259        Object o = getColumn(columnLabel);
260        return ((Number) o).longValue();
261    }
262
263    public float getFloat(String columnLabel) throws SQLException {
264        Object o = getColumn(columnLabel);
265        return ((Number) o).floatValue();
266    }
267
268    public double getDouble(String columnLabel) throws SQLException {
269        Object o = getColumn(columnLabel);
270        return ((Number) o).doubleValue();
271    }
272
273    public BigDecimal getBigDecimal(
274        String columnLabel, int scale) throws SQLException
275    {
276        throw new UnsupportedOperationException();
277    }
278
279    public byte[] getBytes(String columnLabel) throws SQLException {
280        Object o = getColumn(columnLabel);
281        return (byte[]) o;
282    }
283
284    public Date getDate(String columnLabel) throws SQLException {
285        Object o = getColumn(columnLabel);
286        return (Date) o;
287    }
288
289    public Time getTime(String columnLabel) throws SQLException {
290        Object o = getColumn(columnLabel);
291        return (Time) o;
292    }
293
294    public Timestamp getTimestamp(String columnLabel) throws SQLException {
295        Object o = getColumn(columnLabel);
296        return (Timestamp) o;
297    }
298
299    public InputStream getAsciiStream(String columnLabel) throws SQLException {
300        throw new UnsupportedOperationException();
301    }
302
303    public InputStream getUnicodeStream(String columnLabel) throws SQLException
304    {
305        throw new UnsupportedOperationException();
306    }
307
308    public InputStream getBinaryStream(String columnLabel) throws SQLException {
309        throw new UnsupportedOperationException();
310    }
311
312    public SQLWarning getWarnings() throws SQLException {
313        throw new UnsupportedOperationException();
314    }
315
316    public void clearWarnings() throws SQLException {
317        throw new UnsupportedOperationException();
318    }
319
320    public String getCursorName() throws SQLException {
321        throw new UnsupportedOperationException();
322    }
323
324    public ResultSetMetaData getMetaData() throws SQLException {
325        return metaData;
326    }
327
328    public Object getObject(int columnIndex) throws SQLException {
329        throw new UnsupportedOperationException();
330    }
331
332    public Object getObject(String columnLabel) throws SQLException {
333        throw new UnsupportedOperationException();
334    }
335
336    public int findColumn(String columnLabel) throws SQLException {
337        throw new UnsupportedOperationException();
338    }
339
340    public Reader getCharacterStream(int columnIndex) throws SQLException {
341        throw new UnsupportedOperationException();
342    }
343
344    public Reader getCharacterStream(String columnLabel) throws SQLException {
345        throw new UnsupportedOperationException();
346    }
347
348    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
349        throw new UnsupportedOperationException();
350    }
351
352    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
353        throw new UnsupportedOperationException();
354    }
355
356    public boolean isBeforeFirst() throws SQLException {
357        return rowOrdinal < 0;
358    }
359
360    public boolean isAfterLast() throws SQLException {
361        return rowOrdinal >= rowList.size();
362    }
363
364    public boolean isFirst() throws SQLException {
365        return rowOrdinal == 0;
366    }
367
368    public boolean isLast() throws SQLException {
369        return rowOrdinal == rowList.size() - 1;
370    }
371
372    public void beforeFirst() throws SQLException {
373        rowOrdinal = -1;
374    }
375
376    public void afterLast() throws SQLException {
377        rowOrdinal = rowList.size();
378    }
379
380    public boolean first() throws SQLException {
381        if (rowList.size() == 0) {
382            return false;
383        } else {
384            rowOrdinal = 0;
385            return true;
386        }
387    }
388
389    public boolean last() throws SQLException {
390        if (rowList.size() == 0) {
391            return false;
392        } else {
393            rowOrdinal = rowList.size() - 1;
394            return true;
395        }
396    }
397
398    public int getRow() throws SQLException {
399        return rowOrdinal + 1; // 1-based
400    }
401
402    public boolean absolute(int row) throws SQLException {
403        int newRowOrdinal = row - 1;// convert to 0-based
404        if (newRowOrdinal >= 0 && newRowOrdinal < rowList.size()) {
405            rowOrdinal = newRowOrdinal;
406            return true;
407        } else {
408            return false;
409        }
410    }
411
412    public boolean relative(int rows) throws SQLException {
413        int newRowOrdinal = rowOrdinal + (rows - 1);
414        if (newRowOrdinal >= 0 && newRowOrdinal < rowList.size()) {
415            rowOrdinal = newRowOrdinal;
416            return true;
417        } else {
418            return false;
419        }
420    }
421
422    public boolean previous() throws SQLException {
423        // converse of next(); note that if rowOrdinal == 0, we decrement
424        // but return false
425        if (rowOrdinal >= 0) {
426            --rowOrdinal;
427        }
428        return rowOrdinal >= 0;
429    }
430
431    public void setFetchDirection(int direction) throws SQLException {
432        throw new UnsupportedOperationException();
433    }
434
435    public int getFetchDirection() throws SQLException {
436        throw new UnsupportedOperationException();
437    }
438
439    public void setFetchSize(int rows) throws SQLException {
440        throw new UnsupportedOperationException();
441    }
442
443    public int getFetchSize() throws SQLException {
444        throw new UnsupportedOperationException();
445    }
446
447    public int getType() throws SQLException {
448        throw new UnsupportedOperationException();
449    }
450
451    public int getConcurrency() throws SQLException {
452        throw new UnsupportedOperationException();
453    }
454
455    public boolean rowUpdated() throws SQLException {
456        throw new UnsupportedOperationException();
457    }
458
459    public boolean rowInserted() throws SQLException {
460        throw new UnsupportedOperationException();
461    }
462
463    public boolean rowDeleted() throws SQLException {
464        throw new UnsupportedOperationException();
465    }
466
467    public void updateNull(int columnIndex) throws SQLException {
468        throw new UnsupportedOperationException();
469    }
470
471    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
472        throw new UnsupportedOperationException();
473    }
474
475    public void updateByte(int columnIndex, byte x) throws SQLException {
476        throw new UnsupportedOperationException();
477    }
478
479    public void updateShort(int columnIndex, short x) throws SQLException {
480        throw new UnsupportedOperationException();
481    }
482
483    public void updateInt(int columnIndex, int x) throws SQLException {
484        throw new UnsupportedOperationException();
485    }
486
487    public void updateLong(int columnIndex, long x) throws SQLException {
488        throw new UnsupportedOperationException();
489    }
490
491    public void updateFloat(int columnIndex, float x) throws SQLException {
492        throw new UnsupportedOperationException();
493    }
494
495    public void updateDouble(int columnIndex, double x) throws SQLException {
496        throw new UnsupportedOperationException();
497    }
498
499    public void updateBigDecimal(
500        int columnIndex, BigDecimal x) throws SQLException
501    {
502        throw new UnsupportedOperationException();
503    }
504
505    public void updateString(int columnIndex, String x) throws SQLException {
506        throw new UnsupportedOperationException();
507    }
508
509    public void updateBytes(int columnIndex, byte x[]) throws SQLException {
510        throw new UnsupportedOperationException();
511    }
512
513    public void updateDate(int columnIndex, Date x) throws SQLException {
514        throw new UnsupportedOperationException();
515    }
516
517    public void updateTime(int columnIndex, Time x) throws SQLException {
518        throw new UnsupportedOperationException();
519    }
520
521    public void updateTimestamp(
522        int columnIndex, Timestamp x) throws SQLException
523    {
524        throw new UnsupportedOperationException();
525    }
526
527    public void updateAsciiStream(
528        int columnIndex, InputStream x, int length) throws SQLException
529    {
530        throw new UnsupportedOperationException();
531    }
532
533    public void updateBinaryStream(
534        int columnIndex, InputStream x, int length) throws SQLException
535    {
536        throw new UnsupportedOperationException();
537    }
538
539    public void updateCharacterStream(
540        int columnIndex, Reader x, int length) throws SQLException
541    {
542        throw new UnsupportedOperationException();
543    }
544
545    public void updateObject(
546        int columnIndex, Object x, int scaleOrLength) throws SQLException
547    {
548        throw new UnsupportedOperationException();
549    }
550
551    public void updateObject(int columnIndex, Object x) throws SQLException {
552        throw new UnsupportedOperationException();
553    }
554
555    public void updateNull(String columnLabel) throws SQLException {
556        throw new UnsupportedOperationException();
557    }
558
559    public void updateBoolean(
560        String columnLabel, boolean x) throws SQLException
561    {
562        throw new UnsupportedOperationException();
563    }
564
565    public void updateByte(String columnLabel, byte x) throws SQLException {
566        throw new UnsupportedOperationException();
567    }
568
569    public void updateShort(String columnLabel, short x) throws SQLException {
570        throw new UnsupportedOperationException();
571    }
572
573    public void updateInt(String columnLabel, int x) throws SQLException {
574        throw new UnsupportedOperationException();
575    }
576
577    public void updateLong(String columnLabel, long x) throws SQLException {
578        throw new UnsupportedOperationException();
579    }
580
581    public void updateFloat(String columnLabel, float x) throws SQLException {
582        throw new UnsupportedOperationException();
583    }
584
585    public void updateDouble(String columnLabel, double x) throws SQLException {
586        throw new UnsupportedOperationException();
587    }
588
589    public void updateBigDecimal(
590        String columnLabel, BigDecimal x) throws SQLException
591    {
592        throw new UnsupportedOperationException();
593    }
594
595    public void updateString(String columnLabel, String x) throws SQLException {
596        throw new UnsupportedOperationException();
597    }
598
599    public void updateBytes(String columnLabel, byte x[]) throws SQLException {
600        throw new UnsupportedOperationException();
601    }
602
603    public void updateDate(String columnLabel, Date x) throws SQLException {
604        throw new UnsupportedOperationException();
605    }
606
607    public void updateTime(String columnLabel, Time x) throws SQLException {
608        throw new UnsupportedOperationException();
609    }
610
611    public void updateTimestamp(
612        String columnLabel, Timestamp x) throws SQLException
613    {
614        throw new UnsupportedOperationException();
615    }
616
617    public void updateAsciiStream(
618        String columnLabel, InputStream x, int length) throws SQLException
619    {
620        throw new UnsupportedOperationException();
621    }
622
623    public void updateBinaryStream(
624        String columnLabel, InputStream x, int length) throws SQLException
625    {
626        throw new UnsupportedOperationException();
627    }
628
629    public void updateCharacterStream(
630        String columnLabel, Reader reader, int length) throws SQLException
631    {
632        throw new UnsupportedOperationException();
633    }
634
635    public void updateObject(
636        String columnLabel, Object x, int scaleOrLength) throws SQLException
637    {
638        throw new UnsupportedOperationException();
639    }
640
641    public void updateObject(String columnLabel, Object x) throws SQLException {
642        throw new UnsupportedOperationException();
643    }
644
645    public void insertRow() throws SQLException {
646        throw new UnsupportedOperationException();
647    }
648
649    public void updateRow() throws SQLException {
650        throw new UnsupportedOperationException();
651    }
652
653    public void deleteRow() throws SQLException {
654        throw new UnsupportedOperationException();
655    }
656
657    public void refreshRow() throws SQLException {
658        throw new UnsupportedOperationException();
659    }
660
661    public void cancelRowUpdates() throws SQLException {
662        throw new UnsupportedOperationException();
663    }
664
665    public void moveToInsertRow() throws SQLException {
666        throw new UnsupportedOperationException();
667    }
668
669    public void moveToCurrentRow() throws SQLException {
670        throw new UnsupportedOperationException();
671    }
672
673    public Statement getStatement() throws SQLException {
674        throw new UnsupportedOperationException();
675    }
676
677    public Object getObject(
678        int columnIndex, Map<String, Class<?>> map) throws SQLException
679    {
680        throw new UnsupportedOperationException();
681    }
682
683    public Ref getRef(int columnIndex) throws SQLException {
684        throw new UnsupportedOperationException();
685    }
686
687    public Blob getBlob(int columnIndex) throws SQLException {
688        throw new UnsupportedOperationException();
689    }
690
691    public Clob getClob(int columnIndex) throws SQLException {
692        throw new UnsupportedOperationException();
693    }
694
695    public Array getArray(int columnIndex) throws SQLException {
696        throw new UnsupportedOperationException();
697    }
698
699    public Object getObject(
700        String columnLabel, Map<String, Class<?>> map) throws SQLException
701    {
702        throw new UnsupportedOperationException();
703    }
704
705    public Ref getRef(String columnLabel) throws SQLException {
706        throw new UnsupportedOperationException();
707    }
708
709    public Blob getBlob(String columnLabel) throws SQLException {
710        throw new UnsupportedOperationException();
711    }
712
713    public Clob getClob(String columnLabel) throws SQLException {
714        throw new UnsupportedOperationException();
715    }
716
717    public Array getArray(String columnLabel) throws SQLException {
718        throw new UnsupportedOperationException();
719    }
720
721    public Date getDate(int columnIndex, Calendar cal) throws SQLException {
722        throw new UnsupportedOperationException();
723    }
724
725    public Date getDate(String columnLabel, Calendar cal) throws SQLException {
726        throw new UnsupportedOperationException();
727    }
728
729    public Time getTime(int columnIndex, Calendar cal) throws SQLException {
730        throw new UnsupportedOperationException();
731    }
732
733    public Time getTime(String columnLabel, Calendar cal) throws SQLException {
734        throw new UnsupportedOperationException();
735    }
736
737    public Timestamp getTimestamp(
738        int columnIndex, Calendar cal) throws SQLException
739    {
740        throw new UnsupportedOperationException();
741    }
742
743    public Timestamp getTimestamp(
744        String columnLabel, Calendar cal) throws SQLException
745    {
746        throw new UnsupportedOperationException();
747    }
748
749    public URL getURL(int columnIndex) throws SQLException {
750        throw new UnsupportedOperationException();
751    }
752
753    public URL getURL(String columnLabel) throws SQLException {
754        throw new UnsupportedOperationException();
755    }
756
757    public void updateRef(int columnIndex, Ref x) throws SQLException {
758        throw new UnsupportedOperationException();
759    }
760
761    public void updateRef(String columnLabel, Ref x) throws SQLException {
762        throw new UnsupportedOperationException();
763    }
764
765    public void updateBlob(int columnIndex, Blob x) throws SQLException {
766        throw new UnsupportedOperationException();
767    }
768
769    public void updateBlob(String columnLabel, Blob x) throws SQLException {
770        throw new UnsupportedOperationException();
771    }
772
773    public void updateClob(int columnIndex, Clob x) throws SQLException {
774        throw new UnsupportedOperationException();
775    }
776
777    public void updateClob(String columnLabel, Clob x) throws SQLException {
778        throw new UnsupportedOperationException();
779    }
780
781    public void updateArray(int columnIndex, Array x) throws SQLException {
782        throw new UnsupportedOperationException();
783    }
784
785    public void updateArray(String columnLabel, Array x) throws SQLException {
786        throw new UnsupportedOperationException();
787    }
788
789    // implement Wrapper
790
791    public <T> T unwrap(Class<T> iface) throws SQLException {
792        if (iface.isInstance(this)) {
793            return iface.cast(this);
794        }
795        throw olap4jConnection.helper.createException("cannot cast");
796    }
797
798    public boolean isWrapperFor(Class<?> iface) throws SQLException {
799        return iface.isInstance(this);
800    }
801}
802
803// End EmptyResultSet.java