001 package railo.runtime.tag; 002 003 import java.sql.DatabaseMetaData; 004 import java.sql.ResultSet; 005 import java.sql.SQLException; 006 import java.util.HashMap; 007 import java.util.HashSet; 008 import java.util.Map; 009 import java.util.Set; 010 import java.util.regex.Pattern; 011 012 import railo.commons.lang.StringUtil; 013 import railo.commons.sql.SQLUtil; 014 import railo.runtime.PageContext; 015 import railo.runtime.config.Constants; 016 import railo.runtime.db.DataSource; 017 import railo.runtime.db.DataSourceManager; 018 import railo.runtime.db.DatasourceConnection; 019 import railo.runtime.exp.ApplicationException; 020 import railo.runtime.exp.DatabaseException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.ext.tag.TagImpl; 023 import railo.runtime.listener.ApplicationContextPro; 024 import railo.runtime.op.Caster; 025 import railo.runtime.timer.Stopwatch; 026 import railo.runtime.type.Array; 027 import railo.runtime.type.ArrayImpl; 028 import railo.runtime.type.Collection; 029 import railo.runtime.type.Collection.Key; 030 import railo.runtime.type.KeyImpl; 031 import railo.runtime.type.Query; 032 import railo.runtime.type.QueryColumn; 033 import railo.runtime.type.QueryImpl; 034 import railo.runtime.type.SVArray; 035 import railo.runtime.type.Struct; 036 import railo.runtime.type.StructImpl; 037 import railo.runtime.type.util.KeyConstants; 038 039 /** 040 * Handles all interactions with files. The attributes you use with cffile depend on the value of the action attribute. 041 * For example, if the action = "write", use the attributes associated with writing a text file. 042 * 043 * 044 * 045 **/ 046 public final class DBInfo extends TagImpl { 047 048 private static final Key TABLE_NAME = KeyImpl.intern("TABLE_NAME"); 049 private static final Key COLUMN_NAME = KeyImpl.intern("COLUMN_NAME"); 050 private static final Key IS_PRIMARYKEY = KeyImpl.intern("IS_PRIMARYKEY"); 051 private static final Key IS_FOREIGNKEY = KeyImpl.intern("IS_FOREIGNKEY"); 052 private static final Key COLUMN_DEF = KeyImpl.intern("COLUMN_DEF"); 053 private static final Key COLUMN_DEFAULT_VALUE = KeyImpl.intern("COLUMN_DEFAULT_VALUE"); 054 private static final Key COLUMN_DEFAULT = KeyImpl.intern("COLUMN_DEFAULT"); 055 private static final Key REFERENCED_PRIMARYKEY = KeyImpl.intern("REFERENCED_PRIMARYKEY"); 056 private static final Key REFERENCED_PRIMARYKEY_TABLE = KeyImpl.intern("REFERENCED_PRIMARYKEY_TABLE"); 057 private static final Key USER = KeyImpl.intern("USER"); 058 private static final Key TABLE_SCHEM = KeyImpl.intern("TABLE_SCHEM"); 059 private static final Key DECIMAL_DIGITS = KeyImpl.intern("DECIMAL_DIGITS"); 060 061 private static final Key DATABASE_NAME = KeyImpl.intern("database_name"); 062 private static final Key TABLE_CAT = KeyImpl.intern("TABLE_CAT"); 063 private static final Key PROCEDURE = KeyImpl.intern("procedure"); 064 private static final Key CATALOG = KeyImpl.intern("catalog"); 065 private static final Key SCHEMA = KeyImpl.intern("schema"); 066 private static final Key DATABASE_PRODUCTNAME = KeyImpl.intern("DATABASE_PRODUCTNAME"); 067 private static final Key DATABASE_VERSION = KeyImpl.intern("DATABASE_VERSION"); 068 private static final Key DRIVER_NAME = KeyImpl.intern("DRIVER_NAME"); 069 private static final Key DRIVER_VERSION = KeyImpl.intern("DRIVER_VERSION"); 070 private static final Key JDBC_MAJOR_VERSION = KeyImpl.intern("JDBC_MAJOR_VERSION"); 071 private static final Key JDBC_MINOR_VERSION = KeyImpl.intern("JDBC_MINOR_VERSION"); 072 073 private static final int TYPE_NONE=0; 074 private static final int TYPE_DBNAMES=1; 075 private static final int TYPE_TABLES=2; 076 private static final int TYPE_TABLE_COLUMNS = 3; 077 private static final int TYPE_VERSION = 4; 078 private static final int TYPE_PROCEDURES = 5; 079 private static final int TYPE_PROCEDURE_COLUMNS = 6; 080 private static final int TYPE_FOREIGNKEYS = 7; 081 private static final int TYPE_INDEX = 8; 082 private static final int TYPE_USERS = 9; 083 private static final int TYPE_TERMS = 10; 084 private static final Collection.Key CARDINALITY = KeyImpl.init("CARDINALITY"); 085 086 087 //private static final String[] ALL_TABLE_TYPES = {"TABLE", "VIEW", "SYSTEM TABLE", "SYNONYM"}; 088 089 private String datasource; 090 private String name; 091 private int type; 092 093 094 private String dbname; 095 private String password; 096 private String pattern; 097 private String table; 098 private String procedure; 099 private String username; 100 private String strType; 101 102 103 @Override 104 public void release() { 105 super.release(); 106 datasource=null; 107 name=null; 108 type=TYPE_NONE; 109 dbname=null; 110 password=null; 111 pattern=null; 112 table=null; 113 procedure=null; 114 username=null; 115 116 117 118 } 119 120 /** 121 * @param procedure the procedure to set 122 */ 123 public void setProcedure(String procedure) { 124 this.procedure = procedure; 125 } 126 127 /** 128 * @param datasource the datasource to set 129 */ 130 public void setDatasource(String datasource) { 131 this.datasource = datasource; 132 } 133 134 /** 135 * @param name the name to set 136 */ 137 public void setName(String name) { 138 this.name = name; 139 } 140 141 /** 142 * @param type the type to set 143 * @throws ApplicationException 144 */ 145 public void setType(String strType) throws ApplicationException { 146 this.strType=strType; 147 strType=strType.toLowerCase().trim(); 148 149 if("dbnames".equals(strType)) this.type=TYPE_DBNAMES; 150 else if("dbname".equals(strType)) this.type=TYPE_DBNAMES; 151 else if("tables".equals(strType)) this.type=TYPE_TABLES; 152 else if("table".equals(strType)) this.type=TYPE_TABLES; 153 else if("columns".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 154 else if("column".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 155 else if("version".equals(strType)) this.type=TYPE_VERSION; 156 else if("procedures".equals(strType)) this.type=TYPE_PROCEDURES; 157 else if("procedure".equals(strType)) this.type=TYPE_PROCEDURES; 158 159 160 else if("table_columns".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 161 else if("table_column".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 162 else if("column_table".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 163 else if("column_tables".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 164 165 else if("tablecolumns".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 166 else if("tablecolumn".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 167 else if("columntable".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 168 else if("columntables".equals(strType)) this.type=TYPE_TABLE_COLUMNS; 169 170 else if("procedure_columns".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 171 else if("procedure_column".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 172 else if("column_procedure".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 173 else if("column_procedures".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 174 175 else if("procedurecolumns".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 176 else if("procedurecolumn".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 177 else if("columnprocedure".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 178 else if("columnprocedures".equals(strType)) this.type=TYPE_PROCEDURE_COLUMNS; 179 180 else if("foreignkeys".equals(strType)) this.type=TYPE_FOREIGNKEYS; 181 else if("foreignkey".equals(strType)) this.type=TYPE_FOREIGNKEYS; 182 else if("index".equals(strType)) this.type=TYPE_INDEX; 183 else if("users".equals(strType)) this.type=TYPE_USERS; 184 else if("user".equals(strType)) this.type=TYPE_USERS; 185 186 else if("term".equals(strType)) this.type=TYPE_TERMS; 187 else if("terms".equals(strType)) this.type=TYPE_TERMS; 188 189 else throw new ApplicationException("invalid value for attribute type ["+strType+"]", 190 "valid values are [dbname,tables,columns,version,procedures,foreignkeys,index,users]"); 191 192 } 193 194 /** 195 * @param dbname the dbname to set 196 */ 197 public void setDbname(String dbname) { 198 this.dbname = dbname; 199 } 200 public void setDbnames(String dbname) { 201 this.dbname = dbname; 202 } 203 204 /** 205 * @param password the password to set 206 */ 207 public void setPassword(String password) { 208 this.password = password; 209 } 210 211 /** 212 * @param pattern the pattern to set 213 */ 214 public void setPattern(String pattern) { 215 this.pattern = pattern; 216 } 217 218 /** 219 * @param table the table to set 220 */ 221 public void setTable(String table) { 222 this.table = table; 223 } 224 225 /** 226 * @param username the username to set 227 */ 228 public void setUsername(String username) { 229 this.username = username; 230 } 231 232 233 @Override 234 public int doStartTag() throws PageException { 235 Object ds=getDatasource(pageContext, datasource); 236 DataSourceManager manager = pageContext.getDataSourceManager(); 237 DatasourceConnection dc=ds instanceof DataSource? 238 manager.getConnection(pageContext,(DataSource)ds,username,password): 239 manager.getConnection(pageContext,Caster.toString(ds),username,password); 240 try { 241 242 if(type==TYPE_TABLE_COLUMNS) typeColumns(dc.getConnection().getMetaData()); 243 else if(type==TYPE_DBNAMES) typeDBNames(dc.getConnection().getMetaData()); 244 else if(type==TYPE_FOREIGNKEYS) typeForeignKeys(dc.getConnection().getMetaData()); 245 else if(type==TYPE_INDEX) typeIndex(dc.getConnection().getMetaData()); 246 else if(type==TYPE_PROCEDURES) typeProcedures(dc.getConnection().getMetaData()); 247 else if(type==TYPE_PROCEDURE_COLUMNS)typeProcedureColumns(dc.getConnection().getMetaData()); 248 else if(type==TYPE_TERMS) typeTerms(dc.getConnection().getMetaData()); 249 else if(type==TYPE_TABLES) typeTables(dc.getConnection().getMetaData()); 250 else if(type==TYPE_VERSION) typeVersion(dc.getConnection().getMetaData()); 251 else if(type==TYPE_USERS) typeUsers(dc.getConnection().getMetaData()); 252 253 } 254 catch(SQLException sqle) { 255 throw new DatabaseException(sqle,dc); 256 } 257 finally { 258 manager.releaseConnection(pageContext,dc); 259 } 260 261 262 263 264 return SKIP_BODY; 265 } 266 267 268 269 private void typeColumns(DatabaseMetaData metaData) throws PageException, SQLException { 270 required("table",table); 271 272 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 273 stopwatch.start(); 274 275 table=setCase(metaData, table); 276 pattern=setCase(metaData, pattern); 277 if(StringUtil.isEmpty(pattern,true)) pattern=null; 278 String schema=null; 279 int index=table.indexOf('.'); 280 if(index>0) { 281 schema=table.substring(0,index); 282 table=table.substring(index+1); 283 } 284 checkTable(metaData); 285 286 ResultSet columns = metaData.getColumns(dbname, schema, table, pattern); 287 Query qry = new QueryImpl(columns,"query",pageContext.getTimeZone()); 288 289 int len=qry.getRecordcount(); 290 291 if(qry.getColumn(COLUMN_DEF,null) != null) 292 qry.rename(COLUMN_DEF,COLUMN_DEFAULT_VALUE); 293 else if(qry.getColumn(COLUMN_DEFAULT,null) != null) 294 qry.rename(COLUMN_DEFAULT,COLUMN_DEFAULT_VALUE); 295 296 // make sure decimal digits exists 297 QueryColumn col = qry.getColumn(DECIMAL_DIGITS,null); 298 if(col==null){ 299 Array arr=new ArrayImpl(); 300 for(int i=1;i<=len;i++) { 301 arr.append(railo.runtime.op.Constants.DOUBLE_ZERO); 302 } 303 qry.addColumn(DECIMAL_DIGITS, arr); 304 } 305 306 307 // add is primary 308 Map primaries = new HashMap(); 309 String tblName; 310 Array isPrimary=new ArrayImpl(); 311 Set set; 312 Object o; 313 for(int i=1;i<=len;i++) { 314 315 // decimal digits 316 o=qry.getAt(DECIMAL_DIGITS, i,null); 317 if(o==null)qry.setAtEL(DECIMAL_DIGITS, i,railo.runtime.op.Constants.DOUBLE_ZERO); 318 319 set=(Set) primaries.get(tblName=(String) qry.getAt(TABLE_NAME, i)); 320 if(set==null) { 321 set=toSet(metaData.getPrimaryKeys(dbname, null, tblName),"COLUMN_NAME"); 322 primaries.put(tblName,set); 323 } 324 isPrimary.append(set.contains(qry.getAt(COLUMN_NAME, i))?"YES":"NO"); 325 } 326 qry.addColumn(IS_PRIMARYKEY, isPrimary); 327 328 // add is foreignkey 329 Map foreigns = new HashMap(); 330 Array isForeign=new ArrayImpl(); 331 Array refPrim=new ArrayImpl(); 332 Array refPrimTbl=new ArrayImpl(); 333 //Map map,inner; 334 Map<String, Map<String, SVArray>> map; 335 Map<String, SVArray> inner; 336 for(int i=1;i<=len;i++) { 337 map=(Map) foreigns.get(tblName=(String) qry.getAt(TABLE_NAME, i)); 338 if(map==null) { 339 map=toMap(metaData.getImportedKeys(dbname, schema, table),"FKCOLUMN_NAME",new String[]{"PKCOLUMN_NAME","PKTABLE_NAME"}); 340 foreigns.put(tblName, map); 341 } 342 inner = map.get(qry.getAt(COLUMN_NAME, i)); 343 if(inner!=null) { 344 isForeign.append("YES"); 345 refPrim.append(inner.get("PKCOLUMN_NAME")); 346 refPrimTbl.append(inner.get("PKTABLE_NAME")); 347 } 348 else { 349 isForeign.append("NO"); 350 refPrim.append("N/A"); 351 refPrimTbl.append("N/A"); 352 } 353 } 354 qry.addColumn(IS_FOREIGNKEY, isForeign); 355 qry.addColumn(REFERENCED_PRIMARYKEY, refPrim); 356 qry.addColumn(REFERENCED_PRIMARYKEY_TABLE, refPrimTbl); 357 358 359 qry.setExecutionTime(stopwatch.time()); 360 361 362 pageContext.setVariable(name, qry); 363 } 364 365 private Map<String,Map<String, SVArray>> toMap(ResultSet result,String columnName,String[] additional) throws SQLException { 366 Map<String,Map<String, SVArray>> map=new HashMap<String,Map<String, SVArray>>(); 367 Map<String, SVArray> inner; 368 String col; 369 SVArray item; 370 while(result.next()){ 371 col=result.getString(columnName); 372 inner=map.get(col); 373 if(inner!=null) { 374 for(int i=0;i<additional.length;i++) { 375 item=inner.get(additional[i]); 376 item.add(result.getString(additional[i])); 377 item.setPosition(item.size()); 378 } 379 } 380 else { 381 inner=new HashMap<String, SVArray>(); 382 map.put(col, inner); 383 for(int i=0;i<additional.length;i++) { 384 item=new SVArray(); 385 item.add(result.getString(additional[i])); 386 inner.put(additional[i], item); 387 } 388 } 389 } 390 return map; 391 } 392 393 private Set<String> toSet(ResultSet result,String columnName) throws SQLException { 394 Set<String> set = new HashSet<String>(); 395 while(result.next()){ 396 set.add(result.getString(columnName)); 397 } 398 return set; 399 } 400 401 private void typeDBNames(DatabaseMetaData metaData) throws PageException, SQLException { 402 403 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 404 stopwatch.start(); 405 406 railo.runtime.type.Query catalogs = new QueryImpl(metaData.getCatalogs(),"query",pageContext.getTimeZone()); 407 railo.runtime.type.Query scheme = new QueryImpl(metaData.getSchemas(),"query",pageContext.getTimeZone()); 408 409 Pattern p=null; 410 if(pattern!=null && !"%".equals(pattern)) 411 p=SQLUtil.pattern(pattern, true); 412 413 414 415 String[] columns=new String[]{"database_name","type"}; 416 String[] types=new String[]{"VARCHAR","VARCHAR"}; 417 railo.runtime.type.Query qry=new QueryImpl(columns,types,0,"query"); 418 int row=1,len=catalogs.getRecordcount(); 419 String value; 420 // catalog 421 for(int i=1;i<=len;i++) { 422 value=(String) catalogs.getAt(TABLE_CAT, i); 423 if(!matchPattern(value,p)) continue; 424 qry.addRow(); 425 qry.setAt(DATABASE_NAME, row, value); 426 qry.setAt(KeyConstants._type, row, "CATALOG"); 427 row++; 428 } 429 // scheme 430 len=scheme.getRecordcount(); 431 for(int i=1;i<=len;i++) { 432 value=(String) scheme.getAt(TABLE_SCHEM, i); 433 if(!matchPattern(value,p)) continue; 434 qry.addRow(); 435 qry.setAt(DATABASE_NAME, row, value); 436 qry.setAt(KeyConstants._type, row, "SCHEMA"); 437 row++; 438 } 439 440 qry.setExecutionTime(stopwatch.time()); 441 442 443 pageContext.setVariable(name, qry); 444 } 445 446 private void typeForeignKeys(DatabaseMetaData metaData) throws PageException, SQLException { 447 required("table",table); 448 449 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 450 stopwatch.start(); 451 table=setCase(metaData, table); 452 int index=table.indexOf('.'); 453 String schema=null; 454 if(index>0) { 455 schema=table.substring(0,index); 456 table=table.substring(index+1); 457 } 458 459 checkTable(metaData); 460 461 ResultSet columns = metaData.getExportedKeys(dbname, schema, table); 462 railo.runtime.type.Query qry = new QueryImpl(columns,"query",pageContext.getTimeZone()); 463 464 qry.setExecutionTime(stopwatch.time()); 465 466 pageContext.setVariable(name, qry); 467 } 468 469 private void checkTable(DatabaseMetaData metaData) throws SQLException, ApplicationException { 470 ResultSet tables =null; 471 472 try { 473 tables = metaData.getTables(null, null, setCase(metaData,table), null); 474 if(!tables.next()) throw new ApplicationException("there is no table that match the following pattern ["+table+"]"); 475 } 476 finally { 477 if(tables!=null) tables.close(); 478 } 479 } 480 481 private String setCase(DatabaseMetaData metaData, String id) throws SQLException { 482 if(id==null) return null; 483 484 if(metaData.storesLowerCaseIdentifiers()) return id.toLowerCase(); 485 if(metaData.storesUpperCaseIdentifiers()) return id.toUpperCase(); 486 return id; 487 } 488 489 private void typeIndex(DatabaseMetaData metaData) throws PageException, SQLException { 490 required("table",table); 491 492 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 493 stopwatch.start(); 494 495 table=setCase(metaData, table); 496 int index=table.indexOf('.'); 497 String schema=null; 498 if(index>0) { 499 schema=table.substring(0,index); 500 table=table.substring(index+1); 501 } 502 503 checkTable(metaData); 504 505 ResultSet tables = metaData.getIndexInfo(dbname, schema, table, false, true); 506 railo.runtime.type.Query qry = new QueryImpl(tables,"query",pageContext.getTimeZone()); 507 508 // type int 2 string 509 int rows = qry.getRecordcount(); 510 String strType; 511 int type,card; 512 for(int row=1;row<=rows;row++){ 513 514 // type 515 switch(type=Caster.toIntValue(qry.getAt(KeyConstants._type,row))){ 516 case 0: 517 strType="Table Statistic"; 518 break; 519 case 1: 520 strType="Clustered Index"; 521 break; 522 case 2: 523 strType="Hashed Index"; 524 break; 525 case 3: 526 strType="Other Index"; 527 break; 528 default: 529 strType=Caster.toString(type); 530 } 531 qry.setAt(KeyConstants._type, row, strType); 532 533 // CARDINALITY 534 card=Caster.toIntValue(qry.getAt(CARDINALITY,row),0); 535 qry.setAt(CARDINALITY, row, Caster.toDouble(card)); 536 537 } 538 qry.setExecutionTime(stopwatch.time()); 539 540 541 pageContext.setVariable(name, qry); 542 } 543 544 private void typeProcedures(DatabaseMetaData metaData) throws SQLException, PageException { 545 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 546 stopwatch.start(); 547 548 String schema=null; 549 pattern=setCase(metaData, pattern); 550 if(StringUtil.isEmpty(pattern,true)) { 551 pattern=null; 552 } 553 554 ResultSet tables = metaData.getProcedures(dbname, schema, pattern); 555 railo.runtime.type.Query qry = new QueryImpl(tables,"query",pageContext.getTimeZone()); 556 qry.setExecutionTime(stopwatch.time()); 557 558 559 pageContext.setVariable(name, qry); 560 } 561 562 private void typeProcedureColumns(DatabaseMetaData metaData) throws SQLException, PageException { 563 required("procedure",procedure); 564 565 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 566 stopwatch.start(); 567 568 procedure=setCase(metaData, procedure); 569 pattern=setCase(metaData, pattern); 570 if(StringUtil.isEmpty(pattern,true)) pattern=null; 571 String schema=null; 572 int index=procedure.indexOf('.'); 573 if(index>0) { 574 schema=procedure.substring(0,index); 575 procedure=procedure.substring(index+1); 576 } 577 578 579 ResultSet tables = metaData.getProcedureColumns(dbname, schema, procedure, pattern); 580 581 railo.runtime.type.Query qry = new QueryImpl(tables,"query",pageContext.getTimeZone()); 582 qry.setExecutionTime(stopwatch.time()); 583 584 585 pageContext.setVariable(name, qry); 586 } 587 588 private void typeTerms(DatabaseMetaData metaData) throws SQLException, PageException { 589 Struct sct=new StructImpl(); 590 sct.setEL(PROCEDURE, metaData.getProcedureTerm()); 591 sct.setEL(CATALOG, metaData.getCatalogTerm()); 592 sct.setEL(SCHEMA, metaData.getSchemaTerm()); 593 594 pageContext.setVariable(name, sct); 595 } 596 597 private void typeTables(DatabaseMetaData metaData) throws PageException, SQLException { 598 599 600 601 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 602 stopwatch.start(); 603 604 pattern=setCase(metaData, pattern); 605 606 ResultSet tables = metaData.getTables(dbname, null, pattern, null); 607 railo.runtime.type.Query qry = new QueryImpl(tables,"query",pageContext.getTimeZone()); 608 609 qry.setExecutionTime(stopwatch.time()); 610 611 612 pageContext.setVariable(name, qry); 613 } 614 615 private void typeVersion(DatabaseMetaData metaData) throws PageException, SQLException { 616 617 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 618 stopwatch.start(); 619 620 Key[] columns=new Key[]{DATABASE_PRODUCTNAME,DATABASE_VERSION,DRIVER_NAME,DRIVER_VERSION,JDBC_MAJOR_VERSION,JDBC_MINOR_VERSION}; 621 String[] types=new String[]{"VARCHAR","VARCHAR","VARCHAR","VARCHAR","DOUBLE","DOUBLE"}; 622 623 railo.runtime.type.Query qry=new QueryImpl(columns,types,1,"query"); 624 625 qry.setAt(DATABASE_PRODUCTNAME,1,metaData.getDatabaseProductName()); 626 qry.setAt(DATABASE_VERSION,1,metaData.getDatabaseProductVersion()); 627 qry.setAt(DRIVER_NAME,1,metaData.getDriverName()); 628 qry.setAt(DRIVER_VERSION,1,metaData.getDriverVersion()); 629 qry.setAt(JDBC_MAJOR_VERSION,1,new Double(metaData.getJDBCMajorVersion())); 630 qry.setAt(JDBC_MINOR_VERSION,1,new Double(metaData.getJDBCMinorVersion())); 631 632 633 qry.setExecutionTime(stopwatch.time()); 634 635 636 pageContext.setVariable(name, qry); 637 } 638 639 private void typeUsers(DatabaseMetaData metaData) throws PageException, SQLException { 640 641 Stopwatch stopwatch=new Stopwatch(Stopwatch.UNIT_NANO); 642 stopwatch.start(); 643 644 checkTable(metaData); 645 ResultSet result = metaData.getSchemas(); 646 Query qry = new QueryImpl(result,"query",pageContext.getTimeZone()); 647 648 649 qry.rename(TABLE_SCHEM,USER); 650 651 qry.setExecutionTime(stopwatch.time()); 652 653 654 pageContext.setVariable(name, qry); 655 } 656 657 private void required(String name, String value) throws ApplicationException { 658 if(value==null) 659 throw new ApplicationException("Missing attribute ["+name+"]. The type ["+strType+"] requires the attribute [" + name + "]."); 660 } 661 662 private static boolean matchPattern(String value, Pattern pattern) { 663 if(pattern==null) return true; 664 return SQLUtil.match(pattern, value); 665 } 666 667 @Override 668 public int doEndTag() { 669 return EVAL_PAGE; 670 } 671 672 673 public static Object getDatasource(PageContext pageContext, String datasource) throws ApplicationException { 674 if(StringUtil.isEmpty(datasource)){ 675 Object ds=((ApplicationContextPro)pageContext.getApplicationContext()).getDefDataSource(); 676 677 if(StringUtil.isEmpty(ds)) 678 throw new ApplicationException( 679 "attribute [datasource] is required, when no default datasource is defined", 680 "you can define a default datasource as attribute [defaultdatasource] of the tag "+Constants.CFAPP_NAME+" or as data member of the "+Constants.APP_CFC+" (this.defaultdatasource=\"mydatasource\";)"); 681 return ds; 682 } 683 return datasource; 684 } 685 }