/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
package IT.picosoft.jdbc;

import java.sql.*;

public class PicoDatabaseMetaData implements DatabaseMetaData {

   protected PicoDbApi odbcApi;
   protected PicoConnection con;

   public PicoDatabaseMetaData(PicoDbApi api, PicoConnection conn) {
      odbcApi = api;
      con = conn;
   }

   protected String getInfoString(short opt) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("getInfoString opt=" + opt);
      validateConnection();
      switch (opt) {
         case OdbcDef.SQL_ACCESSIBLE_TABLES:
            return "Y";
         case OdbcDef.SQL_ACCESSIBLE_PROCEDURES:
            return "N";
         case OdbcDef.SQL_TXN_CAPABLE:
            return String.valueOf(OdbcDef.SQL_TC_DDL_IGNORE);
         case OdbcDef.SQL_MAX_ROW_SIZE_INCLUDES_LONG:
            return "Y";
         case OdbcDef.SQL_QUALIFIER_NAME_SEPARATOR:
            return "";
         case OdbcDef.SQL_QUALIFIER_TERM:
            return "";
         case OdbcDef.SQL_DBMS_NAME:
            return "picoSQL";
         case OdbcDef.SQL_DBMS_VER:
            return "4.00.0000";
         case OdbcDef.SQL_DRIVER_VER:
            return "4.00.0000";
         case OdbcDef.SQL_DEFAULT_TXN_ISOLATION:
            return String.valueOf(OdbcDef.SQL_TXN_READ_UNCOMMITTED);
         case OdbcDef.SQL_SPECIAL_CHARACTERS:
            return "";
         case OdbcDef.SQL_IDENTIFIER_QUOTE_CHAR:
            return " ";
         case OdbcDef.SQL_MAX_BINARY_LITERAL_LEN:
            return "0";
         case OdbcDef.SQL_MAX_QUALIFIER_NAME_LEN:
            return "0";
         case OdbcDef.SQL_MAX_CHAR_LITERAL_LEN:
            return "32767";
         case OdbcDef.SQL_MAX_COLUMN_NAME_LEN:
            return "30";
         case OdbcDef.SQL_MAX_COLUMNS_IN_GROUP_BY:
            return "0";
         case OdbcDef.SQL_MAX_COLUMNS_IN_INDEX:
            return "0";
         case OdbcDef.SQL_MAX_COLUMNS_IN_ORDER_BY:
            return "0";
         case OdbcDef.SQL_MAX_COLUMNS_IN_SELECT:
            return "0";
         case OdbcDef.SQL_MAX_COLUMNS_IN_TABLE:
            return "0";
         case OdbcDef.SQL_ACTIVE_CONNECTIONS:
            return "0";
         case OdbcDef.SQL_MAX_CURSOR_NAME_LEN:
            return "0";
         case OdbcDef.SQL_MAX_INDEX_SIZE:
            return "250";
         case OdbcDef.SQL_MAX_PROCEDURE_NAME_LEN:
            return "0";
         case OdbcDef.SQL_MAX_ROW_SIZE:
            return "32767";
         case OdbcDef.SQL_MAX_OWNER_NAME_LEN:
            return "0";
         case OdbcDef.SQL_MAX_STATEMENT_LEN:
            return "0";
         case OdbcDef.SQL_ACTIVE_STATEMENTS:
            return "0";
         case OdbcDef.SQL_MAX_TABLE_NAME_LEN:
            return "30";
         case OdbcDef.SQL_MAX_TABLES_IN_SELECT:
            return "0";
         case OdbcDef.SQL_MAX_USER_NAME_LEN:
            return "30";
         case OdbcDef.SQL_NUMERIC_FUNCTIONS:
            return String.valueOf (OdbcDef.SQL_FN_NUM_ABS|
                                   OdbcDef.SQL_FN_NUM_ROUND);
         case OdbcDef.SQL_PROCEDURE_TERM:
            return "";
         case OdbcDef.SQL_KEYWORDS:
            return "";
         case OdbcDef.SQL_OWNER_TERM:
            return "";
         case OdbcDef.SQL_SEARCH_PATTERN_ESCAPE:
            return "\\";
         case OdbcDef.SQL_STRING_FUNCTIONS:
            return String.valueOf (OdbcDef.SQL_FN_STR_CONCAT|
                                   OdbcDef.SQL_FN_STR_LTRIM|
                                   OdbcDef.SQL_FN_STR_LENGTH|
                                   OdbcDef.SQL_FN_STR_LCASE |
                                   OdbcDef.SQL_FN_STR_RTRIM |
                                   OdbcDef.SQL_FN_STR_SUBSTRING |
                                   OdbcDef.SQL_FN_STR_UCASE);
         case OdbcDef.SQL_SYSTEM_FUNCTIONS:
            return "0";
         case OdbcDef.SQL_TIMEDATE_FUNCTIONS:
            return "0";
         case OdbcDef.SQL_USER_NAME:
            return "";
         case OdbcDef.SQL_QUALIFIER_LOCATION:
            return "0";
         case OdbcDef.SQL_DATA_SOURCE_READ_ONLY:
            return "N";
         case OdbcDef.SQL_CONCAT_NULL_BEHAVIOR:
            return String.valueOf(OdbcDef.SQL_CB_NON_NULL);
         case OdbcDef.SQL_NULL_COLLATION:
            return String.valueOf (OdbcDef.SQL_NC_START);
         case OdbcDef.SQL_IDENTIFIER_CASE:
            return String.valueOf (OdbcDef.SQL_IC_UPPER);
         case OdbcDef.SQL_QUOTED_IDENTIFIER_CASE:
            return String.valueOf (OdbcDef.SQL_IC_UPPER);
         case OdbcDef.SQL_ALTER_TABLE:
            return "0";
         case OdbcDef.SQL_QUALIFIER_USAGE:
            return "0";
         case OdbcDef.SQL_COLUMN_ALIAS:
            return "Y";
         case OdbcDef.SQL_CONVERT_FUNCTIONS:
            return String.valueOf (OdbcDef.SQL_FN_CVT_CONVERT);
         case OdbcDef.SQL_ODBC_SQL_CONFORMANCE:
            return String.valueOf (OdbcDef.SQL_OSC_CORE);
         case OdbcDef.SQL_SUBQUERIES:
            return String.valueOf (OdbcDef.SQL_SQ_EXISTS);
         case OdbcDef.SQL_EXPRESSIONS_IN_ORDERBY:
            return "N";
         case OdbcDef.SQL_OUTER_JOINS:
            return "Y";
         case OdbcDef.SQL_GROUP_BY:
            return String.valueOf(
                          OdbcDef.SQL_GB_GROUP_BY_CONTAINS_SELECT);
         case OdbcDef.SQL_ODBC_SQL_OPT_IEF:
            return "N";
         case OdbcDef.SQL_LIKE_ESCAPE_CLAUSE:
            return "N";
         case OdbcDef.SQL_MULT_RESULT_SETS:
            return "N";
         case OdbcDef.SQL_MULTIPLE_ACTIVE_TXN:
            return "N";
         case OdbcDef.SQL_NON_NULLABLE_COLUMNS:
            return "0";
         case OdbcDef.SQL_CURSOR_COMMIT_BEHAVIOR:
         case OdbcDef.SQL_CURSOR_ROLLBACK_BEHAVIOR:
            return String.valueOf(OdbcDef.SQL_CB_PRESERVE);
         case OdbcDef.SQL_POSITIONED_STATEMENTS:
            return "0";
         case OdbcDef.SQL_OWNER_USAGE:
            return "0";
         case OdbcDef.SQL_PROCEDURES:
            return "N";
         case OdbcDef.SQL_CORRELATION_NAME:
            return String.valueOf(OdbcDef.SQL_CN_ANY);
         case OdbcDef.SQL_UNION:
            return "0";
         case OdbcDef.SQL_FILE_USAGE:
            return String.valueOf(OdbcDef.SQL_FILE_NOT_SUPPORTED);
      }
      throw new UnsupportedOperationException();
   }
   protected int getInfo(short opt) throws SQLException {
      return Integer.parseInt (getInfoString(opt));
   }
   protected short getInfoShort(short opt) throws SQLException {
      return Short.parseShort (getInfoString(opt));
   }

   protected void validateConnection() throws SQLException {
      con.validateConnection();
   }

   protected boolean getInfoBooleanString(short opt) throws SQLException {
      validateConnection();
      String s = "N";
      return s.equalsIgnoreCase("Y");
   }

   public boolean allProceduresAreCallable() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.allProceduresAreCallable");
      return getInfoBooleanString(OdbcDef.SQL_ACCESSIBLE_PROCEDURES);
   }

   public boolean allTablesAreSelectable() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.allTablesAreSelectable");
      return getInfoBooleanString(OdbcDef.SQL_ACCESSIBLE_TABLES);
   }

   public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.dataDefintionCausesTransactionCommit");
      int i = getInfoShort(OdbcDef.SQL_TXN_CAPABLE);
      return (i & 0x3) > 0;
   }
   public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.dataDefintionIgnoredInTransactions");
      int i = getInfoShort(OdbcDef.SQL_TXN_CAPABLE);
      return (i & 0x4) > 0;
   }

   public boolean deletesAreDetected(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.doesMaxRowSizeIncludeBlobs");
      return getInfoBooleanString(OdbcDef.SQL_MAX_ROW_SIZE_INCLUDES_LONG);
   }

   public ResultSet getBestRowIdentifier(String s, String s1,
                       String s2, int i, boolean flag) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getBestRowIdentifier (" + s + "," + s1 + "," + s2 + "," + i + "," + flag + ")");
      
      PicoResultSet rs = null;
      SQLWarning sqlwarning = null;
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLSpecialColumns(hstmt, (short)1, s, s1, s2, i, flag);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      }
      catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      rs.setSQLTypeColumn(3);
      return rs;
   }

   public String getCatalogSeparator() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getCatalogSeparator");
      return getInfoString(OdbcDef.SQL_QUALIFIER_NAME_SEPARATOR);
   }

   public String getCatalogTerm() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getCatalogTerm");
      return getInfoString(OdbcDef.SQL_QUALIFIER_TERM);
   }

   public ResultSet getCatalogs() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getCatalogs");
      PicoResultSet rs = (PicoResultSet)getTables("%", "", "", null);
      int ai[] = new int[1];
      ai[0] = 1;
      rs.setColumnMappings(ai);
      return rs;
   }

   public ResultSet getColumnPrivileges(String s, String s1, String s2,
                                        String s3) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public ResultSet getColumns(String s, String s1, String s2, String s3)
      throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getColumns (" + s + "," + s1 + "," + s2 + "," + s3 + ")");
      PicoResultSet rs = null;
      SQLWarning sqlwarning = null;
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLColumns(hstmt, s, s1, s2, s3);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      }
      catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      PicoPseudoCol pcol[] = new PicoPseudoCol[10];
      pcol[0] = new PicoPseudoCol("COLUMN_DEF", OdbcDef.SQL_VARCHAR, 254);
      pcol[1] = new PicoPseudoCol("SQL_DATA_TYPE", OdbcDef.SQL_INTEGER, 0);
      pcol[2] = new PicoPseudoCol("SQL_DATETIME_SUB", OdbcDef.SQL_INTEGER, 0);
      pcol[3] = new PicoPseudoCol("CHAR_OCTET_LENGTH", OdbcDef.SQL_INTEGER, 0);
      pcol[4] = new PicoPseudoCol("ORDINAL_POSITION", OdbcDef.SQL_INTEGER, 0);
      pcol[5] = new PicoPseudoCol("IS_NULLABLE", OdbcDef.SQL_VARCHAR, 254);
      pcol[6] = new PicoPseudoCol("SCOPE_CATLOG", OdbcDef.SQL_VARCHAR, 254);
      pcol[7] = new PicoPseudoCol("SCOPE_SCHEMA", OdbcDef.SQL_VARCHAR, 254);
      pcol[8] = new PicoPseudoCol("SCOPE_TABLE", OdbcDef.SQL_VARCHAR, 254);
      pcol[9] = new PicoPseudoCol("SOURCE_DATA_TYPE", OdbcDef.SQL_SMALLINT, 0);
      rs.setPseudoCols(13, 22, pcol);
      rs.setSQLTypeColumn(5);
      return rs;
   }

   public Connection getConnection() {
      return con;
   }

   public ResultSet getCrossReference(String s, String s1, String s2,
                                      String s3, String s4, String s5)
      throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getCrossReference (" + s + "," + s1 + "," + s2 + "," + s3 + "," + s4 + "," + s5 + ")");
      throw new UnsupportedOperationException();
   }

   public String getDatabaseProductName() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getDatabaseProductName");
      return getInfoString(OdbcDef.SQL_DBMS_NAME);
   }

   public String getDatabaseProductVersion() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getDatabaseProductVersion");
      return getInfoString(OdbcDef.SQL_DBMS_VER);
   }

   public int getDefaultTransactionIsolation() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getDefaultTransactionIsolation");
      return (byte) getInfo(OdbcDef.SQL_DEFAULT_TXN_ISOLATION);
   }

   public int getDriverMajorVersion() {
      return 4;
   }

   public int getDriverMinorVersion() {
      return 0001;
   }

   public String getDriverName() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getDriverName");
      return "picoSQL JDBC driver";
   }

   public String getDriverVersion() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getDriverVersion");
      int i = getDriverMinorVersion();
      String s = "";
      if(i < 1000)
         s = s + "0";
      if(i < 100)
         s = s + "0";
      if(i < 10)
         s = s + "0";
      s = s + "" + i;
      return getDriverMajorVersion() + "." + s + " (" + getInfoString(OdbcDef.SQL_DRIVER_VER) + ")";
   }

   public ResultSet getExportedKeys(String s, String s1, String s2)
      throws SQLException {
      throw new UnsupportedOperationException();
   }

   public String getExtraNameCharacters() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getExtraNameCharacters");
      return getInfoString(OdbcDef.SQL_SPECIAL_CHARACTERS);
   }

   public String getIdentifierQuoteString() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getIdentifierQuoteString");
      return getInfoString(OdbcDef.SQL_IDENTIFIER_QUOTE_CHAR);
   }

   public ResultSet getImportedKeys(String s, String s1, String s2)
      throws SQLException {
      throw new UnsupportedOperationException();
   }

   public ResultSet getIndexInfo(String s, String s1, String s2,
                            boolean flag, boolean flag1) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getIndexInfo (" + s + "," + s1 + "," + s2 + flag + "," + flag1 + ")");
      PicoResultSet rs = null;
      SQLWarning sqlwarning = null;
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLStatistics(hstmt, s, s1, s2, flag, flag1);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      } catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      return rs;
   }

   public int getMaxBinaryLiteralLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxBinaryLiteralLength");
      return getInfo(OdbcDef.SQL_MAX_BINARY_LITERAL_LEN);
   }

   public int getMaxCatalogNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxCatalogNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_QUALIFIER_NAME_LEN);
   }

   public int getMaxCharLiteralLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxCharLiteralLength");
      return getInfo(OdbcDef.SQL_MAX_CHAR_LITERAL_LEN);
   }

   public int getMaxColumnNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMN_NAME_LEN);
   }

   public int getMaxColumnsInGroupBy() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnsInGroupBy");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMNS_IN_GROUP_BY);
   }

   public int getMaxColumnsInIndex() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnsInIndex");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMNS_IN_INDEX);
   }

   public int getMaxColumnsInOrderBy() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnsInOrderBy");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMNS_IN_ORDER_BY);
   }

   public int getMaxColumnsInSelect() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnsInSeleted");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMNS_IN_SELECT);
   }

   public int getMaxColumnsInTable() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxColumnsInTable");
      return getInfoShort(OdbcDef.SQL_MAX_COLUMNS_IN_TABLE);
   }

   public int getMaxConnections() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxConnections");
      return getInfoShort(OdbcDef.SQL_ACTIVE_CONNECTIONS);
   }

   public int getMaxCursorNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxCursorNameLength");
      return getInfo(OdbcDef.SQL_MAX_CURSOR_NAME_LEN);
   }

   public int getMaxIndexLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxIndexLength");
      return getInfo(OdbcDef.SQL_MAX_INDEX_SIZE);
   }

   public int getMaxProcedureNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxProcedureNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_PROCEDURE_NAME_LEN);
   }

   public int getMaxRowSize() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxRowSize");
      return getInfo(OdbcDef.SQL_MAX_ROW_SIZE);
   }

   public int getMaxSchemaNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxSchemaNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_OWNER_NAME_LEN);
   }

   public int getMaxStatementLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxStatementLength");
      return getInfo(OdbcDef.SQL_MAX_STATEMENT_LEN);
   }

   public int getMaxStatements() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxStatements");
      return getInfoShort(OdbcDef.SQL_ACTIVE_STATEMENTS);
   }

   public int getMaxTableNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxTableNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_TABLE_NAME_LEN);
   }

   public int getMaxTablesInSelect() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxTablesInSelect");
      return getInfoShort(OdbcDef.SQL_MAX_TABLES_IN_SELECT);
   }

   public int getMaxUserNameLength() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getMaxUserNameLength");
      return getInfoShort(OdbcDef.SQL_MAX_USER_NAME_LEN);
   }

   public String getNumericFunctions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getNumericFunctions");
      String s = "";
      int i = getInfo(OdbcDef.SQL_NUMERIC_FUNCTIONS);
      if((i & 0x1) != 0)
         s = s + "ABS,";
      if((i & 0x2) != 0)
         s = s + "ACOS,";
      if((i & 0x4) != 0)
         s = s + "ASIN,";
      if((i & 0x8) != 0)
         s = s + "ATAN,";
      if((i & 0x10) != 0)
         s = s + "ATAN2,";
      if((i & 0x20) != 0)
         s = s + "CEILING,";
      if((i & 0x40) != 0)
         s = s + "COS,";
      if((i & 0x80) != 0)
         s = s + "COT,";
      if((i & 0x40000) != 0)
         s = s + "DEGREES,";
      if((i & 0x100) != 0)
         s = s + "EXP,";
      if((i & 0x200) != 0)
         s = s + "FLOOR,";
      if((i & 0x400) != 0)
         s = s + "LOG,";
      if((i & 0x80000) != 0)
         s = s + "LOG10,";
      if((i & 0x800) != 0)
         s = s + "MOD,";
      if((i & 0x10000) != 0)
         s = s + "PI,";
      if((i & 0x100000) != 0)
         s = s + "POWER,";
      if((i & 0x200000) != 0)
         s = s + "RADIANS,";
      if((i & 0x20000) != 0)
         s = s + "RAND,";
      if((i & 0x400000) != 0)
         s = s + "ROUND,";
      if((i & 0x1000) != 0)
         s = s + "SIGN,";
      if((i & 0x2000) != 0)
         s = s + "SIN,";
      if((i & 0x4000) != 0)
         s = s + "SQRT,";
      if((i & 0x8000) != 0)
         s = s + "TAN,";
      if((i & 0x800000) != 0)
         s = s + "TRUNCATE,";
      if(s.length() > 0)
         s = s.substring(0, s.length() - 1);
      return s;
   }

   public ResultSet getPrimaryKeys(String s, String s1, String s2)
      throws SQLException {
      throw new UnsupportedOperationException();
   }

   public ResultSet getProcedureColumns(String s, String s1, String s2,
                                        String s3) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public String getProcedureTerm() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getProcedureTerm");
      return getInfoString(OdbcDef.SQL_PROCEDURE_TERM);
   }

   public ResultSet getProcedures(String s, String s1, String s2)
      throws SQLException {
      throw new UnsupportedOperationException();
   }

   public String getSQLKeywords() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getSQLKeywords");
      return getInfoString(OdbcDef.SQL_KEYWORDS);
   }

   public String getSchemaTerm() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getSchemaTerm");
      return getInfoString(OdbcDef.SQL_OWNER_TERM);
   }

   public ResultSet getSchemas() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getSchemas");
      PicoResultSet rs = (PicoResultSet)getTables("", "%", "", null);
      int ai[] = new int[1];
      ai[0] = 2;
      rs.setColumnMappings(ai);
      return rs;
   }

   public String getSearchStringEscape() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getSearchStringEscape");
      return getInfoString(OdbcDef.SQL_SEARCH_PATTERN_ESCAPE);
   }

   public String getStringFunctions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getStringFunctions");
      String s = "";
      int i = getInfo(OdbcDef.SQL_STRING_FUNCTIONS);
      if((i & 0x2000) != 0)
         s = s + "ASCII,";
      if((i & 0x4000) != 0)
         s = s + "CHAR,";
      if((i & 0x1) != 0)
         s = s + "CONCAT,";
      if((i & 0x8000) != 0)
         s = s + "DIFFERENCE,";
      if((i & 0x2) != 0)
         s = s + "INSERT,";
      if((i & 0x40) != 0)
         s = s + "LCASE,";
      if((i & 0x4) != 0)
         s = s + "LEFT,";
      if((i & 0x10) != 0)
         s = s + "LENGTH,";
      if((i & 0x20) != 0)
         s = s + "LOCATE,";
      if((i & 0x10000) != 0)
         s = s + "LOCATE_2,";
      if((i & 0x8) != 0)
         s = s + "LTRIM,";
      if((i & 0x80) != 0)
         s = s + "REPEAT,";
      if((i & 0x100) != 0)
         s = s + "REPLACE,";
      if((i & 0x200) != 0)
         s = s + "RIGHT,";
      if((i & 0x400) != 0)
         s = s + "RTRIM,";
      if((i & 0x20000) != 0)
         s = s + "SOUNDEX,";
      if((i & 0x40000) != 0)
         s = s + "SPACE,";
      if((i & 0x800) != 0)
         s = s + "SUBSTRING,";
      if((i & 0x1000) != 0)
         s = s + "UCASE,";
      if(s.length() > 0)
         s = s.substring(0, s.length() - 1);
      return s;
   }

   public String getSystemFunctions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getSystemFunctions");
      String s = "";
      int i = getInfo(OdbcDef.SQL_SYSTEM_FUNCTIONS);
      if((i & 0x2) != 0)
         s = s + "DBNAME,";
      if((i & 0x4) != 0)
         s = s + "IFNULL,";
      if((i & 0x1) != 0)
         s = s + "USERNAME,";
      if(s.length() > 0)
         s = s.substring(0, s.length() - 1);
      return s;
   }

   public ResultSet getTablePrivileges(String s, String s1, String s2)
      throws SQLException {
      throw new UnsupportedOperationException();
   }

   public ResultSet getTableTypes() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getTableTypes");
      String as[] = new String[1];
      as[0] = "%";
      PicoResultSet rs = (PicoResultSet)getTables("", "", "", as);
      int ai[] = new int[1];
      ai[0] = 4;
      rs.setColumnMappings(ai);
      return rs;
   }

   public ResultSet getTables(String s, String s1, String s2, String as[])
      throws SQLException {
      PicoResultSet rs = null;
      String s3 = null;
      SQLWarning sqlwarning = null;
      if(as != null) {
         s3 = "";
         boolean flag = false;
         for(short word0 = 0; word0 < as.length; word0++) {
            String s4 = as[word0];
            if(word0 > 0)
               s3 = s3 + ",";
            s3 = s3 + s4;
         }

      }
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getTables (" + s + "," + s1 + "," + s2 + "," + s3 + ")");
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLTables(hstmt, s, s1, s2, s3);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      } catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      return rs;
   }

   public String getTimeDateFunctions() throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getTimeDateFunctions");
      String s = "";
      int i = getInfo(OdbcDef.SQL_TIMEDATE_FUNCTIONS);
      if((i & 0x2) != 0)
         s = s + "CURDATE,";
      if((i & 0x200) != 0)
         s = s + "CURTIME,";
      if((i & 0x8000) != 0)
         s = s + "DAYNAME,";
      if((i & 0x4) != 0)
         s = s + "DAYOFMONTH,";
      if((i & 0x8) != 0)
         s = s + "DAYOFWEEK,";
      if((i & 0x10) != 0)
         s = s + "DAYOFYEAR,";
      if((i & 0x400) != 0)
         s = s + "HOUR,";
      if((i & 0x800) != 0)
         s = s + "MINUTE,";
      if((i & 0x20) != 0)
         s = s + "MONTH,";
      if((i & 0x10000) != 0)
         s = s + "MONTHNAME,";
      if((i & 0x1) != 0)
         s = s + "NOW,";
      if((i & 0x40) != 0)
         s = s + "QUARTER,";
      if((i & 0x1000) != 0)
         s = s + "SECOND,";
      if((i & 0x2000) != 0)
         s = s + "TIMESTAMPADD,";
      if((i & 0x4000) != 0)
         s = s + "TIMESTAMPDIFF,";
      if((i & 0x80) != 0)
         s = s + "WEEK,";
      if((i & 0x100) != 0)
         s = s + "YEAR,";
      if(s.length() > 0)
         s = s.substring(0, s.length() - 1);
      return s;
   }

   public ResultSet getTypeInfo() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getTypeInfo");
      PicoResultSet rs = null;
      SQLWarning sqlwarning = null;
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLGetTypeInfo(hstmt, (short)0);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      } catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      PicoPseudoCol pcol[] = new PicoPseudoCol[5];
      pcol[0] = new PicoPseudoCol("OdbcDef.SQL_DATA_TYPE", 5, 0);
      pcol[1] = new PicoPseudoCol("OdbcDef.SQL_DATETIME_SUB", 5, 0);
      pcol[2] = new PicoPseudoCol("NUM_PREC_RADIX", 5, 0);
      rs.setPseudoCols(16, 18, pcol);
      rs.setSQLTypeColumn(2);
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("getTypeInfo rs=" + rs);
      return rs;
   }

   public ResultSet getUDTs(String s, String s1, String s2, int ai[]) {
      throw new UnsupportedOperationException();
   }

   public String getURL() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getURL");
      return con.getURL();
   }

   public String getUserName() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getUserName");
      return getInfoString(OdbcDef.SQL_USER_NAME);
   }

   public ResultSet getVersionColumns(String s, String s1, String s2)
      throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.getVersionColumns (" + s + "," + s1 + "," + s2 + ")");
      PicoResultSet rs = null;
      SQLWarning sqlwarning = null;
      OdbcStatement hstmt = new OdbcStatement (odbcApi, con.getHDBC());
      try {
         odbcApi.SQLSpecialColumns(hstmt, (short)2, s, s1, s2, 0, false);
      } catch(SQLWarning sqlwarning1) {
         sqlwarning = sqlwarning1;
      } catch(SQLException sqlexception) {
         hstmt.drop();
         throw sqlexception;
      }
      rs = new PicoResultSet(odbcApi, hstmt, con);
      rs.setWarning(sqlwarning);
      rs.setSQLTypeColumn(3);
      return rs;
   }

   public boolean insertsAreDetected(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean isCatalogAtStart() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.isCatalogAtStart");
      int i = getInfoShort(OdbcDef.SQL_QUALIFIER_LOCATION);
      return i == 1;
   }

   public boolean isReadOnly() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.isReadOnly");
      return getInfoBooleanString(OdbcDef.SQL_DATA_SOURCE_READ_ONLY);
   }

   public boolean nullPlusNonNullIsNull() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.nullPlusNullIsNull");
      int i = getInfoShort(OdbcDef.SQL_CONCAT_NULL_BEHAVIOR);
      return i == 0;
   }

   public boolean nullsAreSortedAtEnd() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.nullsAreSortedAtEnd");
      int i = getInfo(OdbcDef.SQL_NULL_COLLATION);
      return i == 4;
   }

   public boolean nullsAreSortedAtStart() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.nullsAreSortedAtStart");
      int i = getInfo(OdbcDef.SQL_NULL_COLLATION);
      return i == 2;
   }

   public boolean nullsAreSortedHigh() throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.nullsAreSortedHigh");
      int i = getInfoShort(OdbcDef.SQL_NULL_COLLATION);
      return i == 0;
   }

   public boolean nullsAreSortedLow() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.nullsAreSortedLow");
      int i = getInfo(OdbcDef.SQL_NULL_COLLATION);
      return i == 1;
   }

   public boolean othersDeletesAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean othersInsertsAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean othersUpdatesAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean ownDeletesAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean ownInsertsAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean ownUpdatesAreVisible(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean storesLowerCaseIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesLowerCaseIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_IDENTIFIER_CASE);
      return i == 2;
   }

   public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesLowerCaseQuotedIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_QUOTED_IDENTIFIER_CASE);
      return i == 2;
   }

   public boolean storesMixedCaseIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesMixedCaseIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_IDENTIFIER_CASE);
      return i == 4;
   }

   public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesMixedCaseQuotedIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_QUOTED_IDENTIFIER_CASE);
      return i == 4;
   }

   public boolean storesUpperCaseIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesUpperCaseIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_IDENTIFIER_CASE);
      return i == 1;
   }

   public boolean storesUpperCaseQuotedIdentifiers()
      throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.storesUpperCaseQuotedIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_QUOTED_IDENTIFIER_CASE);
      return i == 1;
   }

   public boolean supportsANSI92EntryLevelSQL() throws SQLException {
      return true;
   }

   public boolean supportsANSI92FullSQL() throws SQLException {
      return false;
   }

   public boolean supportsANSI92IntermediateSQL() throws SQLException {
      return false;
   }

   public boolean supportsAlterTableWithAddColumn() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsAlterTableWithAddColumn");
      int i = getInfo(OdbcDef.SQL_ALTER_TABLE);
      return (i & 0x1) > 0;
   }

   public boolean supportsAlterTableWithDropColumn() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsAlterTableWithDropColumn");
      int i = getInfo(OdbcDef.SQL_ALTER_TABLE);
      return (i & 0x2) > 0;
   }

   public boolean supportsBatchUpdates() {
      throw new UnsupportedOperationException();
   }

   public boolean supportsCatalogsInDataManipulation() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCatalogsInDataManipulation");
      int i = getInfo(OdbcDef.SQL_QUALIFIER_USAGE);
      return (i & 0x1) > 0;
   }

   public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCatalogsInIndexDefinitions");
      int i = getInfo(OdbcDef.SQL_QUALIFIER_USAGE);
      return (i & 0x8) > 0;
   }

   public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCatalogsInPrivilegeDefintions");
      int i = getInfo(OdbcDef.SQL_QUALIFIER_USAGE);
      return (i & 0x10) > 0;
   }

   public boolean supportsCatalogsInProcedureCalls() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCatalogsInProcedureCalls");
      int i = getInfo(OdbcDef.SQL_QUALIFIER_USAGE);
      return (i & 0x2) > 0;
   }

   public boolean supportsCatalogsInTableDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCatalogsInTableDefinitions");
      int i = getInfo(OdbcDef.SQL_QUALIFIER_USAGE);
      return (i & 0x4) > 0;
   }

   public boolean supportsColumnAliasing() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsColumnAliasing");
      return getInfoBooleanString(OdbcDef.SQL_COLUMN_ALIAS);
   }

   public boolean supportsConvert() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsConvert");
      int i = getInfo(OdbcDef.SQL_CONVERT_FUNCTIONS);
      return i == 1;
   }

   public boolean supportsConvert(int i, int j) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsConvert (" + i + "," + j + ")");
      short word0 = 0;
      boolean flag = false;
      int k = 0;
      switch(i) {
      case -7: 
         word0 = 55;
         break;

      case -6: 
         word0 = 68;
         break;

      case 5: // '\005'
         word0 = 65;
         break;

      case 4: // '\004'
         word0 = 61;
         break;

      case -5: 
         word0 = 53;
         break;

      case 6: // '\006'
         word0 = 60;
         break;

      case 7: // '\007'
         word0 = 64;
         break;

      case 8: // '\b'
         word0 = 59;
         break;

      case 2: // '\002'
         word0 = 63;
         break;

      case 3: // '\003'
         word0 = 58;
         break;

      case 1: // '\001'
         word0 = 56;
         break;

      case 12: // '\f'
         word0 = 70;
         break;

      case -1: 
         word0 = 62;
         break;

      case 91: // '['
         word0 = 57;
         break;

      case 92: // '\\'
         word0 = 66;
         break;

      case 93: // ']'
         word0 = 67;
         break;

      case -2: 
         word0 = 54;
         break;

      case -3: 
         word0 = 69;
         break;

      case -4: 
         word0 = 71;
         break;

      }
      int l = getInfo(word0);
      switch(j) {
      case -7: 
         k = 4096;
         break;

      case -6: 
         k = 8192;
         break;

      case 5: // '\005'
         k = 16;
         break;

      case 4: // '\004'
         k = 8;
         break;

      case -5: 
         k = 16384;
         break;

      case 6: // '\006'
         k = 32;
         break;

      case 7: // '\007'
         k = 64;
         break;

      case 8: // '\b'
         k = 128;
         break;

      case 2: // '\002'
         k = 2;
         break;

      case 3: // '\003'
         k = 4;
         break;

      case 1: // '\001'
         k = 1;
         break;

      case 12: // '\f'
         k = 256;
         break;

      case -1: 
         k = 512;
         break;

      case 91: // '['
         k = 32768;
         break;

      case 92: // '\\'
         k = 0x10000;
         break;

      case 93: // ']'
         k = 0x20000;
         break;

      case -2: 
         k = 1024;
         break;

      case -3: 
         k = 2048;
         break;

      case -4: 
         k = 0x40000;
         break;

      }
      return (l & k) > 0;
   }

   public boolean supportsCoreSQLGrammar() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCoreSQLGrammar");
      int i = getInfoShort(OdbcDef.SQL_ODBC_SQL_CONFORMANCE);
      return i == 1 || i == 2;
   }

   public boolean supportsCorrelatedSubqueries() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsCorrelatedSubqueries");
      int i = getInfo(OdbcDef.SQL_SUBQUERIES);
      return (i & 0x10) > 0;
   }

   public boolean supportsDataDefinitionAndDataManipulationTransactions()
      throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsDataDefinitionAndDataManipulationTransactions");
      int i = getInfoShort(OdbcDef.SQL_TXN_CAPABLE);
      return (i & 0x2) > 0;
   }

   public boolean supportsDataManipulationTransactionsOnly()
      throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsDataManipulationTransactionsOnly");
      int i = getInfoShort(OdbcDef.SQL_TXN_CAPABLE);
      return (i & 0x1) > 0;
   }

   public boolean supportsDifferentTableCorrelationNames()
      throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsDifferentTableCorrelationNames");
      int i = getInfoShort(OdbcDef.SQL_CORRELATION_NAME);
      return i == 1;
   }

   public boolean supportsExpressionsInOrderBy() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsExpressionsInOrderBy");
      return getInfoBooleanString(OdbcDef.SQL_EXPRESSIONS_IN_ORDERBY);
   }

   public boolean supportsExtendedSQLGrammar() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsExtendedSQLGrammar");
      int i = getInfoShort(OdbcDef.SQL_ODBC_SQL_CONFORMANCE);
      return i == 2;
   }

   public boolean supportsFullOuterJoins() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsFullOuterJoins");
      String s = getInfoString(OdbcDef.SQL_OUTER_JOINS);
      return s.equalsIgnoreCase("F");
   }

   public boolean supportsGroupBy() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsGroupBy");
      int i = getInfoShort(OdbcDef.SQL_GROUP_BY);
      return i != 0;
   }

   public boolean supportsGroupByBeyondSelect() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsGroupByBeyondSelect");
      int i = getInfoShort(OdbcDef.SQL_GROUP_BY);
      return i == 2;
   }

   public boolean supportsGroupByUnrelated() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsGroupByUnrelated");
      int i = getInfoShort(OdbcDef.SQL_GROUP_BY);
      return i == 3;
   }

   public boolean supportsIntegrityEnhancementFacility() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsIntegrityEnhancementFacility");
      return getInfoBooleanString(OdbcDef.SQL_ODBC_SQL_OPT_IEF);
   }

   public boolean supportsLikeEscapeClause() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsLikeEscapeClause");
      return getInfoBooleanString(OdbcDef.SQL_LIKE_ESCAPE_CLAUSE);
   }

   public boolean supportsLimitedOuterJoins() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsLimitedOuterJoins");
      String s = getInfoString(OdbcDef.SQL_OUTER_JOINS);
      return s.equalsIgnoreCase("P");
   }

   public boolean supportsMinimumSQLGrammar() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsMinimumSQLGrammar");
      int i = getInfoShort(OdbcDef.SQL_ODBC_SQL_CONFORMANCE);
      return i == 0 || i == 1 || i == 2;
   }

   public boolean supportsMixedCaseIdentifiers() throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsMixedCaseIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_IDENTIFIER_CASE);
      return i == 4 || i == 1 || i == 2;
   }

   public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsMixedCaseQuotedIdentifiers");
      int i = getInfoShort(OdbcDef.SQL_QUOTED_IDENTIFIER_CASE);
      return i == 4 || i == 1 || i == 2;
   }

   public boolean supportsMultipleResultSets() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsMultipleResultSets");
      return getInfoBooleanString(OdbcDef.SQL_MULT_RESULT_SETS);
   }

   public boolean supportsMultipleTransactions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsMultipleTransactions");
      return getInfoBooleanString(OdbcDef.SQL_MULTIPLE_ACTIVE_TXN);
   }

   public boolean supportsNonNullableColumns() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsNonNullableColumns");
      int i = getInfoShort(OdbcDef.SQL_NON_NULLABLE_COLUMNS);
      return i == 1;
   }

   public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOpenCursorsAcrossCommit");
      int i = getInfoShort(OdbcDef.SQL_CURSOR_COMMIT_BEHAVIOR);
      return i == 2;
   }

   public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOpenCursorsAcrossRollback");
      int i = getInfoShort(OdbcDef.SQL_CURSOR_ROLLBACK_BEHAVIOR);
      return i == 2;
   }

   public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOpenStatementsAcrossCommit");
      int i = getInfoShort(OdbcDef.SQL_CURSOR_COMMIT_BEHAVIOR);
      return i == 2 || i == 1;
   }

   public boolean supportsOpenStatementsAcrossRollback() throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOpenStatementsAcrossRollback");
      int i = getInfoShort(OdbcDef.SQL_CURSOR_ROLLBACK_BEHAVIOR);
      return i == 2 || i == 1;
   }

   public boolean supportsOrderByUnrelated() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOrderByUnrelated");
      return getInfoBooleanString(OdbcDef.SQL_ORDER_BY_COLUMNS_IN_SELECT);
   }

   public boolean supportsOuterJoins() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsOuterJoins");
      String s = getInfoString(OdbcDef.SQL_OUTER_JOINS);
      return s.equalsIgnoreCase("N") ^ true;
   }

   public boolean supportsPositionedDelete() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsPositionedDelete");
      int i = getInfo(OdbcDef.SQL_POSITIONED_STATEMENTS);
      return (i & 0x1) > 0;
   }

   public boolean supportsPositionedUpdate() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsPositionedUpdate");
      int i = getInfo(OdbcDef.SQL_POSITIONED_STATEMENTS);
      return (i & 0x2) > 0;
   }

   public boolean supportsResultSetConcurrency(int i, int j)
   {
      throw new UnsupportedOperationException();
   }

   public boolean supportsResultSetType(int i)
   {
      throw new UnsupportedOperationException();
   }

   public boolean supportsSchemasInDataManipulation() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSchemasInDataManipulation");
      int i = getInfo(OdbcDef.SQL_OWNER_USAGE);
      return (i & 0x1) > 0;
   }

   public boolean supportsSchemasInIndexDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSchemasInIndexDefintions");
      int i = getInfo(OdbcDef.SQL_OWNER_USAGE);
      return (i & 0x8) > 0;
   }

   public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSchemasInPrivilegeDefintions");
      int i = getInfo(OdbcDef.SQL_OWNER_USAGE);
      return (i & 0x10) > 0;
   }

   public boolean supportsSchemasInProcedureCalls() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSchemasInProcedureCalls");
      int i = getInfo(OdbcDef.SQL_OWNER_USAGE);
      return (i & 0x2) > 0;
   }

   public boolean supportsSchemasInTableDefinitions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSchemasInTableDefinitions");
      int i = getInfo(OdbcDef.SQL_OWNER_USAGE);
      return (i & 0x4) > 0;
   }

   public boolean supportsSelectForUpdate() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSelectForUpdate");
      int i = getInfo(OdbcDef.SQL_POSITIONED_STATEMENTS);
      return (i & 0x4) > 0;
   }

   public boolean supportsStoredProcedures() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsStoredProcedures");
      return getInfoBooleanString(OdbcDef.SQL_PROCEDURES);
   }

   public boolean supportsSubqueriesInComparisons() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSubqueriesInComparisions");
      int i = getInfo(OdbcDef.SQL_SUBQUERIES);
      return (i & 0x1) > 0;
   }

   public boolean supportsSubqueriesInExists() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSubqueriesInExists");
      int i = getInfo(OdbcDef.SQL_SUBQUERIES);
      return (i & 0x2) > 0;
   }

   public boolean supportsSubqueriesInIns() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSubqueriesInIns");
      int i = getInfo(OdbcDef.SQL_SUBQUERIES);
      return (i & 0x4) > 0;
   }

   public boolean supportsSubqueriesInQuantifieds() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSubqueriesInQuantifieds");
      int i = getInfo(OdbcDef.SQL_SUBQUERIES);
      return (i & 0x8) > 0;
   }

   public boolean supportsTableCorrelationNames() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsTableCorrelationNames");
      int i = getInfoShort(OdbcDef.SQL_CORRELATION_NAME);
      return i == 1 || i == 2;
   }

   public boolean supportsTransactionIsolationLevel(int i) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsTransactionIsolationLevel (" + i + ")");
      if(i == 0)
         return !supportsTransactions();
      int j = getInfo((short)72);
      boolean flag = false;
      switch(i)
      {
      case 1: // '\001'
         flag = (j & 0x1) > 0;
         break;

      case 2: // '\002'
         flag = (j & 0x2) > 0;
         break;

      case 4: // '\004'
         flag = (j & 0x4) > 0;
         break;

      case 8: // '\b'
         flag = (j & 0x8) > 0;
         break;

      }
      return flag;
   }

   public boolean supportsTransactions() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsTransactions");
      int i = getInfoShort(OdbcDef.SQL_TXN_CAPABLE);
      return i != 0;
   }

   public boolean supportsUnion() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsUnion");
      int i = getInfo(OdbcDef.SQL_UNION);
      return (i & 0x1) > 0;
   }

   public boolean supportsUnionAll() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsUnionAll");
      int i = getInfo(OdbcDef.SQL_UNION);
      return (i & 0x2) > 0;
   }

   public boolean supportsSavepoints() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.supportsSavepoints");
      return false;
   }

   public boolean supportsNamedParameters () throws SQLException {
      return false;
   }

   public boolean supportsMultipleOpenResults() throws SQLException {
      return false;
   }

   public boolean supportsGetGeneratedKeys () throws SQLException {
      return false;
   }

   public boolean supportsResultSetHoldability (int holdability)
                                                         throws SQLException {
      return false;
   }

   public boolean supportsStatementPooling () throws SQLException {
      return false;
   }

   public int getResultSetHoldability() throws SQLException {
      return ResultSet.HOLD_CURSORS_OVER_COMMIT;
   }

   public ResultSet getSuperTypes (String catalog, String schemaPattern,
                                   String typeNamePattern) throws SQLException{
      throw new UnsupportedOperationException();
   }

   public int getDatabaseMajorVersion() throws SQLException {
      return 5;
   }

   public int getDatabaseMinorVersion() throws SQLException {
      return 0;
   }

   public int getJDBCMajorVersion() throws SQLException {
      return 1;
   }

   public int getJDBCMinorVersion() throws SQLException {
      return 4;
   }

   public int getSQLStateType() throws SQLException {
      return sqlStateXOpen;
   }

   public boolean locatorsUpdateCopy() throws SQLException {
      return false;
   }

   public ResultSet getSuperTables(String catalog, String schemaPattern,
                                   String tableNamePattern) throws SQLException{
      throw new UnsupportedOperationException();
   }

   public ResultSet getAttributes(String catalog, String schemaPattern,
                                  String typeNamePattern,
                                  String attributeNamePattern)
                                                          throws SQLException {
      throw new UnsupportedOperationException();
   }

   public boolean updatesAreDetected(int i) {
      throw new UnsupportedOperationException();
   }

   public boolean usesLocalFilePerTable() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.usesLocalFilePerTable");
      int i = getInfoShort(OdbcDef.SQL_FILE_USAGE);
      return i == 1;
   }

   public boolean usesLocalFiles() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*DatabaseMetaData.usesLocalFiles");
      int i = getInfoShort(OdbcDef.SQL_FILE_USAGE);
      return i == 2;
   }

}
