package railo.runtime.type; import java.io.Serializable; import java.sql.Types; import java.util.Date; import railo.runtime.op.Caster; import railo.runtime.op.Decision; /** * Helper class for the QueryColumnImpl */ public final class QueryColumnUtil implements Serializable { private static final long serialVersionUID = 4654833724194716718L; /** * reset the type of the column */ protected static void resetType(QueryColumnImpl column) { column.type=Types.OTHER; } /** * redefine type of value * @param value * @return redefined type of the value */ protected static Object reDefineType(QueryColumnImpl column,Object value) { column.typeChecked=false; if(value==null || column.type==Types.OTHER)return value; if(value instanceof String && ((String)value).isEmpty()) return null; switch(column.type) { // Numeric Values case Types.DOUBLE: return reDefineDouble(column,value); case Types.BIGINT: return reDefineDecimal(column,value); case Types.NUMERIC: return reDefineDouble(column,value); case Types.INTEGER: return reDefineInteger(column,value); case Types.TINYINT: return reDefineTinyInt(column,value); case Types.FLOAT: return reDefineFloat(column,value); case Types.DECIMAL: return reDefineDecimal(column,value); case Types.REAL: return reDefineFloat(column,value); case Types.SMALLINT:return reDefineShort(column,value); // DateTime Values case Types.TIMESTAMP: return reDefineDateTime(column,value); case Types.DATE: return reDefineDateTime(column,value); case Types.TIME: return reDefineDateTime(column,value); // Char case Types.CHAR: return reDefineString(column,value); case Types.VARCHAR: return reDefineString(column,value); case Types.LONGVARCHAR: return reDefineString(column,value); case Types.CLOB: return reDefineClob(column,value); // Boolean case Types.BOOLEAN: return reDefineBoolean(column,value); case Types.BIT: return reDefineBoolean(column,value); // Binary case Types.BINARY: return reDefineBinary(column,value); case Types.VARBINARY: return reDefineBinary(column,value); case Types.LONGVARBINARY: return reDefineBinary(column,value); case Types.BLOB: return reDefineBlob(column,value); // Others case Types.ARRAY: return reDefineOther(column,value); case Types.DATALINK: return reDefineOther(column,value); case Types.DISTINCT: return reDefineOther(column,value); case Types.JAVA_OBJECT: return reDefineOther(column,value); case Types.NULL: return reDefineOther(column,value); case Types.STRUCT: return reDefineOther(column,value); case Types.REF: return reDefineOther(column,value); default: return value; } } private static Object reDefineBoolean(QueryColumnImpl column,Object value) { if(Decision.isCastableToBoolean(value)) return value; resetType(column); return value; } private static Object reDefineDouble(QueryColumnImpl column,Object value) { if(Decision.isCastableToNumeric(value)) return value; resetType(column); return value; } private static Object reDefineFloat(QueryColumnImpl column,Object value) { if(Decision.isCastableToNumeric(value)) return value; resetType(column); return value; } private static Object reDefineInteger(QueryColumnImpl column,Object value) { if(Decision.isCastableToNumeric(value)) return value; resetType(column); return value; } private static Object reDefineShort(QueryColumnImpl column, Object value) { double dbl = Caster.toDoubleValue(value,Double.NaN); if(Decision.isValid(dbl)) { short sht=(short)dbl; if(sht==dbl)return value; column.type=Types.DOUBLE; return value; } resetType(column); return value; } private static Object reDefineTinyInt(QueryColumnImpl column,Object value) { if(Decision.isCastableToNumeric(value)) return value; resetType(column); return value; } private static Object reDefineDecimal(QueryColumnImpl column,Object value) { if(Decision.isCastableToNumeric(value)) return value; resetType(column); return value; } private static Object reDefineDateTime(QueryColumnImpl column, Object value) { if(Decision.isDateSimple(value,true)) return value; resetType(column); return value; } private static Object reDefineString(QueryColumnImpl column, Object value) { if(Decision.isCastableToString(value)) return value; resetType(column); return value; } private static Object reDefineClob(QueryColumnImpl column, Object value) { if(Decision.isCastableToString(value)) return value; resetType(column); return value; } private static Object reDefineBinary(QueryColumnImpl column, Object value) { if(Decision.isCastableToBinary(value,false)) return value; resetType(column); return value; } private static Object reDefineBlob(QueryColumnImpl column,Object value) { if(Decision.isCastableToBinary(value,false)) return value; resetType(column); return value; } private static Object reDefineOther(QueryColumnImpl column,Object value) { resetType(column); return value; } /** * reorganize type of a column * @param reorganize */ protected static void reOrganizeType(QueryColumnImpl column) { if((column.type==Types.OTHER) && !column.typeChecked) { column.typeChecked=true; if(column.size()>0) { checkOther(column,column.data[0]); // get Type for(int i=1;i<column.size();i++) { switch(column.type) { case Types.NULL:checkOther(column,column.data[i]);break; case Types.TIMESTAMP:checkDate(column,column.data[i]);break; //case Types.DATE:checkDate(column.data[i]);break; case Types.BOOLEAN:checkBoolean(column,column.data[i]);break; case Types.DOUBLE:checkDouble(column,column.data[i]);break; case Types.VARCHAR:checkBasic(column,column.data[i]);break; default:break; } } } } } private static void checkOther(QueryColumnImpl column, Object value) { // NULL if(value==null) { column.type=Types.NULL; return; } // DateTime if(Decision.isDateSimple(value,false)) { column.type=Types.TIMESTAMP; return; } // Boolean if(Decision.isBoolean(value)) { column.type=Types.BOOLEAN; return; } // Double if(Decision.isNumeric(value)) { column.type=Types.DOUBLE; return; } // String String str = Caster.toString(value,null); if(str!=null) { column.type=Types.VARCHAR; return; } } private static void checkDate(QueryColumnImpl column,Object value) { // NULL if(value==null) return; // DateTime if(Decision.isDateSimple(value,false)) { column.type=Types.TIMESTAMP; return; } // String String str = Caster.toString(value,null); if(str!=null) { column.type=Types.VARCHAR; return; } // Other column.type=Types.OTHER; return; } private static void checkBoolean(QueryColumnImpl column, Object value) { // NULL if(value==null) return; // Boolean if(Decision.isBoolean(value)) { column.type=Types.BOOLEAN; return; } // Double if(Decision.isNumeric(value)) { column.type=Types.DOUBLE; return; } // String String str = Caster.toString(value,null); if(str!=null) { column.type=Types.VARCHAR; return; } // Other column.type=Types.OTHER; return; } private static void checkDouble(QueryColumnImpl column,Object value) { // NULL if(value==null) return; // Double if(Decision.isNumeric(value)) { column.type=Types.DOUBLE; return; } // String String str = Caster.toString(value,null); if(str!=null) { column.type=Types.VARCHAR; return; } // Other column.type=Types.OTHER; return; } private static void checkBasic(QueryColumnImpl column,Object value) { // NULL if(value==null) return; // Date if(value instanceof Date || value instanceof Number) return; // String String str = Caster.toString(value,null); if(str!=null) { return; } // OTHER column.type=Types.OTHER; return; } }