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    }