001    package railo.runtime.type;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.io.ObjectInput;
007    import java.io.ObjectOutput;
008    import java.io.Reader;
009    import java.io.StringReader;
010    import java.io.UnsupportedEncodingException;
011    import java.math.BigDecimal;
012    import java.net.URL;
013    import java.sql.Blob;
014    import java.sql.Clob;
015    import java.sql.NClob;
016    import java.sql.PreparedStatement;
017    import java.sql.Ref;
018    import java.sql.ResultSet;
019    import java.sql.ResultSetMetaData;
020    import java.sql.RowId;
021    import java.sql.SQLException;
022    import java.sql.SQLWarning;
023    import java.sql.SQLXML;
024    import java.sql.Statement;
025    import java.sql.Time;
026    import java.sql.Timestamp;
027    import java.sql.Types;
028    import java.util.Arrays;
029    import java.util.Calendar;
030    import java.util.Comparator;
031    import java.util.HashMap;
032    import java.util.HashSet;
033    import java.util.Iterator;
034    import java.util.Map;
035    import java.util.Set;
036    
037    import railo.commons.db.DBUtil;
038    import railo.commons.io.IOUtil;
039    import railo.commons.lang.SizeOf;
040    import railo.commons.lang.StringUtil;
041    import railo.commons.sql.SQLUtil;
042    import railo.loader.engine.CFMLEngineFactory;
043    import railo.runtime.PageContext;
044    import railo.runtime.converter.ScriptConverter;
045    import railo.runtime.db.CFTypes;
046    import railo.runtime.db.DataSourceUtil;
047    import railo.runtime.db.DatasourceConnection;
048    import railo.runtime.db.DatasourceConnectionImpl;
049    import railo.runtime.db.DatasourceConnectionPro;
050    import railo.runtime.db.SQL;
051    import railo.runtime.db.SQLCaster;
052    import railo.runtime.db.SQLItem;
053    import railo.runtime.dump.DumpData;
054    import railo.runtime.dump.DumpProperties;
055    import railo.runtime.engine.ThreadLocalPageContext;
056    import railo.runtime.exp.ApplicationException;
057    import railo.runtime.exp.DatabaseException;
058    import railo.runtime.exp.ExpressionException;
059    import railo.runtime.exp.PageException;
060    import railo.runtime.exp.PageRuntimeException;
061    import railo.runtime.interpreter.CFMLExpressionInterpreter;
062    import railo.runtime.op.Caster;
063    import railo.runtime.op.Decision;
064    import railo.runtime.op.ThreadLocalDuplication;
065    import railo.runtime.op.date.DateCaster;
066    import railo.runtime.query.caster.Cast;
067    import railo.runtime.reflection.Reflector;
068    import railo.runtime.timer.Stopwatch;
069    import railo.runtime.type.comparator.NumberSortRegisterComparator;
070    import railo.runtime.type.comparator.SortRegister;
071    import railo.runtime.type.comparator.SortRegisterComparator;
072    import railo.runtime.type.dt.DateTime;
073    import railo.runtime.type.dt.DateTimeImpl;
074    import railo.runtime.type.it.CollectionIterator;
075    import railo.runtime.type.it.KeyIterator;
076    import railo.runtime.type.sql.BlobImpl;
077    import railo.runtime.type.sql.ClobImpl;
078    import railo.runtime.type.util.ArrayUtil;
079    import railo.runtime.type.util.CollectionUtil;
080    import railo.runtime.type.util.QueryUtil;
081    
082    /**
083     * implementation of the query interface
084     */
085    /**
086     * 
087     */
088    public class QueryImpl implements QueryPro,Objects,Sizeable {
089    
090            private static final long serialVersionUID = 1035795427320192551L;
091    
092    
093            /**
094             * @return the template
095             */
096            public String getTemplate() {
097                    return template;
098            }
099    
100            public static final Collection.Key COLUMNS = KeyImpl.intern("COLUMNS");
101            public static final Collection.Key SQL = KeyImpl.intern("SQL");
102            public static final Collection.Key EXECUTION_TIME = KeyImpl.intern("executionTime");
103            public static final Collection.Key RECORDCOUNT = KeyImpl.intern("RECORDCOUNT");
104            public static final Collection.Key CACHED = KeyImpl.intern("cached");
105            public static final Collection.Key COLUMNLIST = KeyImpl.intern("COLUMNLIST");
106            public static final Collection.Key CURRENTROW = KeyImpl.intern("CURRENTROW");
107            public static final Collection.Key IDENTITYCOL =  KeyImpl.intern("IDENTITYCOL");
108            public static final Collection.Key GENERATED_KEYS = KeyImpl.intern("GENERATED_KEYS");
109            
110            
111            
112            //private static int count=0;
113            private QueryColumnPro[] columns;
114            private Collection.Key[] columnNames;
115            private SQL sql;
116            private ArrayInt arrCurrentRow=new ArrayInt();
117            private int recordcount=0;
118            private int columncount;
119            private long exeTime=0;
120        private boolean isCached=false;
121        private String name;
122            private int updateCount;
123        private QueryImpl generatedKeys;
124            private String template;
125            
126            
127            /**
128             * @return return execution time to get query
129             */
130            public int executionTime() {
131                    return (int) exeTime;
132            }
133    
134            /**
135             * create a QueryImpl from a SQL Resultset
136         * @param result SQL Resultset
137             * @param maxrow
138             * @param name 
139             * @throws PageException
140         */
141        public QueryImpl(ResultSet result, int maxrow, String name) throws PageException {
142            this.name=name;
143            Stopwatch stopwatch=new Stopwatch();
144                    stopwatch.start();
145                    try {
146                fillResult(null,result,maxrow,false,false);
147            } catch (SQLException e) {
148                throw new DatabaseException(e,null);
149            } catch (IOException e) {
150                throw Caster.toPageException(e);
151            }
152                    exeTime=stopwatch.time();
153        }
154        
155        /**
156         * Constructor of the class
157         * only for internal usage (cloning/deserialize)
158         */
159        public QueryImpl() {
160        }
161        
162        
163        public QueryImpl(ResultSet result, String name) throws PageException {
164                    this.name=name;
165            
166                    try {   
167                        fillResult(null,result,-1,true,false);
168                    } 
169                    catch (SQLException e) {
170                            throw new DatabaseException(e,null);
171                    } 
172                    catch (Exception e) {
173                        throw Caster.toPageException(e);
174                    } 
175            }
176            
177            /**
178             * constructor of the class, to generate a resultset from a sql query
179             * @param dc Connection to a database
180             * @param name 
181             * @param sql sql to execute
182             * @param maxrow maxrow for the resultset
183             * @throws PageException
184             */     
185        public QueryImpl(DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name) throws PageException {
186            this(dc, sql, maxrow, fetchsize, timeout, name,null,false,true);
187        }
188        
189    
190        public QueryImpl(DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name,String template) throws PageException {
191            this(dc, sql, maxrow, fetchsize, timeout, name,template,false,true);
192        }
193        
194            public QueryImpl(DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name,String template,boolean createUpdateData, boolean allowToCachePreperadeStatement) throws PageException {
195                    this.name=name;
196                    this.template=template;
197            this.sql=sql;
198                    
199            //ResultSet result=null;
200                    Statement stat=null;
201                    // check SQL Restrictions
202                    if(dc.getDatasource().hasSQLRestriction()) {
203                            QueryUtil.checkSQLRestriction(dc,sql);
204            }
205                    // check if datasource support Generated Keys
206                    boolean createGeneratedKeys=createUpdateData;
207            if(createUpdateData){
208                    DatasourceConnectionImpl dci=(DatasourceConnectionImpl) dc;
209                    if(!dci.supportsGetGeneratedKeys())createGeneratedKeys=false;
210            }
211                    
212                    Stopwatch stopwatch=new Stopwatch();
213                    stopwatch.start();
214                    boolean hasResult=false;
215                    //boolean closeStatement=true;
216                    try {   
217                            SQLItem[] items=sql.getItems();
218                            if(items.length==0) {
219                            stat=dc.getConnection().createStatement();
220                            setAttributes(stat,maxrow,fetchsize,timeout);
221                         // some driver do not support second argument
222                            hasResult=createGeneratedKeys?stat.execute(sql.getSQLString(),Statement.RETURN_GENERATED_KEYS):stat.execute(sql.getSQLString());
223                    }
224                    else {
225                            // some driver do not support second argument
226                            PreparedStatement preStat = ((DatasourceConnectionPro)dc).getPreparedStatement(sql, createGeneratedKeys,allowToCachePreperadeStatement);
227                            //closeStatement=false;
228                            stat=preStat;
229                        setAttributes(preStat,maxrow,fetchsize,timeout);
230                        setItems(preStat,items);
231                            hasResult=preStat.execute();    
232                    }
233                            int uc;
234                            ResultSet res;
235                            
236                            do {
237                                    if(hasResult) {
238                                            res=stat.getResultSet();
239                                            if(fillResult(dc,res, maxrow, true,createGeneratedKeys))break;
240                                    }
241                                    else if((uc=setUpdateCount(stat))!=-1){
242                                            if(uc>0 && createGeneratedKeys)setGeneratedKeys(dc, stat);
243                                    }
244                                    else break;
245                                    try{
246                                            hasResult=stat.getMoreResults(Statement.CLOSE_CURRENT_RESULT);
247                                    }
248                                    catch(Throwable t){
249                                            break;
250                                    }
251                            }
252                            while(true);
253                    } 
254                    catch (SQLException e) {
255                            throw new DatabaseException(e,sql,dc);
256                    } 
257                    catch (Throwable e) {
258                            throw Caster.toPageException(e);
259                    }
260            finally {
261                    //if(closeStatement)
262                            DBUtil.closeEL(stat);
263            }  
264                    exeTime=stopwatch.time();
265            }
266            
267            private int setUpdateCount(Statement stat)  {
268                    try{
269                            int uc=stat.getUpdateCount();
270                            if(uc>-1){
271                                    updateCount+=uc;
272                                    return uc;
273                            }
274                    }
275                    catch(Throwable t){}
276                    return -1;
277            }
278            
279            private boolean setGeneratedKeys(DatasourceConnection dc,Statement stat)  {
280                    try{
281                            ResultSet rs = stat.getGeneratedKeys();
282                            setGeneratedKeys(dc, rs);
283                            return true;
284                    }
285                    catch(Throwable t) {
286                            return false;
287                    }
288            }
289            
290            private void setGeneratedKeys(DatasourceConnection dc,ResultSet rs) throws PageException  {
291                    generatedKeys=new QueryImpl(rs,"");
292                    if(DataSourceUtil.isMSSQL(dc)) generatedKeys.renameEL(GENERATED_KEYS,IDENTITYCOL);
293            }
294            
295            /*private void setUpdateData(Statement stat, boolean createGeneratedKeys, boolean createUpdateCount)  {
296                    
297                    // update Count
298                    if(createUpdateCount){
299                            try{
300                                    updateCount=stat.getUpdateCount();
301                            }
302                            catch(Throwable t){
303                                    t.printStackTrace();
304                            }
305                    }
306                    // generated keys
307                    if(createGeneratedKeys){
308                            try{
309                                    ResultSet rs = stat.getGeneratedKeys();
310                                    generatedKeys=new QueryImpl(rs,"");
311                            }
312                            catch(Throwable t){
313                                    t.printStackTrace();
314                            }
315                    }
316            }*/
317    
318    
319            private void setItems(PreparedStatement preStat, SQLItem[] items) throws DatabaseException, PageException, SQLException {
320                    
321                    for(int i=0;i<items.length;i++) {
322                SQLCaster.setValue(preStat,i+1,items[i]);
323            }
324            }
325    
326            public int getUpdateCount() {
327                    return updateCount;
328            }
329            public Query getGeneratedKeys() {
330                    return generatedKeys;
331            }
332    
333            private void setAttributes(Statement stat,int maxrow, int fetchsize,int timeout) throws SQLException {
334                    if(maxrow>-1) stat.setMaxRows(maxrow);
335            if(fetchsize>0)stat.setFetchSize(fetchsize);
336            if(timeout>0)stat.setQueryTimeout(timeout);
337            }
338    
339            private ResultSet getResultSetEL(Statement stat) {
340                    try {
341                            return stat.getResultSet();
342                    }
343                    catch(SQLException sqle) {
344                            return null;
345                    }
346            }
347    
348            
349    
350        
351    
352        private boolean fillResult(DatasourceConnection dc, ResultSet result, int maxrow, boolean closeResult,boolean createGeneratedKeys) throws SQLException, IOException, PageException {
353            if(result==null) return false;
354            recordcount=0;
355                    ResultSetMetaData meta = result.getMetaData();
356                    columncount=meta.getColumnCount();
357                    
358            // set header arrays
359                    Collection.Key[] tmpColumnNames = new Collection.Key[columncount];
360                    int count=0;
361                    Collection.Key key;
362                    String columnName;
363                    for(int i=0;i<columncount;i++) {
364                            columnName=meta.getColumnName(i+1);
365                            if(StringUtil.isEmpty(columnName))columnName="column_"+i;
366                            key=KeyImpl.init(columnName);
367                            int index=getIndexFrom(tmpColumnNames,key,0,i);
368                            if(index==-1) {
369                                    tmpColumnNames[i]=key;
370                                    count++;
371                            }
372                    }
373                    
374    
375                    columncount=count;
376                    columnNames=new Collection.Key[columncount];
377                    columns=new QueryColumnPro[columncount];
378                    Cast[] casts = new Cast[columncount];
379                    
380            // get all used ints
381                    int[] usedColumns=new int[columncount];
382                    count=0;
383                    for(int i=0;i<tmpColumnNames.length;i++) {
384                            if(tmpColumnNames[i]!=null) {
385                                    usedColumns[count++]=i;
386                            }
387                    }       
388                                            
389            // set used column names
390                    int[] types=new int[columns.length];
391                    for(int i=0;i<usedColumns.length;i++) {
392                columnNames[i]=tmpColumnNames[usedColumns[i]];
393                columns[i]=new QueryColumnImpl(this,columnNames[i],types[i]=meta.getColumnType(usedColumns[i]+1));
394                
395                if(types[i]==Types.TIMESTAMP)       casts[i]=Cast.TIMESTAMP;
396                else if(types[i]==Types.TIME)       casts[i]=Cast.TIME;
397                else if(types[i]==Types.DATE)       casts[i]=Cast.DATE;
398                else if(types[i]==Types.CLOB)       casts[i]=Cast.CLOB;
399                else if(types[i]==Types.BLOB)       casts[i]=Cast.BLOB;
400                else if(types[i]==Types.BIT)        casts[i]=Cast.BIT;
401                else if(types[i]==Types.ARRAY)      casts[i]=Cast.ARRAY;
402                //else if(types[i]==Types.TINYINT)  casts[i]=Cast.ARRAY;
403                
404                else if(types[i]==CFTypes.OPAQUE){
405                    if(SQLUtil.isOracle(result.getStatement().getConnection()))
406                            casts[i]=Cast.ORACLE_OPAQUE;
407                    else 
408                            casts[i]=Cast.OTHER;
409                                    
410                }
411                else casts[i]=Cast.OTHER;
412                    }
413                    
414                    if(createGeneratedKeys && columncount==1 && columnNames[0].equals(GENERATED_KEYS) && dc!=null && DataSourceUtil.isMSSQLDriver(dc)) {
415                            columncount=0;
416                            columnNames=null;
417                            columns=null;
418                            setGeneratedKeys(dc, result);
419                            return false;
420                    }
421                    
422    
423            // fill data
424                    //Object o;
425                    while(result.next()) {
426                            if(maxrow>-1 && recordcount>=maxrow) {
427                                    break;
428                            }
429                            for(int i=0;i<usedColumns.length;i++) {
430                                columns[i].add(casts[i].toCFType(types[i], result, usedColumns[i]+1));
431                            }
432                            ++recordcount;
433                    }
434                    if(closeResult)result.close();
435                    return true;
436            }
437    
438        private Object toBytes(Blob blob) throws IOException, SQLException {
439                    return IOUtil.toBytes((blob).getBinaryStream());
440            }
441    
442            private static Object toString(Clob clob) throws IOException, SQLException {
443                    return IOUtil.toString(clob.getCharacterStream());
444            }
445    
446        private static int getIndexFrom(Collection.Key[] tmpColumnNames, Collection.Key key, int from, int to) {
447                    for(int i=from;i<to;i++) {
448                            if(tmpColumnNames[i]!=null && tmpColumnNames[i].equalsIgnoreCase(key))return i;
449                    }
450                    return -1;
451            }
452    
453            /**
454             * constructor of the class, to generate a empty resultset (no database execution)
455             * @param strColumns columns for the resultset
456             * @param rowNumber count of rows to generate (empty fields)
457             * @param name 
458             */
459            public QueryImpl(String[] strColumns, int rowNumber,String name) {
460            this.name=name;
461            columncount=strColumns.length;
462                    recordcount=rowNumber;
463                    columnNames=new Collection.Key[columncount];
464                    columns=new QueryColumnPro[columncount];
465                    for(int i=0;i<strColumns.length;i++) {
466                            columnNames[i]=KeyImpl.init(strColumns[i].trim());
467                            columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
468                    }
469            }
470    
471            /**
472             * constructor of the class, to generate a empty resultset (no database execution)
473             * @param strColumns columns for the resultset
474             * @param rowNumber count of rows to generate (empty fields)
475             * @param name 
476             */
477            public QueryImpl(Collection.Key[] columnKeys, int rowNumber,String name) throws DatabaseException {
478                    this.name=name;
479            columncount=columnKeys.length;
480                    recordcount=rowNumber;
481                    columnNames=new Collection.Key[columncount];
482                    columns=new QueryColumnPro[columncount];
483                    for(int i=0;i<columnKeys.length;i++) {
484                            columnNames[i]=columnKeys[i];
485                            columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
486                    }
487                    validateColumnNames(columnNames);
488            }
489            
490            /**
491             * constructor of the class, to generate a empty resultset (no database execution)
492             * @param strColumns columns for the resultset
493             * @param strTypes array of the types
494             * @param rowNumber count of rows to generate (empty fields)
495             * @param name 
496             * @throws DatabaseException 
497             */
498            public QueryImpl(String[] strColumns, String[] strTypes, int rowNumber, String name) throws DatabaseException {
499            this.name=name;
500            columncount=strColumns.length;
501                    if(strTypes.length!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
502                    recordcount=rowNumber;
503                    columnNames=new Collection.Key[columncount];
504                    columns=new QueryColumnPro[columncount];
505                    for(int i=0;i<strColumns.length;i++) {
506                            columnNames[i]=KeyImpl.init(strColumns[i].trim());
507                            columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(strTypes[i]),recordcount);
508                    }
509            }
510            
511            /**
512             * constructor of the class, to generate a empty resultset (no database execution)
513             * @param strColumns columns for the resultset
514             * @param strTypes array of the types
515             * @param rowNumber count of rows to generate (empty fields)
516             * @param name 
517             * @throws DatabaseException 
518             */
519            public QueryImpl(Collection.Key[] columnNames, String[] strTypes, int rowNumber, String name) throws DatabaseException {
520            this.name=name;
521            this.columnNames=columnNames;
522            columncount=columnNames.length;
523                    if(strTypes.length!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
524                    recordcount=rowNumber;
525                    columns=new QueryColumnPro[columncount];
526                    for(int i=0;i<columnNames.length;i++) {
527                            columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(strTypes[i]),recordcount);
528                    }
529                    validateColumnNames(columnNames);
530            }
531            
532            /**
533             * constructor of the class, to generate a empty resultset (no database execution)
534             * @param arrColumns columns for the resultset
535             * @param rowNumber count of rows to generate (empty fields)
536             * @param name 
537             * @throws DatabaseException 
538             */
539            public QueryImpl(Array arrColumns, int rowNumber, String name) throws DatabaseException {
540            this.name=name;
541            columncount=arrColumns.size();
542                    recordcount=rowNumber;
543                    columnNames=new Collection.Key[columncount];
544                    columns=new QueryColumnPro[columncount];
545                    for(int i=0;i<columncount;i++) {
546                            columnNames[i]=KeyImpl.init(arrColumns.get(i+1,"").toString().trim());
547                            columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
548                    }
549                    validateColumnNames(columnNames);
550            }
551    
552            /**
553             * constructor of the class, to generate a empty resultset (no database execution)
554             * @param arrColumns columns for the resultset
555             * @param arrTypes type of the columns
556             * @param rowNumber count of rows to generate (empty fields)
557             * @param name 
558             * @throws PageException
559             */
560            public QueryImpl(Array arrColumns, Array arrTypes, int rowNumber, String name) throws PageException {
561            this.name=name;
562            columncount=arrColumns.size();
563                    if(arrTypes.size()!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
564                    recordcount=rowNumber;
565                    columnNames=new Collection.Key[columncount];
566                    columns=new QueryColumnPro[columncount];
567                    for(int i=0;i<columncount;i++) {
568                            columnNames[i]=KeyImpl.init(arrColumns.get(i+1,"").toString().trim());
569                            columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(Caster.toString(arrTypes.get(i+1,""))),recordcount);
570                    }
571                    validateColumnNames(columnNames);
572            }
573    
574            /**
575             * constructor of the class
576             * @param columnNames columns definition as String Array
577             * @param arrColumns values
578             * @param name 
579             * @throws DatabaseException
580             */
581    
582            public QueryImpl(String[] strColumnNames, Array[] arrColumns, String name) throws DatabaseException {
583                    this(_toKeys(strColumnNames),arrColumns,name);          
584            }       
585            
586            private static void validateColumnNames(Key[] columnNames) throws DatabaseException {
587                    Set<String> testMap=new HashSet<String>();
588                    for(int i=0     ;i<columnNames.length;i++) {
589                            
590                            // Only allow column names that are valid variable name
591                            //if(!Decision.isSimpleVariableName(columnNames[i]))
592                            //      throw new DatabaseException("invalid column name ["+columnNames[i]+"] for query", "column names must start with a letter and can be followed by letters numbers and underscores [_]. RegExp:[a-zA-Z][a-zA-Z0-9_]*",null,null,null);
593                            
594                            if(testMap.contains(columnNames[i].getLowerString()))
595                                    throw new DatabaseException("invalid parameter for query, ambiguous column name "+columnNames[i],"columnNames: "+List.arrayToListTrim( _toStringKeys(columnNames),","),null,null,null);
596                            testMap.add(columnNames[i].getLowerString());
597                    }
598            }
599            
600    
601            private static Collection.Key[] _toKeys(String[] strColumnNames) {
602                    Collection.Key[] columnNames=new Collection.Key[strColumnNames.length];
603                    for(int i=0     ;i<columnNames.length;i++) {
604                            columnNames[i]=KeyImpl.init(strColumnNames[i].trim());
605                    }
606                    return columnNames;
607            }
608            private static String[] _toStringKeys(Collection.Key[] columnNames) {
609                    String[] strColumnNames=new String[columnNames.length];
610                    for(int i=0     ;i<strColumnNames.length;i++) {
611                            strColumnNames[i]=columnNames[i].getString();
612                    }
613                    return strColumnNames;
614            }
615            
616            /*public QueryImpl(Collection.Key[] columnNames, QueryColumn[] columns, String name,long exeTime, boolean isCached,SQL sql) throws DatabaseException {
617                    this.columnNames=columnNames;
618                    this.columns=columns;
619                    this.exeTime=exeTime;
620                    this.isCached=isCached;
621                    this.name=name;
622                    this.columncount=columnNames.length;
623                    this.recordcount=columns.length==0?0:columns[0].size();
624                    this.sql=sql;
625                    
626            }*/
627    
628            public QueryImpl(Collection.Key[] columnNames, Array[] arrColumns, String name) throws DatabaseException {
629            this.name=name;
630            
631            if(columnNames.length!=arrColumns.length)
632                            throw new DatabaseException("invalid parameter for query, not the same count from names and columns","names:"+columnNames.length+";columns:"+arrColumns.length,null,null,null);
633                    int len=0;
634                    columns=new QueryColumnPro[arrColumns.length];
635                    if(arrColumns.length>0) {
636                    // test columns
637                            len=arrColumns[0].size();
638                            for(int i=0;i<arrColumns.length;i++) {
639                                    if(arrColumns[i].size()!=len)
640                                            throw new DatabaseException("invalid parameter for query, all columns must have the same size","column[1]:"+len+"<>column["+(i+1)+"]:"+arrColumns[i].size(),null,null,null);
641                                    //columns[i]=new QueryColumnTypeFlex(arrColumns[i]);
642                                    columns[i]=new QueryColumnImpl(this,columnNames[i],arrColumns[i],Types.OTHER);
643                            }
644                    // test keys
645                            validateColumnNames(columnNames);
646                    }
647                    
648                    columncount=columns.length;
649                    recordcount=len;
650                    this.columnNames=columnNames;
651            }
652            
653        /**
654         * constructor of the class
655         * @param columnList
656         * @param data
657         * @param name 
658         * @throws DatabaseException 
659         */
660        public QueryImpl(String[] strColumnList, Object[][] data,String name) throws DatabaseException {
661            
662            this(toCollKeyArr(strColumnList),data.length,name);
663            
664            for(int iRow=0;iRow<data.length;iRow++) {
665                Object[] row=data[iRow];
666                for(int iCol=0;iCol<row.length;iCol++) {
667                    //print.ln(columnList[iCol]+":"+iRow+"="+row[iCol]);
668                    setAtEL(columnNames[iCol],iRow+1,row[iCol]);
669                }
670            }
671        }
672    
673        private static Collection.Key[] toCollKeyArr(String[] strColumnList) {
674            Collection.Key[] columnList=new Collection.Key[strColumnList.length];
675                    for(int i=0     ;i<columnList.length;i++) {
676                            columnList[i]=KeyImpl.init(strColumnList[i].trim());
677                    }
678                    return columnList;
679            }
680    
681            /**
682             * @see railo.runtime.type.Collection#size()
683             */
684            public int size() {
685                    return columncount;
686            }
687    
688            /**
689             * @see railo.runtime.type.Collection#keys()
690             */
691            public Collection.Key[] keys() {
692                    return columnNames;
693            }
694    
695            /**
696             * @see railo.runtime.type.Collection#keysAsString()
697             */
698            public String[] keysAsString() {
699                    return QueryUtil.toStringArray(columnNames);
700            }
701    
702            
703    
704            /**
705             * @see railo.runtime.type.Collection#removeEL(java.lang.String)
706             */
707            public synchronized Object removeEL(String key) {
708                    return setEL(key,null);
709            /*int index=getIndexFromKey(key);
710                    if(index!=-1) _removeEL(index);
711                    return null;*/
712            }
713    
714            /**
715             * @see railo.runtime.type.Collection#removeEL(railo.runtime.type.Collection.Key)
716             */
717            public Object removeEL(Collection.Key key) {
718                    return setEL(key,null);
719            }
720    
721            /**
722             * @see railo.runtime.type.Collection#remove(java.lang.String)
723             */
724            public synchronized Object remove(String key) throws PageException {
725                    return set(key,null);
726            }
727    
728            
729            
730            /**
731             * @throws PageException 
732             * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key)
733             */
734            public Object remove(Collection.Key key) throws PageException {
735                    return set(key,null);
736            }
737    
738            /**
739             * @see railo.runtime.type.Collection#clear()
740             */
741            public void clear() {
742                    for(int i=0;i<columns.length;i++) {
743                columns[i].clear();
744            }
745            recordcount=0;
746            }
747    
748            /**
749             *
750             * @see railo.runtime.type.Collection#get(java.lang.String, java.lang.Object)
751             */
752            public Object get(String key, Object defaultValue) {
753                    return getAt(key,
754                                    arrCurrentRow.get(getPid(), 1),
755                                    defaultValue);
756            }
757    
758            //private static int pidc=0;
759            private int getPid() {
760                    
761                    PageContext pc = ThreadLocalPageContext.get();
762                    if(pc==null) {
763                            pc=CFMLEngineFactory.getInstance().getThreadPageContext();
764                            if(pc==null)throw new RuntimeException("cannot get pid for current thread");
765                    }
766                    return pc.getId();
767            }
768    
769            /**
770             *
771             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object)
772             */
773            public Object get(Collection.Key key, Object defaultValue) {
774                    return getAt(key,
775                                    arrCurrentRow.get(getPid(), 1),
776                                    defaultValue);
777            }
778    
779            /**
780             * @see railo.runtime.type.Collection#get(java.lang.String)
781             */
782            public Object get(String key) throws PageException {
783                    return getAt(key,
784                                    arrCurrentRow.get(getPid(), 1)
785                                    );
786            }
787    
788            /**
789             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key)
790             */
791            public Object get(Collection.Key key) throws PageException {
792                    return getAt(key,
793                                    arrCurrentRow.get(getPid(), 1)
794                                    );
795            }
796    
797            /**
798             *
799             * @see railo.runtime.type.Query#getAt(java.lang.String, int, java.lang.Object)
800             */
801            public Object getAt(String key, int row, Object defaultValue) {
802                    int index=getIndexFromKey(key);
803                    if(index!=-1) {
804                            return columns[index].get(row,defaultValue);
805                    }
806                    if(key.length()>0) {
807                    char c=key.charAt(0);
808                    if(c=='r' || c=='R') {
809                        if(key.equalsIgnoreCase("recordcount")) return new Double(getRecordcount());
810                    }
811                    if(c=='c' || c=='C') {
812                        if(key.equalsIgnoreCase("currentrow")) return new Double(row);
813                        else if(key.equalsIgnoreCase("columnlist")) return getColumnlist(true);
814                    }
815                    }
816            return null;
817            }
818    
819            public Object getAt(Collection.Key key, int row, Object defaultValue) {
820                    int index=getIndexFromKey(key);
821                    if(index!=-1) {
822                            return columns[index].get(row,defaultValue);
823                    }
824                    if(key.getString().length()>0) {
825                    char c=key.lowerCharAt(0);
826                    if(c=='r') {
827                        if(key.equals(RECORDCOUNT)) return new Double(getRecordcount());
828                    }
829                    else if(c=='c') {
830                        if(key.equals(CURRENTROW)) return new Double(row);
831                        else if(key.equals(COLUMNLIST)) return getColumnlist(true);
832                    }
833                    }
834            return null;
835            }
836            
837            /**
838             * @see railo.runtime.type.Query#getAt(java.lang.String, int)
839             */
840            public Object getAt(String key, int row) throws PageException {
841                    //print.err("str:"+key);
842            int index=getIndexFromKey(key);
843                    if(index!=-1) {
844                            return columns[index].get(row);
845                    }
846                    if(key.length()>0){
847                    char c=key.charAt(0);
848                    if(c=='r' || c=='R') {
849                        if(key.equalsIgnoreCase("recordcount")) return new Double(getRecordcount());
850                            }
851                    else if(c=='c' || c=='C') {
852                                if(key.equalsIgnoreCase("currentrow")) return new Double(row);
853                                else if(key.equalsIgnoreCase("columnlist")) return getColumnlist(true);
854                            }
855                    }
856                    throw new DatabaseException("column ["+key+"] not found in query, columns are ["+getColumnlist(false)+"]",null,sql,null);
857            }
858    
859            /**
860             * @see railo.runtime.type.Query#getAt(railo.runtime.type.Collection.Key, int)
861             */
862            public Object getAt(Collection.Key key, int row) throws PageException {
863                    int index=getIndexFromKey(key);
864                    if(index!=-1) {
865                            return columns[index].get(row);
866                    }
867            if(key.getString().length()>0) {
868                    char c=key.lowerCharAt(0);
869                    if(c=='r') {
870                        if(key.equals(RECORDCOUNT)) return new Double(getRecordcount());
871                            }
872                    else if(c=='c') {
873                                if(key.equals(CURRENTROW)) return new Double(row);
874                                else if(key.equals(COLUMNLIST)) return getColumnlist(true);
875                            }
876            }
877                    throw new DatabaseException("column ["+key+"] not found in query, columns are ["+getColumnlist(false)+"]",null,sql,null);
878            }
879    
880        /**
881         * @see railo.runtime.type.Query#removeRow(int)
882         */
883        public synchronized int removeRow(int row) throws PageException {
884            //disconnectCache();
885            
886            for(int i=0;i<columns.length;i++) {
887                columns[i].removeRow(row);
888            }
889            return --recordcount;
890        }
891    
892        /**
893         * @see railo.runtime.type.Query#removeRowEL(int)
894         */
895        public int removeRowEL(int row) {
896            //disconnectCache();
897            
898            try {
899                return removeRow(row);
900            } catch (PageException e) {
901                return recordcount;
902            }
903        }
904        
905        /**
906         * @see railo.runtime.type.Query#removeColumn(java.lang.String)
907         */
908        public QueryColumn removeColumn(String key) throws DatabaseException {
909            //disconnectCache();
910            
911            QueryColumn removed = removeColumnEL(key);
912            if(removed==null) {
913                if(key.equalsIgnoreCase("recordcount") || key.equalsIgnoreCase("currentrow") || key.equalsIgnoreCase("columnlist"))
914                    throw new DatabaseException("can't remove "+key+" this is not a row","existing rows are ["+getColumnlist(false)+"]",null,null,null);
915                throw new DatabaseException("can't remove row ["+key+"], this row doesn't exist",
916                        "existing rows are ["+getColumnlist(false)+"]",null,null,null);
917            }
918            return removed;
919        }
920    
921            /**
922             * @see railo.runtime.type.Query#removeColumn(railo.runtime.type.Collection.Key)
923             */
924            public QueryColumn removeColumn(Collection.Key key) throws DatabaseException {
925                    //disconnectCache();
926            
927            QueryColumn removed = removeColumnEL(key);
928            if(removed==null) {
929                if(key.equals(RECORDCOUNT) || 
930                            key.equals(CURRENTROW) || 
931                            key.equals(COLUMNLIST))
932                    throw new DatabaseException("can't remove "+key+" this is not a row","existing rows are ["+getColumnlist(false)+"]",null,null,null);
933                throw new DatabaseException("can't remove row ["+key+"], this row doesn't exist",
934                        "existing rows are ["+getColumnlist(false)+"]",null,null,null);
935            }
936            return removed;
937            }
938    
939        /**
940         * @see railo.runtime.type.Query#removeColumnEL(java.lang.String)
941         */
942        public synchronized QueryColumn removeColumnEL(String key) {
943            //disconnectCache();
944            
945            int index=getIndexFromKey(key);
946            if(index!=-1) {
947                int current=0;
948                QueryColumn removed=null;
949                Collection.Key[] newColumnNames=new Collection.Key[columnNames.length-1];
950                QueryColumnPro[] newColumns=new QueryColumnPro[columns.length-1];
951                for(int i=0;i<columns.length;i++) {
952                    if(i==index) {
953                        removed=columns[i];
954                    }
955                    else {
956                        newColumnNames[current]=columnNames[i];
957                        newColumns[current++]=columns[i];
958                    }
959                }
960                columnNames=newColumnNames;
961                columns=newColumns;
962                columncount--;
963                return removed;
964            }
965            return null;
966        }
967    
968            public QueryColumn removeColumnEL(Collection.Key key) {
969                    //disconnectCache();
970            
971            int index=getIndexFromKey(key);
972            if(index!=-1) {
973                int current=0;
974                QueryColumn removed=null;
975                Collection.Key[] newColumnNames=new Collection.Key[columnNames.length-1];
976                QueryColumnPro[] newColumns=new QueryColumnPro[columns.length-1];
977                for(int i=0;i<columns.length;i++) {
978                    if(i==index) {
979                        removed=columns[i];
980                    }
981                    else {
982                        newColumnNames[current]=columnNames[i];
983                        newColumns[current++]=columns[i];
984                    }
985                }
986                columnNames=newColumnNames;
987                columns=newColumns;
988                columncount--;
989                return removed;
990            }
991            return null;
992            }
993    
994            /**
995             * @see railo.runtime.type.Collection#setEL(java.lang.String, java.lang.Object)
996             */
997            public Object setEL(String key, Object value) { 
998                    return setAtEL(key,
999                                    arrCurrentRow.get(getPid(), 1),
1000                                    value); 
1001            }
1002    
1003            /**
1004             * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object)
1005             */
1006            public Object setEL(Collection.Key key, Object value) {
1007                    return setAtEL(key,
1008                                    arrCurrentRow.get(getPid(), 1),
1009                                    value);
1010            }
1011            
1012            /**
1013             * @see railo.runtime.type.Collection#set(java.lang.String, java.lang.Object)
1014             */
1015            public Object set(String key, Object value) throws PageException {
1016                    return setAt(key,
1017                                    arrCurrentRow.get(getPid(), 1),
1018                                    value);
1019            }
1020    
1021            /**
1022             * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object)
1023             */
1024            public Object set(Collection.Key key, Object value) throws PageException {
1025                    return setAt(key,
1026                                    arrCurrentRow.get(getPid(), 1),
1027                                    value);
1028            }
1029        
1030        /**
1031         * @see railo.runtime.type.Query#setAt(java.lang.String, int, java.lang.Object)
1032         */
1033        public Object setAt(String key,int row, Object value) throws PageException {
1034            //disconnectCache();
1035            
1036            int index=getIndexFromKey(key);
1037            if(index!=-1) {
1038                return columns[index].set(row,value);
1039            }
1040            throw new DatabaseException("column ["+key+"] does not exist","columns are ["+getColumnlist(false)+"]",null,sql,null);
1041        }
1042    
1043        public Object setAt(Collection.Key key, int row, Object value) throws PageException {
1044                    //disconnectCache();
1045            
1046            int index=getIndexFromKey(key);
1047            if(index!=-1) {
1048                return columns[index].set(row,value);
1049            }
1050            throw new DatabaseException("column ["+key+"] does not exist","columns are ["+getColumnlist(false)+"]",null,sql,null);
1051            }
1052        
1053        /**
1054         * @see railo.runtime.type.Query#setAtEL(java.lang.String, int, java.lang.Object)
1055         */
1056        public Object setAtEL(String key,int row, Object value) {
1057            //disconnectCache();
1058            
1059            int index=getIndexFromKey(key);
1060            if(index!=-1) {
1061                return columns[index].setEL(row,value);
1062            }
1063            return null;
1064        }
1065    
1066            public Object setAtEL(Collection.Key key, int row, Object value) {
1067                    //disconnectCache();
1068            
1069            int index=getIndexFromKey(key);
1070            if(index!=-1) {
1071                return columns[index].setEL(row,value);
1072            }
1073            return null;
1074            }
1075    
1076            /**
1077             * @see railo.runtime.type.Iterator#next()
1078             */
1079            public boolean next() {
1080                    return next(getPid());
1081            }
1082    
1083            /**
1084             * @see railo.runtime.type.Iterator#next(int)
1085             */
1086            public boolean next(int pid) {
1087                    if(recordcount>=(arrCurrentRow.set(pid,arrCurrentRow.get(pid,0)+1))) {
1088                            return true;
1089                    }
1090                    arrCurrentRow.set(pid,0);
1091                    return false;
1092            }
1093    
1094            /**
1095             * @see railo.runtime.type.Iterator#reset()
1096             */
1097            public void reset() {
1098                    reset(getPid());
1099            }
1100            
1101            public void reset(int pid) {
1102                    arrCurrentRow.set(pid,0);
1103            }
1104    
1105            /**
1106             * @see railo.runtime.type.Iterator#getRecordcount()
1107             */
1108            public int getRecordcount() {
1109                    return recordcount;
1110            }
1111    
1112            /**
1113             * @see railo.runtime.type.Iterator#getCurrentrow()
1114             * FUTURE set this to deprectaed
1115             */
1116            public int getCurrentrow() {
1117                    return getCurrentrow(getPid());
1118            }
1119            
1120            /**
1121             * @see railo.runtime.type.QueryPro#getCurrentrow(int)
1122             */
1123            public int getCurrentrow(int pid) {
1124                    return arrCurrentRow.get(pid,1);
1125            }
1126    
1127    
1128            /**
1129             * return a string list of all columns
1130             * @return string list
1131             */
1132            public String getColumnlist(boolean upperCase) {
1133                    
1134                    StringBuffer sb=new StringBuffer();
1135                    for(int i=0;i<columnNames.length;i++) {
1136                            if(i>0)sb.append(',');
1137                            sb.append(upperCase?columnNames[i].getString().toUpperCase():columnNames[i].getString());// FUTURE getUpperString
1138                    }
1139                    return sb.toString();
1140            }
1141            public String getColumnlist() {
1142                    return getColumnlist(true);
1143            }
1144    
1145            /**
1146             * @deprecated use instead go(int,int)
1147             * @see railo.runtime.type.Iterator#go(int)
1148             */
1149            public boolean go(int index) {
1150                    return go(index,getPid());
1151            }
1152            
1153            public boolean go(int index, int pid) {
1154                    if(index>0 && index<=recordcount) {
1155                            arrCurrentRow.set(pid, index);
1156                            return true;
1157                    }
1158                    arrCurrentRow.set(pid, 0);
1159                    return false;
1160            }
1161    
1162            /**
1163             * @see railo.runtime.type.Iterator#isEmpty()
1164             */
1165            public boolean isEmpty() {
1166                    return recordcount+columncount==0;
1167            }
1168    
1169            /**
1170             * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int)
1171             */
1172            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
1173                    return QueryUtil.toDumpData(this, pageContext, maxlevel, dp);
1174            }
1175            
1176            /**
1177             * sorts a query by a column
1178             * @param column colun to sort
1179             * @throws PageException
1180             */
1181            public void sort(String column) throws PageException {
1182                    sort(column,Query.ORDER_ASC);
1183            }
1184    
1185            /**
1186             * @see railo.runtime.type.Query#sort(railo.runtime.type.Collection.Key)
1187             */
1188            public void sort(Collection.Key column) throws PageException {
1189                    sort(column,Query.ORDER_ASC);
1190            }
1191    
1192            /**
1193             * sorts a query by a column 
1194             * @param strColumn column to sort
1195             * @param order sort type (Query.ORDER_ASC or Query.ORDER_DESC)
1196             * @throws PageException
1197             */
1198            public synchronized void sort(String strColumn, int order) throws PageException {
1199                    //disconnectCache();
1200            sort(getColumn(strColumn),order);
1201            }
1202            
1203            /**
1204             * @see railo.runtime.type.Query#sort(railo.runtime.type.Collection.Key, int)
1205             */
1206            public synchronized void sort(Collection.Key keyColumn, int order) throws PageException {
1207                    //disconnectCache();
1208            sort(getColumn(keyColumn),order);
1209            }
1210            
1211            private void sort(QueryColumn column, int order) throws PageException {
1212            int type = column.getType();
1213                    
1214                    SortRegister[] arr= ArrayUtil.toSortRegisterArray(column);
1215                    
1216                    Arrays.sort(arr,
1217                    (
1218                                    type==Types.BIGINT || 
1219                                    type==Types.BIT || 
1220                                    type==Types.INTEGER || 
1221                                    type==Types.SMALLINT || 
1222                                    type==Types.TINYINT     ||
1223                            type==Types.DECIMAL || 
1224                            type==Types.DOUBLE || 
1225                            type==Types.NUMERIC || 
1226                            type==Types.REAL)?
1227                    
1228                    (Comparator)new NumberSortRegisterComparator(order==ORDER_ASC):(Comparator)new SortRegisterComparator(order==ORDER_ASC,true)
1229                    );
1230                    
1231                    for(int i=0;i<columns.length;i++) {
1232                            column=columns[i];
1233                            int len=column.size();
1234                            QueryColumnPro newCol=new QueryColumnImpl(this,columnNames[i],columns[i].getType(),len);
1235                            for(int y=1;y<=len;y++) {
1236                                    newCol.set(y,column.get(arr[y-1].getOldPosition()+1));
1237                            }
1238                            columns[i]=newCol;
1239                    }
1240            }
1241    
1242            /**
1243             * @see railo.runtime.type.Query#addRow(int)
1244             */
1245             public synchronized boolean addRow(int count) {                
1246             //disconnectCache();
1247                
1248             for(int i=0;i<columns.length;i++) {
1249                     QueryColumnPro column = columns[i];
1250                            column.addRow(count);
1251                     }
1252                     recordcount+=count;
1253                     return true;
1254             }
1255             
1256             /**
1257             * @see railo.runtime.type.Query#addColumn(java.lang.String, railo.runtime.type.Array)
1258             */
1259            public boolean addColumn(String columnName, Array content) throws DatabaseException {
1260                    return addColumn(columnName,content,Types.OTHER);
1261             }
1262    
1263            public boolean addColumn(Collection.Key columnName, Array content) throws PageException {
1264                    return addColumn(columnName,content,Types.OTHER);
1265            }
1266            
1267        /**
1268         * @throws DatabaseException
1269         * @see railo.runtime.type.Query#addColumn(java.lang.String, railo.runtime.type.Array, int)
1270         */
1271        public synchronized boolean addColumn(String columnName, Array content, int type) throws DatabaseException {
1272                    return addColumn(KeyImpl.init(columnName.trim()), content, type);
1273        }
1274    
1275            /**
1276             * @see railo.runtime.type.Query#addColumn(railo.runtime.type.Collection.Key, railo.runtime.type.Array, int)
1277             */
1278            public boolean addColumn(Collection.Key columnName, Array content, int type) throws DatabaseException {
1279                    //disconnectCache();
1280            // TODO Meta type
1281                    content=(Array) content.duplicate(false);
1282                    
1283                    if(getIndexFromKey(columnName)!=-1)
1284                            throw new DatabaseException("column name ["+columnName.getString()+"] already exist",null,sql,null);
1285                    if(content.size()!=getRecordcount()) {
1286                            //throw new DatabaseException("array for the new column has not the same size like the query (arrayLen!=query.recordcount)");
1287                            if(content.size()>getRecordcount()) addRow(content.size()-getRecordcount());
1288                            else content.setEL(getRecordcount(),"");
1289                    }
1290                    QueryColumnPro[] newColumns=new QueryColumnPro[columns.length+1];
1291                    Collection.Key[] newColumnNames=new Collection.Key[columns.length+1];
1292                    boolean logUsage=false;
1293                    for(int i=0;i<columns.length;i++) {
1294                            newColumns[i]=columns[i];
1295                            newColumnNames[i]=columnNames[i];
1296                            if(!logUsage && columns[i] instanceof DebugQueryColumn) logUsage=true;
1297                    }
1298                    newColumns[columns.length]=new QueryColumnImpl(this,columnName,content,type);
1299                    newColumnNames[columns.length]=columnName;
1300                    columns=newColumns;
1301                    columnNames=newColumnNames;
1302                    
1303                    columncount++;
1304                    
1305                    if(logUsage)enableShowQueryUsage();
1306                    
1307                    return true;
1308            }
1309            
1310    
1311            /* *
1312             * if this query is still connected with cache (same query also in cache)
1313         * it will disconnetd from cache (clone object and add clone to cache)
1314             */
1315            //protected void disconnectCache() {}
1316    
1317            
1318            /**
1319             * @see railo.runtime.type.Query#clone()
1320             */
1321        public Object clone() {
1322            return cloneQuery(true);
1323        }
1324        
1325        /**
1326         * @see railo.runtime.type.Collection#duplicate(boolean)
1327         */
1328        public Collection duplicate(boolean deepCopy) {
1329            return cloneQuery(true);
1330        }
1331        
1332    
1333            
1334        
1335        /**
1336         * @return clones the query object
1337         */
1338        public QueryImpl cloneQuery(boolean deepCopy) {
1339            QueryImpl newResult=new QueryImpl();
1340            ThreadLocalDuplication.set(this, newResult);
1341            try{
1342                    if(columnNames!=null){
1343                            newResult.columnNames=new Collection.Key[columnNames.length];
1344                            newResult.columns=new QueryColumnPro[columnNames.length];
1345                            for(int i=0;i<columnNames.length;i++) {
1346                                    newResult.columnNames[i]=columnNames[i];
1347                                    newResult.columns[i]=columns[i].cloneColumn(newResult,deepCopy);
1348                            }
1349                    }
1350                    newResult.sql=sql;
1351                    newResult.template=template;
1352                    newResult.recordcount=recordcount;
1353                    newResult.columncount=columncount;
1354                    newResult.isCached=isCached;
1355                    newResult.name=name;
1356                    newResult.exeTime=exeTime;
1357                    newResult.updateCount=updateCount;
1358                    if(generatedKeys!=null)newResult.generatedKeys=generatedKeys.cloneQuery(false);
1359                    return newResult;
1360            }
1361            finally {
1362                    ThreadLocalDuplication.remove(this);
1363            }
1364        }
1365    
1366            /**
1367             * @see railo.runtime.type.Query#getTypes()
1368             */
1369            public synchronized int[] getTypes() {
1370                    int[] types=new int[columns.length];
1371                    for(int i=0;i<columns.length;i++) {
1372                        types[i]=columns[i].getType();
1373                    }
1374                    return types;
1375            }
1376            
1377            /**
1378             * @see railo.runtime.type.Query#getTypesAsMap()
1379             */
1380            public synchronized Map getTypesAsMap() {
1381                    
1382                    Map map=new HashMap();
1383                    for(int i=0;i<columns.length;i++) {
1384                            map.put(columnNames[i],columns[i].getTypeAsString());
1385                    }
1386                    return map;
1387            }
1388    
1389            /**
1390             * @see railo.runtime.type.Query#getColumn(java.lang.String)
1391             */
1392            public QueryColumn getColumn(String key) throws DatabaseException {
1393                    return getColumn(KeyImpl.init(key.trim()));
1394            }
1395    
1396            /**
1397             * @see railo.runtime.type.Query#getColumn(railo.runtime.type.Collection.Key)
1398             */
1399            public QueryColumn getColumn(Collection.Key key) throws DatabaseException {
1400                    int index=getIndexFromKey(key);
1401                    if(index!=-1) return columns[index];
1402            
1403                    if(key.getString().length()>0) {
1404                    char c=key.lowerCharAt(0);
1405                    if(c=='r') {
1406                        if(key.equals(RECORDCOUNT)) return new QueryColumnRef(this,key,Types.INTEGER);
1407                    }
1408                    if(c=='c') {
1409                        if(key.equals(CURRENTROW)) return new QueryColumnRef(this,key,Types.INTEGER);
1410                        else if(key.equals(COLUMNLIST)) return new QueryColumnRef(this,key,Types.INTEGER);
1411                    }
1412                    }
1413            throw new DatabaseException("key ["+key.getString()+"] not found in query, columns are ["+getColumnlist(false)+"]",null,sql,null);
1414            }
1415            
1416    
1417            private void renameEL(Collection.Key src, Collection.Key trg) {
1418                    int index=getIndexFromKey(src);
1419                    if(index!=-1){
1420                            columnNames[index]=trg;
1421                            columns[index].setKey(trg);
1422                    }
1423            }
1424            
1425            public synchronized void rename(Collection.Key columnName,Collection.Key newColumnName) throws ExpressionException {
1426                    int index=getIndexFromKey(columnName);
1427                    if(index==-1) throw new ExpressionException("invalid column name definitions");
1428                    columnNames[index]=newColumnName;
1429                    columns[index].setKey(newColumnName);
1430            }
1431            
1432    
1433            /**
1434             *
1435             * @see railo.runtime.type.Query#getColumn(java.lang.String, railo.runtime.type.QueryColumn)
1436             */
1437            public QueryColumn getColumn(String key, QueryColumn defaultValue) {
1438                    return getColumn(KeyImpl.init(key.trim()),defaultValue);
1439            }
1440    
1441            /**
1442             * @see railo.runtime.type.Query#getColumn(railo.runtime.type.Collection.Key, railo.runtime.type.QueryColumn)
1443             */
1444            public QueryColumn getColumn(Collection.Key key, QueryColumn defaultValue) {
1445            int index=getIndexFromKey(key);
1446                    if(index!=-1) return columns[index];
1447            if(key.getString().length()>0) {//FUTURE add length method to Key Interface
1448                    char c=key.lowerCharAt(0);
1449                    if(c=='r') {
1450                        if(key.equals(RECORDCOUNT)) return new QueryColumnRef(this,key,Types.INTEGER);
1451                    }
1452                    if(c=='c') {
1453                        if(key.equals(CURRENTROW)) return new QueryColumnRef(this,key,Types.INTEGER);
1454                        else if(key.equals(COLUMNLIST)) return new QueryColumnRef(this,key,Types.INTEGER);
1455                    }
1456            }
1457            return defaultValue;
1458            }
1459            
1460            /**
1461             * @see java.lang.Object#toString()
1462             */
1463            public String toString() {
1464                    String[] keys=keysAsString();
1465                    
1466                    StringBuffer sb=new StringBuffer();
1467    
1468                    sb.append("Query\n");
1469                    sb.append("---------------------------------------------------\n");
1470                    
1471                    if(sql!=null) {
1472                            sb.append(sql+"\n");
1473                            sb.append("---------------------------------------------------\n");
1474                    }
1475    
1476                    if(exeTime>0)        {
1477                            sb.append("Execution Time: "+exeTime+"\n");
1478                            sb.append("---------------------------------------------------\n");
1479                    }
1480                    
1481                    sb.append("Recordcount: "+getRecordcount()+"\n");
1482                    sb.append("---------------------------------------------------\n");
1483                    String trenner="";
1484                    for(int i=0;i<keys.length;i++) {
1485                            trenner+="+---------------------";
1486                    }
1487                    trenner+="+\n";
1488                    sb.append(trenner);
1489            
1490            // Header
1491                    for(int i=0;i<keys.length;i++) {
1492                            sb.append(getToStringField(keys[i]));
1493                    }
1494                    sb.append("|\n");
1495                    sb.append(trenner);
1496                    sb.append(trenner);
1497                    
1498            // body
1499                    for(int i=0;i<recordcount;i++) {
1500                            for(int y=0;y<keys.length;y++) {
1501                                    try {
1502                                            Object o=getAt(keys[y],i+1);
1503                                            if(o instanceof String)sb.append(getToStringField(o.toString()));
1504                                            else if(o instanceof Number) sb.append(getToStringField(Caster.toString(((Number)o).doubleValue())));
1505                                            else if(o instanceof Clob) sb.append(getToStringField(Caster.toString(o)));                                                     
1506                                            else sb.append(getToStringField(o.toString()));
1507                                    } catch (PageException e) {
1508                                            sb.append(getToStringField("[empty]"));
1509                                    }
1510                            }
1511                            sb.append("|\n");
1512                            sb.append(trenner);
1513                    }
1514                    return sb.toString();
1515            }
1516    
1517            private String getToStringField(String str) {
1518                    if(str==null) return "|                    ";
1519                    else if(str.length()<21) {
1520                            String s="|"+str;
1521                            for(int i=str.length();i<21;i++)s+=" ";
1522                            return s;
1523                    }
1524                    else if(str.length()==21) return "|"+str;
1525                    else  return "|"+str.substring(0,18)+"...";
1526            }
1527            
1528            /**
1529             * 
1530             * @param type
1531             * @return return String represetation of a Type from int type
1532             */
1533            public static String getColumTypeName(int type) {
1534                    switch(type) {
1535                            case Types.ARRAY: return "OBJECT";
1536                            case Types.BIGINT: return "BIGINT";
1537                            case Types.BINARY: return "BINARY";
1538                            case Types.BIT: return "BIT";
1539                            case Types.BLOB: return "OBJECT";
1540                            case Types.BOOLEAN: return "BOOLEAN";
1541                            case Types.CHAR: return "CHAR";
1542                            case Types.NCHAR: return "NCHAR";
1543                            case Types.CLOB: return "OBJECT";
1544                            case Types.NCLOB: return "OBJECT";
1545                            case Types.DATALINK: return "OBJECT";
1546                            case Types.DATE: return "DATE";
1547                            case Types.DECIMAL: return "DECIMAL";
1548                            case Types.DISTINCT: return "OBJECT";
1549                            case Types.DOUBLE: return "DOUBLE";
1550                            case Types.FLOAT: return "DOUBLE";
1551                            case Types.INTEGER: return "INTEGER";
1552                            case Types.JAVA_OBJECT: return "OBJECT";
1553                            case Types.LONGVARBINARY: return "LONGVARBINARY";
1554                            case Types.LONGVARCHAR: return "LONGVARCHAR";
1555                            case Types.NULL: return "OBJECT";
1556                            case Types.NUMERIC: return "NUMERIC";
1557                            case Types.OTHER: return "OBJECT";
1558                            case Types.REAL: return "REAL";
1559                            case Types.REF: return "OBJECT";
1560                            case Types.SMALLINT: return "SMALLINT";
1561                            case Types.STRUCT: return "OBJECT";
1562                            case Types.TIME: return "TIME";
1563                            case Types.TIMESTAMP: return "TIMESTAMP";
1564                            case Types.TINYINT: return "TINYINT";
1565                            case Types.VARBINARY: return "VARBINARY";
1566                            case Types.NVARCHAR: return "NVARCHAR";
1567                            case Types.VARCHAR: return "VARCHAR";
1568                            default : return "VARCHAR";
1569                    }
1570            }
1571    
1572            private int getIndexFromKey(String key) {
1573                    String lc = StringUtil.toLowerCase(key);
1574                    for(int i=0;i<columnNames.length;i++) {
1575                            if(columnNames[i].getLowerString().equals(lc)) return i;
1576                    }
1577                    return -1;
1578            }
1579            
1580            private int getIndexFromKey(Collection.Key key) {
1581                    
1582                    for(int i=0;i<columnNames.length;i++) {
1583                            if(columnNames[i].equalsIgnoreCase(key)) return i;
1584                    }
1585                    return -1;
1586            }
1587            
1588    
1589            /**
1590             * @see railo.runtime.type.Query#setExecutionTime(long)
1591             */
1592            public void setExecutionTime(long exeTime) {
1593                    this.exeTime=exeTime;
1594            }
1595    
1596        /**
1597         * @param maxrows
1598         * @return has cutted or not
1599         */
1600        public synchronized boolean cutRowsTo(int maxrows) {
1601            //disconnectCache();
1602            
1603            if(maxrows>-1 && maxrows<getRecordcount()) {
1604                             for(int i=0;i<columns.length;i++) {
1605                                    QueryColumn column = columns[i];
1606                                    column.cutRowsTo(maxrows);
1607                             }
1608                             recordcount=maxrows;
1609                             return true;
1610            }
1611            return false;
1612        }
1613    
1614        /**
1615         * @see railo.runtime.type.Query#setCached(boolean)
1616         */
1617        public void setCached(boolean isCached) {
1618            this.isCached=isCached; 
1619        }
1620    
1621        /**
1622         * @see railo.runtime.type.Query#isCached()
1623         */
1624        public boolean isCached() {
1625            return isCached;
1626        }
1627    
1628    
1629    
1630        /**
1631         * @see com.allaire.cfx.Query#addRow()
1632         */
1633        public int addRow() {
1634                    addRow(1);
1635                    return getRecordcount();
1636        }
1637    
1638    
1639        public Key getColumnName(int columnIndex) {
1640            Key[] keys = keys();
1641                    if(columnIndex<1 || columnIndex>keys.length) return null;
1642                    return keys[columnIndex-1];
1643        }
1644    
1645        /**
1646         * @see com.allaire.cfx.Query#getColumnIndex(java.lang.String)
1647         */
1648        public int getColumnIndex(String coulmnName) {
1649            String[] keys = keysAsString();
1650                    for(int i=0;i<keys.length;i++) {
1651                            if(keys[i].equalsIgnoreCase(coulmnName)) return i+1;
1652                    }
1653                    return -1;
1654        }
1655    
1656    
1657    
1658        /**
1659         * @see com.allaire.cfx.Query#getColumns()
1660         */
1661        public String[] getColumns() {
1662            return getColumnNamesAsString();
1663        }
1664        
1665        /**
1666         * @see railo.runtime.type.QueryPro#getColumnNames()
1667         */
1668        public Collection.Key[] getColumnNames() {
1669            Collection.Key[] keys = keys();
1670            Collection.Key[] rtn=new Collection.Key[keys.length];
1671                    System.arraycopy(keys,0,rtn,0,keys.length);
1672                    return rtn;
1673        }
1674        
1675        public void setColumnNames(Collection.Key[] trg) throws PageException {
1676            columncount=trg.length;
1677            Collection.Key[] src = keys();
1678            
1679            // target < source
1680            if(trg.length<src.length){
1681                    this.columnNames=new Collection.Key[trg.length];
1682                    QueryColumnPro[] tmp=new QueryColumnPro[trg.length];
1683                    for(int i=0;i<trg.length;i++){
1684                            this.columnNames[i]=trg[i];
1685                            tmp[i]=this.columns[i];
1686                            tmp[i].setKey(trg[i]);
1687                    }
1688                    this.columns=tmp;
1689                    return;
1690            }
1691            
1692            if(trg.length>src.length){
1693                    int recordcount=getRecordcount();
1694                    for(int i=src.length;i<trg.length;i++){
1695                            
1696                            Array arr=new ArrayImpl();
1697                            for(int r=1;r<=recordcount;r++){
1698                                    arr.setE(i,"");
1699                            }
1700                            addColumn(trg[i], arr);
1701                    }
1702                    src = keys();
1703            }
1704            
1705                    for(int i=0;i<trg.length;i++){
1706                            this.columnNames[i]=trg[i];
1707                            this.columns[i].setKey(trg[i]);
1708            }
1709        }
1710        
1711    
1712    
1713            /**
1714             * @see railo.runtime.type.QueryPro#getColumnNamesAsString()
1715             */
1716            public String[] getColumnNamesAsString() {
1717                    String[] keys = keysAsString();
1718                    String[] rtn=new String[keys.length];
1719                    System.arraycopy(keys,0,rtn,0,keys.length);
1720                    return rtn;
1721            }
1722    
1723        /**
1724         * @see com.allaire.cfx.Query#getData(int, int)
1725         */
1726        public String getData(int row, int col) throws IndexOutOfBoundsException {
1727            String[] keys = keysAsString();
1728                    if(col<1 || col>keys.length) {
1729                            new IndexOutOfBoundsException("invalid column index to retrieve Data from query, valid index goes from 1 to "+keys.length);
1730                    }
1731                    
1732                    Object o=getAt(keys[col-1],row,null);
1733                    if(o==null)
1734                            throw new IndexOutOfBoundsException("invalid row index to retrieve Data from query, valid index goes from 1 to "+getRecordcount());
1735                    return Caster.toString( o,"" );
1736        }
1737    
1738    
1739    
1740        /**
1741         * @see com.allaire.cfx.Query#getName()
1742         */
1743        public String getName() {
1744            return this.name;
1745        }
1746    
1747    
1748    
1749        /**
1750         * @see com.allaire.cfx.Query#getRowCount()
1751         */
1752        public int getRowCount() {
1753            return getRecordcount();
1754        }
1755    
1756    
1757    
1758        /**
1759         * @see com.allaire.cfx.Query#setData(int, int, java.lang.String)
1760         */
1761        public void setData(int row, int col, String value) throws IndexOutOfBoundsException {
1762            String[] keys = keysAsString();
1763                    if(col<1 || col>keys.length) {
1764                            new IndexOutOfBoundsException("invalid column index to retrieve Data from query, valid index goes from 1 to "+keys.length);
1765                    }
1766                    try {
1767                            setAt(keys[col-1],row,value);
1768                    } 
1769                    catch (PageException e) {
1770                            throw new IndexOutOfBoundsException("invalid row index to retrieve Data from query, valid index goes from 1 to "+getRecordcount());
1771                    }
1772        }
1773    
1774        /**
1775         * @see railo.runtime.type.Collection#containsKey(java.lang.String)
1776         */
1777        public boolean containsKey(String key) {
1778            return getColumn(key,null)!=null;
1779        }   
1780    
1781    
1782            /**
1783             *
1784             * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key)
1785             */
1786            public boolean containsKey(Collection.Key key) {
1787            return getColumn(key,null)!=null;
1788            }
1789        /**
1790         * @see railo.runtime.op.Castable#castToString()
1791         */
1792        public String castToString() throws ExpressionException {
1793            throw new ExpressionException("Can't cast Complex Object Type Query to String",
1794              "Use Build-In-Function \"serialize(Query):String\" to create a String from Query");
1795        }
1796    
1797            /**
1798             * @see railo.runtime.op.Castable#castToString(java.lang.String)
1799             */
1800            public String castToString(String defaultValue) {
1801                    return defaultValue;
1802            }
1803    
1804    
1805        /**
1806         * @see railo.runtime.op.Castable#castToBooleanValue()
1807         */
1808        public boolean castToBooleanValue() throws ExpressionException {
1809            throw new ExpressionException("Can't cast Complex Object Type Query to a boolean value");
1810        }
1811        
1812        /**
1813         * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean)
1814         */
1815        public Boolean castToBoolean(Boolean defaultValue) {
1816            return defaultValue;
1817        }
1818    
1819    
1820        /**
1821         * @see railo.runtime.op.Castable#castToDoubleValue()
1822         */
1823        public double castToDoubleValue() throws ExpressionException {
1824            throw new ExpressionException("Can't cast Complex Object Type Query to a number value");
1825        }
1826        
1827        /**
1828         * @see railo.runtime.op.Castable#castToDoubleValue(double)
1829         */
1830        public double castToDoubleValue(double defaultValue) {
1831            return defaultValue;
1832        }
1833    
1834    
1835        /**
1836         * @see railo.runtime.op.Castable#castToDateTime()
1837         */
1838        public DateTime castToDateTime() throws ExpressionException {
1839            throw new ExpressionException("Can't cast Complex Object Type Query to a Date");
1840        }
1841        
1842        /**
1843         * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime)
1844         */
1845        public DateTime castToDateTime(DateTime defaultValue) {
1846            return defaultValue;
1847        }
1848    
1849            /**
1850             * @see railo.runtime.op.Castable#compare(boolean)
1851             */
1852            public int compareTo(boolean b) throws ExpressionException {
1853                    throw new ExpressionException("can't compare Complex Object Type Query with a boolean value");
1854            }
1855    
1856            /**
1857             * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime)
1858             */
1859            public int compareTo(DateTime dt) throws PageException {
1860                    throw new ExpressionException("can't compare Complex Object Type Query with a DateTime Object");
1861            }
1862    
1863            /**
1864             * @see railo.runtime.op.Castable#compareTo(double)
1865             */
1866            public int compareTo(double d) throws PageException {
1867                    throw new ExpressionException("can't compare Complex Object Type Query with a numeric value");
1868            }
1869    
1870            /**
1871             * @see railo.runtime.op.Castable#compareTo(java.lang.String)
1872             */
1873            public int compareTo(String str) throws PageException {
1874                    throw new ExpressionException("can't compare Complex Object Type Query with a String");
1875            }
1876    
1877        public synchronized Array getMetaDataSimple() {
1878            Array cols=new ArrayImpl();
1879            Struct column;
1880            for(int i=0;i<columns.length;i++) {
1881                    column=new StructImpl();
1882                    column.setEL(KeyImpl.NAME,columnNames[i].getString());
1883                    column.setEL("isCaseSensitive",Boolean.FALSE);
1884                    column.setEL("typeName",columns[i].getTypeAsString());
1885                    cols.appendEL(column);
1886            }
1887            return cols;
1888        }
1889    
1890        public synchronized Struct _getMetaData() {
1891            
1892            Struct cols=new StructImpl();
1893            for(int i=0;i<columns.length;i++) {
1894                cols.setEL(columnNames[i],columns[i].getTypeAsString());
1895            }
1896            
1897            Struct sct=new StructImpl();
1898            sct.setEL(KeyImpl.NAME_UC,getName());
1899            sct.setEL(COLUMNS,cols);
1900            sct.setEL(SQL,sql==null?"":sql.toString());
1901            sct.setEL(EXECUTION_TIME,new Double(exeTime));
1902            sct.setEL(RECORDCOUNT,new Double(getRowCount()));
1903            sct.setEL(CACHED,Caster.toBoolean(isCached()));
1904            return sct;
1905            
1906        }
1907    
1908            /**
1909             * @return the sql
1910             */
1911            public SQL getSql() {
1912                    return sql;
1913            }
1914    
1915            /**
1916             * @param sql the sql to set
1917             */
1918            public void setSql(SQL sql) {
1919                    this.sql = sql;
1920            }
1921    
1922    
1923            /**
1924             * @see java.sql.ResultSet#getObject(java.lang.String)
1925             */
1926            public Object getObject(String columnName) throws SQLException {
1927                    int currentrow;
1928                    if((currentrow=arrCurrentRow.get(getPid(),0))==0) return null;
1929                    return getAt(columnName,currentrow,null);
1930            }
1931            
1932            /**
1933             * @see java.sql.ResultSet#getObject(int)
1934             */
1935            public Object getObject(int columnIndex) throws SQLException {
1936                    if(columnIndex>0 && columnIndex<=columncount) return  getObject(this.columnNames[columnIndex-1].getString());
1937                    return null;
1938            }
1939            
1940            /**
1941             * @see java.sql.ResultSet#getString(int)
1942             */
1943            public String getString(int columnIndex) throws SQLException {
1944                    Object rtn = getObject(columnIndex);
1945                    if(rtn==null)return null;
1946                    if(Decision.isCastableToString(rtn)) return Caster.toString(rtn,null);
1947                    throw new SQLException("can't cast value to string");
1948            }
1949            
1950            /**
1951             * @see java.sql.ResultSet#getString(java.lang.String)
1952             */
1953            public String getString(String columnName) throws SQLException {
1954                    Object rtn = getObject(columnName);
1955                    if(rtn==null)return null;
1956                    if(Decision.isCastableToString(rtn)) return Caster.toString(rtn,null);
1957                    throw new SQLException("can't cast value to string");
1958            }
1959            
1960            /**
1961             * @see java.sql.ResultSet#getBoolean(int)
1962             */
1963            public boolean getBoolean(int columnIndex) throws SQLException {
1964                    Object rtn = getObject(columnIndex);
1965                    if(rtn==null)return false;
1966                    if(rtn!=null && Decision.isCastableToBoolean(rtn)) return Caster.toBooleanValue(rtn,false);
1967                    throw new SQLException("can't cast value to boolean");
1968            }
1969            
1970            /**
1971             * @see java.sql.ResultSet#getBoolean(java.lang.String)
1972             */
1973            public boolean getBoolean(String columnName) throws SQLException {
1974                    Object rtn = getObject(columnName);
1975                    if(rtn==null)return false;
1976                    if(rtn!=null && Decision.isCastableToBoolean(rtn)) return Caster.toBooleanValue(rtn,false);
1977                    throw new SQLException("can't cast value to boolean");
1978            }
1979            
1980            
1981            // ---------------------------------------
1982    
1983            /**
1984             *
1985             * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, java.lang.String, java.lang.Object[])
1986             */
1987            public Object call(PageContext pc, String methodName, Object[] arguments) throws PageException {
1988                    return Reflector.callMethod(this,methodName,arguments);
1989            }
1990    
1991            /**
1992             *
1993             * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object[])
1994             */
1995            public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException {
1996                    return Reflector.callMethod(this,methodName,arguments);
1997            }
1998    
1999            /**
2000             *
2001             * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct)
2002             */
2003            public Object callWithNamedValues(PageContext pc, String methodName,Struct args) throws PageException {         
2004                    throw new ExpressionException("No matching Method/Function ["+methodName+"] for call with named arguments found");
2005            }
2006    
2007            /**
2008             * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, railo.runtime.type.Collection.Key, railo.runtime.type.Struct)
2009             */
2010            public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException {   
2011                    throw new ExpressionException("No matching Method/Function ["+methodName.getString()+"] for call with named arguments found");
2012            }
2013    
2014            /**
2015             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String, java.lang.Object)
2016             */
2017            public Object get(PageContext pc, String key, Object defaultValue) {
2018                    return getAt(key,arrCurrentRow.get(pc.getId(),1),defaultValue);
2019            }
2020    
2021            /**
2022             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
2023             */
2024            public Object get(PageContext pc, Key key, Object defaultValue) {
2025                    return getAt(key,arrCurrentRow.get(
2026                                    pc.getId(),1),defaultValue);
2027            }
2028    
2029            /**
2030             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String)
2031             */
2032            public Object get(PageContext pc, String key) throws PageException {
2033                    return getAt(key,arrCurrentRow.get(pc.getId(),1));
2034            }
2035    
2036            /**
2037             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key)
2038             */
2039            public Object get(PageContext pc, Key key) throws PageException {
2040                    return getAt(key,arrCurrentRow.get(pc.getId(),1));
2041            }
2042    
2043            /**
2044             * @see railo.runtime.type.Objects#isInitalized()
2045             */
2046            public boolean isInitalized() {
2047                    return true;
2048            }
2049    
2050            /**
2051             * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, java.lang.String, java.lang.Object)
2052             */
2053            public Object set(PageContext pc, String propertyName, Object value) throws PageException {
2054                    return setAt(propertyName,arrCurrentRow.get(pc.getId(),1),value);
2055            }
2056    
2057            /**
2058             * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
2059             */
2060            public Object set(PageContext pc, Key propertyName, Object value) throws PageException {
2061                    return setAt(propertyName,arrCurrentRow.get(pc.getId(),1),value);
2062            }
2063    
2064            /**
2065             * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, java.lang.String, java.lang.Object)
2066             */
2067            public Object setEL(PageContext pc, String propertyName, Object value) {
2068                    return setAtEL(propertyName,arrCurrentRow.get(pc.getId(),1),value);
2069            }
2070    
2071            /**
2072             * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
2073             */
2074            public Object setEL(PageContext pc, Key propertyName, Object value) {
2075                    return setAtEL(propertyName,arrCurrentRow.get(pc.getId(),1),value);
2076            }
2077            
2078            /**
2079             * @see java.sql.ResultSet#wasNull()
2080             */
2081            public boolean wasNull() {
2082                    throw new PageRuntimeException(new ApplicationException("method [wasNull] is not supported"));
2083            }
2084    
2085            /**
2086             * @see java.sql.ResultSet#absolute(int)
2087             */
2088            public boolean absolute(int row) throws SQLException {
2089                    if(recordcount==0) {
2090                            if(row!=0) throw new SQLException("invalid row ["+row+"], query is Empty");
2091                            return false;
2092                    }
2093                    //row=row%recordcount;
2094                    
2095                    if(row>0) arrCurrentRow.set(getPid(),row);
2096                    else arrCurrentRow.set(getPid(),(recordcount+1)+row);
2097                    return true;
2098            }
2099    
2100            /**
2101             * @see java.sql.ResultSet#afterLast()
2102             */
2103            public void afterLast() throws SQLException {
2104                    arrCurrentRow.set(getPid(),recordcount+1);
2105            }
2106    
2107            /**
2108             * @see java.sql.ResultSet#beforeFirst()
2109             */
2110            public void beforeFirst() throws SQLException {
2111                    arrCurrentRow.set(getPid(),0);
2112            }
2113    
2114            /**
2115             * @see java.sql.ResultSet#cancelRowUpdates()
2116             */
2117            public void cancelRowUpdates() throws SQLException {
2118                    // ignored
2119            }
2120    
2121            /**
2122             * @see java.sql.ResultSet#clearWarnings()
2123             */
2124            public void clearWarnings() throws SQLException {
2125                    // ignored
2126            }
2127    
2128            /**
2129             * @see java.sql.ResultSet#close()
2130             */
2131            public void close() throws SQLException {
2132                    // ignored
2133            }
2134    
2135            /**
2136             * @see java.sql.ResultSet#deleteRow()
2137             */
2138            public void deleteRow() throws SQLException {
2139                    try {
2140                            removeRow(arrCurrentRow.get(getPid()));
2141                    } catch (Exception e) {
2142                            throw new SQLException(e.getMessage());
2143                    }
2144            }
2145    
2146            /**
2147             * @see java.sql.ResultSet#findColumn(java.lang.String)
2148             */
2149            public int findColumn(String columnName) throws SQLException {
2150                    int index= getColumnIndex(columnName);
2151                    if(index==-1) throw new SQLException("invald column definitions ["+columnName+"]");
2152                    return index;
2153            }
2154    
2155            /**
2156             * @see java.sql.ResultSet#first()
2157             */
2158            public boolean first() throws SQLException {
2159                    return absolute(1);
2160            }
2161    
2162            public java.sql.Array getArray(int i) throws SQLException {
2163                    throw new SQLException("method is not implemented");
2164            }
2165    
2166            public java.sql.Array getArray(String colName) throws SQLException {
2167                    throw new SQLException("method is not implemented");
2168            }
2169    
2170            /**
2171             * @see java.sql.ResultSet#getAsciiStream(int)
2172             */
2173            public InputStream getAsciiStream(int columnIndex) throws SQLException {
2174                    String res = getString(columnIndex);
2175                    if(res==null)return null;
2176                    return new ByteArrayInputStream(res.getBytes());
2177            }
2178    
2179            /**
2180             * @see java.sql.ResultSet#getAsciiStream(java.lang.String)
2181             */
2182            public InputStream getAsciiStream(String columnName) throws SQLException {
2183                    String res = getString(columnName);
2184                    if(res==null)return null;
2185                    return new ByteArrayInputStream(res.getBytes());
2186            }
2187    
2188            /**
2189             * @see java.sql.ResultSet#getBigDecimal(int)
2190             */
2191            public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
2192                    return new BigDecimal(getDouble(columnIndex));
2193            }
2194    
2195            /**
2196             * @see java.sql.ResultSet#getBigDecimal(java.lang.String)
2197             */
2198            public BigDecimal getBigDecimal(String columnName) throws SQLException {
2199                    return new BigDecimal(getDouble(columnName));
2200            }
2201    
2202            /**
2203             * @see java.sql.ResultSet#getBigDecimal(int, int)
2204             */
2205            public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2206                    return new BigDecimal(getDouble(columnIndex));
2207            }
2208    
2209            /**
2210             * @see java.sql.ResultSet#getBigDecimal(java.lang.String, int)
2211             */
2212            public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2213                    return new BigDecimal(getDouble(columnName));
2214            }
2215    
2216            /**
2217             * @see java.sql.ResultSet#getBinaryStream(int)
2218             */
2219            public InputStream getBinaryStream(int columnIndex) throws SQLException {
2220                    Object obj = getObject(columnIndex);
2221                    if(obj==null)return null;
2222                    try {
2223                            return Caster.toBinaryStream(obj);
2224                    } catch (Exception e) {
2225                            throw new SQLException(e.getMessage());
2226                    }
2227            }
2228    
2229            /**
2230             * @see java.sql.ResultSet#getBinaryStream(java.lang.String)
2231             */
2232            public InputStream getBinaryStream(String columnName) throws SQLException {
2233                    Object obj = getObject(columnName);
2234                    if(obj==null)return null;
2235                    try {
2236                            return Caster.toBinaryStream(obj);
2237                    } catch (Exception e) {
2238                            throw new SQLException(e.getMessage());
2239                    }
2240            }
2241    
2242            /**
2243             * @see java.sql.ResultSet#getBlob(int)
2244             */
2245            public Blob getBlob(int i) throws SQLException {
2246                    byte[] bytes = getBytes(i);
2247                    if(bytes==null) return null;
2248                    try {
2249                            return BlobImpl.toBlob(bytes);
2250                    } 
2251                    catch (PageException e) {
2252                            throw new SQLException(e.getMessage());
2253                    }
2254            }
2255    
2256            /**
2257             * @see java.sql.ResultSet#getBlob(java.lang.String)
2258             */
2259            public Blob getBlob(String colName) throws SQLException {
2260                    byte[] bytes = getBytes(colName);
2261                    if(bytes==null) return null;
2262                    try {
2263                            return BlobImpl.toBlob(bytes);
2264                    } catch (PageException e) {
2265                            throw new SQLException(e.getMessage());
2266                    }
2267            }
2268    
2269            /**
2270             * @see java.sql.ResultSet#getByte(int)
2271             */
2272            public byte getByte(int columnIndex) throws SQLException {
2273                    Object obj = getObject(columnIndex);
2274                    if(obj==null) return (byte)0;
2275                    try {
2276                            return Caster.toByteValue(obj);
2277                    } catch (PageException e) {
2278                            throw new SQLException(e.getMessage());
2279                    }
2280            }
2281    
2282            /**
2283             * @see java.sql.ResultSet#getByte(java.lang.String)
2284             */
2285            public byte getByte(String columnName) throws SQLException {
2286                    Object obj = getObject(columnName);
2287                    if(obj==null) return (byte)0;
2288                    try {
2289                            return Caster.toByteValue(obj);
2290                    } catch (PageException e) {
2291                            throw new SQLException(e.getMessage());
2292                    }
2293            }
2294    
2295            /**
2296             * @see java.sql.ResultSet#getBytes(int)
2297             */
2298            public byte[] getBytes(int columnIndex) throws SQLException {
2299                    Object obj = getObject(columnIndex);
2300                    if(obj==null) return null;
2301                    try {
2302                            return Caster.toBytes(obj);
2303                    } catch (Exception e) {
2304                            throw new SQLException(e.getMessage());
2305                    }
2306            }
2307    
2308            /**
2309             * @see java.sql.ResultSet#getBytes(java.lang.String)
2310             */
2311            public byte[] getBytes(String columnName) throws SQLException {
2312                    Object obj = getObject(columnName);
2313                    if(obj==null) return null;
2314                    try {
2315                            return Caster.toBytes(obj);
2316                    } catch (Exception e) {
2317                            throw new SQLException(e.getMessage());
2318                    }
2319            }
2320    
2321            /**
2322             * @see java.sql.ResultSet#getCharacterStream(int)
2323             */
2324            public Reader getCharacterStream(int columnIndex) throws SQLException {
2325                    String str=getString(columnIndex);
2326                    if(str==null) return null;
2327                    return new StringReader(str);
2328            }
2329    
2330            /**
2331             * @see java.sql.ResultSet#getCharacterStream(java.lang.String)
2332             */
2333            public Reader getCharacterStream(String columnName) throws SQLException {
2334                    String str=getString(columnName);
2335                    if(str==null) return null;
2336                    return new StringReader(str);
2337            }
2338    
2339            /**
2340             * @see java.sql.ResultSet#getClob(int)
2341             */
2342            public Clob getClob(int i) throws SQLException {
2343                    String str=getString(i);
2344                    if(str==null) return null;
2345                    return ClobImpl.toClob(str);
2346            }
2347    
2348            /**
2349             * @see java.sql.ResultSet#getClob(java.lang.String)
2350             */
2351            public Clob getClob(String colName) throws SQLException {
2352                    String str=getString(colName);
2353                    if(str==null) return null;
2354                    return ClobImpl.toClob(str);
2355            }
2356    
2357            /**
2358             * @see java.sql.ResultSet#getConcurrency()
2359             */
2360            public int getConcurrency() throws SQLException {
2361                    return 0;
2362            }
2363    
2364            /**
2365             * @see java.sql.ResultSet#getCursorName()
2366             */
2367            public String getCursorName() throws SQLException {
2368                    return null;
2369            }
2370    
2371            /**
2372             * @see java.sql.ResultSet#getDate(int)
2373             */
2374            public java.sql.Date getDate(int columnIndex) throws SQLException {
2375                    Object obj=getObject(columnIndex);
2376                    if(obj==null) return null;
2377                    try {
2378                            return new java.sql.Date(Caster.toDate(obj, false, null).getTime());
2379                    } catch (PageException e) {
2380                            throw new SQLException(e.getMessage());
2381                    }
2382            }
2383    
2384            /**
2385             * @see java.sql.ResultSet#getDate(java.lang.String)
2386             */
2387            public java.sql.Date getDate(String columnName) throws SQLException {
2388                    Object obj=getObject(columnName);
2389                    if(obj==null) return null;
2390                    try {
2391                            return new java.sql.Date(Caster.toDate(obj, false, null).getTime());
2392                    } catch (PageException e) {
2393                            throw new SQLException(e.getMessage());
2394                    }
2395            }
2396    
2397            /**
2398             * @see java.sql.ResultSet#getDate(int, java.util.Calendar)
2399             */
2400            public java.sql.Date getDate(int columnIndex, Calendar cal)throws SQLException {
2401                    return getDate(columnIndex); // TODO impl
2402            }
2403    
2404            /**
2405             * @see java.sql.ResultSet#getDate(java.lang.String, java.util.Calendar)
2406             */
2407            public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
2408                    return getDate(columnName);// TODO impl
2409            }
2410    
2411            /**
2412             * @see java.sql.ResultSet#getDouble(int)
2413             */
2414            public double getDouble(int columnIndex) throws SQLException {
2415                    Object obj=getObject(columnIndex);
2416                    if(obj==null) return 0;
2417                    try {
2418                            return Caster.toDoubleValue(obj);
2419                    } catch (PageException e) {
2420                            throw new SQLException(e.getMessage());
2421                    }
2422            }
2423    
2424            /**
2425             * @see java.sql.ResultSet#getDouble(java.lang.String)
2426             */
2427            public double getDouble(String columnName) throws SQLException {
2428                    Object obj=getObject(columnName);
2429                    if(obj==null) return 0;
2430                    try {
2431                            return Caster.toDoubleValue(obj);
2432                    } catch (PageException e) {
2433                            throw new SQLException(e.getMessage());
2434                    }
2435            }
2436    
2437            /**
2438             * @see java.sql.ResultSet#getFetchDirection()
2439             */
2440            public int getFetchDirection() throws SQLException {
2441                    return 1000;
2442            }
2443    
2444            /**
2445             * @see java.sql.ResultSet#getFetchSize()
2446             */
2447            public int getFetchSize() throws SQLException {
2448                    return 0;
2449            }
2450    
2451            /**
2452             * @see java.sql.ResultSet#getFloat(int)
2453             */
2454            public float getFloat(int columnIndex) throws SQLException {
2455                    Object obj=getObject(columnIndex);
2456                    if(obj==null) return 0;
2457                    try {
2458                            return Caster.toFloatValue(obj);
2459                    } catch (PageException e) {
2460                            throw new SQLException(e.getMessage());
2461                    }
2462            }
2463    
2464            /**
2465             * @see java.sql.ResultSet#getFloat(java.lang.String)
2466             */
2467            public float getFloat(String columnName) throws SQLException {
2468                    Object obj=getObject(columnName);
2469                    if(obj==null) return 0;
2470                    try {
2471                            return Caster.toFloatValue(obj);
2472                    } catch (PageException e) {
2473                            throw new SQLException(e.getMessage());
2474                    }
2475            }
2476    
2477            /**
2478             * @see java.sql.ResultSet#getInt(int)
2479             */
2480            public int getInt(int columnIndex) throws SQLException {
2481                    Object obj=getObject(columnIndex);
2482                    if(obj==null) return 0;
2483                    try {
2484                            return Caster.toIntValue(obj);
2485                    } catch (PageException e) {
2486                            throw new SQLException(e.getMessage());
2487                    }
2488            }
2489    
2490            /**
2491             * @see java.sql.ResultSet#getInt(java.lang.String)
2492             */
2493            public int getInt(String columnName) throws SQLException {
2494                    Object obj=getObject(columnName);
2495                    if(obj==null) return 0;
2496                    try {
2497                            return Caster.toIntValue(obj);
2498                    } catch (PageException e) {
2499                            throw new SQLException(e.getMessage());
2500                    }
2501            }
2502    
2503            /**
2504             * @see java.sql.ResultSet#getLong(int)
2505             */
2506            public long getLong(int columnIndex) throws SQLException {
2507                    Object obj=getObject(columnIndex);
2508                    if(obj==null) return 0;
2509                    try {
2510                            return Caster.toLongValue(obj);
2511                    } catch (PageException e) {
2512                            throw new SQLException(e.getMessage());
2513                    }
2514            }
2515    
2516            /**
2517             * @see java.sql.ResultSet#getLong(java.lang.String)
2518             */
2519            public long getLong(String columnName) throws SQLException {
2520                    Object obj=getObject(columnName);
2521                    if(obj==null) return 0;
2522                    try {
2523                            return Caster.toLongValue(obj);
2524                    } catch (PageException e) {
2525                            throw new SQLException(e.getMessage());
2526                    }
2527            }
2528    
2529            /**
2530             * @see java.sql.ResultSet#getObject(int, java.util.Map)
2531             */
2532            public Object getObject(int i, Map map) throws SQLException {
2533                    throw new SQLException("method is not implemented");
2534            }
2535    
2536            /**
2537             * @see java.sql.ResultSet#getObject(java.lang.String, java.util.Map)
2538             */
2539            public Object getObject(String colName, Map map) throws SQLException {
2540                    throw new SQLException("method is not implemented");
2541            }
2542    
2543            /**
2544             * @see java.sql.ResultSet#getRef(int)
2545             */
2546            public Ref getRef(int i) throws SQLException {
2547                    throw new SQLException("method is not implemented");
2548            }
2549    
2550            /**
2551             * @see java.sql.ResultSet#getRef(java.lang.String)
2552             */
2553            public Ref getRef(String colName) throws SQLException {
2554                    throw new SQLException("method is not implemented");
2555            }
2556    
2557            /**
2558             * @see java.sql.ResultSet#getRow()
2559             */
2560            public int getRow() throws SQLException {
2561                    return arrCurrentRow.get(getPid(),0);
2562            }
2563    
2564            /**
2565             * @see java.sql.ResultSet#getShort(int)
2566             */
2567            public short getShort(int columnIndex) throws SQLException {
2568                    Object obj=getObject(columnIndex);
2569                    if(obj==null) return 0;
2570                    try {
2571                            return Caster.toShortValue(obj);
2572                    } catch (PageException e) {
2573                            throw new SQLException(e.getMessage());
2574                    }
2575            }
2576    
2577            /**
2578             * @see java.sql.ResultSet#getShort(java.lang.String)
2579             */
2580            public short getShort(String columnName) throws SQLException {
2581                    Object obj=getObject(columnName);
2582                    if(obj==null) return 0;
2583                    try {
2584                            return Caster.toShortValue(obj);
2585                    } catch (PageException e) {
2586                            throw new SQLException(e.getMessage());
2587                    }
2588            }
2589    
2590            public Statement getStatement() throws SQLException {
2591                    throw new SQLException("method is not implemented");
2592            }
2593    
2594            /**
2595             * @see java.sql.ResultSet#getTime(int)
2596             */
2597            public Time getTime(int columnIndex) throws SQLException {
2598                    Object obj=getObject(columnIndex);
2599                    if(obj==null) return null;
2600                    try {
2601                            return new Time(DateCaster.toTime(null, obj).getTime());
2602                    } catch (PageException e) {
2603                            throw new SQLException(e.getMessage());
2604                    }
2605            }
2606    
2607            /**
2608             * @see java.sql.ResultSet#getTime(java.lang.String)
2609             */
2610            public Time getTime(String columnName) throws SQLException {
2611                    Object obj=getObject(columnName);
2612                    if(obj==null) return null;
2613                    try {
2614                            return new Time(DateCaster.toTime(null, obj).getTime());
2615                    } catch (PageException e) {
2616                            throw new SQLException(e.getMessage());
2617                    }
2618            }
2619    
2620            /**
2621             * @see java.sql.ResultSet#getTime(int, java.util.Calendar)
2622             */
2623            public Time getTime(int columnIndex, Calendar cal) throws SQLException {
2624                    return getTime(columnIndex);// TODO impl
2625            }
2626    
2627            /**
2628             * @see java.sql.ResultSet#getTime(java.lang.String, java.util.Calendar)
2629             */
2630            public Time getTime(String columnName, Calendar cal) throws SQLException {
2631                    return getTime(columnName);// TODO impl
2632            }
2633    
2634            /**
2635             * @see java.sql.ResultSet#getTimestamp(int)
2636             */
2637            public Timestamp getTimestamp(int columnIndex) throws SQLException {
2638                    Object obj=getObject(columnIndex);
2639                    if(obj==null) return null;
2640                    try {
2641                            return new Timestamp(DateCaster.toTime(null, obj).getTime());
2642                    } catch (PageException e) {
2643                            throw new SQLException(e.getMessage());
2644                    }
2645            }
2646    
2647            /**
2648             * @see java.sql.ResultSet#getTimestamp(java.lang.String)
2649             */
2650            public Timestamp getTimestamp(String columnName) throws SQLException {
2651                    Object obj=getObject(columnName);
2652                    if(obj==null) return null;
2653                    try {
2654                            return new Timestamp(DateCaster.toTime(null, obj).getTime());
2655                    } catch (PageException e) {
2656                            throw new SQLException(e.getMessage());
2657                    }
2658            }
2659    
2660            /**
2661             * @see java.sql.ResultSet#getTimestamp(int, java.util.Calendar)
2662             */
2663            public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
2664                    return getTimestamp(columnIndex);// TODO impl
2665            }
2666    
2667            /**
2668             * @see java.sql.ResultSet#getTimestamp(java.lang.String, java.util.Calendar)
2669             */
2670            public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
2671                    return getTimestamp(columnName);// TODO impl
2672            }
2673    
2674            /**
2675             * @see java.sql.ResultSet#getType()
2676             */
2677            public int getType() throws SQLException {
2678                    return 0;
2679            }
2680    
2681            /**
2682             * @see java.sql.ResultSet#getURL(int)
2683             */
2684            public URL getURL(int columnIndex) throws SQLException {
2685                    throw new SQLException("method is not implemented");
2686            }
2687    
2688            /**
2689             * @see java.sql.ResultSet#getURL(java.lang.String)
2690             */
2691            public URL getURL(String columnName) throws SQLException {
2692                    throw new SQLException("method is not implemented");
2693            }
2694    
2695            /**
2696             * @see java.sql.ResultSet#getUnicodeStream(int)
2697             */
2698            public InputStream getUnicodeStream(int columnIndex) throws SQLException {
2699                    String str=getString(columnIndex);
2700                    if(str==null) return null;
2701                    try {
2702                            return new ByteArrayInputStream(str.getBytes("UTF-8"));
2703                    } 
2704                    catch (UnsupportedEncodingException e) {
2705                            throw new SQLException(e.getMessage());
2706                    }
2707            }
2708    
2709            /**
2710             * @see java.sql.ResultSet#getUnicodeStream(java.lang.String)
2711             */
2712            public InputStream getUnicodeStream(String columnName) throws SQLException {
2713                    String str=getString(columnName);
2714                    if(str==null) return null;
2715                    try {
2716                            return new ByteArrayInputStream(str.getBytes("UTF-8"));
2717                    } 
2718                    catch (UnsupportedEncodingException e) {
2719                            throw new SQLException(e.getMessage());
2720                    }
2721            }
2722    
2723            /**
2724             * @see java.sql.ResultSet#getWarnings()
2725             */
2726            public SQLWarning getWarnings() throws SQLException {
2727                    throw new SQLException("method is not implemented");
2728            }
2729    
2730            /**
2731             * @see java.sql.ResultSet#insertRow()
2732             */
2733            public void insertRow() throws SQLException {
2734                    throw new SQLException("method is not implemented");
2735            }
2736    
2737            /**
2738             * @see java.sql.ResultSet#isAfterLast()
2739             */
2740            public boolean isAfterLast() throws SQLException {
2741                    return getCurrentrow()>recordcount;
2742            }
2743    
2744            /**
2745             * @see java.sql.ResultSet#isBeforeFirst()
2746             */
2747            public boolean isBeforeFirst() throws SQLException {
2748                    return arrCurrentRow.get(getPid(),0)==0;
2749            }
2750    
2751            /**
2752             * @see java.sql.ResultSet#isFirst()
2753             */
2754            public boolean isFirst() throws SQLException {
2755                    return arrCurrentRow.get(getPid(),0)==1;
2756            }
2757    
2758            public boolean isLast() throws SQLException {
2759                    return arrCurrentRow.get(getPid(),0)==recordcount;
2760            }
2761    
2762            public boolean last() throws SQLException {
2763                    return absolute(recordcount);
2764            }
2765    
2766            public void moveToCurrentRow() throws SQLException {
2767                    // ignore
2768            }
2769    
2770            public void moveToInsertRow() throws SQLException {
2771                    // ignore
2772            }
2773    
2774    
2775            public boolean previous() {
2776                    return previous(getPid());
2777            }
2778            
2779            public boolean previous(int pid) {
2780                    if(0<(arrCurrentRow.set(pid,arrCurrentRow.get(pid,0)-1))) {
2781                            return true;
2782                    }
2783                    arrCurrentRow.set(pid,0);
2784                    return false;
2785            }
2786    
2787            public void refreshRow() throws SQLException {
2788                    // ignore
2789                    
2790            }
2791    
2792            /**
2793             * @see java.sql.ResultSet#relative(int)
2794             */
2795            public boolean relative(int rows) throws SQLException {
2796                    return absolute(getRow()+rows);
2797            }
2798    
2799            /**
2800             * @see java.sql.ResultSet#rowDeleted()
2801             */
2802            public boolean rowDeleted() throws SQLException {
2803                    return false;
2804            }
2805    
2806            /**
2807             * @see java.sql.ResultSet#rowInserted()
2808             */
2809            public boolean rowInserted() throws SQLException {
2810                    return false;
2811            }
2812    
2813            /**
2814             * @see java.sql.ResultSet#rowUpdated()
2815             */
2816            public boolean rowUpdated() throws SQLException {
2817                    return false;
2818            }
2819    
2820            public void setFetchDirection(int direction) throws SQLException {
2821                    // ignore
2822            }
2823    
2824            public void setFetchSize(int rows) throws SQLException {
2825                    // ignore
2826            }
2827    
2828            /**
2829             * @see java.sql.ResultSet#updateArray(int, java.sql.Array)
2830             */
2831            public void updateArray(int columnIndex, java.sql.Array x)throws SQLException {
2832                    updateObject(columnIndex, x.getArray());
2833            }
2834    
2835            /**
2836             * @see java.sql.ResultSet#updateArray(java.lang.String, java.sql.Array)
2837             */
2838            public void updateArray(String columnName, java.sql.Array x)throws SQLException {
2839                    updateObject(columnName, x.getArray());
2840            }
2841    
2842            /**
2843             * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream, int)
2844             */
2845            public void updateAsciiStream(int columnIndex, InputStream x, int length)throws SQLException {
2846                    updateBinaryStream(columnIndex, x, length);
2847            }
2848    
2849            /**
2850             * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream, int)
2851             */
2852            public void updateAsciiStream(String columnName, InputStream x, int length)throws SQLException {
2853                    updateBinaryStream(columnName, x, length);
2854            }
2855    
2856            /**
2857             * @see java.sql.ResultSet#updateBigDecimal(int, java.math.BigDecimal)
2858             */
2859            public void updateBigDecimal(int columnIndex, BigDecimal x)throws SQLException {
2860                    updateObject(columnIndex, x.toString());
2861            }
2862    
2863            /**
2864             * @see java.sql.ResultSet#updateBigDecimal(java.lang.String, java.math.BigDecimal)
2865             */
2866            public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
2867                    updateObject(columnName, x.toString());
2868            }
2869    
2870            /**
2871             * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream, int)
2872             */
2873            public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
2874                    try {
2875                            updateObject(columnIndex, IOUtil.toBytesMax(x, length));
2876                    } catch (IOException e) {
2877                            throw new SQLException(e.getMessage());
2878                    }
2879            }
2880    
2881            /**
2882             * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream, int)
2883             */
2884            public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException {
2885                    try {
2886                            updateObject(columnName, IOUtil.toBytesMax(x, length));
2887                    } catch (IOException e) {
2888                            throw new SQLException(e.getMessage());
2889                    }
2890            }
2891    
2892            /**
2893             * @see java.sql.ResultSet#updateBlob(int, java.sql.Blob)
2894             */
2895            public void updateBlob(int columnIndex, Blob x) throws SQLException {
2896                    try {
2897                            updateObject(columnIndex, toBytes(x));
2898                    } catch (IOException e) {
2899                            throw new SQLException(e.getMessage());
2900                    }
2901            }
2902    
2903            /**
2904             * @see java.sql.ResultSet#updateBlob(java.lang.String, java.sql.Blob)
2905             */
2906            public void updateBlob(String columnName, Blob x) throws SQLException {
2907                    try {
2908                            updateObject(columnName, toBytes(x));
2909                    } catch (IOException e) {
2910                            throw new SQLException(e.getMessage());
2911                    }
2912            }
2913    
2914            /**
2915             * @see java.sql.ResultSet#updateBoolean(int, boolean)
2916             */
2917            public void updateBoolean(int columnIndex, boolean x) throws SQLException {
2918                    updateObject(columnIndex, Caster.toBoolean(x));
2919            }
2920    
2921            /**
2922             * @see java.sql.ResultSet#updateBoolean(java.lang.String, boolean)
2923             */
2924            public void updateBoolean(String columnName, boolean x) throws SQLException {
2925                    updateObject(columnName, Caster.toBoolean(x));
2926            }
2927    
2928            /**
2929             * @see java.sql.ResultSet#updateByte(int, byte)
2930             */
2931            public void updateByte(int columnIndex, byte x) throws SQLException {
2932                    updateObject(columnIndex, new Byte(x));
2933            }
2934    
2935            /**
2936             * @see java.sql.ResultSet#updateByte(java.lang.String, byte)
2937             */
2938            public void updateByte(String columnName, byte x) throws SQLException {
2939                    updateObject(columnName, new Byte(x));
2940            }
2941    
2942            /**
2943             * @see java.sql.ResultSet#updateBytes(int, byte[])
2944             */
2945            public void updateBytes(int columnIndex, byte[] x) throws SQLException {
2946                    updateObject(columnIndex, x);
2947            }
2948    
2949            /**
2950             * @see java.sql.ResultSet#updateBytes(java.lang.String, byte[])
2951             */
2952            public void updateBytes(String columnName, byte[] x) throws SQLException {
2953                    updateObject(columnName, x);
2954            }
2955    
2956            /**
2957             * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader, int)
2958             */
2959            public void updateCharacterStream(int columnIndex, Reader reader, int length)throws SQLException {
2960                    try {
2961                            updateObject(columnIndex, IOUtil.toString(reader));
2962                    } catch (Exception e) {
2963                            throw new SQLException(e.getMessage());
2964                    }
2965            }
2966    
2967            /**
2968             * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader, int)
2969             */
2970            public void updateCharacterStream(String columnName, Reader reader,int length) throws SQLException {
2971                    try {
2972                            updateObject(columnName, IOUtil.toString(reader));
2973                    } catch (Exception e) {
2974                            throw new SQLException(e.getMessage());
2975                    }
2976            }
2977    
2978            /**
2979             * @see java.sql.ResultSet#updateClob(int, java.sql.Clob)
2980             */
2981            public void updateClob(int columnIndex, Clob x) throws SQLException {
2982                    try {
2983                            updateObject(columnIndex, toString(x));
2984                    } catch (IOException e) {
2985                            throw new SQLException(e.getMessage());
2986                    }
2987            }
2988    
2989            /**
2990             * @see java.sql.ResultSet#updateClob(java.lang.String, java.sql.Clob)
2991             */
2992            public void updateClob(String columnName, Clob x) throws SQLException {
2993                    try {
2994                            updateObject(columnName, toString(x));
2995                    } catch (IOException e) {
2996                            throw new SQLException(e.getMessage());
2997                    }
2998            }
2999    
3000            /**
3001             * @see java.sql.ResultSet#updateDate(int, java.sql.Date)
3002             */
3003            public void updateDate(int columnIndex, java.sql.Date x)throws SQLException {
3004                    updateObject(columnIndex, Caster.toDate(x, false, null, null));
3005            }
3006    
3007            /**
3008             * @see java.sql.ResultSet#updateDate(java.lang.String, java.sql.Date)
3009             */
3010            public void updateDate(String columnName, java.sql.Date x)throws SQLException {
3011                    updateObject(columnName, Caster.toDate(x, false, null, null));
3012            }
3013    
3014            /**
3015             * @see java.sql.ResultSet#updateDouble(int, double)
3016             */
3017            public void updateDouble(int columnIndex, double x) throws SQLException {
3018                    updateObject(columnIndex, Caster.toDouble(x));
3019            }
3020    
3021            /**
3022             * @see java.sql.ResultSet#updateDouble(java.lang.String, double)
3023             */
3024            public void updateDouble(String columnName, double x) throws SQLException {
3025                    updateObject(columnName, Caster.toDouble(x));
3026            }
3027    
3028            /**
3029             * @see java.sql.ResultSet#updateFloat(int, float)
3030             */
3031            public void updateFloat(int columnIndex, float x) throws SQLException {
3032                    updateObject(columnIndex, Caster.toDouble(x));
3033            }
3034    
3035            /**
3036             * @see java.sql.ResultSet#updateFloat(java.lang.String, float)
3037             */
3038            public void updateFloat(String columnName, float x) throws SQLException {
3039                    updateObject(columnName, Caster.toDouble(x));
3040            }
3041    
3042            /**
3043             * @see java.sql.ResultSet#updateInt(int, int)
3044             */
3045            public void updateInt(int columnIndex, int x) throws SQLException {
3046                    updateObject(columnIndex, Caster.toDouble(x));
3047            }
3048    
3049            /**
3050             * @see java.sql.ResultSet#updateInt(java.lang.String, int)
3051             */
3052            public void updateInt(String columnName, int x) throws SQLException {
3053                    updateObject(columnName, Caster.toDouble(x));
3054            }
3055    
3056            /**
3057             * @see java.sql.ResultSet#updateLong(int, long)
3058             */
3059            public void updateLong(int columnIndex, long x) throws SQLException {
3060                    updateObject(columnIndex, Caster.toDouble(x));
3061            }
3062    
3063            /**
3064             * @see java.sql.ResultSet#updateLong(java.lang.String, long)
3065             */
3066            public void updateLong(String columnName, long x) throws SQLException {
3067                    updateObject(columnName, Caster.toDouble(x));
3068            }
3069    
3070            /**
3071             * @see java.sql.ResultSet#updateNull(int)
3072             */
3073            public void updateNull(int columnIndex) throws SQLException {
3074                    updateObject(columnIndex, null);
3075            }
3076    
3077            /**
3078             * @see java.sql.ResultSet#updateNull(java.lang.String)
3079             */
3080            public void updateNull(String columnName) throws SQLException {
3081                    updateObject(columnName, null);
3082            }
3083    
3084            /**
3085             * @see java.sql.ResultSet#updateObject(int, java.lang.Object)
3086             */
3087            public void updateObject(int columnIndex, Object x) throws SQLException {
3088                    try {
3089                            set(getColumnName(columnIndex), x);
3090                    } catch (PageException e) {
3091                            throw new SQLException(e.getMessage());
3092                    }
3093            }
3094    
3095            /**
3096             * @see java.sql.ResultSet#updateObject(java.lang.String, java.lang.Object)
3097             */
3098            public void updateObject(String columnName, Object x) throws SQLException {
3099                    try {
3100                            set(KeyImpl.init(columnName), x);
3101                    } catch (PageException e) {
3102                            throw new SQLException(e.getMessage());
3103                    }
3104            }
3105    
3106            /**
3107             * @see java.sql.ResultSet#updateObject(int, java.lang.Object, int)
3108             */
3109            public void updateObject(int columnIndex, Object x, int scale)throws SQLException {
3110                    updateObject(columnIndex, x);
3111            }
3112    
3113            /**
3114             * @see java.sql.ResultSet#updateObject(java.lang.String, java.lang.Object, int)
3115             */
3116            public void updateObject(String columnName, Object x, int scale)throws SQLException {
3117                    updateObject(columnName, x);
3118            }
3119    
3120            /**
3121             * @see java.sql.ResultSet#updateRef(int, java.sql.Ref)
3122             */
3123            public void updateRef(int columnIndex, Ref x) throws SQLException {
3124                    updateObject(columnIndex, x.getObject());
3125            }
3126    
3127            /**
3128             * @see java.sql.ResultSet#updateRef(java.lang.String, java.sql.Ref)
3129             */
3130            public void updateRef(String columnName, Ref x) throws SQLException {
3131                    updateObject(columnName, x.getObject());
3132            }
3133    
3134            public void updateRow() throws SQLException {
3135                    throw new SQLException("method is not implemented");
3136            }
3137    
3138            /**
3139             * @see java.sql.ResultSet#updateShort(int, short)
3140             */
3141            public void updateShort(int columnIndex, short x) throws SQLException {
3142                    updateObject(columnIndex, Caster.toDouble(x));
3143            }
3144    
3145            /**
3146             * @see java.sql.ResultSet#updateShort(java.lang.String, short)
3147             */
3148            public void updateShort(String columnName, short x) throws SQLException {
3149                    updateObject(columnName, Caster.toDouble(x));
3150            }
3151    
3152            /**
3153             * @see java.sql.ResultSet#updateString(int, java.lang.String)
3154             */
3155            public void updateString(int columnIndex, String x) throws SQLException {
3156                    updateObject(columnIndex, x);
3157            }
3158    
3159            /**
3160             * @see java.sql.ResultSet#updateString(java.lang.String, java.lang.String)
3161             */
3162            public void updateString(String columnName, String x) throws SQLException {
3163                    updateObject(columnName, x);
3164            }
3165    
3166            /**
3167             * @see java.sql.ResultSet#updateTime(int, java.sql.Time)
3168             */
3169            public void updateTime(int columnIndex, Time x) throws SQLException {
3170                    updateObject(columnIndex, new DateTimeImpl(x.getTime(),false));
3171            }
3172    
3173            /**
3174             * @see java.sql.ResultSet#updateTime(java.lang.String, java.sql.Time)
3175             */
3176            public void updateTime(String columnName, Time x) throws SQLException {
3177                    updateObject(columnName, new DateTimeImpl(x.getTime(),false));
3178            }
3179    
3180            /**
3181             * @see java.sql.ResultSet#updateTimestamp(int, java.sql.Timestamp)
3182             */
3183            public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
3184                    updateObject(columnIndex, new DateTimeImpl(x.getTime(),false));
3185            }
3186    
3187            /**
3188             * @see java.sql.ResultSet#updateTimestamp(java.lang.String, java.sql.Timestamp)
3189             */
3190            public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
3191                    updateObject(columnName, new DateTimeImpl(x.getTime(),false));
3192            }
3193    
3194            public ResultSetMetaData getMetaData() throws SQLException {
3195                    
3196                    throw new SQLException("method is not implemented");
3197            }
3198    
3199    
3200        /**
3201             * @see railo.runtime.type.Collection#keyIterator()
3202             */
3203            public Iterator keyIterator() {
3204                    return new KeyIterator(keys());
3205            }
3206            
3207    
3208            /**
3209             * @see railo.runtime.type.Iteratorable#iterator()
3210             */
3211            public Iterator iterator() {
3212                    return keyIterator();
3213            }
3214            
3215            public Iterator valueIterator() {
3216                    return new CollectionIterator(keys(),this);
3217            }
3218    
3219            public void readExternal(ObjectInput in) throws IOException {
3220                    try {
3221                            QueryImpl other=(QueryImpl) new CFMLExpressionInterpreter().interpret(ThreadLocalPageContext.get(),in.readUTF());
3222                            this.arrCurrentRow=other.arrCurrentRow;
3223                            this.columncount=other.columncount;
3224                            this.columnNames=other.columnNames;
3225                            this.columns=other.columns;
3226                            this.exeTime=other.exeTime;
3227                            this.generatedKeys=other.generatedKeys;
3228                            this.isCached=other.isCached;
3229                            this.name=other.name;
3230                            this.recordcount=other.recordcount;
3231                            this.sql=other.sql;
3232                            this.updateCount=other.updateCount;
3233                            
3234                    } catch (PageException e) {
3235                            throw new IOException(e.getMessage());
3236                    }
3237            }
3238    
3239            public void writeExternal(ObjectOutput out) {
3240                    try {
3241                            out.writeUTF(new ScriptConverter().serialize(this));
3242                    } 
3243                    catch (Throwable t) {}
3244            }
3245            
3246            /**
3247             * @see railo.runtime.type.Sizeable#sizeOf()
3248             */
3249            public long sizeOf(){
3250                    long size=SizeOf.size(this.exeTime)+
3251                    SizeOf.size(this.isCached)+
3252                    SizeOf.size(this.arrCurrentRow)+
3253                    SizeOf.size(this.columncount)+
3254                    SizeOf.size(this.generatedKeys)+
3255                    SizeOf.size(this.name)+
3256                    SizeOf.size(this.recordcount)+
3257                    SizeOf.size(this.sql)+
3258                    SizeOf.size(this.template)+
3259                    SizeOf.size(this.updateCount);
3260                    
3261                    for(int i=0;i<columns.length;i++){
3262                            size+=this.columns[i].sizeOf();
3263                    }
3264                    return size;
3265            }
3266            
3267    
3268            public boolean equals(Object obj){
3269                    if(!(obj instanceof Collection)) return false;
3270                    return CollectionUtil.equals(this,(Collection)obj);
3271            }
3272    
3273            public int getHoldability() throws SQLException {
3274                    throw notSupported();
3275            }
3276    
3277            public boolean isClosed() throws SQLException {
3278                    return false;
3279            }
3280    
3281            public void updateNString(int columnIndex, String nString)throws SQLException {
3282                    updateString(columnIndex, nString);
3283            }
3284    
3285            public void updateNString(String columnLabel, String nString)throws SQLException {
3286                    updateString(columnLabel, nString);
3287            }
3288    
3289            
3290    
3291            public String getNString(int columnIndex) throws SQLException {
3292                    return getString(columnIndex);
3293            }
3294    
3295            public String getNString(String columnLabel) throws SQLException {
3296                    return getString(columnLabel);
3297            }
3298    
3299            public Reader getNCharacterStream(int columnIndex) throws SQLException {
3300                    return getCharacterStream(columnIndex);
3301            }
3302    
3303            public Reader getNCharacterStream(String columnLabel) throws SQLException {
3304                    return getCharacterStream(columnLabel);
3305            }
3306    
3307            public void updateNCharacterStream(int columnIndex, Reader x, long length)throws SQLException {
3308                    updateCharacterStream(columnIndex, x, length);
3309            }
3310    
3311            public void updateNCharacterStream(String columnLabel, Reader reader,long length) throws SQLException {
3312                    throw notSupported();
3313            }
3314    
3315            public void updateAsciiStream(int columnIndex, InputStream x, long length)throws SQLException {
3316                    throw notSupported();
3317            }
3318    
3319            public void updateBinaryStream(int columnIndex, InputStream x, long length)throws SQLException {
3320                    throw notSupported();
3321            }
3322    
3323            public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
3324                    throw notSupported();
3325            }
3326    
3327            public void updateAsciiStream(String columnLabel, InputStream x, long length)throws SQLException {
3328                    throw notSupported();
3329            }
3330    
3331            public void updateBinaryStream(String columnLabel, InputStream x,long length) throws SQLException {
3332                    throw notSupported();
3333            }
3334    
3335            public void updateCharacterStream(String columnLabel, Reader reader,long length) throws SQLException {
3336                    throw notSupported();
3337            }
3338    
3339            public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
3340                    throw notSupported();
3341            }
3342    
3343            public void updateBlob(String columnLabel, InputStream inputStream,long length) throws SQLException {
3344                    throw notSupported();
3345            }
3346    
3347            public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
3348                    throw notSupported();
3349            }
3350    
3351            public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
3352                    throw notSupported();
3353            }
3354    
3355            public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
3356                    updateClob(columnIndex, reader, length);
3357            }
3358    
3359            public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
3360                    updateClob(columnLabel, reader,length);
3361            }
3362    
3363            public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
3364                    updateCharacterStream(columnIndex, x);
3365            }
3366    
3367            public void updateNCharacterStream(String columnLabel, Reader reader)throws SQLException {
3368                    throw notSupported();
3369            }
3370    
3371            public void updateAsciiStream(int columnIndex, InputStream x)throws SQLException {
3372                    throw notSupported();
3373            }
3374    
3375            public void updateBinaryStream(int columnIndex, InputStream x)throws SQLException {
3376                    throw notSupported();
3377            }
3378    
3379            public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
3380                    throw notSupported();
3381            }
3382    
3383            public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
3384                    throw notSupported();
3385            }
3386    
3387            public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
3388                    throw notSupported();
3389            }
3390    
3391            public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
3392                    throw notSupported();
3393            }
3394    
3395            public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
3396                    throw notSupported();
3397            }
3398    
3399            public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
3400                    throw notSupported();
3401            }
3402    
3403            public void updateClob(int columnIndex, Reader reader) throws SQLException {
3404                    throw notSupported();
3405            }
3406    
3407            public void updateClob(String columnLabel, Reader reader) throws SQLException {
3408                    throw notSupported();
3409            }
3410    
3411            public void updateNClob(int columnIndex, Reader reader) throws SQLException {
3412                    updateClob(columnIndex, reader);
3413            }
3414    
3415            public void updateNClob(String columnLabel, Reader reader) throws SQLException {
3416                    updateClob(columnLabel, reader);
3417            }
3418    
3419            public <T> T unwrap(Class<T> iface) throws SQLException {
3420                    throw notSupported();
3421            }
3422    
3423            public boolean isWrapperFor(Class<?> iface) throws SQLException {
3424                    throw notSupported();
3425            }
3426            
3427    
3428            
3429            //JDK6: uncomment this for compiling with JDK6 
3430             
3431            public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
3432                    throw notSupported();
3433            }
3434    
3435            public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
3436                    throw notSupported();
3437            }
3438    
3439            public NClob getNClob(int columnIndex) throws SQLException {
3440                    throw notSupported();
3441            }
3442    
3443            public NClob getNClob(String columnLabel) throws SQLException {
3444                    throw notSupported();
3445            }
3446    
3447            public SQLXML getSQLXML(int columnIndex) throws SQLException {
3448                    throw notSupported();
3449            }
3450    
3451            public SQLXML getSQLXML(String columnLabel) throws SQLException {
3452                    throw notSupported();
3453            }
3454    
3455            public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
3456                    throw notSupported();
3457            }
3458    
3459            public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
3460                    throw notSupported();
3461            }
3462            
3463            public RowId getRowId(int columnIndex) throws SQLException {
3464                    throw notSupported();
3465            }
3466    
3467            public RowId getRowId(String columnLabel) throws SQLException {
3468                    throw notSupported();
3469            }
3470    
3471            public void updateRowId(int columnIndex, RowId x) throws SQLException {
3472                    throw notSupported();
3473            }
3474    
3475            public void updateRowId(String columnLabel, RowId x) throws SQLException {
3476                    throw notSupported();
3477            }
3478            
3479            public void removeRows(int index, int count) throws PageException {
3480                    QueryUtil.removeRows(this,index,count);
3481            }
3482            
3483    
3484            private SQLException notSupported() {
3485                    return new SQLException("this feature is not supported");
3486            }
3487            private RuntimeException notSupportedEL() {
3488                    return new RuntimeException(new SQLException("this feature is not supported"));
3489            }
3490    
3491            public synchronized void enableShowQueryUsage() {
3492                    if(columns!=null)for(int i=0;i<columns.length;i++){
3493                            columns[i]=columns[i].toDebugColumn();
3494                    }
3495            }
3496    
3497            public long getExecutionTime() {
3498                    return exeTime;
3499            }
3500            
3501            public static QueryImpl cloneQuery(QueryPro qry,boolean deepCopy) {
3502            QueryImpl newResult=new QueryImpl();
3503            ThreadLocalDuplication.set(qry, newResult);
3504            try{
3505                    
3506                newResult.columnNames=qry.getColumnNames();
3507                    newResult.columns=new QueryColumnPro[newResult.columnNames.length];
3508                    QueryColumnPro col;
3509                    for(int i=0;i<newResult.columnNames.length;i++) {
3510                            col = (QueryColumnPro) qry.getColumn(newResult.columnNames[i],null);
3511                            newResult.columns[i]=col.cloneColumn(newResult,deepCopy);
3512                    }
3513                    
3514                            
3515                        newResult.sql=qry.getSql();
3516                    newResult.template=qry.getTemplate();
3517                    newResult.recordcount=qry.getRecordcount();
3518                    newResult.columncount=newResult.columnNames.length;
3519                    newResult.isCached=qry.isCached();
3520                    newResult.name=qry.getName();
3521                    newResult.exeTime=qry.getExecutionTime();
3522                    newResult.updateCount=qry.getUpdateCount();
3523                    if(qry.getGeneratedKeys()!=null)newResult.generatedKeys=((QueryImpl)qry.getGeneratedKeys()).cloneQuery(false);
3524                    return newResult;
3525            }
3526            finally {
3527                    ThreadLocalDuplication.remove(qry);
3528            }
3529        }
3530    }