public List<Type> guessTypes() throws SQLException { final ResultSetMetaData metaData = resultSet.getMetaData(); final int columnCount = metaData.getColumnCount(); assert this.types == null || this.types.size() == columnCount; List<Type> types = new ArrayList<Type>(); for (int i = 0; i < columnCount; i++) { final Type suggestedType = this.types == null ? null : this.types.get(i); types.add(guessType(suggestedType, metaData, i)); } return types; }
/** * Chooses the most appropriate type for accessing the values of a column in a result set. * * <p>NOTE: It is possible that this method is driver-dependent. If this is the case, move it to * {@link mondrian.spi.Dialect}. * * @param suggestedType Type suggested by Level.internalType attribute * @param metaData Result set metadata * @param i Column ordinal (0-based) * @return Best client type * @throws SQLException on error */ public static Type guessType(Type suggestedType, ResultSetMetaData metaData, int i) throws SQLException { if (suggestedType != null) { return suggestedType; } final String typeName = metaData.getColumnTypeName(i + 1); final int columnType = metaData.getColumnType(i + 1); int precision; int scale; switch (columnType) { case Types.SMALLINT: case Types.INTEGER: case Types.BOOLEAN: return Type.INT; case Types.NUMERIC: precision = metaData.getPrecision(i + 1); scale = metaData.getScale(i + 1); if (precision == 0 && (scale == 0 || scale == -127) && (typeName.equalsIgnoreCase("NUMBER") || (typeName.equalsIgnoreCase("NUMERIC")))) { // In Oracle and Greenplum the NUMBER/NUMERIC datatype with no // precision or scale (not NUMBER(p) or NUMBER(p, s)) means // floating point. Some drivers represent this with scale 0, // others scale -127. // // There is a further problem. In GROUPING SETS queries, Oracle // loosens the type of columns compared to mere GROUP BY // queries. We need integer GROUP BY columns to remain integers, // otherwise the segments won't be found; but if we convert // measure (whose column names are like "m0", "m1") to integers, // data loss will occur. final String columnName = metaData.getColumnName(i + 1); if (columnName.startsWith("m")) { return Type.OBJECT; } else { return Type.INT; } } return getDecimalType(precision, scale); case Types.DECIMAL: precision = metaData.getPrecision(i + 1); scale = metaData.getScale(i + 1); return getDecimalType(precision, scale); case Types.DOUBLE: case Types.FLOAT: return Type.DOUBLE; default: return Type.OBJECT; } }