0001: package net.sourceforge.squirrel_sql.fw.sql;
0002:
0003: /*
0004: * Copyright (C) 2002-2003 Colin Bell
0005: * colbell@users.sourceforge.net
0006: *
0007: * This library is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU Lesser General Public
0009: * License as published by the Free Software Foundation; either
0010: * version 2.1 of the License, or (at your option) any later version.
0011: *
0012: * This library is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this library; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0020: */
0021: import java.sql.DatabaseMetaData;
0022: import java.sql.ResultSet;
0023: import java.sql.SQLException;
0024: import java.sql.Statement;
0025: import java.util.ArrayList;
0026: import java.util.Collections;
0027: import java.util.HashMap;
0028: import java.util.Iterator;
0029: import java.util.List;
0030: import java.util.Map;
0031: import java.util.Set;
0032: import java.util.StringTokenizer;
0033: import java.util.TreeMap;
0034: import java.util.TreeSet;
0035:
0036: import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException;
0037: import net.sourceforge.squirrel_sql.fw.datasetviewer.DatabaseTypesDataSet;
0038: import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSet;
0039: import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet;
0040: import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory;
0041: import net.sourceforge.squirrel_sql.fw.sql.dbobj.BestRowIdentifier;
0042: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
0043: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
0044:
0045: /**
0046: * This class represents the metadata for a database. It is essentially
0047: * a wrapper around <TT>java.sql.DatabaseMetaData</TT>.
0048: *
0049: * <P>Some data can be cached on the first retrieval in order to speed up
0050: * subsequent retrievals. To clear this cache call <TT>clearCache()</TT>.
0051: *
0052: * <P>From the JavaDoc for <TT>java.sql.DatabaseMetaData</TT>. "Some
0053: * methods take arguments that are String patterns. These arguments all
0054: * have names such as fooPattern. Within a pattern String, "%" means match any
0055: * substring of 0 or more characters, and "_" means match any one character. Only
0056: * metadata entries matching the search pattern are returned. If a search pattern
0057: * argument is set to null, that argument's criterion will be dropped from the
0058: * search."
0059: *
0060: * <P>Additionally, it should be noted that some JDBC drivers (like Oracle) do
0061: * not handle multi-threaded access to methods that return ResultSets very well.
0062: * It is therefore highly recommended that methods in this class that return
0063: * a ResultSet, should not be called outside of this class where this class'
0064: * monitor has no jurisdiction. Furthermore, methods that are meant to be
0065: * called externally that create a ResultSet should package the data in some
0066: * container object structure for use by the caller, and should always be
0067: * synchronized on this class' monitor.
0068: *
0069: *
0070: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
0071: */
0072: public class SQLDatabaseMetaData implements ISQLDatabaseMetaData {
0073:
0074: /** Logger for this class. */
0075: private final static ILogger s_log = LoggerController
0076: .createLogger(SQLDatabaseMetaData.class);
0077:
0078: /**
0079: * Full or partial names of various JDBC driivers that can be matched
0080: * to <tt>getDriverName()</tt>.
0081: */
0082: private interface IDriverNames {
0083: String AS400 = "AS/400 Toolbox for Java JDBC Driver";
0084: /* work-around for bug which means we must use "dbo" for schema */
0085: String FREE_TDS = "InternetCDS Type 4 JDBC driver for MS SQLServer";
0086: String OPTA2000 = "i-net OPTA 2000";
0087: }
0088:
0089: public static class DriverMatch {
0090: private static final String COM_HTTX_DRIVER_PREFIX = "com.hxtt.sql.";
0091:
0092: public static boolean isComHttxDriver(ISQLConnection con) {
0093: if (null == con) {
0094: return false;
0095: }
0096: return con.getSQLDriver().getDriverClassName().startsWith(
0097: COM_HTTX_DRIVER_PREFIX);
0098: }
0099: }
0100:
0101: /** Connection to database this class is supplying information for. */
0102: private ISQLConnection _conn;
0103:
0104: /**
0105: * Cache of commonly accessed metadata properties keyed by the method
0106: * name that attempts to retrieve them.
0107: * Note, this cache should only be used for metadata that are not
0108: * likely to be changed during an open Session.
0109: * Meta data that is likely to be changed should be kept in SchemaInfo.
0110: */
0111: private Map<String, Object> _cache = Collections
0112: .synchronizedMap(new HashMap<String, Object>());
0113:
0114: /**
0115: * If previous attempts to getSuperTables fail, then this will be set to
0116: * false, and prevent further attempts.
0117: */
0118: private boolean supportsSuperTables = true;
0119:
0120: /**
0121: * ctor specifying the connection that we are retrieving metadata for.
0122: *
0123: * @param conn Connection to database.
0124: *
0125: * @throws IllegalArgumentException
0126: * Thrown if null SQLConnection passed.
0127: */
0128: SQLDatabaseMetaData(ISQLConnection conn) {
0129: super ();
0130: if (conn == null) {
0131: throw new IllegalArgumentException(
0132: "SQLDatabaseMetaData == null");
0133: }
0134: _conn = conn;
0135: }
0136:
0137: /* (non-Javadoc)
0138: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getUserName()
0139: */
0140: public synchronized String getUserName() throws SQLException {
0141: final String key = "getUserName";
0142: String value = (String) _cache.get(key);
0143: if (value == null) {
0144: value = privateGetJDBCMetaData().getUserName();
0145: _cache.put(key, value);
0146: }
0147: return value;
0148: }
0149:
0150: /* (non-Javadoc)
0151: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getDatabaseProductName()
0152: */
0153: public synchronized String getDatabaseProductName()
0154: throws SQLException {
0155: final String key = "getDatabaseProductName";
0156: String value = (String) _cache.get(key);
0157: if (value == null) {
0158: value = privateGetJDBCMetaData().getDatabaseProductName();
0159: _cache.put(key, value);
0160: }
0161: return value;
0162: }
0163:
0164: /* (non-Javadoc)
0165: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getDatabaseProductVersion()
0166: */
0167: public synchronized String getDatabaseProductVersion()
0168: throws SQLException {
0169: final String key = "getDatabaseProductVersion";
0170: String value = (String) _cache.get(key);
0171: if (value == null) {
0172: value = privateGetJDBCMetaData()
0173: .getDatabaseProductVersion();
0174: _cache.put(key, value);
0175: }
0176: return value;
0177: }
0178:
0179: public synchronized int getDatabaseMajorVersion()
0180: throws SQLException {
0181: final String key = "getDatabaseMajorVersion";
0182: Integer value = (Integer) _cache.get(key);
0183: if (value == null) {
0184: value = privateGetJDBCMetaData().getDatabaseMajorVersion();
0185: _cache.put(key, value);
0186: }
0187: return value;
0188: }
0189:
0190: /* (non-Javadoc)
0191: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getDriverName()
0192: */
0193: public synchronized String getDriverName() throws SQLException {
0194: final String key = "getDriverName";
0195: String value = (String) _cache.get(key);
0196: if (value == null) {
0197: value = privateGetJDBCMetaData().getDriverName();
0198: _cache.put(key, value);
0199: }
0200: return value;
0201: }
0202:
0203: /* (non-Javadoc)
0204: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getJDBCVersion()
0205: */
0206: public int getJDBCVersion() throws SQLException {
0207: final String key = "getJDBCVersion";
0208: Integer value = (Integer) _cache.get(key);
0209: if (value == null) {
0210: DatabaseMetaData md = privateGetJDBCMetaData();
0211: int major = md.getJDBCMajorVersion();
0212: int minor = md.getJDBCMinorVersion();
0213: int vers = (major * 100) + minor;
0214: value = Integer.valueOf(vers);
0215: _cache.put(key, value);
0216: }
0217: return value.intValue();
0218: }
0219:
0220: /* (non-Javadoc)
0221: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getIdentifierQuoteString()
0222: */
0223: public synchronized String getIdentifierQuoteString()
0224: throws SQLException {
0225: final String key = "getIdentifierQuoteString";
0226: String value = (String) _cache.get(key);
0227: if (value == null) {
0228: value = privateGetJDBCMetaData().getIdentifierQuoteString();
0229: if (value == null) {
0230: value = "";
0231: }
0232: _cache.put(key, value);
0233: }
0234: return value;
0235: }
0236:
0237: /* (non-Javadoc)
0238: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getCascadeClause()
0239: */
0240: public synchronized String getCascadeClause() throws SQLException {
0241: final String key = "getCascadeClause";
0242: String value = (String) _cache.get(key);
0243: if (value == null) {
0244: if (DialectFactory.isDB2(this )
0245: || DialectFactory.isOracle(this )) {
0246: value = "CASCADE";
0247: } else {
0248: value = "";
0249: }
0250: _cache.put(key, value);
0251: }
0252: return value;
0253: }
0254:
0255: /* (non-Javadoc)
0256: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getSchemas()
0257: */
0258: public synchronized String[] getSchemas() throws SQLException {
0259: // final String key = "getSchemas";
0260: // String[] value = (String[])_cache.get(key);
0261: // if (value != null)
0262: // {
0263: // return value;
0264: // }
0265:
0266: boolean hasGuest = false;
0267: boolean hasSysFun = false;
0268:
0269: final boolean isMSSQLorSYBASE = DialectFactory.isSyBase(this )
0270: || DialectFactory.isMSSQLServer(this );
0271:
0272: final boolean isDB2 = DialectFactory.isDB2(this );
0273:
0274: final ArrayList<String> list = new ArrayList<String>();
0275: ResultSet rs = privateGetJDBCMetaData().getSchemas();
0276: try {
0277: if (rs != null) {
0278: final ResultSetReader rdr = new ResultSetReader(rs);
0279: Object[] row = null;
0280: while ((row = rdr.readRow()) != null) {
0281: if (isMSSQLorSYBASE && row[0].equals("guest")) {
0282: hasGuest = true;
0283: }
0284: if (isDB2 && row[0].equals("SYSFUN")) {
0285: hasSysFun = true;
0286: }
0287: list.add((String) row[0]);
0288: }
0289: }
0290: } finally {
0291: close(rs);
0292: }
0293:
0294: // Some drivers for both MS SQL and Sybase don't return guest as
0295: // a schema name.
0296: if (isMSSQLorSYBASE && !hasGuest) {
0297: list.add("guest");
0298: }
0299:
0300: // Some drivers for DB2 don't return SYSFUN as a schema name. A
0301: // number of system stored procs are kept in this schema.
0302: if (isDB2 && !hasSysFun) {
0303: list.add("SYSFUN");
0304: }
0305:
0306: // value = (String[])list.toArray(new String[list.size()]);
0307: // _cache.put(key, value);
0308:
0309: return list.toArray(new String[list.size()]);
0310: }
0311:
0312: /* (non-Javadoc)
0313: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsSchemas()
0314: */
0315: public boolean supportsSchemas() throws SQLException {
0316: return supportsSchemasInDataManipulation()
0317: || supportsSchemasInTableDefinitions();
0318: }
0319:
0320: /* (non-Javadoc)
0321: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsSchemasInDataManipulation()
0322: */
0323: public synchronized boolean supportsSchemasInDataManipulation()
0324: throws SQLException {
0325: final String key = "supportsSchemasInDataManipulation";
0326: Boolean value = (Boolean) _cache.get(key);
0327: if (value != null) {
0328: return value.booleanValue();
0329: }
0330:
0331: try {
0332: value = Boolean.valueOf(privateGetJDBCMetaData()
0333: .supportsSchemasInDataManipulation());
0334: } catch (SQLException ex) {
0335: boolean isSQLServer = DialectFactory.isSyBase(this )
0336: || DialectFactory.isMSSQLServer(this );
0337:
0338: if (isSQLServer) {
0339: value = Boolean.TRUE;
0340: _cache.put(key, value);
0341: }
0342: throw ex;
0343: }
0344:
0345: _cache.put(key, value);
0346:
0347: return value.booleanValue();
0348: }
0349:
0350: /* (non-Javadoc)
0351: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsSchemasInTableDefinitions()
0352: */
0353: public synchronized boolean supportsSchemasInTableDefinitions()
0354: throws SQLException {
0355: final String key = "supportsSchemasInTableDefinitions";
0356: Boolean value = (Boolean) _cache.get(key);
0357: if (value != null) {
0358: return value.booleanValue();
0359: }
0360:
0361: try {
0362: value = Boolean.valueOf(privateGetJDBCMetaData()
0363: .supportsSchemasInTableDefinitions());
0364: } catch (SQLException ex) {
0365: boolean isSQLServer = DialectFactory.isSyBase(this )
0366: || DialectFactory.isMSSQLServer(this );
0367: if (isSQLServer) {
0368: value = Boolean.TRUE;
0369: _cache.put(key, value);
0370: }
0371: throw ex;
0372: }
0373:
0374: _cache.put(key, value);
0375:
0376: return value.booleanValue();
0377: }
0378:
0379: /* (non-Javadoc)
0380: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsStoredProcedures()
0381: */
0382: public synchronized boolean supportsStoredProcedures()
0383: throws SQLException {
0384: final String key = "supportsStoredProcedures";
0385: Boolean value = (Boolean) _cache.get(key);
0386: if (value != null) {
0387: return value.booleanValue();
0388: }
0389:
0390: // PostgreSQL (at least 7.3.2) returns false for
0391: // supportsStoredProcedures() even though it does support them.
0392: if (DialectFactory.isPostgreSQL(this )) {
0393: value = Boolean.TRUE;
0394: } else {
0395: value = Boolean.valueOf(privateGetJDBCMetaData()
0396: .supportsStoredProcedures());
0397: }
0398: _cache.put(key, value);
0399:
0400: return value.booleanValue();
0401: }
0402:
0403: /* (non-Javadoc)
0404: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsSavepoints()
0405: */
0406: public synchronized boolean supportsSavepoints()
0407: throws SQLException {
0408:
0409: final String key = "supportsSavepoints";
0410: Boolean value = (Boolean) _cache.get(key);
0411: if (value != null) {
0412: return value.booleanValue();
0413: }
0414: value = Boolean.valueOf(privateGetJDBCMetaData()
0415: .supportsSavepoints());
0416:
0417: _cache.put(key, value);
0418:
0419: return value.booleanValue();
0420: }
0421:
0422: /* (non-Javadoc)
0423: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsResultSetType(int)
0424: */
0425: public synchronized boolean supportsResultSetType(int type)
0426: throws SQLException {
0427: final String key = "supportsResultSetType";
0428: Boolean value = (Boolean) _cache.get(key);
0429: if (value != null) {
0430: return value.booleanValue();
0431: }
0432: value = Boolean.valueOf(privateGetJDBCMetaData()
0433: .supportsResultSetType(type));
0434:
0435: _cache.put(key, value);
0436:
0437: return value.booleanValue();
0438: }
0439:
0440: /* Not cached.
0441: * (non-Javadoc)
0442: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getCatalogs()
0443: */
0444: public synchronized String[] getCatalogs() throws SQLException {
0445: final ArrayList<String> list = new ArrayList<String>();
0446: ResultSet rs = privateGetJDBCMetaData().getCatalogs();
0447: try {
0448: if (rs != null) {
0449: final ResultSetReader rdr = new ResultSetReader(rs);
0450: Object[] row = null;
0451: while ((row = rdr.readRow()) != null) {
0452: if (row != null && row[0] != null) {
0453: list.add(row[0].toString());
0454: }
0455: }
0456: }
0457: } finally {
0458: close(rs);
0459: }
0460:
0461: return list.toArray(new String[list.size()]);
0462: }
0463:
0464: /* (non-Javadoc)
0465: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getURL()
0466: */
0467: public synchronized String getURL() throws SQLException {
0468: final String key = "getURL";
0469: String value = (String) _cache.get(key);
0470: if (value != null) {
0471: return value;
0472: }
0473:
0474: value = privateGetJDBCMetaData().getURL();
0475: _cache.put(key, value);
0476:
0477: return value;
0478: }
0479:
0480: /* (non-Javadoc)
0481: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getCatalogTerm()
0482: */
0483: public synchronized String getCatalogTerm() throws SQLException {
0484: final String key = "getCatalogTerm";
0485: String value = (String) _cache.get(key);
0486: if (value != null) {
0487: return value;
0488: }
0489:
0490: value = privateGetJDBCMetaData().getCatalogTerm();
0491: _cache.put(key, value);
0492:
0493: return value;
0494: }
0495:
0496: /* (non-Javadoc)
0497: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getSchemaTerm()
0498: */
0499: public synchronized String getSchemaTerm() throws SQLException {
0500: final String key = "getSchemaTerm";
0501: String value = (String) _cache.get(key);
0502: if (value != null) {
0503: return value;
0504: }
0505:
0506: value = privateGetJDBCMetaData().getSchemaTerm();
0507: _cache.put(key, value);
0508:
0509: return value;
0510: }
0511:
0512: /* (non-Javadoc)
0513: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getProcedureTerm()
0514: */
0515: public synchronized String getProcedureTerm() throws SQLException {
0516: final String key = "getProcedureTerm";
0517: String value = (String) _cache.get(key);
0518: if (value != null) {
0519: return value;
0520: }
0521:
0522: value = privateGetJDBCMetaData().getProcedureTerm();
0523: _cache.put(key, value);
0524:
0525: return value;
0526: }
0527:
0528: /* (non-Javadoc)
0529: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getCatalogSeparator()
0530: */
0531: public synchronized String getCatalogSeparator()
0532: throws SQLException {
0533: final String key = "getCatalogSeparator";
0534: String value = (String) _cache.get(key);
0535: if (value != null) {
0536: return value;
0537: }
0538:
0539: value = privateGetJDBCMetaData().getCatalogSeparator();
0540: _cache.put(key, value);
0541:
0542: return value;
0543: }
0544:
0545: /* (non-Javadoc)
0546: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsCatalogs()
0547: */
0548: public boolean supportsCatalogs() throws SQLException {
0549: return supportsCatalogsInTableDefinitions()
0550: || supportsCatalogsInDataManipulation()
0551: || supportsCatalogsInProcedureCalls();
0552: }
0553:
0554: /* (non-Javadoc)
0555: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsCatalogsInTableDefinitions()
0556: */
0557: public synchronized boolean supportsCatalogsInTableDefinitions()
0558: throws SQLException {
0559: final String key = "supportsCatalogsInTableDefinitions";
0560: Boolean value = (Boolean) _cache.get(key);
0561: if (value != null) {
0562: return value.booleanValue();
0563: }
0564:
0565: try {
0566: value = Boolean.valueOf(privateGetJDBCMetaData()
0567: .supportsCatalogsInTableDefinitions());
0568: } catch (SQLException ex) {
0569: boolean isSQLServer = DialectFactory.isSyBase(this )
0570: || DialectFactory.isMSSQLServer(this );
0571:
0572: if (isSQLServer) {
0573: value = Boolean.TRUE;
0574: _cache.put(key, value);
0575: }
0576: throw ex;
0577: }
0578:
0579: _cache.put(key, value);
0580:
0581: return value.booleanValue();
0582: }
0583:
0584: /* (non-Javadoc)
0585: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsCatalogsInDataManipulation()
0586: */
0587: public synchronized boolean supportsCatalogsInDataManipulation()
0588: throws SQLException {
0589: final String key = "supportsCatalogsInDataManipulation";
0590: Boolean value = (Boolean) _cache.get(key);
0591: if (value != null) {
0592: return value.booleanValue();
0593: }
0594:
0595: try {
0596: value = Boolean.valueOf(privateGetJDBCMetaData()
0597: .supportsCatalogsInDataManipulation());
0598: } catch (SQLException ex) {
0599: boolean isSQLServer = DialectFactory.isSyBase(this )
0600: || DialectFactory.isMSSQLServer(this );
0601:
0602: if (isSQLServer) {
0603: value = Boolean.TRUE;
0604: _cache.put(key, value);
0605: }
0606: throw ex;
0607: }
0608: _cache.put(key, value);
0609:
0610: return value.booleanValue();
0611: }
0612:
0613: /* (non-Javadoc)
0614: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsCatalogsInProcedureCalls()
0615: */
0616: public synchronized boolean supportsCatalogsInProcedureCalls()
0617: throws SQLException {
0618: final String key = "supportsCatalogsInProcedureCalls";
0619: Boolean value = (Boolean) _cache.get(key);
0620: if (value != null) {
0621: return value.booleanValue();
0622: }
0623:
0624: try {
0625: value = Boolean.valueOf(privateGetJDBCMetaData()
0626: .supportsCatalogsInProcedureCalls());
0627: } catch (SQLException ex) {
0628: boolean isSQLServer = DialectFactory.isSyBase(this )
0629: || DialectFactory.isMSSQLServer(this );
0630:
0631: if (isSQLServer) {
0632: value = Boolean.TRUE;
0633: _cache.put(key, value);
0634: }
0635: throw ex;
0636: }
0637: _cache.put(key, value);
0638:
0639: return value.booleanValue();
0640: }
0641:
0642: /* (non-Javadoc)
0643: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getJDBCMetaData()
0644: */
0645: public synchronized DatabaseMetaData getJDBCMetaData()
0646: throws SQLException {
0647: return privateGetJDBCMetaData();
0648: }
0649:
0650: /* (non-Javadoc)
0651: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getMetaDataSet()
0652: */
0653: public synchronized IDataSet getMetaDataSet() throws SQLException {
0654: return new MetaDataDataSet(privateGetJDBCMetaData());
0655: }
0656:
0657: /* (non-Javadoc)
0658: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTypeInfo()
0659: *
0660: * @deprecated Replaced by getDataTypes
0661: */
0662: public ResultSet getTypeInfo() throws SQLException {
0663: return privateGetJDBCMetaData().getTypeInfo();
0664: }
0665:
0666: /* (non-Javadoc)
0667: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTypesDataSet()
0668: */
0669: public synchronized IDataSet getTypesDataSet()
0670: throws DataSetException {
0671: ResultSet rs = null;
0672: try {
0673: rs = privateGetJDBCMetaData().getTypeInfo();
0674: return (new DatabaseTypesDataSet(rs));
0675: } catch (SQLException e) {
0676: throw new DataSetException(e);
0677: } finally {
0678: SQLUtilities.closeResultSet(rs);
0679: }
0680: }
0681:
0682: /* (non-Javadoc)
0683: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getDataTypes()
0684: */
0685: public synchronized DataTypeInfo[] getDataTypes()
0686: throws SQLException {
0687: final DatabaseMetaData md = privateGetJDBCMetaData();
0688: final ArrayList<DataTypeInfo> list = new ArrayList<DataTypeInfo>();
0689: final ResultSet rs = md.getTypeInfo();
0690: try {
0691: ResultSetColumnReader rdr = new ResultSetColumnReader(rs);
0692: while (rdr.next()) {
0693: final String typeName = rdr.getString(1);
0694: final int dataType = rdr.getLong(2).intValue();
0695: final int precis = rdr.getLong(3).intValue();
0696: final String literalPrefix = rdr.getString(4);
0697: final String literalSuffix = rdr.getString(5);
0698: final String createParams = rdr.getString(6);
0699: final int nullable = rdr.getLong(7).intValue();
0700: final boolean caseSens = rdr.getBoolean(8)
0701: .booleanValue();
0702: final int searchable = rdr.getLong(9).intValue();
0703: final boolean unsigned = rdr.getBoolean(10)
0704: .booleanValue();
0705: final boolean canBeMoney = rdr.getBoolean(11)
0706: .booleanValue();
0707: final boolean canBeAutoInc = rdr.getBoolean(12)
0708: .booleanValue();
0709: final String localTypeName = rdr.getString(13);
0710: final int min = rdr.getLong(14).intValue();
0711: final int max = rdr.getLong(15).intValue();
0712: final int radix = rdr.getLong(18).intValue();
0713: list.add(new DataTypeInfo(typeName, dataType, precis,
0714: literalPrefix, literalSuffix, createParams,
0715: nullable, caseSens, searchable, unsigned,
0716: canBeMoney, canBeAutoInc, localTypeName, min,
0717: max, radix, this ));
0718: }
0719: } finally {
0720: close(rs);
0721: }
0722: return list.toArray(new DataTypeInfo[list.size()]);
0723: }
0724:
0725: private void close(ResultSet rs) {
0726: try {
0727: if (rs != null) {
0728: rs.close();
0729: }
0730: } catch (Exception e) {
0731: s_log.info("closing resultset failed", e);
0732: }
0733: }
0734:
0735: /* (non-Javadoc)
0736: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getProcedures(java.lang.String, java.lang.String, java.lang.String, net.sourceforge.squirrel_sql.fw.sql.ProgressCallBack)
0737: */
0738: public synchronized IProcedureInfo[] getProcedures(String catalog,
0739: String schemaPattern, String procedureNamePattern,
0740: ProgressCallBack progressCallBack) throws SQLException {
0741: DatabaseMetaData md = privateGetJDBCMetaData();
0742: ArrayList<ProcedureInfo> list = new ArrayList<ProcedureInfo>();
0743: ResultSet rs = md.getProcedures(catalog, schemaPattern,
0744: procedureNamePattern);
0745: if (rs != null) {
0746: int count = 0;
0747: try {
0748: final int[] cols = new int[] { 1, 2, 3, 7, 8 };
0749: final ResultSetReader rdr = new ResultSetReader(rs,
0750: cols);
0751: Object[] row = null;
0752: while ((row = rdr.readRow()) != null) {
0753: final int type = ((Number) row[4]).intValue();
0754: ProcedureInfo pi = new ProcedureInfo(
0755: getAsString(row[0]), getAsString(row[1]),
0756: getAsString(row[2]), getAsString(row[3]),
0757: type, this );
0758:
0759: list.add(pi);
0760:
0761: if (null != progressCallBack) {
0762: if (0 == count++ % 200) {
0763: progressCallBack.currentlyLoading(pi
0764: .getSimpleName());
0765: }
0766: }
0767: }
0768: } finally {
0769: close(rs);
0770:
0771: }
0772: }
0773: return list.toArray(new IProcedureInfo[list.size()]);
0774: }
0775:
0776: /* (non-Javadoc)
0777: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTableTypes()
0778: */
0779: public synchronized String[] getTableTypes() throws SQLException {
0780: final String key = "getTableTypes";
0781: String[] value = (String[]) _cache.get(key);
0782: if (value != null) {
0783: return value;
0784: }
0785:
0786: final DatabaseMetaData md = privateGetJDBCMetaData();
0787:
0788: // Use a set rather than a list as some combinations of MS SQL and the
0789: // JDBC/ODBC return multiple copies of each table type.
0790: final Set<String> tableTypes = new TreeSet<String>();
0791: final ResultSet rs = md.getTableTypes();
0792: if (rs != null) {
0793: try {
0794: while (rs.next()) {
0795: tableTypes.add(rs.getString(1).trim());
0796: }
0797: } finally {
0798: close(rs);
0799: }
0800: }
0801:
0802: final String dbProductName = getDatabaseProductName();
0803: final int nbrTableTypes = tableTypes.size();
0804:
0805: // InstantDB (at least version 3.13) only returns "TABLES"
0806: // for getTableTypes(). If you try to use this in a call to
0807: // DatabaseMetaData.getTables() no tables will be found. For the
0808: // moment hard code the types for InstantDB.
0809: if (nbrTableTypes == 1 && dbProductName.equals("InstantDB")) {
0810: tableTypes.clear();
0811: tableTypes.add("TABLE");
0812: tableTypes.add("SYSTEM TABLE");
0813: }
0814:
0815: // At least one version of PostgreSQL through the JDBC/ODBC
0816: // bridge returns an empty result set for the list of table
0817: // types. Another version of PostgreSQL returns 6 entries
0818: // of "SYSTEM TABLE" (which we have already filtered back to one).
0819: else if (dbProductName.equals("PostgreSQL")) {
0820: if (nbrTableTypes == 0 || nbrTableTypes == 1) {
0821: if (s_log.isDebugEnabled()) {
0822: s_log
0823: .debug("Detected PostgreSQL and "
0824: + nbrTableTypes
0825: + " table types - overriding to 4 table types");
0826: }
0827: tableTypes.clear();
0828: tableTypes.add("TABLE");
0829: tableTypes.add("SYSTEM TABLE");
0830: tableTypes.add("VIEW");
0831: tableTypes.add("SYSTEM VIEW");
0832: }
0833: // Treating indexes as tables interferes with the operation of the
0834: // PostgreSQL plugin
0835: if (tableTypes.contains("INDEX")) {
0836: tableTypes.remove("INDEX");
0837: }
0838: // Treating sequences as tables interferes with the operation of the
0839: // PostgreSQL plugin
0840: if (tableTypes.contains("SEQUENCE")) {
0841: tableTypes.remove("SEQUENCE");
0842: }
0843: // There are many of these "tables", that PostgreSQL throws
0844: // SQLExceptions for whenever a table-like operation is attempted.
0845: if (tableTypes.contains("SYSTEM INDEX")) {
0846: tableTypes.remove("SYSTEM INDEX");
0847: }
0848: }
0849:
0850: // Informix: when no database is given in the connect url, then no table types are returned. The
0851: // catalog can be changed which will select a database, but by that time it is too late.
0852: else if (DialectFactory.isInformix(this )) {
0853: if (nbrTableTypes == 0) {
0854: if (s_log.isDebugEnabled()) {
0855: s_log
0856: .debug("Detected Informix with no table types returned. Defaulting to "
0857: + "TABLE | SYSTEM TABLE | VIEW");
0858: }
0859: tableTypes.add("TABLE");
0860: tableTypes.add("SYSTEM TABLE");
0861: tableTypes.add("VIEW");
0862: }
0863: }
0864:
0865: value = tableTypes.toArray(new String[tableTypes.size()]);
0866: _cache.put(key, value);
0867: return value;
0868: }
0869:
0870: /* (non-Javadoc)
0871: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.sourceforge.squirrel_sql.fw.sql.ProgressCallBack)
0872: */
0873: public synchronized ITableInfo[] getTables(String catalog,
0874: String schemaPattern, String tableNamePattern,
0875: String[] types, ProgressCallBack progressCallBack)
0876: throws SQLException {
0877:
0878: final DatabaseMetaData md = privateGetJDBCMetaData();
0879: final String dbDriverName = getDriverName();
0880: Set<ITableInfo> list = new TreeSet<ITableInfo>();
0881:
0882: /* work-around for this driver, which must have "dbo" for schema. The
0883: * JConnect family of drivers appears to not be affected and can accept a
0884: * null schema, which is necessary to find tables in other schemas, within
0885: * the same catalog. Similarly, jTDS 1.2.2 doesn't require this, yet it
0886: * doesn't return non-dbo schema tables, unfortunately.
0887: */
0888: if (dbDriverName.equals(IDriverNames.FREE_TDS)
0889: && schemaPattern == null) {
0890: schemaPattern = "dbo";
0891: }
0892: if (dbDriverName.equals(IDriverNames.AS400)
0893: && schemaPattern == null) {
0894: schemaPattern = "*ALLUSR";
0895: }
0896:
0897: //Add begin
0898: if (catalog == null && DriverMatch.isComHttxDriver(_conn)) {
0899: String[] catalogs = getCatalogs();
0900: if (catalogs != null) {
0901: for (int i = 0; i < catalogs.length; i++) {
0902: ITableInfo[] tables = getTables(catalogs[i],
0903: schemaPattern, tableNamePattern, types,
0904: progressCallBack);
0905: for (int j = 0; j < tables.length; j++) {
0906: list.add(tables[j]);
0907: }
0908: }
0909: return list.toArray(new ITableInfo[list.size()]);
0910: }
0911: }
0912: //Add end
0913:
0914: Map<String, ITableInfo> nameMap = null;
0915: ResultSet super TabResult = null;
0916: ResultSet tabResult = null;
0917: try {
0918: if (supportsSuperTables) {
0919: try {
0920: super TabResult = md.getSuperTables(catalog,
0921: schemaPattern, tableNamePattern);
0922: // create a mapping of names if we have supertable info, since
0923: // we need to find the ITableInfo again for re-ordering.
0924: if (super TabResult != null && super TabResult.next()) {
0925: nameMap = new HashMap<String, ITableInfo>();
0926: }
0927: } catch (Throwable th) {
0928: s_log
0929: .debug("DBMS/Driver doesn't support getSupertables(): "
0930: + th.getMessage());
0931: supportsSuperTables = false;
0932: }
0933: }
0934: // store all plain table info we have.
0935: tabResult = md.getTables(catalog, schemaPattern,
0936: tableNamePattern, types);
0937: int count = 0;
0938: while (tabResult != null && tabResult.next()) {
0939: ITableInfo tabInfo = new TableInfo(tabResult
0940: .getString(1), tabResult.getString(2),
0941: tabResult.getString(3), tabResult.getString(4),
0942: tabResult.getString(5), this );
0943: if (nameMap != null) {
0944: nameMap.put(tabInfo.getSimpleName(), tabInfo);
0945: }
0946: list.add(tabInfo);
0947:
0948: if (null != progressCallBack) {
0949: if (0 == count++ % 100) {
0950: progressCallBack.currentlyLoading(tabInfo
0951: .getSimpleName());
0952: }
0953: }
0954: }
0955:
0956: // re-order nodes if the tables are stored hierachically
0957: if (nameMap != null) {
0958: do {
0959: String tabName = super TabResult.getString(3);
0960: TableInfo tabInfo = (TableInfo) nameMap
0961: .get(tabName);
0962: if (tabInfo == null)
0963: continue;
0964: String super TabName = super TabResult.getString(4);
0965: if (super TabName == null)
0966: continue;
0967: TableInfo super Info = (TableInfo) nameMap
0968: .get(super TabName);
0969: if (super Info == null)
0970: continue;
0971: super Info.addChild(tabInfo);
0972: list.remove(tabInfo); // remove from toplevel.
0973:
0974: if (null != progressCallBack) {
0975: if (0 == count++ % 20) {
0976: progressCallBack.currentlyLoading(tabInfo
0977: .getSimpleName());
0978: }
0979: }
0980: } while (super TabResult.next());
0981: }
0982: } finally {
0983: close(tabResult);
0984: close(super TabResult);
0985: }
0986:
0987: return list.toArray(new ITableInfo[list.size()]);
0988: }
0989:
0990: /* (non-Javadoc)
0991: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])
0992: */
0993: public synchronized IUDTInfo[] getUDTs(String catalog,
0994: String schemaPattern, String typeNamePattern, int[] types)
0995: throws SQLException {
0996: DatabaseMetaData md = privateGetJDBCMetaData();
0997: ArrayList<UDTInfo> list = new ArrayList<UDTInfo>();
0998: checkForInformix();
0999: ResultSet rs = md.getUDTs(catalog, schemaPattern,
1000: typeNamePattern, types);
1001: try {
1002: final int[] cols = new int[] { 1, 2, 3, 4, 5, 6 };
1003: final ResultSetReader rdr = new ResultSetReader(rs, cols);
1004: Object[] row = null;
1005: while ((row = rdr.readRow()) != null) {
1006: list.add(new UDTInfo(getAsString(row[0]),
1007: getAsString(row[1]), getAsString(row[2]),
1008: getAsString(row[3]), getAsString(row[4]),
1009: getAsString(row[5]), this ));
1010: }
1011: } finally {
1012: close(rs);
1013: }
1014:
1015: return list.toArray(new IUDTInfo[list.size()]);
1016: }
1017:
1018: /**
1019: * If we are connected to Informix, then we may need to cleanup
1020: * @param catalogName
1021: */
1022: private void checkForInformix() {
1023: if (!DialectFactory.isInformix(this )) {
1024: return;
1025: }
1026:
1027: Statement stmt = null;
1028:
1029: try {
1030: stmt = _conn.createStatement();
1031: stmt.execute("Drop procedure mode_decode");
1032: } catch (SQLException e) {
1033: // The mode_decode routine may or may not be there. We don't care if it is not there, but log an
1034: // info if we failed to drop it for some other reason.
1035: s_log.info(
1036: "setInformixCatalog: unable to drop procedure mode_decode: "
1037: + e.getMessage(), e);
1038: } finally {
1039: SQLUtilities.closeStatement(stmt);
1040: }
1041: }
1042:
1043: private String getAsString(Object val) {
1044: if (null == val) {
1045: return null;
1046: } else {
1047: if (val instanceof String) {
1048: return (String) val;
1049: } else {
1050: return "" + val;
1051: }
1052: }
1053:
1054: }
1055:
1056: /* (non-Javadoc)
1057: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getNumericFunctions()
1058: */
1059: public synchronized String[] getNumericFunctions()
1060: throws SQLException {
1061: final String key = "getNumericFunctions";
1062: String[] value = (String[]) _cache.get(key);
1063: if (value != null) {
1064: return value;
1065: }
1066:
1067: value = makeArray(privateGetJDBCMetaData()
1068: .getNumericFunctions());
1069: _cache.put(key, value);
1070: return value;
1071: }
1072:
1073: /* (non-Javadoc)
1074: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getStringFunctions()
1075: */
1076: public synchronized String[] getStringFunctions()
1077: throws SQLException {
1078: final String key = "getStringFunctions";
1079: String[] value = (String[]) _cache.get(key);
1080: if (value != null) {
1081: return value;
1082: }
1083:
1084: value = makeArray(privateGetJDBCMetaData().getStringFunctions());
1085: _cache.put(key, value);
1086: return value;
1087: }
1088:
1089: /* (non-Javadoc)
1090: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getSystemFunctions()
1091: */
1092: public synchronized String[] getSystemFunctions()
1093: throws SQLException {
1094: final String key = "getSystemFunctions";
1095: String[] value = (String[]) _cache.get(key);
1096: if (value != null) {
1097: return value;
1098: }
1099:
1100: value = makeArray(privateGetJDBCMetaData().getSystemFunctions());
1101: _cache.put(key, value);
1102: return value;
1103: }
1104:
1105: /* (non-Javadoc)
1106: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTimeDateFunctions()
1107: */
1108: public synchronized String[] getTimeDateFunctions()
1109: throws SQLException {
1110: final String key = "getTimeDateFunctions";
1111: String[] value = (String[]) _cache.get(key);
1112: if (value != null) {
1113: return value;
1114: }
1115:
1116: value = makeArray(privateGetJDBCMetaData()
1117: .getTimeDateFunctions());
1118: _cache.put(key, value);
1119: return value;
1120: }
1121:
1122: /* (non-Javadoc)
1123: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getSQLKeywords()
1124: */
1125: public synchronized String[] getSQLKeywords() throws SQLException {
1126: final String key = "getSQLKeywords";
1127: String[] value = (String[]) _cache.get(key);
1128: if (value != null) {
1129: return value;
1130: }
1131:
1132: value = makeArray(privateGetJDBCMetaData().getSQLKeywords());
1133: _cache.put(key, value);
1134: return value;
1135: }
1136:
1137: /* (non-Javadoc)
1138: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getBestRowIdentifier(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1139: */
1140: public synchronized BestRowIdentifier[] getBestRowIdentifier(
1141: ITableInfo ti) throws SQLException {
1142: final List<BestRowIdentifier> results = new ArrayList<BestRowIdentifier>();
1143:
1144: ResultSet rs = null;
1145: try {
1146:
1147: rs = privateGetJDBCMetaData().getBestRowIdentifier(
1148: ti.getCatalogName(), ti.getSchemaName(),
1149: ti.getSimpleName(),
1150: DatabaseMetaData.bestRowTransaction, true);
1151:
1152: final String catalog = ti.getCatalogName();
1153: final String schema = ti.getSchemaName();
1154: final String table = ti.getSimpleName();
1155:
1156: final ResultSetColumnReader rdr = new ResultSetColumnReader(
1157: rs);
1158: while (rdr.next()) {
1159: final BestRowIdentifier rid = new BestRowIdentifier(
1160: catalog, schema, table, rdr.getLong(1)
1161: .intValue(), rdr.getString(2), rdr
1162: .getLong(3).shortValue(), rdr
1163: .getString(4), rdr.getLong(5)
1164: .intValue(), rdr.getLong(7)
1165: .shortValue(), rdr.getLong(8)
1166: .shortValue(), this );
1167: results.add(rid);
1168: }
1169: } finally {
1170: SQLUtilities.closeResultSet(rs);
1171: }
1172:
1173: final BestRowIdentifier[] ar = new BestRowIdentifier[results
1174: .size()];
1175: return results.toArray(ar);
1176: }
1177:
1178: /* (non-Javadoc)
1179: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getColumnPrivileges(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1180: *
1181: * @deprecated use getColumnPrivilegesDataSet instead.
1182: */
1183: public ResultSet getColumnPrivileges(ITableInfo ti)
1184: throws SQLException {
1185: // MM-MYSQL driver doesnt support null for column name.
1186: final String columns = DialectFactory.isMySQL(this ) ? "%"
1187: : null;
1188: return privateGetJDBCMetaData().getColumnPrivileges(
1189: ti.getCatalogName(), ti.getSchemaName(),
1190: ti.getSimpleName(), columns);
1191: }
1192:
1193: /* (non-Javadoc)
1194: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getColumnPrivilegesDataSet(net.sourceforge.squirrel_sql.fw.sql.ITableInfo, int[], boolean)
1195: */
1196: public synchronized IDataSet getColumnPrivilegesDataSet(
1197: ITableInfo ti, int[] columnIndices, boolean computeWidths)
1198: throws DataSetException {
1199: ResultSet rs = null;
1200: try {
1201: DatabaseMetaData md = privateGetJDBCMetaData();
1202: final String columns = DialectFactory.isMySQL(this ) ? "%"
1203: : null;
1204:
1205: rs = md.getColumnPrivileges(ti.getCatalogName(), ti
1206: .getSchemaName(), ti.getSimpleName(), columns);
1207: ResultSetDataSet rsds = new ResultSetDataSet();
1208: rsds.setResultSet(rs, columnIndices, computeWidths);
1209: return rsds;
1210: } catch (SQLException e) {
1211: throw new DataSetException(e);
1212: } finally {
1213: SQLUtilities.closeResultSet(rs);
1214: }
1215: }
1216:
1217: /* (non-Javadoc)
1218: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getExportedKeys(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1219: *
1220: * @deprecated. Replaced by getExportedKeysInfo
1221: */
1222: public ResultSet getExportedKeys(ITableInfo ti) throws SQLException {
1223: return privateGetJDBCMetaData().getExportedKeys(
1224: ti.getCatalogName(), ti.getSchemaName(),
1225: ti.getSimpleName());
1226: }
1227:
1228: /* (non-Javadoc)
1229: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getExportedKeysDataSet(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1230: */
1231: public synchronized IDataSet getExportedKeysDataSet(ITableInfo ti)
1232: throws DataSetException {
1233: ResultSet rs = null;
1234: try {
1235: rs = privateGetJDBCMetaData().getExportedKeys(
1236: ti.getCatalogName(), ti.getSchemaName(),
1237: ti.getSimpleName());
1238: ResultSetDataSet rsds = new ResultSetDataSet();
1239: rsds.setResultSet(rs, null, true);
1240: return rsds;
1241: } catch (SQLException e) {
1242: throw new DataSetException(e);
1243: } finally {
1244: SQLUtilities.closeResultSet(rs);
1245: }
1246: }
1247:
1248: /* (non-Javadoc)
1249: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getImportedKeys(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1250: *
1251: * @deprecated. Replaced by getImportedKeysInfo
1252: */
1253: public ResultSet getImportedKeys(ITableInfo ti) throws SQLException {
1254: return privateGetJDBCMetaData().getImportedKeys(
1255: ti.getCatalogName(), ti.getSchemaName(),
1256: ti.getSimpleName());
1257: }
1258:
1259: /* (non-Javadoc)
1260: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getImportedKeysInfo(java.lang.String, java.lang.String, java.lang.String)
1261: */
1262: public synchronized ForeignKeyInfo[] getImportedKeysInfo(
1263: String catalog, String schema, String tableName)
1264: throws SQLException {
1265: ResultSet rs = privateGetJDBCMetaData().getImportedKeys(
1266: catalog, schema, tableName);
1267: return getForeignKeyInfo(rs);
1268: }
1269:
1270: /* (non-Javadoc)
1271: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getImportedKeysInfo(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1272: */
1273: public synchronized ForeignKeyInfo[] getImportedKeysInfo(
1274: ITableInfo ti) throws SQLException {
1275: return getForeignKeyInfo(privateGetJDBCMetaData()
1276: .getImportedKeys(ti.getCatalogName(),
1277: ti.getSchemaName(), ti.getSimpleName()));
1278: }
1279:
1280: /* (non-Javadoc)
1281: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getImportedKeysDataSet(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1282: */
1283: public synchronized IDataSet getImportedKeysDataSet(ITableInfo ti)
1284: throws DataSetException {
1285: ResultSet rs = null;
1286: try {
1287: rs = privateGetJDBCMetaData().getImportedKeys(
1288: ti.getCatalogName(), ti.getSchemaName(),
1289: ti.getSimpleName());
1290: ResultSetDataSet rsds = new ResultSetDataSet();
1291: rsds.setResultSet(rs, null, true);
1292: return rsds;
1293: } catch (SQLException e) {
1294: throw new DataSetException(e);
1295: } finally {
1296: SQLUtilities.closeResultSet(rs);
1297: }
1298: }
1299:
1300: /* (non-Javadoc)
1301: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getExportedKeysInfo(java.lang.String, java.lang.String, java.lang.String)
1302: */
1303: public synchronized ForeignKeyInfo[] getExportedKeysInfo(
1304: String catalog, String schema, String tableName)
1305: throws SQLException {
1306: ResultSet rs = privateGetJDBCMetaData().getExportedKeys(
1307: catalog, schema, tableName);
1308: return getForeignKeyInfo(rs);
1309: }
1310:
1311: /* (non-Javadoc)
1312: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getExportedKeysInfo(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1313: */
1314: public synchronized ForeignKeyInfo[] getExportedKeysInfo(
1315: ITableInfo ti) throws SQLException {
1316: return getForeignKeyInfo(privateGetJDBCMetaData()
1317: .getExportedKeys(ti.getCatalogName(),
1318: ti.getSchemaName(), ti.getSimpleName()));
1319: }
1320:
1321: private ForeignKeyInfo[] getForeignKeyInfo(ResultSet rs)
1322: throws SQLException {
1323: final Map<String, ForeignKeyInfo> keys = new HashMap<String, ForeignKeyInfo>();
1324: final Map<String, ArrayList<ForeignKeyColumnInfo>> columns = new HashMap<String, ArrayList<ForeignKeyColumnInfo>>();
1325:
1326: try {
1327: final ResultSetColumnReader rdr = new ResultSetColumnReader(
1328: rs);
1329: while (rdr.next()) {
1330: final ForeignKeyInfo fki = new ForeignKeyInfo(rdr
1331: .getString(1), rdr.getString(2), rdr
1332: .getString(3), rdr.getString(4), rdr
1333: .getString(5), rdr.getString(6), rdr
1334: .getString(7), rdr.getString(8), rdr
1335: .getLong(10).intValue(), rdr.getLong(11)
1336: .intValue(), rdr.getString(12), rdr
1337: .getString(13), rdr.getLong(14).intValue(),
1338: null, this );
1339: final String key = createForeignKeyInfoKey(fki);
1340: if (!keys.containsKey(key)) {
1341: keys.put(key, fki);
1342: columns.put(key,
1343: new ArrayList<ForeignKeyColumnInfo>());
1344: }
1345:
1346: ForeignKeyColumnInfo fkiCol = new ForeignKeyColumnInfo(
1347: rdr.getString(8), rdr.getString(8), rdr
1348: .getLong(9).intValue());
1349: columns.get(key).add(fkiCol);
1350: }
1351: } finally {
1352: close(rs);
1353: }
1354:
1355: final ForeignKeyInfo[] results = new ForeignKeyInfo[keys.size()];
1356: Iterator<ForeignKeyInfo> it = keys.values().iterator();
1357: int idx = 0;
1358: while (it.hasNext()) {
1359: final ForeignKeyInfo fki = it.next();
1360: final String key = createForeignKeyInfoKey(fki);
1361: final List<ForeignKeyColumnInfo> colsList = columns
1362: .get(key);
1363: final ForeignKeyColumnInfo[] fkiCol = colsList
1364: .toArray(new ForeignKeyColumnInfo[colsList.size()]);
1365: fki.setForeignKeyColumnInfo(fkiCol);
1366: results[idx++] = fki;
1367: }
1368:
1369: return results;
1370: }
1371:
1372: /* (non-Javadoc)
1373: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getIndexInfo(net.sourceforge.squirrel_sql.fw.sql.ITableInfo, int[], boolean)
1374: */
1375: public synchronized ResultSetDataSet getIndexInfo(ITableInfo ti,
1376: int[] columnIndices, boolean computeWidths)
1377: throws DataSetException {
1378: ResultSet rs = null;
1379: try {
1380: rs = privateGetJDBCMetaData().getIndexInfo(
1381: ti.getCatalogName(), ti.getSchemaName(),
1382: ti.getSimpleName(), false, true);
1383: ResultSetDataSet rsds = new ResultSetDataSet();
1384: rsds.setResultSet(rs, columnIndices, computeWidths);
1385: return rsds;
1386: } catch (SQLException e) {
1387: throw new DataSetException(e);
1388: } finally {
1389: SQLUtilities.closeResultSet(rs);
1390: }
1391: }
1392:
1393: /**
1394: * Returns a list of IndexInfos describing indexes for the specified table.
1395: *
1396: * @param ti the table to find all index information for.
1397: * @return a list of IndexInfos
1398: * @throws SQLException
1399: */
1400: public List<IndexInfo> getIndexInfo(ITableInfo ti)
1401: throws SQLException {
1402: List<IndexInfo> result = new ArrayList<IndexInfo>();
1403: ResultSet rs = null;
1404: try {
1405: rs = privateGetJDBCMetaData().getIndexInfo(
1406: ti.getCatalogName(), ti.getSchemaName(),
1407: ti.getSimpleName(), false, true);
1408: while (rs.next()) {
1409: String catalog = rs.getString(1);
1410: String schema = rs.getString(2);
1411: String table = rs.getString(3);
1412: boolean nonunique = rs.getBoolean(4);
1413: String indexQualifier = rs.getString(5);
1414: String indexName = rs.getString(6);
1415: IndexInfo.IndexType indexType = JDBCTypeMapper
1416: .getIndexType(rs.getShort(7));
1417: short ordinalPosition = rs.getShort(8);
1418: String column = rs.getString(9);
1419: IndexInfo.SortOrder sortOrder = JDBCTypeMapper
1420: .getIndexSortOrder(rs.getString(10));
1421: int cardinality = rs.getInt(11);
1422: int pages = rs.getInt(12);
1423: String filterCondition = rs.getString(13);
1424:
1425: IndexInfo indexInfo = new IndexInfo(catalog, schema,
1426: indexName, table, column, nonunique,
1427: indexQualifier, indexType, ordinalPosition,
1428: sortOrder, cardinality, pages, filterCondition,
1429: this );
1430: result.add(indexInfo);
1431: }
1432: } catch (SQLException e) {
1433: } finally {
1434: SQLUtilities.closeResultSet(rs);
1435: }
1436: return result;
1437: }
1438:
1439: /* (non-Javadoc)
1440: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getPrimaryKeys(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1441: *
1442: * @deprecated use getPrimaryKey instead
1443: */
1444: public ResultSet getPrimaryKeys(ITableInfo ti) throws SQLException {
1445: return privateGetJDBCMetaData().getPrimaryKeys(
1446: ti.getCatalogName(), ti.getSchemaName(),
1447: ti.getSimpleName());
1448: }
1449:
1450: /* (non-Javadoc)
1451: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getPrimaryKey(net.sourceforge.squirrel_sql.fw.sql.ITableInfo, int[], boolean)
1452: */
1453: public synchronized IDataSet getPrimaryKey(ITableInfo ti,
1454: int[] columnIndices, boolean computeWidths)
1455: throws DataSetException {
1456: ResultSet rs = null;
1457: try {
1458: rs = privateGetJDBCMetaData().getPrimaryKeys(
1459: ti.getCatalogName(), ti.getSchemaName(),
1460: ti.getSimpleName());
1461: ResultSetDataSet rsds = new ResultSetDataSet();
1462: rsds.setResultSet(rs, columnIndices, computeWidths);
1463: return rsds;
1464: } catch (SQLException e) {
1465: throw new DataSetException(e);
1466: } finally {
1467: SQLUtilities.closeResultSet(rs);
1468: }
1469: }
1470:
1471: /* (non-Javadoc)
1472: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getPrimaryKey(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1473: */
1474: public synchronized PrimaryKeyInfo[] getPrimaryKey(ITableInfo ti)
1475: throws SQLException {
1476: return getPrimaryKey(ti.getCatalogName(), ti.getSchemaName(),
1477: ti.getSimpleName());
1478: }
1479:
1480: /* (non-Javadoc)
1481: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getPrimaryKey(java.lang.String, java.lang.String, java.lang.String)
1482: */
1483: public synchronized PrimaryKeyInfo[] getPrimaryKey(String catalog,
1484: String schema, String table) throws SQLException {
1485: final List<PrimaryKeyInfo> results = new ArrayList<PrimaryKeyInfo>();
1486: ResultSet rs = null;
1487: try {
1488: rs = privateGetJDBCMetaData().getPrimaryKeys(catalog,
1489: schema, table);
1490: while (rs.next()) {
1491: PrimaryKeyInfo pkInfo = new PrimaryKeyInfo(rs
1492: .getString(1), // catalog
1493: rs.getString(2), // schema
1494: rs.getString(3), // tableName
1495: rs.getString(4), // columnName
1496: rs.getShort(5), // keySequence
1497: rs.getString(6), // pkName
1498: this );
1499: results.add(pkInfo);
1500: }
1501: } finally {
1502: SQLUtilities.closeResultSet(rs);
1503: }
1504:
1505: final PrimaryKeyInfo[] ar = new PrimaryKeyInfo[results.size()];
1506: return results.toArray(ar);
1507: }
1508:
1509: /* (non-Javadoc)
1510: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getProcedureColumns(net.sourceforge.squirrel_sql.fw.sql.IProcedureInfo)
1511: *
1512: * @deprecated use getProcedureColumnsDataSet instead
1513: */
1514: public ResultSet getProcedureColumns(IProcedureInfo ti)
1515: throws SQLException {
1516: return privateGetJDBCMetaData().getProcedureColumns(
1517: ti.getCatalogName(), ti.getSchemaName(),
1518: ti.getSimpleName(), "%");
1519: }
1520:
1521: /* (non-Javadoc)
1522: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getProcedureColumnsDataSet(net.sourceforge.squirrel_sql.fw.sql.IProcedureInfo)
1523: */
1524: public synchronized IDataSet getProcedureColumnsDataSet(
1525: IProcedureInfo ti) throws DataSetException {
1526: ResultSet rs = null;
1527: try {
1528: DatabaseMetaData md = privateGetJDBCMetaData();
1529: rs = md.getProcedureColumns(ti.getCatalogName(), ti
1530: .getSchemaName(), ti.getSimpleName(), "%");
1531: ResultSetDataSet rsds = new ResultSetDataSet();
1532: rsds.setResultSet(rs);
1533: return rsds;
1534: } catch (SQLException e) {
1535: throw new DataSetException(e);
1536: } finally {
1537: SQLUtilities.closeResultSet(rs);
1538: }
1539: }
1540:
1541: /* (non-Javadoc)
1542: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTablePrivileges(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1543: *
1544: * @deprecated use getTablePrivilegesDataSet instead
1545: */
1546: public ResultSet getTablePrivileges(ITableInfo ti)
1547: throws SQLException {
1548: return privateGetJDBCMetaData().getTablePrivileges(
1549: ti.getCatalogName(), ti.getSchemaName(),
1550: ti.getSimpleName());
1551: }
1552:
1553: /* (non-Javadoc)
1554: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getTablePrivilegesDataSet(net.sourceforge.squirrel_sql.fw.sql.ITableInfo, int[], boolean)
1555: */
1556: public synchronized IDataSet getTablePrivilegesDataSet(
1557: ITableInfo ti, int[] columnIndices, boolean computeWidths)
1558: throws DataSetException {
1559: ResultSet rs = null;
1560: try {
1561: DatabaseMetaData md = privateGetJDBCMetaData();
1562: rs = md.getTablePrivileges(ti.getCatalogName(), ti
1563: .getSchemaName(), ti.getSimpleName());
1564: ResultSetDataSet rsds = new ResultSetDataSet();
1565: rsds.setResultSet(rs, columnIndices, computeWidths);
1566: return rsds;
1567: } catch (SQLException e) {
1568: throw new DataSetException(e);
1569: } finally {
1570: SQLUtilities.closeResultSet(rs);
1571: }
1572: }
1573:
1574: /* (non-Javadoc)
1575: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getVersionColumns(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1576: *
1577: * @deprecated use getVersionColumnsDataSet instead
1578: */
1579: public ResultSet getVersionColumns(ITableInfo ti)
1580: throws SQLException {
1581: return privateGetJDBCMetaData().getVersionColumns(
1582: ti.getCatalogName(), ti.getSchemaName(),
1583: ti.getSimpleName());
1584: }
1585:
1586: /* (non-Javadoc)
1587: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getVersionColumnsDataSet(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1588: */
1589: public synchronized IDataSet getVersionColumnsDataSet(ITableInfo ti)
1590: throws DataSetException {
1591: ResultSet rs = null;
1592: try {
1593: DatabaseMetaData md = privateGetJDBCMetaData();
1594: rs = md.getVersionColumns(ti.getCatalogName(), ti
1595: .getSchemaName(), ti.getSimpleName());
1596: ResultSetDataSet rsds = new ResultSetDataSet();
1597: rsds.setResultSet(rs);
1598: return rsds;
1599: } catch (SQLException e) {
1600: throw new DataSetException(e);
1601: } finally {
1602: SQLUtilities.closeResultSet(rs);
1603: }
1604: }
1605:
1606: private ResultSet getColumns(ITableInfo ti) throws SQLException {
1607: return privateGetJDBCMetaData().getColumns(ti.getCatalogName(),
1608: ti.getSchemaName(), ti.getSimpleName(), "%");
1609: }
1610:
1611: /* (non-Javadoc)
1612: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getColumns(net.sourceforge.squirrel_sql.fw.sql.ITableInfo, int[], boolean)
1613: */
1614: public synchronized IDataSet getColumns(ITableInfo ti,
1615: int[] columnIndices, boolean computeWidths)
1616: throws DataSetException {
1617: IDataSet result = null;
1618: ResultSet rs = null;
1619: try {
1620: rs = getColumns(ti);
1621: ResultSetDataSet rsds = new ResultSetDataSet();
1622: rsds.setResultSet(rs, columnIndices, computeWidths);
1623: result = rsds;
1624: } catch (SQLException e) {
1625: throw new DataSetException(e);
1626: } finally {
1627: SQLUtilities.closeResultSet(rs);
1628: }
1629: return result;
1630: }
1631:
1632: /* (non-Javadoc)
1633: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getColumnInfo(java.lang.String, java.lang.String, java.lang.String)
1634: */
1635: public synchronized TableColumnInfo[] getColumnInfo(String catalog,
1636: String schema, String table) throws SQLException {
1637: ResultSet rs = null;
1638: try {
1639: final Map<Integer, TableColumnInfo> columns = new TreeMap<Integer, TableColumnInfo>();
1640: DatabaseMetaData md = privateGetJDBCMetaData();
1641: rs = md.getColumns(catalog, schema, table, "%");
1642: final ResultSetColumnReader rdr = new ResultSetColumnReader(
1643: rs);
1644:
1645: int index = 0;
1646: while (rdr.next()) {
1647: final TableColumnInfo tci = new TableColumnInfo(rdr
1648: .getString(1), // TABLE_CAT
1649: rdr.getString(2), // TABLE_SCHEM
1650: rdr.getString(3), // TABLE_NAME
1651: rdr.getString(4), // COLUMN_NAME
1652: rdr.getLong(5).intValue(), // DATA_TYPE
1653: rdr.getString(6), // TYPE_NAME
1654: rdr.getLong(7).intValue(), // COLUMN_SIZE
1655: rdr.getLong(9).intValue(), // DECIMAL_DIGITS
1656: rdr.getLong(10).intValue(), // NUM_PREC_RADIX
1657: rdr.getLong(11).intValue(), // NULLABLE
1658: rdr.getString(12), // REMARKS
1659: rdr.getString(13), // COLUMN_DEF
1660: rdr.getLong(16).intValue(), // CHAR_OCTET_LENGTH
1661: rdr.getLong(17).intValue(), // ORDINAL_POSITION
1662: rdr.getString(18), // IS_NULLABLE
1663: this );
1664: ////////////////////////////////////////////////////////////////////////////////////////////
1665: // The index is needed in case this method is called with schema = null, catalog = null
1666: // and two tables with the same name in different schemas/catalogs.
1667: // Without the index the same ordinal position could only occur once.
1668: ++index;
1669: //
1670: ////////////////////////////////////////////////////////////////////////////////////////////
1671: columns.put(Integer.valueOf(10000
1672: * tci.getOrdinalPosition() + index), tci);
1673: }
1674:
1675: return columns.values().toArray(
1676: new TableColumnInfo[columns.size()]);
1677:
1678: } finally {
1679: SQLUtilities.closeResultSet(rs);
1680: }
1681: }
1682:
1683: /* (non-Javadoc)
1684: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#getColumnInfo(net.sourceforge.squirrel_sql.fw.sql.ITableInfo)
1685: */
1686: public synchronized TableColumnInfo[] getColumnInfo(ITableInfo ti)
1687: throws SQLException {
1688: return getColumnInfo(ti.getCatalogName(), ti.getSchemaName(),
1689: ti.getSimpleName());
1690: }
1691:
1692: /* (non-Javadoc)
1693: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#correctlySupportsSetMaxRows()
1694: */
1695: public boolean correctlySupportsSetMaxRows() throws SQLException {
1696: return !IDriverNames.OPTA2000.equals(getDriverName());
1697: }
1698:
1699: /* (non-Javadoc)
1700: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#supportsMultipleResultSets()
1701: */
1702: public synchronized boolean supportsMultipleResultSets()
1703: throws SQLException {
1704: final String key = "supportsMultipleResultSets";
1705: Boolean value = (Boolean) _cache.get(key);
1706: if (value != null) {
1707: return value.booleanValue();
1708: }
1709:
1710: value = Boolean.valueOf(privateGetJDBCMetaData()
1711: .supportsMultipleResultSets());
1712: _cache.put(key, value);
1713:
1714: return value.booleanValue();
1715: }
1716:
1717: /* (non-Javadoc)
1718: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#storesUpperCaseIdentifiers()
1719: */
1720: public synchronized boolean storesUpperCaseIdentifiers()
1721: throws SQLException {
1722: final String key = "storesUpperCaseIdentifiers";
1723: Boolean value = (Boolean) _cache.get(key);
1724: if (value != null) {
1725: return value.booleanValue();
1726: }
1727:
1728: value = Boolean.valueOf(privateGetJDBCMetaData()
1729: .storesUpperCaseIdentifiers());
1730: _cache.put(key, value);
1731:
1732: return value.booleanValue();
1733: }
1734:
1735: /* (non-Javadoc)
1736: * @see net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData2#clearCache()
1737: */
1738: public void clearCache() {
1739: _cache.clear();
1740: }
1741:
1742: /**
1743: * Make a String array of the passed string. Commas separate the elements
1744: * in the input string. The array is sorted.
1745: *
1746: * @param data Data to be split into the array.
1747: *
1748: * @return data as an array.
1749: */
1750: private static String[] makeArray(String data) {
1751: if (data == null) {
1752: data = "";
1753: }
1754:
1755: final List<String> list = new ArrayList<String>();
1756: final StringTokenizer st = new StringTokenizer(data, ",");
1757: while (st.hasMoreTokens()) {
1758: list.add(st.nextToken());
1759: }
1760: Collections.sort(list);
1761:
1762: return list.toArray(new String[list.size()]);
1763: }
1764:
1765: /**
1766: * Return the <TT>DatabaseMetaData</TT> object for this connection.
1767: *
1768: * @return The <TT>DatabaseMetaData</TT> object for this connection.
1769: *
1770: * @throws SQLException Thrown if an SQL error occurs.
1771: */
1772: private DatabaseMetaData privateGetJDBCMetaData()
1773: throws SQLException {
1774: checkThread();
1775: return _conn.getConnection().getMetaData();
1776: }
1777:
1778: /**
1779: *
1780: * @param fki
1781: * @return
1782: */
1783: private String createForeignKeyInfoKey(ForeignKeyInfo fki) {
1784: final StringBuffer buf = new StringBuffer();
1785: buf.append(fki.getForeignKeyCatalogName()).append(
1786: fki.getForeignKeySchemaName()).append(
1787: fki.getForeignKeyTableName()).append(
1788: fki.getForeignKeyName()).append(
1789: fki.getPrimaryKeyCatalogName()).append(
1790: fki.getPrimaryKeySchemaName()).append(
1791: fki.getPrimaryKeyTableName()).append(
1792: fki.getPrimaryKeyName());
1793: return buf.toString();
1794: }
1795:
1796: /**
1797: * Check the thread of the caller to see if it is the event dispatch thread
1798: * and if we are debugging print a debug log message with the call trace.
1799: */
1800: private void checkThread() {
1801: /* This is extremely useful when trying to track down Swing UI freezing.
1802: * However, it currently fills the log which obscures other debug
1803: * messages even though UI performance is acceptable, so it is commented
1804: * out until it is needed later.
1805: if (s_log.isDebugEnabled() && SwingUtilities.isEventDispatchThread()) {
1806: try {
1807: throw new Exception("GUI Thread is doing database work");
1808: } catch (Exception e) {
1809: s_log.debug(e.getMessage(), e);
1810: }
1811: }
1812: */
1813: }
1814: }
|