001 package railo.runtime.type; 002 003 import java.io.Serializable; 004 import java.sql.Types; 005 import java.util.Date; 006 007 import railo.runtime.op.Caster; 008 import railo.runtime.op.Decision; 009 010 011 /** 012 * Helper class for the QueryColumnImpl 013 */ 014 public final class QueryColumnUtil implements Serializable { 015 016 private static final long serialVersionUID = 4654833724194716718L; 017 018 /** 019 * reset the type of the column 020 */ 021 protected static void resetType(QueryColumnImpl column) { 022 column.type=Types.OTHER; 023 } 024 025 /** 026 * redefine type of value 027 * @param value 028 * @return redefined type of the value 029 */ 030 protected static Object reDefineType(QueryColumnImpl column,Object value) { 031 column.typeChecked=false; 032 if(value==null)return value; 033 switch(column.type) { 034 case Types.OTHER: return value; 035 036 // Numeric Values 037 case Types.DOUBLE: return reDefineDouble(column,value); 038 case Types.BIGINT: return reDefineDecimal(column,value); 039 case Types.NUMERIC: return reDefineDouble(column,value); 040 case Types.INTEGER: return reDefineInteger(column,value); 041 case Types.TINYINT: return reDefineTinyInt(column,value); 042 case Types.FLOAT: return reDefineFloat(column,value); 043 case Types.DECIMAL: return reDefineDecimal(column,value); 044 case Types.REAL: return reDefineFloat(column,value); 045 case Types.SMALLINT:return reDefineShort(column,value); 046 047 // DateTime Values 048 case Types.TIMESTAMP: return reDefineDateTime(column,value); 049 case Types.DATE: return reDefineDateTime(column,value); 050 case Types.TIME: return reDefineDateTime(column,value); 051 052 // Char 053 case Types.CHAR: return reDefineString(column,value); 054 case Types.VARCHAR: return reDefineString(column,value); 055 case Types.LONGVARCHAR: return reDefineString(column,value); 056 case Types.CLOB: return reDefineClob(column,value); 057 058 // Boolean 059 case Types.BOOLEAN: return reDefineBoolean(column,value); 060 case Types.BIT: return reDefineBoolean(column,value); 061 062 // Binary 063 case Types.BINARY: return reDefineBinary(column,value); 064 case Types.VARBINARY: return reDefineBinary(column,value); 065 case Types.LONGVARBINARY: return reDefineBinary(column,value); 066 case Types.BLOB: return reDefineBlob(column,value); 067 068 // Others 069 case Types.ARRAY: return reDefineOther(column,value); 070 case Types.DATALINK: return reDefineOther(column,value); 071 case Types.DISTINCT: return reDefineOther(column,value); 072 case Types.JAVA_OBJECT: return reDefineOther(column,value); 073 case Types.NULL: return reDefineOther(column,value); 074 case Types.STRUCT: return reDefineOther(column,value); 075 case Types.REF: return reDefineOther(column,value); 076 default: return value; 077 } 078 079 } 080 081 private static Object reDefineBoolean(QueryColumnImpl column,Object value) { 082 if(Decision.isCastableToBoolean(value)) 083 return value; 084 085 resetType(column); 086 return value; 087 } 088 089 private static Object reDefineDouble(QueryColumnImpl column,Object value) { 090 if(Decision.isCastableToNumeric(value)) 091 return value; 092 093 resetType(column); 094 return value; 095 } 096 097 private static Object reDefineFloat(QueryColumnImpl column,Object value) { 098 if(Decision.isCastableToNumeric(value)) 099 return value; 100 resetType(column); 101 return value; 102 } 103 104 private static Object reDefineInteger(QueryColumnImpl column,Object value) { 105 if(Decision.isCastableToNumeric(value)) 106 return value; 107 resetType(column); 108 return value; 109 } 110 111 private static Object reDefineShort(QueryColumnImpl column, Object value) { 112 113 double dbl = Caster.toDoubleValue(value,Double.NaN); 114 if(Decision.isValid(dbl)) { 115 short sht=(short)dbl; 116 if(sht==dbl)return value; 117 118 column.type=Types.DOUBLE; 119 return value; 120 } 121 resetType(column); 122 return value; 123 } 124 125 private static Object reDefineTinyInt(QueryColumnImpl column,Object value) { 126 if(Decision.isCastableToNumeric(value)) 127 return value; 128 resetType(column); 129 return value; 130 } 131 132 private static Object reDefineDecimal(QueryColumnImpl column,Object value) { 133 if(Decision.isCastableToNumeric(value)) 134 return value; 135 resetType(column); 136 return value; 137 } 138 139 private static Object reDefineDateTime(QueryColumnImpl column, Object value) { 140 if(Decision.isDateSimple(value,true)) 141 return value; 142 resetType(column); 143 return value; 144 } 145 146 private static Object reDefineString(QueryColumnImpl column, Object value) { 147 if(Decision.isCastableToString(value)) 148 return value; 149 resetType(column); 150 return value; 151 } 152 153 private static Object reDefineClob(QueryColumnImpl column, Object value) { 154 if(Decision.isCastableToString(value)) 155 return value; 156 resetType(column); 157 return value; 158 } 159 160 private static Object reDefineBinary(QueryColumnImpl column, Object value) { 161 if(Decision.isCastableToBinary(value,false)) 162 return value; 163 164 resetType(column); 165 return value; 166 167 168 } 169 170 private static Object reDefineBlob(QueryColumnImpl column,Object value) { 171 if(Decision.isCastableToBinary(value,false)) 172 return value; 173 resetType(column); 174 return value; 175 176 177 } 178 179 private static Object reDefineOther(QueryColumnImpl column,Object value) { 180 resetType(column); 181 return value; 182 } 183 184 185 /** 186 * reorganize type of a column 187 * @param reorganize 188 */ 189 protected static void reOrganizeType(QueryColumnImpl column) { 190 if((column.type==Types.OTHER) && !column.typeChecked) { 191 column.typeChecked=true; 192 if(column.size()>0) { 193 checkOther(column,column.data[0]); 194 195 // get Type 196 for(int i=1;i<column.size();i++) { 197 switch(column.type) { 198 case Types.NULL:checkOther(column,column.data[i]);break; 199 case Types.TIMESTAMP:checkDate(column,column.data[i]);break; 200 //case Types.DATE:checkDate(column.data[i]);break; 201 case Types.BOOLEAN:checkBoolean(column,column.data[i]);break; 202 case Types.DOUBLE:checkDouble(column,column.data[i]);break; 203 case Types.VARCHAR:checkBasic(column,column.data[i]);break; 204 default:break; 205 } 206 } 207 } 208 } 209 } 210 211 212 213 214 private static void checkOther(QueryColumnImpl column, Object value) { 215 // NULL 216 if(value==null) { 217 column.type=Types.NULL; 218 return; 219 } 220 // DateTime 221 if(Decision.isDateSimple(value,false)) { 222 column.type=Types.TIMESTAMP; 223 return; 224 } 225 // Boolean 226 if(Decision.isBoolean(value)) { 227 column.type=Types.BOOLEAN; 228 return; 229 } 230 // Double 231 if(Decision.isNumeric(value)) { 232 column.type=Types.DOUBLE; 233 return; 234 } 235 // String 236 String str = Caster.toString(value,null); 237 if(str!=null) { 238 column.type=Types.VARCHAR; 239 return; 240 } 241 } 242 243 private static void checkDate(QueryColumnImpl column,Object value) { 244 // NULL 245 if(value==null) return; 246 // DateTime 247 if(Decision.isDateSimple(value,false)) { 248 column.type=Types.TIMESTAMP; 249 return; 250 } 251 // String 252 String str = Caster.toString(value,null); 253 if(str!=null) { 254 column.type=Types.VARCHAR; 255 return; 256 } 257 // Other 258 column.type=Types.OTHER; 259 return; 260 } 261 262 private static void checkBoolean(QueryColumnImpl column, Object value) { 263 // NULL 264 if(value==null) return; 265 // Boolean 266 if(Decision.isBoolean(value)) { 267 column.type=Types.BOOLEAN; 268 return; 269 } 270 // Double 271 if(Decision.isNumeric(value)) { 272 column.type=Types.DOUBLE; 273 return; 274 } 275 // String 276 String str = Caster.toString(value,null); 277 if(str!=null) { 278 column.type=Types.VARCHAR; 279 return; 280 } 281 // Other 282 column.type=Types.OTHER; 283 return; 284 } 285 private static void checkDouble(QueryColumnImpl column,Object value) { 286 // NULL 287 if(value==null) return; 288 // Double 289 if(Decision.isNumeric(value)) { 290 column.type=Types.DOUBLE; 291 return; 292 } 293 // String 294 String str = Caster.toString(value,null); 295 if(str!=null) { 296 column.type=Types.VARCHAR; 297 return; 298 } 299 // Other 300 column.type=Types.OTHER; 301 return; 302 } 303 304 private static void checkBasic(QueryColumnImpl column,Object value) { 305 // NULL 306 if(value==null) return; 307 // Date 308 if(value instanceof Date || value instanceof Number) return; 309 // String 310 String str = Caster.toString(value,null); 311 if(str!=null) { 312 return; 313 } 314 // OTHER 315 column.type=Types.OTHER; 316 return; 317 } 318 }