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.query; 020 021import java.io.IOException; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024import java.sql.Types; 025import java.util.Iterator; 026import java.util.Map.Entry; 027 028import lucee.commons.lang.ExceptionUtil; 029import lucee.commons.sql.SQLUtil; 030import lucee.runtime.PageContext; 031import lucee.runtime.db.CFTypes; 032import lucee.runtime.dump.DumpData; 033import lucee.runtime.dump.DumpProperties; 034import lucee.runtime.engine.ThreadLocalPageContext; 035import lucee.runtime.exp.DatabaseException; 036import lucee.runtime.exp.PageException; 037import lucee.runtime.op.Caster; 038import lucee.runtime.query.caster.Cast; 039import lucee.runtime.type.Collection; 040import lucee.runtime.type.KeyImpl; 041import lucee.runtime.type.QueryColumn; 042import lucee.runtime.type.QueryImpl; 043import lucee.runtime.type.dt.DateTime; 044import lucee.runtime.type.it.EntryIterator; 045import lucee.runtime.type.scope.Undefined; 046 047public class SimpleQueryColumn implements QueryColumn { 048 049 private static final long serialVersionUID = 288731277532671308L; 050 051 private SimpleQuery qry; 052 private Key key; 053 private int type; 054 private ResultSet res; 055 private Cast cast; 056 private int index; 057 //private Object[] data; 058 059 public SimpleQueryColumn(SimpleQuery qry, ResultSet res, Collection.Key key, int type, int index) { 060 this.qry=qry; 061 this.res=res; 062 this.key=key; 063 this.index=index; 064 065 try { 066 switch(type){ 067 case Types.TIMESTAMP: 068 cast=Cast.TIMESTAMP; 069 break; 070 case Types.TIME: 071 cast=Cast.TIME; 072 break; 073 case Types.DATE: 074 cast=Cast.DATE; 075 break; 076 case Types.CLOB: 077 cast=Cast.CLOB; 078 break; 079 case Types.BLOB: 080 cast=Cast.BLOB; 081 break; 082 case Types.BIT: 083 cast=Cast.BIT; 084 break; 085 case Types.ARRAY: 086 cast=Cast.ARRAY; 087 break; 088 case Types.BIGINT: 089 cast=Cast.BIGINT; 090 break; 091 092 case CFTypes.OPAQUE: 093 if(SQLUtil.isOracle(res.getStatement().getConnection())) 094 cast=Cast.ORACLE_OPAQUE; 095 else 096 cast=Cast.OTHER; 097 break; 098 default: 099 cast=Cast.OTHER; 100 break; 101 } 102 } 103 catch (Exception e) { 104 throw SimpleQuery.toRuntimeExc(e); 105 } 106 } 107 108 public Object get(Key key, Object defaultValue) { 109 int row=Caster.toIntValue(key,Integer.MIN_VALUE); 110 if(row==Integer.MIN_VALUE) { 111 Object child=getChildElement(key,null); 112 if(child!=null) return child; 113 return defaultValue; 114 } 115 return get(row,defaultValue); 116 } 117 118 public Object get(Key key) throws PageException { 119 int row=Caster.toIntValue(key,Integer.MIN_VALUE); 120 if(row==Integer.MIN_VALUE) { 121 Object child=getChildElement(key,null); 122 if(child!=null) return child; 123 throw new DatabaseException("key ["+key+"] not found",null,null,null); 124 } 125 return get(row); 126 } 127 128 129 private Object getChildElement(Key key, Object defaultValue) { 130 PageContext pc = ThreadLocalPageContext.get(); 131 // column and query has same name 132 if(key.equals(this.key)) { 133 return get(qry.getCurrentrow(pc.getId()),defaultValue); 134 } 135 // get it from undefined scope 136 if(pc!=null){ 137 Undefined undefined = pc.undefinedScope(); 138 boolean old = undefined.setAllowImplicidQueryCall(false); 139 Object sister = undefined.get(this.key,null); 140 undefined.setAllowImplicidQueryCall(old); 141 if(sister!=null){ 142 try { 143 return pc.get(sister, key); 144 } catch (PageException e) { 145 return defaultValue; 146 } 147 } 148 } 149 return defaultValue; 150 } 151 152 public int size() { 153 throw SimpleQuery.notSupported(); 154 } 155 156 157 public Key[] keys() { 158 throw SimpleQuery.notSupported(); 159 } 160 161 162 public Object remove(Key key) throws PageException { 163 throw SimpleQuery.notSupported(); 164 } 165 166 167 public Object removeEL(Key key) { 168 throw SimpleQuery.notSupported(); 169 } 170 171 172 public void clear() { 173 throw SimpleQuery.notSupported(); 174 } 175 176 177 178 public Object get(String key) throws PageException { 179 return get(KeyImpl.init(key)); 180 } 181 182 public Object get(String key, Object defaultValue) { 183 return get(KeyImpl.init(key),defaultValue); 184 } 185 186 public Object set(String key, Object value) throws PageException { 187 throw SimpleQuery.notSupported(); 188 } 189 190 191 public Object set(Key key, Object value) throws PageException { 192 throw SimpleQuery.notSupported(); 193 } 194 195 196 public Object setEL(String key, Object value) { 197 throw SimpleQuery.notSupported(); 198 } 199 200 201 public Object setEL(Key key, Object value) { 202 throw SimpleQuery.notSupported(); 203 } 204 205 206 public Collection duplicate(boolean deepCopy) { 207 throw SimpleQuery.notSupported(); 208 } 209 210 211 public boolean containsKey(String key) { 212 throw SimpleQuery.notSupported(); 213 } 214 215 216 public boolean containsKey(Key key) { 217 throw SimpleQuery.notSupported(); 218 } 219 220 221 @Override 222 public DumpData toDumpData(PageContext pageContext, int maxlevel, 223 DumpProperties properties) { 224 throw SimpleQuery.notSupported(); 225 } 226 227 @Override 228 public Iterator<Collection.Key> keyIterator() { 229 throw SimpleQuery.notSupported(); 230 } 231 232 @Override 233 public Iterator<String> keysAsStringIterator() { 234 throw SimpleQuery.notSupported(); 235 } 236 237 @Override 238 public Iterator<Entry<Key, Object>> entryIterator() { 239 return new EntryIterator(this,keys()); 240 } 241 242 243 public Iterator<Object> valueIterator() { 244 throw SimpleQuery.notSupported(); 245 } 246 247 248 public String castToString() throws PageException { 249 // TODO Auto-generated method stub 250 return Caster.toString(get(key)); 251 } 252 253 254 public String castToString(String defaultValue) { 255 return Caster.toString(get(key,defaultValue),defaultValue); 256 } 257 258 259 public boolean castToBooleanValue() throws PageException { 260 return Caster.toBoolean(get(key)); 261 } 262 263 264 public Boolean castToBoolean(Boolean defaultValue) { 265 return Caster.toBoolean(get(key,defaultValue),defaultValue); 266 } 267 268 269 public double castToDoubleValue() throws PageException { 270 return Caster.toDoubleValue(get(key)); 271 } 272 273 274 public double castToDoubleValue(double defaultValue) { 275 return Caster.toDoubleValue(get(key,defaultValue),true,defaultValue); 276 } 277 278 279 public DateTime castToDateTime() throws PageException { 280 return Caster.toDate(get(key), false, null); 281 } 282 283 284 public DateTime castToDateTime(DateTime defaultValue) { 285 return Caster.toDate(get(key,defaultValue), false, null, defaultValue); 286 } 287 288 289 public int compareTo(String str) throws PageException { 290 throw SimpleQuery.notSupported(); 291 } 292 293 294 public int compareTo(boolean b) throws PageException { 295 throw SimpleQuery.notSupported(); 296 } 297 298 299 public int compareTo(double d) throws PageException { 300 throw SimpleQuery.notSupported(); 301 } 302 303 304 public int compareTo(DateTime dt) throws PageException { 305 throw SimpleQuery.notSupported(); 306 } 307 308 309 public String getKeyAsString() { 310 return key.getString(); 311 } 312 313 314 public Key getKey() { 315 return key; 316 } 317 318 319 public Object get(PageContext pc) throws PageException { 320 return get(key); 321 } 322 323 324 public Object get(PageContext pc, Object defaultValue) { 325 return get(key,defaultValue); 326 } 327 328 329 public Object set(PageContext pc, Object value) throws PageException { 330 throw SimpleQuery.notSupported(); 331 } 332 333 334 public Object setEL(PageContext pc, Object value) { 335 throw SimpleQuery.notSupported(); 336 } 337 338 339 public Object remove(PageContext pc) throws PageException { 340 throw SimpleQuery.notSupported(); 341 } 342 343 344 public Object removeEL(PageContext pc) { 345 throw SimpleQuery.notSupported(); 346 } 347 348 349 public Object touch(PageContext pc) throws PageException { 350 throw SimpleQuery.notSupported(); 351 } 352 353 354 public Object touchEL(PageContext pc) { 355 throw SimpleQuery.notSupported(); 356 } 357 358 359 public Object getParent() { 360 return qry; 361 } 362 363 364 public Object remove(int row) throws PageException { 365 throw SimpleQuery.notSupported(); 366 } 367 368 369 public Object removeRow(int row) throws PageException { 370 throw SimpleQuery.notSupported(); 371 } 372 373 374 public Object removeEL(int row) { 375 throw SimpleQuery.notSupported(); 376 } 377 378 @Override 379 public synchronized Object get(int row) throws PageException { 380 //Object sv = getStoredValue(row); 381 //if(sv!=SimpleQuery.DEFAULT_VALUE) return sv; 382 383 try { 384 if(row!=res.getRow()) { 385 res.absolute(row); 386 } 387 return _get(row); 388 } 389 catch (Throwable t) { 390 throw Caster.toPageException(t); 391 } 392 } 393 394 @Override 395 public synchronized Object get(int row, Object defaultValue) { 396 //Object sv = getStoredValue(row); 397 //if(sv!=SimpleQuery.DEFAULT_VALUE) return sv; 398 399 try { 400 if(row!=res.getRow()) { 401 res.absolute(row); 402 } 403 return _get(row); 404 } 405 catch (Throwable t) { 406 ExceptionUtil.rethrowIfNecessary(t); 407 return defaultValue; 408 } 409 } 410 411 /*private synchronized Object getStoredValue(int row) { 412 if(data==null) return SimpleQuery.DEFAULT_VALUE; 413 return data[row-1]; 414 } 415 416 private synchronized Object _get(int row) throws SQLException, IOException { 417 if(data==null) { 418 data=new Object[qry.getRecordcount()]; 419 for(int i=0;i<data.length;i++){ 420 data[i]=SimpleQuery.DEFAULT_VALUE; 421 } 422 423 } 424 return data[row-1]=cast.toCFType(null, type, res, index); 425 }*/ 426 427 private Object _get(int row) throws SQLException, IOException { 428 return cast.toCFType(null, type, res, index); 429 } 430 431 432 public Object set(int row, Object value) throws PageException { 433 throw SimpleQuery.notSupported(); 434 } 435 436 437 public void add(Object value) { 438 throw SimpleQuery.notSupported(); 439 } 440 441 442 public Object setEL(int row, Object value) { 443 throw SimpleQuery.notSupported(); 444 } 445 446 447 public void addRow(int count) { 448 throw SimpleQuery.notSupported(); 449 } 450 451 452 public int getType() { 453 return type; 454 } 455 456 457 public String getTypeAsString() { 458 return QueryImpl.getColumTypeName(type); 459 } 460 461 462 public void cutRowsTo(int maxrows) { 463 throw SimpleQuery.notSupported(); 464 465 } 466 467 public Object clone() { 468 throw SimpleQuery.notSupported(); 469 } 470 471 472 public int getIndex() { 473 return index; 474 } 475 476 @Override 477 public java.util.Iterator<String> getIterator() { 478 return keysAsStringIterator(); 479 } 480}