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    }