package railo.runtime.type;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import railo.commons.db.DBUtil;
import railo.commons.io.IOUtil;
import railo.commons.lang.StringUtil;
import railo.commons.sql.SQLUtil;
import railo.loader.engine.CFMLEngineFactory;
import railo.runtime.PageContext;
import railo.runtime.config.NullSupportHelper;
import railo.runtime.converter.ScriptConverter;
import railo.runtime.db.CFTypes;
import railo.runtime.db.DataSourceUtil;
import railo.runtime.db.DatasourceConnection;
import railo.runtime.db.DatasourceConnectionImpl;
import railo.runtime.db.SQL;
import railo.runtime.db.SQLCaster;
import railo.runtime.db.SQLItem;
import railo.runtime.dump.DumpData;
import railo.runtime.dump.DumpProperties;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.DatabaseException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.exp.PageRuntimeException;
import railo.runtime.interpreter.CFMLExpressionInterpreter;
import railo.runtime.op.Caster;
import railo.runtime.op.Decision;
import railo.runtime.op.Duplicator;
import railo.runtime.op.ThreadLocalDuplication;
import railo.runtime.op.date.DateCaster;
import railo.runtime.query.caster.Cast;
import railo.runtime.type.comparator.NumberSortRegisterComparator;
import railo.runtime.type.comparator.SortRegister;
import railo.runtime.type.comparator.SortRegisterComparator;
import railo.runtime.type.dt.DateTime;
import railo.runtime.type.dt.DateTimeImpl;
import railo.runtime.type.it.CollectionIterator;
import railo.runtime.type.it.EntryIterator;
import railo.runtime.type.it.ForEachQueryIterator;
import railo.runtime.type.it.KeyIterator;
import railo.runtime.type.it.StringIterator;
import railo.runtime.type.sql.BlobImpl;
import railo.runtime.type.sql.ClobImpl;
import railo.runtime.type.util.ArrayUtil;
import railo.runtime.type.util.CollectionUtil;
import railo.runtime.type.util.KeyConstants;
import railo.runtime.type.util.ListUtil;
import railo.runtime.type.util.MemberUtil;
import railo.runtime.type.util.QueryUtil;
/**
* implementation of the query interface
*/
/**
*
*/
public class QueryImpl implements Query,Objects {
private static final long serialVersionUID = 1035795427320192551L; // do not chnage
/**
* @return the template
*/
public String getTemplate() {
return template;
}
public static final Collection.Key GENERATED_KEYS = KeyImpl.intern("GENERATED_KEYS");
public static final Collection.Key GENERATEDKEYS = KeyImpl.intern("GENERATEDKEYS");
//private static int count=0;
private QueryColumnImpl[] columns;
private Collection.Key[] columnNames;
private SQL sql;
private ArrayInt arrCurrentRow=new ArrayInt();
private int recordcount=0;
private int columncount;
private long exeTime=0;
private boolean isCached=false;
private String name;
private int updateCount;
private QueryImpl generatedKeys;
private String template;
@Override
public int executionTime() {
return (int) exeTime;
}
/**
* create a QueryImpl from a SQL Resultset
* @param result SQL Resultset
* @param maxrow
* @param name
* @throws PageException
*/
public QueryImpl(ResultSet result, int maxrow, String name, TimeZone tz) throws PageException {
this.name=name;
//Stopwatch stopwatch=new Stopwatch();
//stopwatch.start();
long start=System.nanoTime();
try {
fillResult(null,result,maxrow,false,false,tz);
} catch (SQLException e) {
throw new DatabaseException(e,null);
} catch (IOException e) {
throw Caster.toPageException(e);
}
exeTime=System.nanoTime()-start;
}
/**
* Constructor of the class
* only for internal usage (cloning/deserialize)
*/
public QueryImpl() {
}
public QueryImpl(ResultSet result, String name,TimeZone tz) throws PageException {
this.name=name;
try {
fillResult(null,result,-1,true,false,tz);
}
catch (SQLException e) {
throw new DatabaseException(e,null);
}
catch (Exception e) {
throw Caster.toPageException(e);
}
}
/**
* constructor of the class, to generate a resultset from a sql query
* @param dc Connection to a database
* @param name
* @param sql sql to execute
* @param maxrow maxrow for the resultset
* @throws PageException
*/
public QueryImpl(PageContext pc, DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name) throws PageException {
this(pc,dc, sql, maxrow, fetchsize, timeout, name,null,false,true);
}
public QueryImpl(PageContext pc, DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name,String template) throws PageException {
this(pc,dc, sql, maxrow, fetchsize, timeout, name,template,false,true);
}
public QueryImpl(PageContext pc, DatasourceConnection dc,SQL sql,int maxrow, int fetchsize,int timeout, String name,String template,boolean createUpdateData, boolean allowToCachePreperadeStatement) throws PageException {
this.name=name;
this.template=template;
this.sql=sql;
TimeZone tz = ThreadLocalPageContext.getTimeZone(pc);
//ResultSet result=null;
Statement stat=null;
// check SQL Restrictions
if(dc.getDatasource().hasSQLRestriction()) {
QueryUtil.checkSQLRestriction(dc,sql);
}
// check if datasource support Generated Keys
boolean createGeneratedKeys=createUpdateData;
if(createUpdateData){
DatasourceConnectionImpl dci=(DatasourceConnectionImpl) dc;
if(!dci.supportsGetGeneratedKeys())createGeneratedKeys=false;
}
//Stopwatch stopwatch=new Stopwatch();
long start=System.nanoTime();
//stopwatch.start();
boolean hasResult=false;
//boolean closeStatement=true;
try {
SQLItem[] items=sql.getItems();
if(items.length==0) {
stat=dc.getConnection().createStatement();
setAttributes(stat,maxrow,fetchsize,timeout);
// some driver do not support second argument
//hasResult=createGeneratedKeys?stat.execute(sql.getSQLString(),Statement.RETURN_GENERATED_KEYS):stat.execute(sql.getSQLString());
hasResult=QueryUtil.execute(pc,stat,createGeneratedKeys,sql);
}
else {
// some driver do not support second argument
PreparedStatement preStat = dc.getPreparedStatement(sql, createGeneratedKeys,allowToCachePreperadeStatement);
//closeStatement=false;
stat=preStat;
setAttributes(preStat,maxrow,fetchsize,timeout);
setItems(ThreadLocalPageContext.getTimeZone(pc),preStat,items);
hasResult=QueryUtil.execute(pc,preStat);
}
int uc;
ResultSet res;
do {
if(hasResult) {
res=stat.getResultSet();
if(fillResult(dc,res, maxrow, true,createGeneratedKeys,tz))break;
}
else if((uc=setUpdateCount(stat))!=-1){
if(uc>0 && createGeneratedKeys)setGeneratedKeys(dc, stat,tz);
}
else break;
try{
hasResult=stat.getMoreResults(Statement.CLOSE_CURRENT_RESULT);
}
catch(Throwable t){
break;
}
}
while(true);
}
catch (SQLException e) {
throw new DatabaseException(e,sql,dc);
}
catch (Throwable e) {
throw Caster.toPageException(e);
}
finally {
//if(closeStatement)
DBUtil.closeEL(stat);
}
exeTime=System.nanoTime()-start;
if(columncount==0) {
if(columnNames==null) columnNames=new Collection.Key[0];
if(columns==null) columns=new QueryColumnImpl[0];
}
}
private int setUpdateCount(Statement stat) {
try{
int uc=stat.getUpdateCount();
if(uc>-1){
updateCount+=uc;
return uc;
}
}
catch(Throwable t){}
return -1;
}
private boolean setGeneratedKeys(DatasourceConnection dc,Statement stat, TimeZone tz) {
try{
ResultSet rs = stat.getGeneratedKeys();
setGeneratedKeys(dc, rs,tz);
return true;
}
catch(Throwable t) {t.printStackTrace();
return false;
}
}
private void setGeneratedKeys(DatasourceConnection dc,ResultSet rs, TimeZone tz) throws PageException {
generatedKeys=new QueryImpl(rs,"",tz);
// ACF compatibility action
if(generatedKeys.getColumnCount()==1 && DataSourceUtil.isMSSQL(dc)) {
generatedKeys.renameEL(GENERATED_KEYS,KeyConstants._IDENTITYCOL);
generatedKeys.renameEL(GENERATEDKEYS,KeyConstants._IDENTITYCOL);
generatedKeys.renameEL(KeyConstants._ID,KeyConstants._IDENTITYCOL);
}
}
/*private void setUpdateData(Statement stat, boolean createGeneratedKeys, boolean createUpdateCount) {
// update Count
if(createUpdateCount){
try{
updateCount=stat.getUpdateCount();
}
catch(Throwable t){
t.printStackTrace();
}
}
// generated keys
if(createGeneratedKeys){
try{
ResultSet rs = stat.getGeneratedKeys();
generatedKeys=new QueryImpl(rs,"");
}
catch(Throwable t){
t.printStackTrace();
}
}
}*/
private void setItems(TimeZone tz,PreparedStatement preStat, SQLItem[] items) throws DatabaseException, PageException, SQLException {
for(int i=0;i<items.length;i++) {
SQLCaster.setValue(tz,preStat,i+1,items[i]);
}
}
public int getUpdateCount() {
return updateCount;
}
public Query getGeneratedKeys() {
return generatedKeys;
}
private void setAttributes(Statement stat,int maxrow, int fetchsize,int timeout) throws SQLException {
if(maxrow>-1) stat.setMaxRows(maxrow);
if(fetchsize>0)stat.setFetchSize(fetchsize);
if(timeout>0)stat.setQueryTimeout(timeout);
}
private boolean fillResult(DatasourceConnection dc, ResultSet result, int maxrow, boolean closeResult,boolean createGeneratedKeys, TimeZone tz) throws SQLException, IOException, PageException {
if(result==null) return false;
try {
recordcount=0;
ResultSetMetaData meta = result.getMetaData();
columncount=meta.getColumnCount();
// set header arrays
Collection.Key[] tmpColumnNames = new Collection.Key[columncount];
int count=0;
Collection.Key key;
String columnName;
for(int i=0;i<columncount;i++) {
columnName=QueryUtil.getColumnName(meta,i+1);
if(StringUtil.isEmpty(columnName))columnName="column_"+i;
key=KeyImpl.init(columnName);
int index=getIndexFrom(tmpColumnNames,key,0,i);
if(index==-1) {
tmpColumnNames[i]=key;
count++;
}
}
columncount=count;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
Cast[] casts = new Cast[columncount];
// get all used ints
int[] usedColumns=new int[columncount];
count=0;
for(int i=0;i<tmpColumnNames.length;i++) {
if(tmpColumnNames[i]!=null) {
usedColumns[count++]=i;
}
}
// set used column names
int[] types=new int[columns.length];
for(int i=0;i<usedColumns.length;i++) {
columnNames[i]=tmpColumnNames[usedColumns[i]];
columns[i]=new QueryColumnImpl(this,columnNames[i],types[i]=meta.getColumnType(usedColumns[i]+1));
if(types[i]==Types.TIMESTAMP) casts[i]=Cast.TIMESTAMP;
else if(types[i]==Types.TIME) casts[i]=Cast.TIME;
else if(types[i]==Types.DATE) casts[i]=Cast.DATE;
else if(types[i]==Types.CLOB) casts[i]=Cast.CLOB;
else if(types[i]==Types.BLOB) casts[i]=Cast.BLOB;
else if(types[i]==Types.BIT) casts[i]=Cast.BIT;
else if(types[i]==Types.ARRAY) casts[i]=Cast.ARRAY;
else if(types[i]==Types.BIGINT) casts[i]=Cast.BIGINT;
//else if(types[i]==Types.TINYINT) casts[i]=Cast.ARRAY;
else if(types[i]==CFTypes.OPAQUE){
if(SQLUtil.isOracle(result.getStatement().getConnection()))
casts[i]=Cast.ORACLE_OPAQUE;
else
casts[i]=Cast.OTHER;
}
else casts[i]=Cast.OTHER;
}
if(createGeneratedKeys && columncount==1 && columnNames[0].equals(GENERATED_KEYS) && dc!=null && DataSourceUtil.isMSSQLDriver(dc)) {
columncount=0;
columnNames=null;
columns=null;
setGeneratedKeys(dc, result,tz);
return false;
}
// fill data
//Object o;
while(result.next()) {
if(maxrow>-1 && recordcount>=maxrow) {
break;
}
for(int i=0;i<usedColumns.length;i++) {
columns[i].add(casts[i].toCFType(tz,types[i], result, usedColumns[i]+1));
}
++recordcount;
}
}
finally {
if(closeResult)IOUtil.closeEL(result);
}
return true;
}
private Object toBytes(Blob blob) throws IOException, SQLException {
return IOUtil.toBytes((blob).getBinaryStream());
}
private static Object toString(Clob clob) throws IOException, SQLException {
return IOUtil.toString(clob.getCharacterStream());
}
private static int getIndexFrom(Collection.Key[] tmpColumnNames, Collection.Key key, int from, int to) {
for(int i=from;i<to;i++) {
if(tmpColumnNames[i]!=null && tmpColumnNames[i].equalsIgnoreCase(key))return i;
}
return -1;
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param strColumns columns for the resultset
* @param rowNumber count of rows to generate (empty fields)
* @param name
* @deprecated use instead <code>QueryImpl(Collection.Key[] columnKeys, int rowNumber,String name)</code>
*/
public QueryImpl(String[] strColumns, int rowNumber,String name) {
this.name=name;
columncount=strColumns.length;
recordcount=rowNumber;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
for(int i=0;i<strColumns.length;i++) {
columnNames[i]=KeyImpl.init(strColumns[i].trim());
columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
}
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param strColumns columns for the resultset
* @param rowNumber count of rows to generate (empty fields)
* @param name
*/
public QueryImpl(Collection.Key[] columnKeys, int rowNumber,String name) throws DatabaseException {
this.name=name;
columncount=columnKeys.length;
recordcount=rowNumber;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
for(int i=0;i<columnKeys.length;i++) {
columnNames[i]=columnKeys[i];
columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
}
validateColumnNames(columnNames);
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param strColumns columns for the resultset
* @param strTypes array of the types
* @param rowNumber count of rows to generate (empty fields)
* @param name
* @throws DatabaseException
*/
public QueryImpl(String[] strColumns, String[] strTypes, int rowNumber, String name) throws DatabaseException {
this.name=name;
columncount=strColumns.length;
if(strTypes.length!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
recordcount=rowNumber;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
for(int i=0;i<strColumns.length;i++) {
columnNames[i]=KeyImpl.init(strColumns[i].trim());
columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(strTypes[i]),recordcount);
}
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param strColumns columns for the resultset
* @param strTypes array of the types
* @param rowNumber count of rows to generate (empty fields)
* @param name
* @throws DatabaseException
*/
public QueryImpl(Collection.Key[] columnNames, String[] strTypes, int rowNumber, String name) throws DatabaseException {
this.name=name;
this.columnNames=columnNames;
columncount=columnNames.length;
if(strTypes.length!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
recordcount=rowNumber;
columns=new QueryColumnImpl[columncount];
for(int i=0;i<columnNames.length;i++) {
columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(strTypes[i]),recordcount);
}
validateColumnNames(columnNames);
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param arrColumns columns for the resultset
* @param rowNumber count of rows to generate (empty fields)
* @param name
* @throws DatabaseException
*/
public QueryImpl(Array arrColumns, int rowNumber, String name) throws DatabaseException {
this.name=name;
columncount=arrColumns.size();
recordcount=rowNumber;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
for(int i=0;i<columncount;i++) {
columnNames[i]=KeyImpl.init(arrColumns.get(i+1,"").toString().trim());
columns[i]=new QueryColumnImpl(this,columnNames[i],Types.OTHER,recordcount);
}
validateColumnNames(columnNames);
}
/**
* constructor of the class, to generate a empty resultset (no database execution)
* @param arrColumns columns for the resultset
* @param arrTypes type of the columns
* @param rowNumber count of rows to generate (empty fields)
* @param name
* @throws PageException
*/
public QueryImpl(Array arrColumns, Array arrTypes, int rowNumber, String name) throws PageException {
this.name=name;
columncount=arrColumns.size();
if(arrTypes.size()!=columncount) throw new DatabaseException("columns and types has not the same count",null,null,null);
recordcount=rowNumber;
columnNames=new Collection.Key[columncount];
columns=new QueryColumnImpl[columncount];
for(int i=0;i<columncount;i++) {
columnNames[i]=KeyImpl.init(arrColumns.get(i+1,"").toString().trim());
columns[i]=new QueryColumnImpl(this,columnNames[i],SQLCaster.toIntType(Caster.toString(arrTypes.get(i+1,""))),recordcount);
}
validateColumnNames(columnNames);
}
/**
* constructor of the class
* @param columnNames columns definition as String Array
* @param arrColumns values
* @param name
* @throws DatabaseException
*/
public QueryImpl(String[] strColumnNames, Array[] arrColumns, String name) throws DatabaseException {
this(_toKeys(strColumnNames),arrColumns,name);
}
private static void validateColumnNames(Key[] columnNames) throws DatabaseException {
Set<String> testMap=new HashSet<String>();
for(int i=0 ;i<columnNames.length;i++) {
// Only allow column names that are valid variable name
//if(!Decision.isSimpleVariableName(columnNames[i]))
// 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);
if(testMap.contains(columnNames[i].getLowerString()))
throw new DatabaseException("invalid parameter for query, ambiguous column name "+columnNames[i],"columnNames: "+ListUtil.arrayToListTrim( _toStringKeys(columnNames),","),null,null);
testMap.add(columnNames[i].getLowerString());
}
}
private static Collection.Key[] _toKeys(String[] strColumnNames) {
Collection.Key[] columnNames=new Collection.Key[strColumnNames.length];
for(int i=0 ;i<columnNames.length;i++) {
columnNames[i]=KeyImpl.init(strColumnNames[i].trim());
}
return columnNames;
}
private static String[] _toStringKeys(Collection.Key[] columnNames) {
String[] strColumnNames=new String[columnNames.length];
for(int i=0 ;i<strColumnNames.length;i++) {
strColumnNames[i]=columnNames[i].getString();
}
return strColumnNames;
}
/*public QueryImpl(Collection.Key[] columnNames, QueryColumn[] columns, String name,long exeTime, boolean isCached,SQL sql) throws DatabaseException {
this.columnNames=columnNames;
this.columns=columns;
this.exeTime=exeTime;
this.isCached=isCached;
this.name=name;
this.columncount=columnNames.length;
this.recordcount=columns.length==0?0:columns[0].size();
this.sql=sql;
}*/
public QueryImpl(Collection.Key[] columnNames, Array[] arrColumns, String name) throws DatabaseException {
this.name=name;
if(columnNames.length!=arrColumns.length)
throw new DatabaseException("invalid parameter for query, not the same count from names and columns","names:"+columnNames.length+";columns:"+arrColumns.length,null,null);
int len=0;
columns=new QueryColumnImpl[arrColumns.length];
if(arrColumns.length>0) {
// test columns
len=arrColumns[0].size();
for(int i=0;i<arrColumns.length;i++) {
if(arrColumns[i].size()!=len)
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);
//columns[i]=new QueryColumnTypeFlex(arrColumns[i]);
columns[i]=new QueryColumnImpl(this,columnNames[i],arrColumns[i],Types.OTHER);
}
// test keys
validateColumnNames(columnNames);
}
columncount=columns.length;
recordcount=len;
this.columnNames=columnNames;
}
/**
* constructor of the class
* @param columnList
* @param data
* @param name
* @throws DatabaseException
*/
public QueryImpl(String[] strColumnList, Object[][] data,String name) throws DatabaseException {
this(toCollKeyArr(strColumnList),data.length,name);
for(int iRow=0;iRow<data.length;iRow++) {
Object[] row=data[iRow];
for(int iCol=0;iCol<row.length;iCol++) {
//print.ln(columnList[iCol]+":"+iRow+"="+row[iCol]);
setAtEL(columnNames[iCol],iRow+1,row[iCol]);
}
}
}
private static Collection.Key[] toCollKeyArr(String[] strColumnList) {
Collection.Key[] columnList=new Collection.Key[strColumnList.length];
for(int i=0 ;i<columnList.length;i++) {
columnList[i]=KeyImpl.init(strColumnList[i].trim());
}
return columnList;
}
@Override
public int size() {
return columncount;
}
@Override
public Collection.Key[] keys() {
return columnNames;
}
@Override
public Object removeEL(Collection.Key key) {
return setEL(key,null);
}
@Override
public Object remove(Collection.Key key) throws PageException {
return set(key,null);
}
@Override
public void clear() {
for(int i=0;i<columns.length;i++) {
columns[i].clear();
}
recordcount=0;
}
@Override
public Object get(String key, Object defaultValue) {
return getAt(key,
arrCurrentRow.get(getPid(), 1),
defaultValue);
}
//private static int pidc=0;
private int getPid() {
PageContext pc = ThreadLocalPageContext.get();
if(pc==null) {
pc=CFMLEngineFactory.getInstance().getThreadPageContext();
if(pc==null)throw new RuntimeException("cannot get pid for current thread");
}
return pc.getId();
}
@Override
public Object get(Collection.Key key, Object defaultValue) {
return getAt(key,
arrCurrentRow.get(getPid(), 1),
defaultValue);
}
@Override
public Object get(String key) throws PageException {
return getAt(key,
arrCurrentRow.get(getPid(), 1)
);
}
@Override
public Object get(Collection.Key key) throws PageException {
return getAt(key,
arrCurrentRow.get(getPid(), 1)
);
}
@Override
public Object getAt(String key, int row, Object defaultValue) {
return getAt(KeyImpl.init(key), row, defaultValue);
}
public Object getAt(Collection.Key key, int row, Object defaultValue) {
int index=getIndexFromKey(key);
if(index!=-1) {
return columns[index].get(row,defaultValue);
}
if(key.length()>=10) {
if(key.equals(KeyConstants._RECORDCOUNT)) return new Double(getRecordcount());
if(key.equals(KeyConstants._CURRENTROW)) return new Double(row);
if(key.equals(KeyConstants._COLUMNLIST)) return getColumnlist(true);
}
return defaultValue;
}
@Override
public Object getAt(String key, int row) throws PageException {
return getAt(KeyImpl.init(key), row);
}
@Override
public Object getAt(Collection.Key key, int row) throws PageException {
int index=getIndexFromKey(key);
if(index!=-1) {
return columns[index].get(row, NullSupportHelper.empty());
}
if(key.length()>=10) {
if(key.equals(KeyConstants._RECORDCOUNT)) return new Double(getRecordcount());
if(key.equals(KeyConstants._CURRENTROW)) return new Double(row);
if(key.equals(KeyConstants._COLUMNLIST)) return getColumnlist(true);
}
throw new DatabaseException("column ["+key+"] not found in query, columns are ["+getColumnlist(false)+"]",null,sql,null);
}
@Override
public synchronized int removeRow(int row) throws PageException {
//disconnectCache();
for(int i=0;i<columns.length;i++) {
columns[i].removeRow(row);
}
return --recordcount;
}
@Override
public int removeRowEL(int row) {
//disconnectCache();
try {
return removeRow(row);
} catch (PageException e) {
return recordcount;
}
}
@Override
public QueryColumn removeColumn(String key) throws DatabaseException {
return removeColumn(KeyImpl.init(key));
}
@Override
public QueryColumn removeColumn(Collection.Key key) throws DatabaseException {
//disconnectCache();
QueryColumn removed = removeColumnEL(key);
if(removed==null) {
if(key.equals(KeyConstants._RECORDCOUNT) ||
key.equals(KeyConstants._CURRENTROW) ||
key.equals(KeyConstants._COLUMNLIST))
throw new DatabaseException("can't remove "+key+" this is not a row","existing rows are ["+getColumnlist(false)+"]",null,null);
throw new DatabaseException("can't remove row ["+key+"], this row doesn't exist",
"existing rows are ["+getColumnlist(false)+"]",null,null);
}
return removed;
}
@Override
public synchronized QueryColumn removeColumnEL(String key) {
return removeColumnEL(KeyImpl.init(key));
}
public QueryColumn removeColumnEL(Collection.Key key) {
//disconnectCache();
int index=getIndexFromKey(key);
if(index!=-1) {
int current=0;
QueryColumn removed=null;
Collection.Key[] newColumnNames=new Collection.Key[columnNames.length-1];
QueryColumnImpl[] newColumns=new QueryColumnImpl[columns.length-1];
for(int i=0;i<columns.length;i++) {
if(i==index) {
removed=columns[i];
}
else {
newColumnNames[current]=columnNames[i];
newColumns[current++]=columns[i];
}
}
columnNames=newColumnNames;
columns=newColumns;
columncount--;
return removed;
}
return null;
}
@Override
public Object setEL(String key, Object value) {
return setEL(KeyImpl.init(key),value);
}
@Override
public Object setEL(Collection.Key key, Object value) {
return setAtEL(key,
arrCurrentRow.get(getPid(), 1),
value);
}
@Override
public Object set(String key, Object value) throws PageException {
return set(KeyImpl.init(key),value);
}
@Override
public Object set(Collection.Key key, Object value) throws PageException {
return setAt(key,
arrCurrentRow.get(getPid(), 1),
value);
}
@Override
public Object setAt(String key,int row, Object value) throws PageException {
return setAt(KeyImpl.init(key), row, value);
}
public Object setAt(Collection.Key key, int row, Object value) throws PageException {
int index=getIndexFromKey(key);
if(index!=-1) {
return columns[index].set(row,value);
}
throw new DatabaseException("column ["+key+"] does not exist","columns are ["+getColumnlist(false)+"]",sql,null);
}
@Override
public Object setAtEL(String key,int row, Object value) {
return setAtEL(KeyImpl.init(key), row, value);
}
public Object setAtEL(Collection.Key key, int row, Object value) {
int index=getIndexFromKey(key);
if(index!=-1) {
return columns[index].setEL(row,value);
}
return null;
}
@Override
public boolean next() {
return next(getPid());
}
@Override
public boolean next(int pid) {
if(recordcount>=(arrCurrentRow.set(pid,arrCurrentRow.get(pid,0)+1))) {
return true;
}
arrCurrentRow.set(pid,0);
return false;
}
@Override
public void reset() {
reset(getPid());
}
public void reset(int pid) {
arrCurrentRow.set(pid,0);
}
@Override
public int getRecordcount() {
return recordcount;
}
@Override
public int getCurrentrow(int pid) {
return arrCurrentRow.get(pid,1);
}
/**
* return a string list of all columns
* @return string list
*/
public String getColumnlist(boolean upperCase) {
//if(upperCase)upperCase=((ConfigImpl)ThreadLocalPageContext.getConfig()).getDotNotationUpperCase();
StringBuffer sb=new StringBuffer();
for(int i=0;i<columnNames.length;i++) {
if(i>0)sb.append(',');
sb.append(upperCase?columnNames[i].getUpperString():columnNames[i].getString());
}
return sb.toString();
}
public String getColumnlist() {
return getColumnlist(true);
}
public boolean go(int index) {
return go(index,getPid());
}
public boolean go(int index, int pid) {
if(index>0 && index<=recordcount) {
arrCurrentRow.set(pid, index);
return true;
}
arrCurrentRow.set(pid, 0);
return false;
}
@Override
public boolean isEmpty() {
return recordcount+columncount==0;
}
@Override
public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
return QueryUtil.toDumpData(this, pageContext, maxlevel, dp);
}
/**
* sorts a query by a column
* @param column colun to sort
* @throws PageException
*/
public void sort(String column) throws PageException {
sort(column,Query.ORDER_ASC);
}
@Override
public void sort(Collection.Key column) throws PageException {
sort(column,Query.ORDER_ASC);
}
/**
* sorts a query by a column
* @param strColumn column to sort
* @param order sort type (Query.ORDER_ASC or Query.ORDER_DESC)
* @throws PageException
*/
public synchronized void sort(String strColumn, int order) throws PageException {
//disconnectCache();
sort(getColumn(strColumn),order);
}
@Override
public synchronized void sort(Collection.Key keyColumn, int order) throws PageException {
//disconnectCache();
sort(getColumn(keyColumn),order);
}
private void sort(QueryColumn column, int order) throws PageException {
int type = column.getType();
SortRegister[] arr= ArrayUtil.toSortRegisterArray(column);
Arrays.sort(arr,
(
type==Types.BIGINT ||
type==Types.BIT ||
type==Types.INTEGER ||
type==Types.SMALLINT ||
type==Types.TINYINT ||
type==Types.DECIMAL ||
type==Types.DOUBLE ||
type==Types.NUMERIC ||
type==Types.REAL)?
(Comparator)new NumberSortRegisterComparator(order==ORDER_ASC):(Comparator)new SortRegisterComparator(order==ORDER_ASC,true)
);
for(int i=0;i<columns.length;i++) {
column=columns[i];
int len=column.size();
QueryColumnImpl newCol=new QueryColumnImpl(this,columnNames[i],columns[i].getType(),len);
for(int y=1;y<=len;y++) {
newCol.set(y,column.get(arr[y-1].getOldPosition()+1,null));
}
columns[i]=newCol;
}
}
@Override
public synchronized boolean addRow(int count) {
//disconnectCache();
for(int i=0;i<columns.length;i++) {
QueryColumnPro column = columns[i];
column.addRow(count);
}
recordcount+=count;
return true;
}
@Override
public boolean addColumn(String columnName, Array content) throws DatabaseException {
return addColumn(columnName,content,Types.OTHER);
}
public boolean addColumn(Collection.Key columnName, Array content) throws PageException {
return addColumn(columnName,content,Types.OTHER);
}
@Override
public synchronized boolean addColumn(String columnName, Array content, int type) throws DatabaseException {
return addColumn(KeyImpl.init(columnName.trim()), content, type);
}
@Override
public boolean addColumn(Collection.Key columnName, Array content, int type) throws DatabaseException {
//disconnectCache();
// TODO Meta type
content=(Array) Duplicator.duplicate(content,false);
if(getIndexFromKey(columnName)!=-1)
throw new DatabaseException("column name ["+columnName.getString()+"] already exist",null,sql,null);
if(content.size()!=getRecordcount()) {
//throw new DatabaseException("array for the new column has not the same size like the query (arrayLen!=query.recordcount)");
if(content.size()>getRecordcount()) addRow(content.size()-getRecordcount());
else content.setEL(getRecordcount(),"");
}
QueryColumnImpl[] newColumns=new QueryColumnImpl[columns.length+1];
Collection.Key[] newColumnNames=new Collection.Key[columns.length+1];
boolean logUsage=false;
for(int i=0;i<columns.length;i++) {
newColumns[i]=columns[i];
newColumnNames[i]=columnNames[i];
if(!logUsage && columns[i] instanceof DebugQueryColumn) logUsage=true;
}
newColumns[columns.length]=new QueryColumnImpl(this,columnName,content,type);
newColumnNames[columns.length]=columnName;
columns=newColumns;
columnNames=newColumnNames;
columncount++;
if(logUsage)enableShowQueryUsage();
return true;
}
/* *
* if this query is still connected with cache (same query also in cache)
* it will disconnetd from cache (clone object and add clone to cache)
*/
//protected void disconnectCache() {}
@Override
public Object clone() {
return cloneQuery(true);
}
@Override
public Collection duplicate(boolean deepCopy) {
return cloneQuery(true);
}
/**
* @return clones the query object
*/
public QueryImpl cloneQuery(boolean deepCopy) {
QueryImpl newResult=new QueryImpl();
ThreadLocalDuplication.set(this, newResult);
try{
if(columnNames!=null){
newResult.columnNames=new Collection.Key[columnNames.length];
newResult.columns=new QueryColumnImpl[columnNames.length];
for(int i=0;i<columnNames.length;i++) {
newResult.columnNames[i]=columnNames[i];
newResult.columns[i]=columns[i].cloneColumnImpl(deepCopy);
}
}
newResult.sql=sql;
newResult.template=template;
newResult.recordcount=recordcount;
newResult.columncount=columncount;
newResult.isCached=isCached;
newResult.name=name;
newResult.exeTime=exeTime;
newResult.updateCount=updateCount;
if(generatedKeys!=null)newResult.generatedKeys=generatedKeys.cloneQuery(false);
return newResult;
}
finally {
// ThreadLocalDuplication.remove(this); removed "remove" to catch sisters and brothers
}
}
@Override
public synchronized int[] getTypes() {
int[] types=new int[columns.length];
for(int i=0;i<columns.length;i++) {
types[i]=columns[i].getType();
}
return types;
}
@Override
public synchronized Map<Collection.Key,String> getTypesAsMap() {
Map<Collection.Key,String> map=new HashMap<Collection.Key,String>();
for(int i=0;i<columns.length;i++) {
map.put(columnNames[i],columns[i].getTypeAsString());
}
return map;
}
@Override
public QueryColumn getColumn(String key) throws DatabaseException {
return getColumn(KeyImpl.init(key.trim()));
}
@Override
public QueryColumn getColumn(Collection.Key key) throws DatabaseException {
int index=getIndexFromKey(key);
if(index!=-1) return columns[index];
if(key.length()>=10) {
if(key.equals(KeyConstants._RECORDCOUNT)) return new QueryColumnRef(this,key,Types.INTEGER);
if(key.equals(KeyConstants._CURRENTROW)) return new QueryColumnRef(this,key,Types.INTEGER);
if(key.equals(KeyConstants._COLUMNLIST)) return new QueryColumnRef(this,key,Types.INTEGER);
}
throw new DatabaseException("key ["+key.getString()+"] not found in query, columns are ["+getColumnlist(false)+"]",null,sql,null);
}
private void renameEL(Collection.Key src, Collection.Key trg) {
int index=getIndexFromKey(src);
if(index!=-1){
columnNames[index]=trg;
columns[index].setKey(trg);
}
}
public synchronized void rename(Collection.Key columnName,Collection.Key newColumnName) throws ExpressionException {
int index=getIndexFromKey(columnName);
if(index==-1) throw new ExpressionException("invalid column name definitions");
columnNames[index]=newColumnName;
columns[index].setKey(newColumnName);
}
@Override
public QueryColumn getColumn(String key, QueryColumn defaultValue) {
return getColumn(KeyImpl.init(key.trim()),defaultValue);
}
@Override
public QueryColumn getColumn(Collection.Key key, QueryColumn defaultValue) {
int index=getIndexFromKey(key);
if(index!=-1) return columns[index];
if(key.length()>=10) {
if(key.equals(KeyConstants._RECORDCOUNT)) return new QueryColumnRef(this,key,Types.INTEGER);
if(key.equals(KeyConstants._CURRENTROW)) return new QueryColumnRef(this,key,Types.INTEGER);
if(key.equals(KeyConstants._COLUMNLIST)) return new QueryColumnRef(this,key,Types.INTEGER);
}
return defaultValue;
}
@Override
public String toString() {
Collection.Key[] keys=keys();
StringBuffer sb=new StringBuffer();
sb.append("Query\n");
sb.append("---------------------------------------------------\n");
if(sql!=null) {
sb.append(sql+"\n");
sb.append("---------------------------------------------------\n");
}
if(exeTime>0) {
sb.append("Execution Time (ns): "+exeTime+"\n");
sb.append("---------------------------------------------------\n");
}
sb.append("Recordcount: "+getRecordcount()+"\n");
sb.append("---------------------------------------------------\n");
String trenner="";
for(int i=0;i<keys.length;i++) {
trenner+="+---------------------";
}
trenner+="+\n";
sb.append(trenner);
// Header
for(int i=0;i<keys.length;i++) {
sb.append(getToStringField(keys[i].getString()));
}
sb.append("|\n");
sb.append(trenner);
sb.append(trenner);
// body
for(int i=0;i<recordcount;i++) {
for(int y=0;y<keys.length;y++) {
try {
Object o=getAt(keys[y],i+1);
if(o instanceof String)sb.append(getToStringField(o.toString()));
else if(o instanceof Number) sb.append(getToStringField(Caster.toString(((Number)o))));
else if(o instanceof Clob) sb.append(getToStringField(Caster.toString(o)));
else sb.append(getToStringField(o.toString()));
} catch (PageException e) {
sb.append(getToStringField("[empty]"));
}
}
sb.append("|\n");
sb.append(trenner);
}
return sb.toString();
}
private String getToStringField(String str) {
if(str==null) return "| ";
else if(str.length()<21) {
String s="|"+str;
for(int i=str.length();i<21;i++)s+=" ";
return s;
}
else if(str.length()==21) return "|"+str;
else return "|"+str.substring(0,18)+"...";
}
/**
*
* @param type
* @return return String represetation of a Type from int type
*/
public static String getColumTypeName(int type) {
switch(type) {
case Types.ARRAY: return "OBJECT";
case Types.BIGINT: return "BIGINT";
case Types.BINARY: return "BINARY";
case Types.BIT: return "BIT";
case Types.BLOB: return "OBJECT";
case Types.BOOLEAN: return "BOOLEAN";
case Types.CHAR: return "CHAR";
case Types.NCHAR: return "NCHAR";
case Types.CLOB: return "OBJECT";
case Types.NCLOB: return "OBJECT";
case Types.DATALINK: return "OBJECT";
case Types.DATE: return "DATE";
case Types.DECIMAL: return "DECIMAL";
case Types.DISTINCT: return "OBJECT";
case Types.DOUBLE: return "DOUBLE";
case Types.FLOAT: return "DOUBLE";
case Types.INTEGER: return "INTEGER";
case Types.JAVA_OBJECT: return "OBJECT";
case Types.LONGVARBINARY: return "LONGVARBINARY";
case Types.LONGVARCHAR: return "LONGVARCHAR";
case Types.NULL: return "OBJECT";
case Types.NUMERIC: return "NUMERIC";
case Types.OTHER: return "OBJECT";
case Types.REAL: return "REAL";
case Types.REF: return "OBJECT";
case Types.SMALLINT: return "SMALLINT";
case Types.STRUCT: return "OBJECT";
case Types.TIME: return "TIME";
case Types.TIMESTAMP: return "TIMESTAMP";
case Types.TINYINT: return "TINYINT";
case Types.VARBINARY: return "VARBINARY";
case Types.NVARCHAR: return "NVARCHAR";
case Types.SQLXML: return "SQLXML";
case Types.VARCHAR: return "VARCHAR";
default : return "VARCHAR";
}
}
private int getIndexFromKey(String key) {
String lc = StringUtil.toLowerCase(key);
for(int i=0;i<columnNames.length;i++) {
if(columnNames[i].getLowerString().equals(lc)) return i;
}
return -1;
}
private int getIndexFromKey(Collection.Key key) {
for(int i=0;i<columnNames.length;i++) {
if(columnNames[i].equalsIgnoreCase(key)) return i;
}
return -1;
}
@Override
public void setExecutionTime(long exeTime) {
this.exeTime=exeTime;
}
/**
* @param maxrows
* @return has cutted or not
*/
public synchronized boolean cutRowsTo(int maxrows) {
//disconnectCache();
if(maxrows>-1 && maxrows<getRecordcount()) {
for(int i=0;i<columns.length;i++) {
QueryColumn column = columns[i];
column.cutRowsTo(maxrows);
}
recordcount=maxrows;
return true;
}
return false;
}
@Override
public void setCached(boolean isCached) {
this.isCached=isCached;
}
@Override
public boolean isCached() {
return isCached;
}
@Override
public int addRow() {
addRow(1);
return getRecordcount();
}
public Key getColumnName(int columnIndex) {
Key[] keys = keys();
if(columnIndex<1 || columnIndex>keys.length) return null;
return keys[columnIndex-1];
}
@Override
public int getColumnIndex(String coulmnName) {
Collection.Key[] keys = keys();
for(int i=0;i<keys.length;i++) {
if(keys[i].getString().equalsIgnoreCase(coulmnName)) return i+1;
}
return -1;
}
@Override
public String[] getColumns() {
return getColumnNamesAsString();
}
@Override
public Collection.Key[] getColumnNames() {
Collection.Key[] keys = keys();
Collection.Key[] rtn=new Collection.Key[keys.length];
System.arraycopy(keys,0,rtn,0,keys.length);
return rtn;
}
public void setColumnNames(Collection.Key[] trg) throws PageException {
columncount=trg.length;
Collection.Key[] src = keys();
// target < source
if(trg.length<src.length){
this.columnNames=new Collection.Key[trg.length];
QueryColumnImpl[] tmp=new QueryColumnImpl[trg.length];
for(int i=0;i<trg.length;i++){
this.columnNames[i]=trg[i];
tmp[i]=this.columns[i];
tmp[i].setKey(trg[i]);
}
this.columns=tmp;
return;
}
if(trg.length>src.length){
int recordcount=getRecordcount();
for(int i=src.length;i<trg.length;i++){
Array arr=new ArrayImpl();
for(int r=1;r<=recordcount;r++){
arr.setE(i,"");
}
addColumn(trg[i], arr);
}
src = keys();
}
for(int i=0;i<trg.length;i++){
this.columnNames[i]=trg[i];
this.columns[i].setKey(trg[i]);
}
}
@Override
public String[] getColumnNamesAsString() {
return CollectionUtil.keysAsString(this);
}
public int getColumnCount() {
return columncount;
}
@Override
public String getData(int row, int col) throws IndexOutOfBoundsException {
Collection.Key[] keys = keys();
if(col<1 || col>keys.length) {
new IndexOutOfBoundsException("invalid column index to retrieve Data from query, valid index goes from 1 to "+keys.length);
}
Object o=getAt(keys[col-1],row,NullSupportHelper.NULL());
if(o==NullSupportHelper.NULL())
throw new IndexOutOfBoundsException("invalid row index to retrieve Data from query, valid index goes from 1 to "+getRecordcount());
return Caster.toString( o,NullSupportHelper.full()?null:"");
}
@Override
public String getName() {
return this.name;
}
@Override
public int getRowCount() {
return getRecordcount();
}
@Override
public void setData(int row, int col, String value) throws IndexOutOfBoundsException {
Collection.Key[] keys = keys();
if(col<1 || col>keys.length) {
new IndexOutOfBoundsException("invalid column index to retrieve Data from query, valid index goes from 1 to "+keys.length);
}
try {
setAt(keys[col-1],row,value);
}
catch (PageException e) {
throw new IndexOutOfBoundsException("invalid row index to retrieve Data from query, valid index goes from 1 to "+getRecordcount());
}
}
@Override
public boolean containsKey(String key) {
return getColumn(key,null)!=null;
}
@Override
public boolean containsKey(Collection.Key key) {
return getColumn(key,null)!=null;
}
@Override
public String castToString() throws ExpressionException {
throw new ExpressionException("Can't cast Complex Object Type Query to String",
"Use Built-In-Function \"serialize(Query):String\" to create a String from Query");
}
@Override
public String castToString(String defaultValue) {
return defaultValue;
}
@Override
public boolean castToBooleanValue() throws ExpressionException {
throw new ExpressionException("Can't cast Complex Object Type Query to a boolean value");
}
@Override
public Boolean castToBoolean(Boolean defaultValue) {
return defaultValue;
}
@Override
public double castToDoubleValue() throws ExpressionException {
throw new ExpressionException("Can't cast Complex Object Type Query to a number value");
}
@Override
public double castToDoubleValue(double defaultValue) {
return defaultValue;
}
@Override
public DateTime castToDateTime() throws ExpressionException {
throw new ExpressionException("Can't cast Complex Object Type Query to a Date");
}
@Override
public DateTime castToDateTime(DateTime defaultValue) {
return defaultValue;
}
@Override
public int compareTo(boolean b) throws ExpressionException {
throw new ExpressionException("can't compare Complex Object Type Query with a boolean value");
}
@Override
public int compareTo(DateTime dt) throws PageException {
throw new ExpressionException("can't compare Complex Object Type Query with a DateTime Object");
}
@Override
public int compareTo(double d) throws PageException {
throw new ExpressionException("can't compare Complex Object Type Query with a numeric value");
}
@Override
public int compareTo(String str) throws PageException {
throw new ExpressionException("can't compare Complex Object Type Query with a String");
}
public synchronized Array getMetaDataSimple() {
Array cols=new ArrayImpl();
Struct column;
for(int i=0;i<columns.length;i++) {
column=new StructImpl();
column.setEL(KeyConstants._name,columnNames[i].getString());
column.setEL("isCaseSensitive",Boolean.FALSE);
column.setEL("typeName",columns[i].getTypeAsString());
cols.appendEL(column);
}
return cols;
}
/**
* @return the sql
*/
public SQL getSql() {
return sql;
}
/**
* @param sql the sql to set
*/
public void setSql(SQL sql) {
this.sql = sql;
}
@Override
public Object getObject(String columnName) throws SQLException {
int currentrow;
if((currentrow=arrCurrentRow.get(getPid(),0))==0) return null;
return getAt(columnName,currentrow,null);
}
@Override
public Object getObject(int columnIndex) throws SQLException {
if(columnIndex>0 && columnIndex<=columncount) return getObject(this.columnNames[columnIndex-1].getString());
return null;
}
@Override
public String getString(int columnIndex) throws SQLException {
Object rtn = getObject(columnIndex);
if(rtn==null)return null;
if(Decision.isCastableToString(rtn)) return Caster.toString(rtn,null);
throw new SQLException("can't cast value to string");
}
@Override
public String getString(String columnName) throws SQLException {
Object rtn = getObject(columnName);
if(rtn==null)return null;
if(Decision.isCastableToString(rtn)) return Caster.toString(rtn,null);
throw new SQLException("can't cast value to string");
}
@Override
public boolean getBoolean(int columnIndex) throws SQLException {
Object rtn = getObject(columnIndex);
if(rtn==null)return false;
if(Decision.isCastableToBoolean(rtn)) return Caster.toBooleanValue(rtn,false);
throw new SQLException("can't cast value to boolean");
}
@Override
public boolean getBoolean(String columnName) throws SQLException {
Object rtn = getObject(columnName);
if(rtn==null)return false;
if(Decision.isCastableToBoolean(rtn)) return Caster.toBooleanValue(rtn,false);
throw new SQLException("can't cast value to boolean");
}
// ---------------------------------------
@Override
public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException {
return MemberUtil.call(pc, this, methodName, arguments, railo.commons.lang.CFTypes.TYPE_QUERY, "query");
//return Reflector.callMethod(this,methodName,arguments);
}
@Override
public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException {
return MemberUtil.callWithNamedValues(pc, this, methodName, args,railo.commons.lang.CFTypes.TYPE_QUERY, "query");
}
@Override
public Object get(PageContext pc, Key key, Object defaultValue) {
return getAt(key,arrCurrentRow.get(
pc.getId(),1),defaultValue);
}
@Override
public Object get(PageContext pc, Key key) throws PageException {
return getAt(key,arrCurrentRow.get(pc.getId(),1));
}
public boolean isInitalized() {
return true;
}
@Override
public Object set(PageContext pc, Key propertyName, Object value) throws PageException {
return setAt(propertyName,arrCurrentRow.get(pc.getId(),1),value);
}
@Override
public Object setEL(PageContext pc, Key propertyName, Object value) {
return setAtEL(propertyName,arrCurrentRow.get(pc.getId(),1),value);
}
@Override
public boolean wasNull() {
throw new PageRuntimeException(new ApplicationException("method [wasNull] is not supported"));
}
@Override
public boolean absolute(int row) throws SQLException {
if(recordcount==0) {
if(row!=0) throw new SQLException("invalid row ["+row+"], query is Empty");
return false;
}
//row=row%recordcount;
if(row>0) arrCurrentRow.set(getPid(),row);
else arrCurrentRow.set(getPid(),(recordcount+1)+row);
return true;
}
@Override
public void afterLast() throws SQLException {
arrCurrentRow.set(getPid(),recordcount+1);
}
@Override
public void beforeFirst() throws SQLException {
arrCurrentRow.set(getPid(),0);
}
@Override
public void cancelRowUpdates() throws SQLException {
// ignored
}
@Override
public void clearWarnings() throws SQLException {
// ignored
}
@Override
public void close() throws SQLException {
// ignored
}
@Override
public void deleteRow() throws SQLException {
try {
removeRow(arrCurrentRow.get(getPid()));
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public int findColumn(String columnName) throws SQLException {
int index= getColumnIndex(columnName);
if(index==-1) throw new SQLException("invald column definitions ["+columnName+"]");
return index;
}
@Override
public boolean first() throws SQLException {
return absolute(1);
}
public java.sql.Array getArray(int i) throws SQLException {
throw new SQLException("method is not implemented");
}
public java.sql.Array getArray(String colName) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public InputStream getAsciiStream(int columnIndex) throws SQLException {
String res = getString(columnIndex);
if(res==null)return null;
return new ByteArrayInputStream(res.getBytes());
}
@Override
public InputStream getAsciiStream(String columnName) throws SQLException {
String res = getString(columnName);
if(res==null)return null;
return new ByteArrayInputStream(res.getBytes());
}
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
return new BigDecimal(getDouble(columnIndex));
}
@Override
public BigDecimal getBigDecimal(String columnName) throws SQLException {
return new BigDecimal(getDouble(columnName));
}
@Override
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
return new BigDecimal(getDouble(columnIndex));
}
@Override
public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
return new BigDecimal(getDouble(columnName));
}
@Override
public InputStream getBinaryStream(int columnIndex) throws SQLException {
Object obj = getObject(columnIndex);
if(obj==null)return null;
try {
return Caster.toInputStream(obj,(Charset)null);
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public InputStream getBinaryStream(String columnName) throws SQLException {
Object obj = getObject(columnName);
if(obj==null)return null;
try {
return Caster.toInputStream(obj,(Charset)null);
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Blob getBlob(int i) throws SQLException {
byte[] bytes = getBytes(i);
if(bytes==null) return null;
try {
return BlobImpl.toBlob(bytes);
}
catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Blob getBlob(String colName) throws SQLException {
byte[] bytes = getBytes(colName);
if(bytes==null) return null;
try {
return BlobImpl.toBlob(bytes);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public byte getByte(int columnIndex) throws SQLException {
Object obj = getObject(columnIndex);
if(obj==null) return (byte)0;
try {
return Caster.toByteValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public byte getByte(String columnName) throws SQLException {
Object obj = getObject(columnName);
if(obj==null) return (byte)0;
try {
return Caster.toByteValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public byte[] getBytes(int columnIndex) throws SQLException {
Object obj = getObject(columnIndex);
if(obj==null) return null;
try {
return Caster.toBytes(obj,(Charset)null);
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public byte[] getBytes(String columnName) throws SQLException {
Object obj = getObject(columnName);
if(obj==null) return null;
try {
return Caster.toBytes(obj,(Charset)null);
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Reader getCharacterStream(int columnIndex) throws SQLException {
String str=getString(columnIndex);
if(str==null) return null;
return new StringReader(str);
}
@Override
public Reader getCharacterStream(String columnName) throws SQLException {
String str=getString(columnName);
if(str==null) return null;
return new StringReader(str);
}
@Override
public Clob getClob(int i) throws SQLException {
String str=getString(i);
if(str==null) return null;
return ClobImpl.toClob(str);
}
@Override
public Clob getClob(String colName) throws SQLException {
String str=getString(colName);
if(str==null) return null;
return ClobImpl.toClob(str);
}
@Override
public int getConcurrency() throws SQLException {
return 0;
}
@Override
public String getCursorName() throws SQLException {
return null;
}
@Override
public java.sql.Date getDate(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return null;
try {
return new java.sql.Date(Caster.toDate(obj, false, null).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public java.sql.Date getDate(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return null;
try {
return new java.sql.Date(Caster.toDate(obj, false, null).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public java.sql.Date getDate(int columnIndex, Calendar cal)throws SQLException {
return getDate(columnIndex); // TODO impl
}
@Override
public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
return getDate(columnName);// TODO impl
}
@Override
public double getDouble(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return 0;
try {
return Caster.toDoubleValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public double getDouble(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return 0;
try {
return Caster.toDoubleValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public int getFetchDirection() throws SQLException {
return 1000;
}
@Override
public int getFetchSize() throws SQLException {
return 0;
}
@Override
public float getFloat(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return 0;
try {
return Caster.toFloatValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public float getFloat(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return 0;
try {
return Caster.toFloatValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public int getInt(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return 0;
try {
return Caster.toIntValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public int getInt(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return 0;
try {
return Caster.toIntValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public long getLong(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return 0;
try {
return Caster.toLongValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public long getLong(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return 0;
try {
return Caster.toLongValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Object getObject(int i, Map map) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public Object getObject(String colName, Map map) throws SQLException {
throw new SQLException("method is not implemented");
}
// used only with java 7, do not set @Override
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
return (T) QueryUtil.getObject(this,columnIndex, type);
}
// used only with java 7, do not set @Override
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
return (T) QueryUtil.getObject(this,columnLabel, type);
}
@Override
public Ref getRef(int i) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public Ref getRef(String colName) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public int getRow() throws SQLException {
return arrCurrentRow.get(getPid(),0);
}
@Override
public short getShort(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return 0;
try {
return Caster.toShortValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public short getShort(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return 0;
try {
return Caster.toShortValue(obj);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
public Statement getStatement() throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public Time getTime(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return null;
try {
return new Time(DateCaster.toTime(null, obj).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Time getTime(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return null;
try {
return new Time(DateCaster.toTime(null, obj).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Time getTime(int columnIndex, Calendar cal) throws SQLException {
return getTime(columnIndex);// TODO impl
}
@Override
public Time getTime(String columnName, Calendar cal) throws SQLException {
return getTime(columnName);// TODO impl
}
@Override
public Timestamp getTimestamp(int columnIndex) throws SQLException {
Object obj=getObject(columnIndex);
if(obj==null) return null;
try {
return new Timestamp(DateCaster.toTime(null, obj).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Timestamp getTimestamp(String columnName) throws SQLException {
Object obj=getObject(columnName);
if(obj==null) return null;
try {
return new Timestamp(DateCaster.toTime(null, obj).getTime());
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
return getTimestamp(columnIndex);// TODO impl
}
@Override
public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
return getTimestamp(columnName);// TODO impl
}
@Override
public int getType() throws SQLException {
return 0;
}
@Override
public URL getURL(int columnIndex) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public URL getURL(String columnName) throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public InputStream getUnicodeStream(int columnIndex) throws SQLException {
String str=getString(columnIndex);
if(str==null) return null;
try {
return new ByteArrayInputStream(str.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public InputStream getUnicodeStream(String columnName) throws SQLException {
String str=getString(columnName);
if(str==null) return null;
try {
return new ByteArrayInputStream(str.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public SQLWarning getWarnings() throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public void insertRow() throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public boolean isAfterLast() throws SQLException {
return getCurrentrow(ThreadLocalPageContext.get().getId())>recordcount;
}
@Override
public boolean isBeforeFirst() throws SQLException {
return arrCurrentRow.get(getPid(),0)==0;
}
@Override
public boolean isFirst() throws SQLException {
return arrCurrentRow.get(getPid(),0)==1;
}
public boolean isLast() throws SQLException {
return arrCurrentRow.get(getPid(),0)==recordcount;
}
public boolean last() throws SQLException {
return absolute(recordcount);
}
public void moveToCurrentRow() throws SQLException {
// ignore
}
public void moveToInsertRow() throws SQLException {
// ignore
}
public boolean previous() {
return previous(getPid());
}
public boolean previous(int pid) {
if(0<(arrCurrentRow.set(pid,arrCurrentRow.get(pid,0)-1))) {
return true;
}
arrCurrentRow.set(pid,0);
return false;
}
public void refreshRow() throws SQLException {
// ignore
}
@Override
public boolean relative(int rows) throws SQLException {
return absolute(getRow()+rows);
}
@Override
public boolean rowDeleted() throws SQLException {
return false;
}
@Override
public boolean rowInserted() throws SQLException {
return false;
}
@Override
public boolean rowUpdated() throws SQLException {
return false;
}
public void setFetchDirection(int direction) throws SQLException {
// ignore
}
public void setFetchSize(int rows) throws SQLException {
// ignore
}
@Override
public void updateArray(int columnIndex, java.sql.Array x)throws SQLException {
updateObject(columnIndex, x.getArray());
}
@Override
public void updateArray(String columnName, java.sql.Array x)throws SQLException {
updateObject(columnName, x.getArray());
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x, int length)throws SQLException {
updateBinaryStream(columnIndex, x, length);
}
@Override
public void updateAsciiStream(String columnName, InputStream x, int length)throws SQLException {
updateBinaryStream(columnName, x, length);
}
@Override
public void updateBigDecimal(int columnIndex, BigDecimal x)throws SQLException {
updateObject(columnIndex, x.toString());
}
@Override
public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
updateObject(columnName, x.toString());
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
try {
updateObject(columnIndex, IOUtil.toBytesMax(x, length));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException {
try {
updateObject(columnName, IOUtil.toBytesMax(x, length));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateBlob(int columnIndex, Blob x) throws SQLException {
try {
updateObject(columnIndex, toBytes(x));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateBlob(String columnName, Blob x) throws SQLException {
try {
updateObject(columnName, toBytes(x));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateBoolean(int columnIndex, boolean x) throws SQLException {
updateObject(columnIndex, Caster.toBoolean(x));
}
@Override
public void updateBoolean(String columnName, boolean x) throws SQLException {
updateObject(columnName, Caster.toBoolean(x));
}
@Override
public void updateByte(int columnIndex, byte x) throws SQLException {
updateObject(columnIndex, new Byte(x));
}
@Override
public void updateByte(String columnName, byte x) throws SQLException {
updateObject(columnName, new Byte(x));
}
@Override
public void updateBytes(int columnIndex, byte[] x) throws SQLException {
updateObject(columnIndex, x);
}
@Override
public void updateBytes(String columnName, byte[] x) throws SQLException {
updateObject(columnName, x);
}
@Override
public void updateCharacterStream(int columnIndex, Reader reader, int length)throws SQLException {
try {
updateObject(columnIndex, IOUtil.toString(reader));
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateCharacterStream(String columnName, Reader reader,int length) throws SQLException {
try {
updateObject(columnName, IOUtil.toString(reader));
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateClob(int columnIndex, Clob x) throws SQLException {
try {
updateObject(columnIndex, toString(x));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateClob(String columnName, Clob x) throws SQLException {
try {
updateObject(columnName, toString(x));
} catch (IOException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateDate(int columnIndex, java.sql.Date x)throws SQLException {
updateObject(columnIndex, Caster.toDate(x, false, null, null));
}
@Override
public void updateDate(String columnName, java.sql.Date x)throws SQLException {
updateObject(columnName, Caster.toDate(x, false, null, null));
}
@Override
public void updateDouble(int columnIndex, double x) throws SQLException {
updateObject(columnIndex, Caster.toDouble(x));
}
@Override
public void updateDouble(String columnName, double x) throws SQLException {
updateObject(columnName, Caster.toDouble(x));
}
@Override
public void updateFloat(int columnIndex, float x) throws SQLException {
updateObject(columnIndex, Caster.toDouble(x));
}
@Override
public void updateFloat(String columnName, float x) throws SQLException {
updateObject(columnName, Caster.toDouble(x));
}
@Override
public void updateInt(int columnIndex, int x) throws SQLException {
updateObject(columnIndex, Caster.toDouble(x));
}
@Override
public void updateInt(String columnName, int x) throws SQLException {
updateObject(columnName, Caster.toDouble(x));
}
@Override
public void updateLong(int columnIndex, long x) throws SQLException {
updateObject(columnIndex, Caster.toDouble(x));
}
@Override
public void updateLong(String columnName, long x) throws SQLException {
updateObject(columnName, Caster.toDouble(x));
}
@Override
public void updateNull(int columnIndex) throws SQLException {
updateObject(columnIndex, null);
}
@Override
public void updateNull(String columnName) throws SQLException {
updateObject(columnName, null);
}
@Override
public void updateObject(int columnIndex, Object x) throws SQLException {
try {
set(getColumnName(columnIndex), x);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateObject(String columnName, Object x) throws SQLException {
try {
set(KeyImpl.init(columnName), x);
} catch (PageException e) {
throw new SQLException(e.getMessage());
}
}
@Override
public void updateObject(int columnIndex, Object x, int scale)throws SQLException {
updateObject(columnIndex, x);
}
@Override
public void updateObject(String columnName, Object x, int scale)throws SQLException {
updateObject(columnName, x);
}
@Override
public void updateRef(int columnIndex, Ref x) throws SQLException {
updateObject(columnIndex, x.getObject());
}
@Override
public void updateRef(String columnName, Ref x) throws SQLException {
updateObject(columnName, x.getObject());
}
public void updateRow() throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public void updateShort(int columnIndex, short x) throws SQLException {
updateObject(columnIndex, Caster.toDouble(x));
}
@Override
public void updateShort(String columnName, short x) throws SQLException {
updateObject(columnName, Caster.toDouble(x));
}
@Override
public void updateString(int columnIndex, String x) throws SQLException {
updateObject(columnIndex, x);
}
@Override
public void updateString(String columnName, String x) throws SQLException {
updateObject(columnName, x);
}
@Override
public void updateTime(int columnIndex, Time x) throws SQLException {
updateObject(columnIndex, new DateTimeImpl(x.getTime(),false));
}
@Override
public void updateTime(String columnName, Time x) throws SQLException {
updateObject(columnName, new DateTimeImpl(x.getTime(),false));
}
@Override
public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
updateObject(columnIndex, new DateTimeImpl(x.getTime(),false));
}
@Override
public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
updateObject(columnName, new DateTimeImpl(x.getTime(),false));
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
throw new SQLException("method is not implemented");
}
@Override
public Iterator<Collection.Key> keyIterator() {
return new KeyIterator(keys());
}
@Override
public Iterator<String> keysAsStringIterator() {
return new StringIterator(keys());
}
@Override
public Iterator<Entry<Key, Object>> entryIterator() {
return new EntryIterator(this, keys());
}
public Iterator<Object> valueIterator() {
return new CollectionIterator(keys(),this);
}
public void readExternal(ObjectInput in) throws IOException {
try {
QueryImpl other=(QueryImpl) new CFMLExpressionInterpreter().interpret(ThreadLocalPageContext.get(),in.readUTF());
this.arrCurrentRow=other.arrCurrentRow;
this.columncount=other.columncount;
this.columnNames=other.columnNames;
this.columns=other.columns;
this.exeTime=other.exeTime;
this.generatedKeys=other.generatedKeys;
this.isCached=other.isCached;
this.name=other.name;
this.recordcount=other.recordcount;
this.sql=other.sql;
this.updateCount=other.updateCount;
} catch (PageException e) {
throw new IOException(e.getMessage());
}
}
public void writeExternal(ObjectOutput out) {
try {
out.writeUTF(new ScriptConverter().serialize(this));
}
catch (Throwable t) {}
}
public int getHoldability() throws SQLException {
throw notSupported();
}
public boolean isClosed() throws SQLException {
return false;
}
public void updateNString(int columnIndex, String nString)throws SQLException {
updateString(columnIndex, nString);
}
public void updateNString(String columnLabel, String nString)throws SQLException {
updateString(columnLabel, nString);
}
public String getNString(int columnIndex) throws SQLException {
return getString(columnIndex);
}
public String getNString(String columnLabel) throws SQLException {
return getString(columnLabel);
}
public Reader getNCharacterStream(int columnIndex) throws SQLException {
return getCharacterStream(columnIndex);
}
public Reader getNCharacterStream(String columnLabel) throws SQLException {
return getCharacterStream(columnLabel);
}
public void updateNCharacterStream(int columnIndex, Reader x, long length)throws SQLException {
updateCharacterStream(columnIndex, x, length);
}
public void updateNCharacterStream(String columnLabel, Reader reader,long length) throws SQLException {
throw notSupported();
}
public void updateAsciiStream(int columnIndex, InputStream x, long length)throws SQLException {
throw notSupported();
}
public void updateBinaryStream(int columnIndex, InputStream x, long length)throws SQLException {
throw notSupported();
}
public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
throw notSupported();
}
public void updateAsciiStream(String columnLabel, InputStream x, long length)throws SQLException {
throw notSupported();
}
public void updateBinaryStream(String columnLabel, InputStream x,long length) throws SQLException {
throw notSupported();
}
public void updateCharacterStream(String columnLabel, Reader reader,long length) throws SQLException {
throw notSupported();
}
public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
throw notSupported();
}
public void updateBlob(String columnLabel, InputStream inputStream,long length) throws SQLException {
throw notSupported();
}
public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
throw notSupported();
}
public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
throw notSupported();
}
public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
updateClob(columnIndex, reader, length);
}
public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
updateClob(columnLabel, reader,length);
}
public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
updateCharacterStream(columnIndex, x);
}
public void updateNCharacterStream(String columnLabel, Reader reader)throws SQLException {
throw notSupported();
}
public void updateAsciiStream(int columnIndex, InputStream x)throws SQLException {
throw notSupported();
}
public void updateBinaryStream(int columnIndex, InputStream x)throws SQLException {
throw notSupported();
}
public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
throw notSupported();
}
public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
throw notSupported();
}
public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
throw notSupported();
}
public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
throw notSupported();
}
public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
throw notSupported();
}
public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
throw notSupported();
}
public void updateClob(int columnIndex, Reader reader) throws SQLException {
throw notSupported();
}
public void updateClob(String columnLabel, Reader reader) throws SQLException {
throw notSupported();
}
public void updateNClob(int columnIndex, Reader reader) throws SQLException {
updateClob(columnIndex, reader);
}
public void updateNClob(String columnLabel, Reader reader) throws SQLException {
updateClob(columnLabel, reader);
}
public <T> T unwrap(Class<T> iface) throws SQLException {
throw notSupported();
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
throw notSupported();
}
//JDK6: uncomment this for compiling with JDK6
public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
throw notSupported();
}
public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
throw notSupported();
}
public NClob getNClob(int columnIndex) throws SQLException {
throw notSupported();
}
public NClob getNClob(String columnLabel) throws SQLException {
throw notSupported();
}
public SQLXML getSQLXML(int columnIndex) throws SQLException {
throw notSupported();
}
public SQLXML getSQLXML(String columnLabel) throws SQLException {
throw notSupported();
}
public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
throw notSupported();
}
public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
throw notSupported();
}
public RowId getRowId(int columnIndex) throws SQLException {
throw notSupported();
}
public RowId getRowId(String columnLabel) throws SQLException {
throw notSupported();
}
public void updateRowId(int columnIndex, RowId x) throws SQLException {
throw notSupported();
}
public void updateRowId(String columnLabel, RowId x) throws SQLException {
throw notSupported();
}
public void removeRows(int index, int count) throws PageException {
QueryUtil.removeRows(this,index,count);
}
private SQLException notSupported() {
return new SQLException("this feature is not supported");
}
public synchronized void enableShowQueryUsage() {
if(columns!=null)for(int i=0;i<columns.length;i++){
columns[i]=columns[i]._toDebugColumn();
}
}
@Override
public long getExecutionTime() {
return exeTime;
}
public static QueryImpl cloneQuery(Query qry,boolean deepCopy) {
QueryImpl newResult=new QueryImpl();
ThreadLocalDuplication.set(qry, newResult);
try{
newResult.columnNames=qry.getColumnNames();
newResult.columns=new QueryColumnImpl[newResult.columnNames.length];
QueryColumn col;
for(int i=0;i<newResult.columnNames.length;i++) {
col = qry.getColumn(newResult.columnNames[i],null);
newResult.columns[i]=QueryUtil.duplicate2QueryColumnImpl(newResult,col,deepCopy);
}
newResult.sql=qry.getSql();
newResult.template=qry.getTemplate();
newResult.recordcount=qry.getRecordcount();
newResult.columncount=newResult.columnNames.length;
newResult.isCached=qry.isCached();
newResult.name=qry.getName();
newResult.exeTime=qry.getExecutionTime();
newResult.updateCount=qry.getUpdateCount();
if(qry.getGeneratedKeys()!=null)newResult.generatedKeys=((QueryImpl)qry.getGeneratedKeys()).cloneQuery(false);
return newResult;
}
finally {
// ThreadLocalDuplication.remove(qry); removed "remove" to catch sisters and brothers
}
}
@Override
public java.util.Iterator getIterator() {
return new ForEachQueryIterator(this, ThreadLocalPageContext.get().getId());
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof Collection)) return false;
return CollectionUtil.equals(this,(Collection)obj);
}
/*@Override
public int hashCode() {
return CollectionUtil.hashCode(this);
}*/
}