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