| 1 | /* ============================================================= |
| 2 | * SmallSQL : a free Java DBMS library for the Java(tm) platform |
| 3 | * ============================================================= |
| 4 | * |
| 5 | * (C) Copyright 2004-2006, by Volker Berlin. |
| 6 | * |
| 7 | * Project Info: http://www.smallsql.de/ |
| 8 | * |
| 9 | * This library is free software; you can redistribute it and/or modify it |
| 10 | * under the terms of the GNU Lesser General Public License as published by |
| 11 | * the Free Software Foundation; either version 2.1 of the License, or |
| 12 | * (at your option) any later version. |
| 13 | * |
| 14 | * This library is distributed in the hope that it will be useful, but |
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| 16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
| 17 | * License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU Lesser General Public |
| 20 | * License along with this library; if not, write to the Free Software |
| 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
| 22 | * USA. |
| 23 | * |
| 24 | * [Java is a trademark or registered trademark of Sun Microsystems, Inc. |
| 25 | * in the United States and other countries.] |
| 26 | * |
| 27 | * --------------- |
| 28 | * SSResultSetMetaData.java |
| 29 | * --------------- |
| 30 | * Author: Volker Berlin |
| 31 | * |
| 32 | */ |
| 33 | package smallsql.database; |
| 34 | |
| 35 | import java.sql.*; |
| 36 | |
| 37 | |
| 38 | public class SSResultSetMetaData implements ResultSetMetaData { |
| 39 | |
| 40 | Expressions columns; |
| 41 | |
| 42 | public int getColumnCount() throws SQLException { |
| 43 | return columns.size(); |
| 44 | } |
| 45 | |
| 46 | |
| 47 | public boolean isAutoIncrement(int column) throws SQLException { |
| 48 | return getColumnExpression( column ).isAutoIncrement(); |
| 49 | } |
| 50 | |
| 51 | |
| 52 | public boolean isCaseSensitive(int column) throws SQLException { |
| 53 | return getColumnExpression( column ).isCaseSensitive(); |
| 54 | } |
| 55 | |
| 56 | |
| 57 | public boolean isSearchable(int column) throws SQLException { |
| 58 | int type = getColumnExpression( column ).getType(); |
| 59 | return type == Expression.NAME || type == Expression.FUNCTION; |
| 60 | } |
| 61 | |
| 62 | |
| 63 | public boolean isCurrency(int column) throws SQLException { |
| 64 | switch(getColumnExpression( column ).getDataType()){ |
| 65 | case SQLTokenizer.MONEY: |
| 66 | case SQLTokenizer.SMALLMONEY: |
| 67 | return true; |
| 68 | } |
| 69 | return false; |
| 70 | } |
| 71 | |
| 72 | |
| 73 | public int isNullable(int column) throws SQLException { |
| 74 | return getColumnExpression( column ).isNullable() ? columnNullable : columnNoNulls; |
| 75 | } |
| 76 | |
| 77 | |
| 78 | public boolean isSigned(int column) throws SQLException { |
| 79 | return isSignedDataType(getColumnExpression( column ).getDataType()); |
| 80 | } |
| 81 | |
| 82 | |
| 83 | static boolean isSignedDataType(int dataType) { |
| 84 | switch(dataType){ |
| 85 | case SQLTokenizer.SMALLINT: |
| 86 | case SQLTokenizer.INT: |
| 87 | case SQLTokenizer.BIGINT: |
| 88 | case SQLTokenizer.SMALLMONEY: |
| 89 | case SQLTokenizer.MONEY: |
| 90 | case SQLTokenizer.DECIMAL: |
| 91 | case SQLTokenizer.NUMERIC: |
| 92 | case SQLTokenizer.REAL: |
| 93 | case SQLTokenizer.FLOAT: |
| 94 | case SQLTokenizer.DOUBLE: |
| 95 | return true; |
| 96 | } |
| 97 | return false; |
| 98 | } |
| 99 | |
| 100 | |
| 101 | static boolean isNumberDataType(int dataType) { |
| 102 | return isSignedDataType(dataType) || dataType == SQLTokenizer.TINYINT; |
| 103 | } |
| 104 | |
| 105 | |
| 106 | static boolean isBinaryDataType(int dataType) { |
| 107 | switch(dataType){ |
| 108 | case SQLTokenizer.BINARY: |
| 109 | case SQLTokenizer.VARBINARY: |
| 110 | case SQLTokenizer.LONGVARBINARY: |
| 111 | case SQLTokenizer.BLOB: |
| 112 | return true; |
| 113 | } |
| 114 | return false; |
| 115 | } |
| 116 | |
| 117 | |
| 118 | static int getDisplaySize(int dataType, int precision, int scale){ |
| 119 | switch(dataType){ |
| 120 | case SQLTokenizer.BIT: |
| 121 | return 1; // 1 and 0 |
| 122 | case SQLTokenizer.BOOLEAN: |
| 123 | return 5; //true and false |
| 124 | case SQLTokenizer.TINYINT: |
| 125 | return 3; |
| 126 | case SQLTokenizer.SMALLINT: |
| 127 | return 6; |
| 128 | case SQLTokenizer.INT: |
| 129 | return 10; |
| 130 | case SQLTokenizer.BIGINT: |
| 131 | case SQLTokenizer.MONEY: |
| 132 | return 19; |
| 133 | case SQLTokenizer.REAL: |
| 134 | return 13; |
| 135 | case SQLTokenizer.FLOAT: |
| 136 | case SQLTokenizer.DOUBLE: |
| 137 | return 17; |
| 138 | case SQLTokenizer.LONGVARCHAR: |
| 139 | case SQLTokenizer.LONGNVARCHAR: |
| 140 | case SQLTokenizer.LONGVARBINARY: |
| 141 | case SQLTokenizer.JAVA_OBJECT: |
| 142 | return Integer.MAX_VALUE; |
| 143 | case SQLTokenizer.NUMERIC: |
| 144 | return precision + (scale>0 ? 2 : 1); |
| 145 | case SQLTokenizer.VARBINARY: |
| 146 | case SQLTokenizer.BINARY: |
| 147 | return 2 + precision*2; |
| 148 | case SQLTokenizer.SMALLDATETIME: |
| 149 | return 21; |
| 150 | default: |
| 151 | return precision; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | |
| 156 | static int getDataTypePrecision(int dataType, int defaultValue){ |
| 157 | switch(dataType){ |
| 158 | case SQLTokenizer.NULL: |
| 159 | return 0; |
| 160 | case SQLTokenizer.BIT: |
| 161 | case SQLTokenizer.BOOLEAN: |
| 162 | return 1; |
| 163 | case SQLTokenizer.TINYINT: |
| 164 | return 3; |
| 165 | case SQLTokenizer.SMALLINT: |
| 166 | return 5; |
| 167 | case SQLTokenizer.INT: |
| 168 | case SQLTokenizer.SMALLMONEY: |
| 169 | return 10; |
| 170 | case SQLTokenizer.BIGINT: |
| 171 | case SQLTokenizer.MONEY: |
| 172 | return 19; |
| 173 | case SQLTokenizer.REAL: |
| 174 | return 7; |
| 175 | case SQLTokenizer.FLOAT: |
| 176 | case SQLTokenizer.DOUBLE: |
| 177 | return 15; |
| 178 | case SQLTokenizer.CHAR: |
| 179 | case SQLTokenizer.NCHAR: |
| 180 | case SQLTokenizer.VARCHAR: |
| 181 | case SQLTokenizer.NVARCHAR: |
| 182 | case SQLTokenizer.BINARY: |
| 183 | case SQLTokenizer.VARBINARY: |
| 184 | if(defaultValue == -1) |
| 185 | return 0xFFFF; |
| 186 | return defaultValue; |
| 187 | case SQLTokenizer.NUMERIC: |
| 188 | case SQLTokenizer.DECIMAL: |
| 189 | return 38; |
| 190 | case SQLTokenizer.TIMESTAMP: |
| 191 | return 23; |
| 192 | case SQLTokenizer.TIME: |
| 193 | return 8; |
| 194 | case SQLTokenizer.DATE: |
| 195 | return 10; |
| 196 | case SQLTokenizer.SMALLDATETIME: |
| 197 | return 16; |
| 198 | case SQLTokenizer.UNIQUEIDENTIFIER: |
| 199 | return 36; |
| 200 | case SQLTokenizer.LONGVARCHAR: |
| 201 | case SQLTokenizer.LONGNVARCHAR: |
| 202 | case SQLTokenizer.LONGVARBINARY: |
| 203 | return Integer.MAX_VALUE; |
| 204 | } |
| 205 | if(defaultValue == -1) |
| 206 | throw new Error("Precision:"+SQLTokenizer.getKeyWord(dataType)); |
| 207 | return defaultValue; |
| 208 | } |
| 209 | |
| 210 | |
| 211 | public int getColumnDisplaySize(int column) throws SQLException { |
| 212 | return getColumnExpression( column ).getDisplaySize(); |
| 213 | } |
| 214 | public String getColumnLabel(int column) throws SQLException { |
| 215 | return getColumnExpression( column ).getAlias(); |
| 216 | } |
| 217 | public String getColumnName(int column) throws SQLException { |
| 218 | return getColumnExpression( column ).getAlias(); |
| 219 | } |
| 220 | public String getSchemaName(int column) throws SQLException { |
| 221 | return null; |
| 222 | } |
| 223 | public int getPrecision(int column) throws SQLException { |
| 224 | return getColumnExpression( column ).getPrecision(); |
| 225 | } |
| 226 | public int getScale(int column) throws SQLException { |
| 227 | return getColumnExpression( column ).getScale(); |
| 228 | } |
| 229 | public String getTableName(int column) throws SQLException { |
| 230 | return getColumnExpression( column ).getTableName(); |
| 231 | } |
| 232 | public String getCatalogName(int column) throws SQLException { |
| 233 | return null; |
| 234 | } |
| 235 | public int getColumnType(int column) throws SQLException { |
| 236 | return SQLTokenizer.getSQLDataType(getColumnExpression( column ).getDataType() ); |
| 237 | } |
| 238 | public String getColumnTypeName(int column) throws SQLException { |
| 239 | return SQLTokenizer.getKeyWord( getColumnExpression( column ).getDataType() ); |
| 240 | } |
| 241 | public boolean isReadOnly(int column) throws SQLException { |
| 242 | return !getColumnExpression( column ).isDefinitelyWritable(); |
| 243 | } |
| 244 | public boolean isWritable(int column) throws SQLException { |
| 245 | return getColumnExpression( column ).isDefinitelyWritable(); |
| 246 | } |
| 247 | public boolean isDefinitelyWritable(int column) throws SQLException { |
| 248 | return getColumnExpression( column ).isDefinitelyWritable(); |
| 249 | } |
| 250 | public String getColumnClassName(int column) throws SQLException { |
| 251 | switch(getColumnType(column)){ |
| 252 | case Types.TINYINT: |
| 253 | case Types.SMALLINT: |
| 254 | case Types.INTEGER: |
| 255 | return "java.lang.Integer"; |
| 256 | case Types.BIT: |
| 257 | case Types.BOOLEAN: |
| 258 | return "java.lang.Boolean"; |
| 259 | case Types.BINARY: |
| 260 | case Types.VARBINARY: |
| 261 | case Types.LONGVARBINARY: |
| 262 | return "[B"; |
| 263 | case Types.BLOB: |
| 264 | return "java.sql.Blob"; |
| 265 | case Types.BIGINT: |
| 266 | return "java.lang.Long"; |
| 267 | case Types.DECIMAL: |
| 268 | case Types.NUMERIC: |
| 269 | return "java.math.BigDecimal"; |
| 270 | case Types.REAL: |
| 271 | return "java.lang.Float"; |
| 272 | case Types.FLOAT: |
| 273 | case Types.DOUBLE: |
| 274 | return "java.lang.Double"; |
| 275 | case Types.DATE: |
| 276 | return "java.sql.Date"; |
| 277 | case Types.TIME: |
| 278 | return "java.sql.Time"; |
| 279 | case Types.TIMESTAMP: |
| 280 | return "java.sql.Timestamp"; |
| 281 | case Types.CHAR: |
| 282 | case Types.VARCHAR: |
| 283 | case Types.LONGVARCHAR: |
| 284 | case -11: //uniqueidentifier |
| 285 | return "java.lang.String"; |
| 286 | case Types.CLOB: |
| 287 | return "java.sql.Clob"; |
| 288 | default: return "java.lang.Object"; |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | /*======================================================== |
| 293 | |
| 294 | private methods |
| 295 | |
| 296 | =========================================================*/ |
| 297 | |
| 298 | final int getColumnIdx( int column ) throws SQLException{ |
| 299 | if(column < 1 || column > columns.size()) |
| 300 | throw new SQLException( "Column index out of range:" + column ); |
| 301 | return column-1; |
| 302 | } |
| 303 | |
| 304 | final Expression getColumnExpression( int column ) throws SQLException{ |
| 305 | return columns.get( getColumnIdx( column ) ); |
| 306 | } |
| 307 | |
| 308 | |
| 309 | } |