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