DatabaseMetaData.java
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:85k
源码类别:

mpeg/mp3

开发平台:

C/C++

  1. package postgresql;
  2. import java.sql.*;
  3. import java.util.*;
  4. /**
  5.  * This class provides information about the database as a whole.
  6.  *
  7.  * <p>Many of the methods here return lists of information in ResultSets.  You
  8.  * can use the normal ResultSet methods such as getString and getInt to 
  9.  * retrieve the data from these ResultSets.  If a given form of metadata is
  10.  * not available, these methods should throw a SQLException.
  11.  *
  12.  * <p>Some of these methods take arguments that are String patterns.  These
  13.  * arguments all have names such as fooPattern.  Within a pattern String,
  14.  * "%" means match any substring of 0 or more characters, and "_" means
  15.  * match any one character.  Only metadata entries matching the search
  16.  * pattern are returned.  if a search pattern argument is set to a null
  17.  * ref, it means that argument's criteria should be dropped from the
  18.  * search.
  19.  *
  20.  * <p>A SQLException will be throws if a driver does not support a meta
  21.  * data method.  In the case of methods that return a ResultSet, either
  22.  * a ResultSet (which may be empty) is returned or a SQLException is
  23.  * thrown.
  24.  *
  25.  * @see java.sql.DatabaseMetaData
  26.  */
  27. public class DatabaseMetaData implements java.sql.DatabaseMetaData 
  28. {
  29.   Connection connection; // The connection association
  30.   
  31.   // These define various OID's. Hopefully they will stay constant.
  32.   static final int iVarcharOid = 1043; // OID for varchar
  33.   static final int iBoolOid = 16; // OID for bool
  34.   static final int iInt2Oid = 21; // OID for int2
  35.   static final int iInt4Oid = 23; // OID for int4
  36.   static final int VARHDRSZ =  4; // length for int4
  37.   
  38.   // This is a default value for remarks
  39.   private static final byte defaultRemarks[]="no remarks".getBytes();
  40.   
  41.   public DatabaseMetaData(Connection conn)
  42.   {
  43.     this.connection = conn;
  44.   }
  45.   
  46.   /**
  47.    * Can all the procedures returned by getProcedures be called
  48.    * by the current user?
  49.    *
  50.    * @return true if so
  51.    * @exception SQLException if a database access error occurs
  52.    */
  53.   public boolean allProceduresAreCallable() throws SQLException
  54.   {
  55.     return true; // For now...
  56.   }
  57.   
  58.   /**
  59.    * Can all the tables returned by getTable be SELECTed by
  60.    * the current user?
  61.    *
  62.    * @return true if so
  63.    * @exception SQLException if a database access error occurs
  64.    */
  65.   public boolean allTablesAreSelectable() throws SQLException
  66.   {
  67.     return true; // For now...
  68.   }
  69.   
  70.   /**
  71.    * What is the URL for this database?
  72.    *
  73.    * @return the url or null if it cannott be generated
  74.    * @exception SQLException if a database access error occurs
  75.    */
  76.   public String getURL() throws SQLException
  77.   {
  78.     return connection.getURL();
  79.   }
  80.   
  81.   /**
  82.    * What is our user name as known to the database?
  83.    *
  84.    * @return our database user name
  85.    * @exception SQLException if a database access error occurs
  86.    */
  87.   public String getUserName() throws SQLException
  88.   {
  89.     return connection.getUserName();
  90.   }
  91.   
  92.   /**
  93.    * Is the database in read-only mode?
  94.    *
  95.    * @return true if so
  96.    * @exception SQLException if a database access error occurs
  97.    */
  98.   public boolean isReadOnly() throws SQLException
  99.   {
  100.     return connection.isReadOnly();
  101.   }
  102.   
  103.   /**
  104.    * Are NULL values sorted high?
  105.    *
  106.    * @return true if so
  107.    * @exception SQLException if a database access error occurs
  108.    */
  109.   public boolean nullsAreSortedHigh() throws SQLException
  110.   {
  111.     return false;
  112.   }
  113.   
  114.   /**
  115.    * Are NULL values sorted low?
  116.    *
  117.    * @return true if so
  118.    * @exception SQLException if a database access error occurs
  119.    */
  120.   public boolean nullsAreSortedLow() throws SQLException
  121.   {
  122.     return false;
  123.   }
  124.   
  125.   /**
  126.    * Are NULL values sorted at the start regardless of sort order?
  127.    *
  128.    * @return true if so
  129.    * @exception SQLException if a database access error occurs
  130.    */
  131.   public boolean nullsAreSortedAtStart() throws SQLException
  132.   {
  133.     return false;
  134.   }
  135.   
  136.   /**
  137.    * Are NULL values sorted at the end regardless of sort order?
  138.    *
  139.    * @return true if so
  140.    * @exception SQLException if a database access error occurs
  141.    */
  142.   public boolean nullsAreSortedAtEnd() throws SQLException
  143.   {
  144.     return true;
  145.   }
  146.   
  147.   /**
  148.    * What is the name of this database product - we hope that it is
  149.    * PostgreSQL, so we return that explicitly.
  150.    *
  151.    * @return the database product name
  152.    * @exception SQLException if a database access error occurs
  153.    */
  154.   public String getDatabaseProductName() throws SQLException
  155.   {
  156.     return new String("PostgreSQL");
  157.   }
  158.   
  159.   /**
  160.    * What is the version of this database product.
  161.    *
  162.    * <p>Note that PostgreSQL 6.3 has a system catalog called pg_version - 
  163.    * however, select * from pg_version on any database retrieves
  164.    * no rows.
  165.    *
  166.    * <p>For now, we will return the version 6.3 (in the hope that we change
  167.    * this driver as often as we change the database)
  168.    *
  169.    * @return the database version
  170.    * @exception SQLException if a database access error occurs
  171.    */
  172.   public String getDatabaseProductVersion() throws SQLException
  173.   {
  174.     return ("6.4");
  175.   }
  176.   
  177.   /**
  178.    * What is the name of this JDBC driver?  If we don't know this
  179.    * we are doing something wrong!
  180.    *
  181.    * @return the JDBC driver name
  182.    * @exception SQLException why?
  183.    */
  184.   public String getDriverName() throws SQLException
  185.   {
  186.     return new String("PostgreSQL Native Driver");
  187.   }
  188.   
  189.   /**
  190.    * What is the version string of this JDBC driver?  Again, this is
  191.    * static.
  192.    *
  193.    * @return the JDBC driver name.
  194.    * @exception SQLException why?
  195.    */
  196.   public String getDriverVersion() throws SQLException
  197.   {
  198.     return new String(Integer.toString(connection.this_driver.getMajorVersion())+"."+Integer.toString(connection.this_driver.getMinorVersion()));
  199.   }
  200.   
  201.   /**
  202.    * What is this JDBC driver's major version number?
  203.    *
  204.    * @return the JDBC driver major version
  205.    */
  206.   public int getDriverMajorVersion()
  207.   {
  208.     return connection.this_driver.getMajorVersion();
  209.   }
  210.   
  211.   /**
  212.    * What is this JDBC driver's minor version number?
  213.    *
  214.    * @return the JDBC driver minor version
  215.    */
  216.   public int getDriverMinorVersion()
  217.   {
  218.     return connection.this_driver.getMinorVersion();
  219.   }
  220.   
  221.   /**
  222.    * Does the database store tables in a local file?  No - it
  223.    * stores them in a file on the server.
  224.    * 
  225.    * @return true if so
  226.    * @exception SQLException if a database access error occurs
  227.    */
  228.   public boolean usesLocalFiles() throws SQLException
  229.   {
  230.     return false;
  231.   }
  232.   
  233.   /**
  234.    * Does the database use a file for each table?  Well, not really,
  235.    * since it doesnt use local files. 
  236.    *
  237.    * @return true if so
  238.    * @exception SQLException if a database access error occurs
  239.    */
  240.   public boolean usesLocalFilePerTable() throws SQLException
  241.   {
  242.     return false;
  243.   }
  244.   
  245.   /**
  246.    * Does the database treat mixed case unquoted SQL identifiers
  247.    * as case sensitive and as a result store them in mixed case?
  248.    * A JDBC-Compliant driver will always return false.
  249.    *
  250.    * <p>Predicament - what do they mean by "SQL identifiers" - if it
  251.    * means the names of the tables and columns, then the answers
  252.    * given below are correct - otherwise I don't know.
  253.    *
  254.    * @return true if so
  255.    * @exception SQLException if a database access error occurs
  256.    */
  257.   public boolean supportsMixedCaseIdentifiers() throws SQLException
  258.   {
  259.     return false;
  260.   }
  261.   
  262.   /**
  263.    * Does the database treat mixed case unquoted SQL identifiers as
  264.    * case insensitive and store them in upper case?
  265.    *
  266.    * @return true if so
  267.    */
  268.   public boolean storesUpperCaseIdentifiers() throws SQLException
  269.   {
  270.     return false;
  271.   }
  272.   
  273.   /**
  274.    * Does the database treat mixed case unquoted SQL identifiers as
  275.    * case insensitive and store them in lower case?
  276.    *
  277.    * @return true if so
  278.    */
  279.   public boolean storesLowerCaseIdentifiers() throws SQLException
  280.   {
  281.     return true;
  282.   }
  283.   
  284.   /**
  285.    * Does the database treat mixed case unquoted SQL identifiers as
  286.    * case insensitive and store them in mixed case?
  287.    *
  288.    * @return true if so
  289.    */
  290.   public boolean storesMixedCaseIdentifiers() throws SQLException
  291.   {
  292.     return false;
  293.   }
  294.   
  295.   /**
  296.    * Does the database treat mixed case quoted SQL identifiers as
  297.    * case sensitive and as a result store them in mixed case?  A
  298.    * JDBC compliant driver will always return true. 
  299.    *
  300.    * <p>Predicament - what do they mean by "SQL identifiers" - if it
  301.    * means the names of the tables and columns, then the answers
  302.    * given below are correct - otherwise I don't know.
  303.    *
  304.    * @return true if so
  305.    * @exception SQLException if a database access error occurs
  306.    */
  307.   public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException
  308.   {
  309.     return true;
  310.   }
  311.   
  312.   /**
  313.    * Does the database treat mixed case quoted SQL identifiers as
  314.    * case insensitive and store them in upper case?
  315.    *
  316.    * @return true if so
  317.    */
  318.   public boolean storesUpperCaseQuotedIdentifiers() throws SQLException
  319.   {
  320.     return false;
  321.   }
  322.   
  323.   /**
  324.    * Does the database treat mixed case quoted SQL identifiers as case
  325.    * insensitive and store them in lower case?
  326.    *
  327.    * @return true if so
  328.    */
  329.   public boolean storesLowerCaseQuotedIdentifiers() throws SQLException
  330.   {
  331.     return false;
  332.   }
  333.   
  334.   /**
  335.    * Does the database treat mixed case quoted SQL identifiers as case
  336.    * insensitive and store them in mixed case?
  337.    *
  338.    * @return true if so
  339.    */
  340.   public boolean storesMixedCaseQuotedIdentifiers() throws SQLException
  341.   {
  342.     return false;
  343.   }
  344.   
  345.   /**
  346.    * What is the string used to quote SQL identifiers?  This returns
  347.    * a space if identifier quoting isn't supported.  A JDBC Compliant
  348.    * driver will always use a double quote character.
  349.    *
  350.    * <p>If an SQL identifier is a table name, column name, etc. then
  351.    * we do not support it.
  352.    *
  353.    * @return the quoting string
  354.    * @exception SQLException if a database access error occurs
  355.    */
  356.   public String getIdentifierQuoteString() throws SQLException
  357.   {
  358.     return null;
  359.   }
  360.   
  361.   /**
  362.    * Get a comma separated list of all a database's SQL keywords that
  363.    * are NOT also SQL92 keywords.
  364.    *
  365.    * <p>Within PostgreSQL, the keywords are found in
  366.    *  src/backend/parser/keywords.c
  367.    *
  368.    * <p>For SQL Keywords, I took the list provided at
  369.    *  <a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
  370.    * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
  371.    * which is for SQL3, not SQL-92, but it is close enough for
  372.    * this purpose.
  373.    *
  374.    * @return a comma separated list of keywords we use
  375.    * @exception SQLException if a database access error occurs
  376.    */
  377.   public String getSQLKeywords() throws SQLException
  378.   {
  379.     return new String("abort,acl,add,aggregate,append,archive,arch_store,backward,binary,change,cluster,copy,database,delimiters,do,extend,explain,forward,heavy,index,inherits,isnull,light,listen,load,merge,nothing,notify,notnull,oids,purge,rename,replace,retrieve,returns,rule,recipe,setof,stdin,stdout,store,vacuum,verbose,version");
  380.   }
  381.   
  382.   public String getNumericFunctions() throws SQLException
  383.   {
  384.     // XXX-Not Implemented
  385.     return "";
  386.   }
  387.   
  388.   public String getStringFunctions() throws SQLException
  389.   {
  390.     // XXX-Not Implemented
  391.     return "";
  392.   }
  393.   
  394.   public String getSystemFunctions() throws SQLException
  395.   {
  396.     // XXX-Not Implemented
  397.     return "";
  398.   }
  399.   
  400.   public String getTimeDateFunctions() throws SQLException
  401.   {
  402.     // XXX-Not Implemented
  403.     return "";
  404.   }
  405.   
  406.   /**
  407.    * This is the string that can be used to escape '_' and '%' in
  408.    * a search string pattern style catalog search parameters
  409.    *
  410.    * @return the string used to escape wildcard characters
  411.    * @exception SQLException if a database access error occurs
  412.    */
  413.   public String getSearchStringEscape() throws SQLException
  414.   {
  415.     return new String("\");
  416.   }
  417.   
  418.   /**
  419.    * Get all the "extra" characters that can bew used in unquoted
  420.    * identifier names (those beyond a-zA-Z0-9 and _)
  421.    *
  422.    * <p>From the file src/backend/parser/scan.l, an identifier is
  423.    * {letter}{letter_or_digit} which makes it just those listed
  424.    * above.
  425.    *
  426.    * @return a string containing the extra characters
  427.    * @exception SQLException if a database access error occurs
  428.    */
  429.   public String getExtraNameCharacters() throws SQLException
  430.   {
  431.     return new String("");
  432.   }
  433.   
  434.   /**
  435.    * Is "ALTER TABLE" with an add column supported?
  436.    * Yes for PostgreSQL 6.1
  437.    *
  438.    * @return true if so
  439.    * @exception SQLException if a database access error occurs
  440.    */
  441.   public boolean supportsAlterTableWithAddColumn() throws SQLException
  442.   {
  443.     return true;
  444.   }
  445.   
  446.   /**
  447.    * Is "ALTER TABLE" with a drop column supported?
  448.    * Yes for PostgreSQL 6.1
  449.    *
  450.    * @return true if so
  451.    * @exception SQLException if a database access error occurs
  452.    */
  453.   public boolean supportsAlterTableWithDropColumn() throws SQLException
  454.   {
  455.     return true;
  456.   }
  457.   
  458.   /**
  459.    * Is column aliasing supported?
  460.    *
  461.    * <p>If so, the SQL AS clause can be used to provide names for
  462.    * computed columns or to provide alias names for columns as
  463.    * required.  A JDBC Compliant driver always returns true.
  464.    *
  465.    * <p>e.g.
  466.    *
  467.    * <br><pre>
  468.    * select count(C) as C_COUNT from T group by C;
  469.    *
  470.    * </pre><br>
  471.    * should return a column named as C_COUNT instead of count(C)
  472.    *
  473.    * @return true if so
  474.    * @exception SQLException if a database access error occurs
  475.    */
  476.   public boolean supportsColumnAliasing() throws SQLException
  477.   {
  478.     return true;
  479.   }
  480.   
  481.   /**
  482.    * Are concatenations between NULL and non-NULL values NULL?  A
  483.    * JDBC Compliant driver always returns true
  484.    *
  485.    * @return true if so
  486.    * @exception SQLException if a database access error occurs
  487.    */
  488.   public boolean nullPlusNonNullIsNull() throws SQLException
  489.   {
  490.     return true;
  491.   }
  492.   
  493.   public boolean supportsConvert() throws SQLException
  494.   {
  495.     // XXX-Not Implemented
  496.     return false;
  497.   }
  498.   
  499.   public boolean supportsConvert(int fromType, int toType) throws SQLException
  500.   {
  501.     // XXX-Not Implemented
  502.     return false;
  503.   }
  504.   
  505.   public boolean supportsTableCorrelationNames() throws SQLException
  506.   {
  507.     // XXX-Not Implemented
  508.     return false;
  509.   }
  510.   
  511.   public boolean supportsDifferentTableCorrelationNames() throws SQLException
  512.   {
  513.     // XXX-Not Implemented
  514.     return false;
  515.   }
  516.   
  517.   /**
  518.    * Are expressions in "ORCER BY" lists supported?
  519.    * 
  520.    * <br>e.g. select * from t order by a + b;
  521.    *
  522.    * @return true if so
  523.    * @exception SQLException if a database access error occurs
  524.    */
  525.   public boolean supportsExpressionsInOrderBy() throws SQLException
  526.   {
  527.     return true;
  528.   }
  529.   
  530.   /**
  531.    * Can an "ORDER BY" clause use columns not in the SELECT?
  532.    * I checked it, and you can't.
  533.    *
  534.    * @return true if so
  535.    * @exception SQLException if a database access error occurs
  536.    */
  537.   public boolean supportsOrderByUnrelated() throws SQLException
  538.   {
  539.     return false;
  540.   }
  541.   
  542.   /**
  543.    * Is some form of "GROUP BY" clause supported?
  544.    * I checked it, and yes it is.
  545.    *
  546.    * @return true if so
  547.    * @exception SQLException if a database access error occurs
  548.    */
  549.   public boolean supportsGroupBy() throws SQLException
  550.   {
  551.     return true;
  552.   }
  553.   
  554.   /**
  555.    * Can a "GROUP BY" clause use columns not in the SELECT?
  556.    * I checked it - it seems to allow it
  557.    *
  558.    * @return true if so
  559.    * @exception SQLException if a database access error occurs
  560.    */
  561.   public boolean supportsGroupByUnrelated() throws SQLException
  562.   {
  563.     return true;
  564.   }
  565.   
  566.   /**
  567.    * Can a "GROUP BY" clause add columns not in the SELECT provided
  568.    * it specifies all the columns in the SELECT?  Does anyone actually
  569.    * understand what they mean here?
  570.    *
  571.    * @return true if so
  572.    * @exception SQLException if a database access error occurs
  573.    */
  574.   public boolean supportsGroupByBeyondSelect() throws SQLException
  575.   {
  576.     return true; // For now...
  577.   }
  578.   
  579.   /**
  580.    * Is the escape character in "LIKE" clauses supported?  A
  581.    * JDBC compliant driver always returns true.
  582.    *
  583.    * @return true if so
  584.    * @exception SQLException if a database access error occurs
  585.    */
  586.   public boolean supportsLikeEscapeClause() throws SQLException
  587.   {
  588.     return true;
  589.   }
  590.   
  591.   /**
  592.    * Are multiple ResultSets from a single execute supported?
  593.    * Well, I implemented it, but I dont think this is possible from
  594.    * the back ends point of view.
  595.    * 
  596.    * @return true if so
  597.    * @exception SQLException if a database access error occurs
  598.    */
  599.   public boolean supportsMultipleResultSets() throws SQLException
  600.   {
  601.     return false;
  602.   }
  603.   
  604.   /**
  605.    * Can we have multiple transactions open at once (on different
  606.    * connections?)
  607.    * I guess we can have, since Im relying on it.
  608.    *
  609.    * @return true if so
  610.    * @exception SQLException if a database access error occurs
  611.    */
  612.   public boolean supportsMultipleTransactions() throws SQLException
  613.   {
  614.     return true;
  615.   }
  616.   
  617.   /**
  618.    * Can columns be defined as non-nullable.  A JDBC Compliant driver
  619.    * always returns true.
  620.    *
  621.    * <p>This changed from false to true in v6.2 of the driver, as this
  622.    * support was added to the backend.
  623.    *
  624.    * @return true if so
  625.    * @exception SQLException if a database access error occurs
  626.    */
  627.   public boolean supportsNonNullableColumns() throws SQLException
  628.   {
  629.     return true;
  630.   }
  631.   
  632.   /**
  633.    * Does this driver support the minimum ODBC SQL grammar.  This
  634.    * grammar is defined at:
  635.    *
  636.    * <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
  637.    *
  638.    * <p>In Appendix C.  From this description, we seem to support the
  639.    * ODBC minimal (Level 0) grammar.
  640.    *
  641.    * @return true if so
  642.    * @exception SQLException if a database access error occurs
  643.    */
  644.   public boolean supportsMinimumSQLGrammar() throws SQLException
  645.   {
  646.     return true;
  647.   }
  648.   
  649.   /**
  650.    * Does this driver support the Core ODBC SQL grammar.  We need
  651.    * SQL-92 conformance for this.
  652.    *
  653.    * @return true if so
  654.    * @exception SQLException if a database access error occurs
  655.    */
  656.   public boolean supportsCoreSQLGrammar() throws SQLException
  657.   {
  658.     return false;
  659.   }
  660.   
  661.   /**
  662.    * Does this driver support the Extended (Level 2) ODBC SQL
  663.    * grammar.  We don't conform to the Core (Level 1), so we can't
  664.    * conform to the Extended SQL Grammar.
  665.    *
  666.    * @return true if so
  667.    * @exception SQLException if a database access error occurs
  668.    */
  669.   public boolean supportsExtendedSQLGrammar() throws SQLException
  670.   {
  671.     return false;
  672.   }
  673.   
  674.   /**
  675.    * Does this driver support the ANSI-92 entry level SQL grammar?
  676.    * All JDBC Compliant drivers must return true.  I think we have
  677.    * to support outer joins for this to be true.
  678.    *
  679.    * @return true if so
  680.    * @exception SQLException if a database access error occurs
  681.    */
  682.   public boolean supportsANSI92EntryLevelSQL() throws SQLException
  683.   {
  684.     return false;
  685.   }
  686.   
  687.   /**
  688.    * Does this driver support the ANSI-92 intermediate level SQL
  689.    * grammar?  Anyone who does not support Entry level cannot support
  690.    * Intermediate level.
  691.    *
  692.    * @return true if so
  693.    * @exception SQLException if a database access error occurs
  694.    */
  695.   public boolean supportsANSI92IntermediateSQL() throws SQLException
  696.   {
  697.     return false;
  698.   }
  699.   
  700.   /**
  701.    * Does this driver support the ANSI-92 full SQL grammar?
  702.    *
  703.    * @return true if so
  704.    * @exception SQLException if a database access error occurs
  705.    */
  706.   public boolean supportsANSI92FullSQL() throws SQLException
  707.   {
  708.     return false;
  709.   }
  710.   
  711.   /**
  712.    * Is the SQL Integrity Enhancement Facility supported?
  713.    * I haven't seen this mentioned anywhere, so I guess not
  714.    * 
  715.    * @return true if so
  716.    * @exception SQLException if a database access error occurs
  717.    */
  718.   public boolean supportsIntegrityEnhancementFacility() throws SQLException
  719.   {
  720.     return false;
  721.   }
  722.   
  723.   /**
  724.    * Is some form of outer join supported?  From my knowledge, nope.
  725.    *
  726.    * @return true if so
  727.    * @exception SQLException if a database access error occurs
  728.    */
  729.   public boolean supportsOuterJoins() throws SQLException
  730.   {
  731.     return false;
  732.   }
  733.   
  734.   /**
  735.    * Are full nexted outer joins supported?  Well, we dont support any
  736.    * form of outer join, so this is no as well
  737.    *
  738.    * @return true if so
  739.    * @exception SQLException if a database access error occurs
  740.    */
  741.   public boolean supportsFullOuterJoins() throws SQLException
  742.   {
  743.     return false;
  744.   }
  745.   
  746.   /**
  747.    * Is there limited support for outer joins?  (This will be true if
  748.    * supportFullOuterJoins is true)
  749.    *
  750.    * @return true if so
  751.    * @exception SQLException if a database access error occurs
  752.    */
  753.   public boolean supportsLimitedOuterJoins() throws SQLException
  754.   {
  755.     return false;
  756.   }
  757.   
  758.   /**
  759.    * What is the database vendor's preferred term for "schema" - well,
  760.    * we do not provide support for schemas, so lets just use that
  761.    * term.
  762.    *
  763.    * @return the vendor term
  764.    * @exception SQLException if a database access error occurs
  765.    */
  766.   public String getSchemaTerm() throws SQLException
  767.   {
  768.     return new String("Schema");
  769.   }
  770.   
  771.   /**
  772.    * What is the database vendor's preferred term for "procedure" - 
  773.    * I kind of like "Procedure" myself.
  774.    *
  775.    * @return the vendor term
  776.    * @exception SQLException if a database access error occurs
  777.    */
  778.   public String getProcedureTerm() throws SQLException
  779.   {
  780.     return new String("Procedure");
  781.   }
  782.   
  783.   /**
  784.    * What is the database vendor's preferred term for "catalog"? -
  785.    * we dont have a preferred term, so just use Catalog
  786.    *
  787.    * @return the vendor term
  788.    * @exception SQLException if a database access error occurs
  789.    */
  790.   public String getCatalogTerm() throws SQLException
  791.   {
  792.     return new String("Catalog");
  793.   }
  794.   
  795.   /**
  796.    * Does a catalog appear at the start of a qualified table name?
  797.    * (Otherwise it appears at the end).
  798.    *
  799.    * @return true if so
  800.    * @exception SQLException if a database access error occurs
  801.    */
  802.   public boolean isCatalogAtStart() throws SQLException
  803.   {
  804.     return false;
  805.   }
  806.   
  807.   /**
  808.    * What is the Catalog separator.  Hmmm....well, I kind of like
  809.    * a period (so we get catalog.table definitions). - I don't think
  810.    * PostgreSQL supports catalogs anyhow, so it makes no difference.
  811.    *
  812.    * @return the catalog separator string
  813.    * @exception SQLException if a database access error occurs
  814.    */
  815.   public String getCatalogSeparator() throws SQLException
  816.   {
  817.     // PM Sep 29 97 - changed from "." as we don't support catalogs.
  818.     return new String("");
  819.   }
  820.   
  821.   /**
  822.    * Can a schema name be used in a data manipulation statement?  Nope.
  823.    *
  824.    * @return true if so
  825.    * @exception SQLException if a database access error occurs
  826.    */
  827.   public boolean supportsSchemasInDataManipulation() throws SQLException
  828.   {
  829.     return false;
  830.   }
  831.   
  832.   /**
  833.    * Can a schema name be used in a procedure call statement?  Nope.
  834.    *
  835.    * @return true if so
  836.    * @exception SQLException if a database access error occurs
  837.    */
  838.   public boolean supportsSchemasInProcedureCalls() throws SQLException
  839.   {
  840.     return false;
  841.   }
  842.   
  843.   /**
  844.    * Can a schema be used in a table definition statement?  Nope.
  845.    *
  846.    * @return true if so
  847.    * @exception SQLException if a database access error occurs
  848.    */
  849.   public boolean supportsSchemasInTableDefinitions() throws SQLException
  850.   {
  851.     return false;
  852.   }
  853.   
  854.   /**
  855.    * Can a schema name be used in an index definition statement?
  856.    *
  857.    * @return true if so
  858.    * @exception SQLException if a database access error occurs
  859.    */
  860.   public boolean supportsSchemasInIndexDefinitions() throws SQLException
  861.   {
  862.     return false;
  863.   }
  864.   
  865.   /**
  866.    * Can a schema name be used in a privilege definition statement?
  867.    *
  868.    * @return true if so
  869.    * @exception SQLException if a database access error occurs
  870.    */
  871.   public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException
  872.   {
  873.     return false;
  874.   }
  875.   
  876.   /**
  877.    * Can a catalog name be used in a data manipulation statement?
  878.    *
  879.    * @return true if so
  880.    * @exception SQLException if a database access error occurs
  881.    */
  882.   public boolean supportsCatalogsInDataManipulation() throws SQLException
  883.   {
  884.     return false;
  885.   }
  886.   
  887.   /**
  888.    * Can a catalog name be used in a procedure call statement?
  889.    *
  890.    * @return true if so
  891.    * @exception SQLException if a database access error occurs
  892.    */
  893.   public boolean supportsCatalogsInProcedureCalls() throws SQLException
  894.   {
  895.     return false;
  896.   }
  897.   
  898.   /**
  899.    * Can a catalog name be used in a table definition statement?
  900.    *
  901.    * @return true if so
  902.    * @exception SQLException if a database access error occurs
  903.    */
  904.   public boolean supportsCatalogsInTableDefinitions() throws SQLException
  905.   {
  906.     return false;
  907.   }
  908.   
  909.   /**
  910.    * Can a catalog name be used in an index definition?
  911.    *
  912.    * @return true if so
  913.    * @exception SQLException if a database access error occurs
  914.    */
  915.   public boolean supportsCatalogsInIndexDefinitions() throws SQLException
  916.   {
  917.     return false;
  918.   }
  919.   
  920.   /**
  921.    * Can a catalog name be used in a privilege definition statement?
  922.    *
  923.    * @return true if so
  924.    * @exception SQLException if a database access error occurs
  925.    */
  926.   public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException
  927.   {
  928.     return false;
  929.   }
  930.   
  931.   /**
  932.    * We support cursors for gets only it seems.  I dont see a method
  933.    * to get a positioned delete.
  934.    *
  935.    * @return true if so
  936.    * @exception SQLException if a database access error occurs
  937.    */
  938.   public boolean supportsPositionedDelete() throws SQLException
  939.   {
  940.     return false; // For now...
  941.   }
  942.   
  943.   /**
  944.    * Is positioned UPDATE supported?
  945.    * 
  946.    * @return true if so
  947.    * @exception SQLException if a database access error occurs
  948.    */
  949.   public boolean supportsPositionedUpdate() throws SQLException
  950.   {
  951.     return false; // For now...
  952.   }
  953.   
  954.   public boolean supportsSelectForUpdate() throws SQLException
  955.   {
  956.     // XXX-Not Implemented
  957.     return false;
  958.   }
  959.   
  960.   public boolean supportsStoredProcedures() throws SQLException
  961.   {
  962.     // XXX-Not Implemented
  963.     return false;
  964.   }
  965.   
  966.   public boolean supportsSubqueriesInComparisons() throws SQLException
  967.   {
  968.     // XXX-Not Implemented
  969.     return false;
  970.   }
  971.   
  972.   public boolean supportsSubqueriesInExists() throws SQLException
  973.   {
  974.     // XXX-Not Implemented
  975.     return false;
  976.   }
  977.   
  978.   public boolean supportsSubqueriesInIns() throws SQLException
  979.   {
  980.     // XXX-Not Implemented
  981.     return false;
  982.   }
  983.   
  984.   public boolean supportsSubqueriesInQuantifieds() throws SQLException
  985.   {
  986.     // XXX-Not Implemented
  987.     return false;
  988.   }
  989.   
  990.   public boolean supportsCorrelatedSubqueries() throws SQLException
  991.   {
  992.     // XXX-Not Implemented
  993.     return false;
  994.   }
  995.   
  996.   /**
  997.    * Is SQL UNION supported?  Nope.
  998.    *
  999.    * @return true if so
  1000.    * @exception SQLException if a database access error occurs
  1001.    */
  1002.   public boolean supportsUnion() throws SQLException
  1003.   {
  1004.     return false;
  1005.   }
  1006.   
  1007.   /**
  1008.    * Is SQL UNION ALL supported?  Nope.
  1009.    *
  1010.    * @return true if so
  1011.    * @exception SQLException if a database access error occurs
  1012.    */
  1013.   public boolean supportsUnionAll() throws SQLException
  1014.   {
  1015.     return false;
  1016.   }
  1017.   
  1018.   /**
  1019.    * In PostgreSQL, Cursors are only open within transactions.
  1020.    *
  1021.    * @return true if so
  1022.    * @exception SQLException if a database access error occurs
  1023.    */
  1024.   public boolean supportsOpenCursorsAcrossCommit() throws SQLException
  1025.   {
  1026.     return false;
  1027.   }
  1028.   
  1029.   /**
  1030.    * Do we support open cursors across multiple transactions?
  1031.    *
  1032.    * @return true if so
  1033.    * @exception SQLException if a database access error occurs
  1034.    */
  1035.   public boolean supportsOpenCursorsAcrossRollback() throws SQLException
  1036.   {
  1037.     return false;
  1038.   }
  1039.   
  1040.   /**
  1041.    * Can statements remain open across commits?  They may, but
  1042.    * this driver cannot guarentee that.  In further reflection.
  1043.    * we are talking a Statement object jere, so the answer is
  1044.    * yes, since the Statement is only a vehicle to ExecSQL()
  1045.    *
  1046.    * @return true if they always remain open; false otherwise
  1047.    * @exception SQLException if a database access error occurs
  1048.    */
  1049.   public boolean supportsOpenStatementsAcrossCommit() throws SQLException
  1050.   {
  1051.     return true;
  1052.   }
  1053.   
  1054.   /**
  1055.    * Can statements remain open across rollbacks?  They may, but
  1056.    * this driver cannot guarentee that.  In further contemplation,
  1057.    * we are talking a Statement object here, so the answer is yes,
  1058.    * since the Statement is only a vehicle to ExecSQL() in Connection
  1059.    *
  1060.    * @return true if they always remain open; false otherwise
  1061.    * @exception SQLException if a database access error occurs
  1062.    */
  1063.   public boolean supportsOpenStatementsAcrossRollback() throws SQLException
  1064.   {
  1065.     return true;
  1066.   }
  1067.   
  1068.   /**
  1069.    * How many hex characters can you have in an inline binary literal
  1070.    *
  1071.    * @return the max literal length
  1072.    * @exception SQLException if a database access error occurs
  1073.    */
  1074.   public int getMaxBinaryLiteralLength() throws SQLException
  1075.   {
  1076.     return 0; // For now...
  1077.   }
  1078.   
  1079.   /**
  1080.    * What is the maximum length for a character literal
  1081.    * I suppose it is 8190 (8192 - 2 for the quotes)
  1082.    *
  1083.    * @return the max literal length
  1084.    * @exception SQLException if a database access error occurs
  1085.    */
  1086.   public int getMaxCharLiteralLength() throws SQLException
  1087.   {
  1088.     return 8190;
  1089.   }
  1090.   
  1091.   /**
  1092.    * Whats the limit on column name length.  The description of
  1093.    * pg_class would say '32' (length of pg_class.relname) - we
  1094.    * should probably do a query for this....but....
  1095.    *
  1096.    * @return the maximum column name length
  1097.    * @exception SQLException if a database access error occurs
  1098.    */
  1099.   public int getMaxColumnNameLength() throws SQLException
  1100.   {
  1101.     return 32;
  1102.   }
  1103.   
  1104.   /**
  1105.    * What is the maximum number of columns in a "GROUP BY" clause?
  1106.    *
  1107.    * @return the max number of columns
  1108.    * @exception SQLException if a database access error occurs
  1109.    */
  1110.   public int getMaxColumnsInGroupBy() throws SQLException
  1111.   {
  1112.     return getMaxColumnsInTable();
  1113.   }
  1114.   
  1115.   /**
  1116.    * What's the maximum number of columns allowed in an index?
  1117.    * 6.0 only allowed one column, but 6.1 introduced multi-column
  1118.    * indices, so, theoretically, its all of them.
  1119.    *
  1120.    * @return max number of columns
  1121.    * @exception SQLException if a database access error occurs
  1122.    */
  1123.   public int getMaxColumnsInIndex() throws SQLException
  1124.   {
  1125.     return getMaxColumnsInTable();
  1126.   }
  1127.   
  1128.   /**
  1129.    * What's the maximum number of columns in an "ORDER BY clause?
  1130.    * Theoretically, all of them!
  1131.    *
  1132.    * @return the max columns
  1133.    * @exception SQLException if a database access error occurs
  1134.    */
  1135.   public int getMaxColumnsInOrderBy() throws SQLException
  1136.   {
  1137.     return getMaxColumnsInTable();
  1138.   }
  1139.   
  1140.   /**
  1141.    * What is the maximum number of columns in a "SELECT" list?
  1142.    * Theoretically, all of them!
  1143.    *
  1144.    * @return the max columns
  1145.    * @exception SQLException if a database access error occurs
  1146.    */
  1147.   public int getMaxColumnsInSelect() throws SQLException
  1148.   {
  1149.     return getMaxColumnsInTable();
  1150.   }
  1151.   
  1152.   /**
  1153.    * What is the maximum number of columns in a table? From the
  1154.    * create_table(l) manual page...
  1155.    *
  1156.    * <p>"The new class is created as a heap with no initial data.  A
  1157.    * class can have no more than 1600 attributes (realistically,
  1158.    * this is limited by the fact that tuple sizes must be less than
  1159.    * 8192 bytes)..."
  1160.    *
  1161.    * @return the max columns
  1162.    * @exception SQLException if a database access error occurs
  1163.    */
  1164.   public int getMaxColumnsInTable() throws SQLException
  1165.   {
  1166.     return 1600;
  1167.   }
  1168.   
  1169.   /**
  1170.    * How many active connection can we have at a time to this
  1171.    * database?  Well, since it depends on postmaster, which just
  1172.    * does a listen() followed by an accept() and fork(), its
  1173.    * basically very high.  Unless the system runs out of processes,
  1174.    * it can be 65535 (the number of aux. ports on a TCP/IP system).
  1175.    * I will return 8192 since that is what even the largest system
  1176.    * can realistically handle,
  1177.    *
  1178.    * @return the maximum number of connections
  1179.    * @exception SQLException if a database access error occurs
  1180.    */
  1181.   public int getMaxConnections() throws SQLException
  1182.   {
  1183.     return 8192;
  1184.   }
  1185.   
  1186.   /**
  1187.    * What is the maximum cursor name length (the same as all
  1188.    * the other F***** identifiers!)
  1189.    *
  1190.    * @return max cursor name length in bytes
  1191.    * @exception SQLException if a database access error occurs
  1192.    */
  1193.   public int getMaxCursorNameLength() throws SQLException
  1194.   {
  1195.     return 32;
  1196.   }
  1197.   
  1198.   /**
  1199.    * What is the maximum length of an index (in bytes)?  Now, does
  1200.    * the spec. mean name of an index (in which case its 32, the 
  1201.    * same as a table) or does it mean length of an index element
  1202.    * (in which case its 8192, the size of a row) or does it mean
  1203.    * the number of rows it can access (in which case it 2^32 - 
  1204.    * a 4 byte OID number)?  I think its the length of an index
  1205.    * element, personally, so Im setting it to 8192.
  1206.    *
  1207.    * @return max index length in bytes
  1208.    * @exception SQLException if a database access error occurs
  1209.    */
  1210.   public int getMaxIndexLength() throws SQLException
  1211.   {
  1212.     return 8192;
  1213.   }
  1214.   
  1215.   public int getMaxSchemaNameLength() throws SQLException
  1216.   {
  1217.     // XXX-Not Implemented
  1218.     return 0;
  1219.   }
  1220.   
  1221.   /**
  1222.    * What is the maximum length of a procedure name?
  1223.    * (length of pg_proc.proname used) - again, I really
  1224.    * should do a query here to get it.
  1225.    *
  1226.    * @return the max name length in bytes
  1227.    * @exception SQLException if a database access error occurs
  1228.    */
  1229.   public int getMaxProcedureNameLength() throws SQLException
  1230.   {
  1231.     return 32;
  1232.   }
  1233.   
  1234.   public int getMaxCatalogNameLength() throws SQLException
  1235.   {
  1236.     // XXX-Not Implemented
  1237.     return 0;
  1238.   }
  1239.   
  1240.   /**
  1241.    * What is the maximum length of a single row?  (not including
  1242.    * blobs).  8192 is defined in PostgreSQL.
  1243.    *
  1244.    * @return max row size in bytes
  1245.    * @exception SQLException if a database access error occurs
  1246.    */
  1247.   public int getMaxRowSize() throws SQLException
  1248.   {
  1249.     return 8192;
  1250.   }
  1251.   
  1252.   /**
  1253.    * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
  1254.    * blobs?  We don't handle blobs yet
  1255.    *
  1256.    * @return true if so
  1257.    * @exception SQLException if a database access error occurs
  1258.    */
  1259.   public boolean doesMaxRowSizeIncludeBlobs() throws SQLException
  1260.   {
  1261.     return false;
  1262.   }
  1263.   
  1264.   /**
  1265.    * What is the maximum length of a SQL statement?
  1266.    *
  1267.    * @return max length in bytes
  1268.    * @exception SQLException if a database access error occurs
  1269.    */
  1270.   public int getMaxStatementLength() throws SQLException
  1271.   {
  1272.     return 8192;
  1273.   }
  1274.   
  1275.   /**
  1276.    * How many active statements can we have open at one time to
  1277.    * this database?  Basically, since each Statement downloads
  1278.    * the results as the query is executed, we can have many.  However,
  1279.    * we can only really have one statement per connection going
  1280.    * at once (since they are executed serially) - so we return
  1281.    * one.
  1282.    *
  1283.    * @return the maximum
  1284.    * @exception SQLException if a database access error occurs
  1285.    */
  1286.   public int getMaxStatements() throws SQLException
  1287.   {
  1288.     return 1;
  1289.   }
  1290.   
  1291.   /**
  1292.    * What is the maximum length of a table name?  This was found
  1293.    * from pg_class.relname length
  1294.    *
  1295.    * @return max name length in bytes
  1296.    * @exception SQLException if a database access error occurs
  1297.    */
  1298.   public int getMaxTableNameLength() throws SQLException
  1299.   {
  1300.     return 32;
  1301.   }
  1302.   
  1303.   /**
  1304.    * What is the maximum number of tables that can be specified
  1305.    * in a SELECT?  Theoretically, this is the same number as the
  1306.    * number of tables allowable.  In practice tho, it is much smaller
  1307.    * since the number of tables is limited by the statement, we
  1308.    * return 1024 here - this is just a number I came up with (being
  1309.    * the number of tables roughly of three characters each that you
  1310.    * can fit inside a 8192 character buffer with comma separators).
  1311.    *
  1312.    * @return the maximum
  1313.    * @exception SQLException if a database access error occurs
  1314.    */
  1315.   public int getMaxTablesInSelect() throws SQLException
  1316.   {
  1317.     return 1024;
  1318.   }
  1319.   
  1320.   /**
  1321.    * What is the maximum length of a user name?  Well, we generally
  1322.    * use UNIX like user names in PostgreSQL, so I think this would
  1323.    * be 8.  However, showing the schema for pg_user shows a length
  1324.    * for username of 32.
  1325.    *
  1326.    * @return the max name length in bytes
  1327.    * @exception SQLException if a database access error occurs
  1328.    */
  1329.   public int getMaxUserNameLength() throws SQLException
  1330.   {
  1331.     return 32;
  1332.   }
  1333.   
  1334.   
  1335.   /**
  1336.    * What is the database's default transaction isolation level?  We
  1337.    * do not support this, so all transactions are SERIALIZABLE.
  1338.    *
  1339.    * @return the default isolation level
  1340.    * @exception SQLException if a database access error occurs
  1341.    * @see Connection
  1342.    */
  1343.   public int getDefaultTransactionIsolation() throws SQLException
  1344.   {
  1345.     return Connection.TRANSACTION_SERIALIZABLE;
  1346.   }
  1347.   
  1348.   /**
  1349.    * Are transactions supported?  If not, commit and rollback are noops
  1350.    * and the isolation level is TRANSACTION_NONE.  We do support
  1351.    * transactions.
  1352.    *
  1353.    * @return true if transactions are supported
  1354.    * @exception SQLException if a database access error occurs
  1355.    */
  1356.   public boolean supportsTransactions() throws SQLException
  1357.   {
  1358.     return true;
  1359.   }
  1360.   
  1361.   /**
  1362.    * Does the database support the given transaction isolation level?
  1363.    * We only support TRANSACTION_SERIALIZABLE
  1364.    * 
  1365.    * @param level the values are defined in java.sql.Connection
  1366.    * @return true if so
  1367.    * @exception SQLException if a database access error occurs
  1368.    * @see Connection
  1369.    */
  1370.   public boolean supportsTransactionIsolationLevel(int level) throws SQLException
  1371.   {
  1372.     if (level == Connection.TRANSACTION_SERIALIZABLE)
  1373.       return true;
  1374.     else
  1375.       return false;
  1376.   }
  1377.   
  1378.   /**
  1379.    * Are both data definition and data manipulation transactions 
  1380.    * supported?  I checked it, and could not do a CREATE TABLE
  1381.    * within a transaction, so I am assuming that we don't
  1382.    *
  1383.    * @return true if so
  1384.    * @exception SQLException if a database access error occurs
  1385.    */
  1386.   public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException
  1387.   {
  1388.     return false;
  1389.   }
  1390.   
  1391.   /**
  1392.    * Are only data manipulation statements withing a transaction
  1393.    * supported?
  1394.    *
  1395.    * @return true if so
  1396.    * @exception SQLException if a database access error occurs
  1397.    */
  1398.   public boolean supportsDataManipulationTransactionsOnly() throws SQLException
  1399.   {
  1400.     return true;
  1401.   }
  1402.   
  1403.   /**
  1404.    * Does a data definition statement within a transaction force
  1405.    * the transaction to commit?  I think this means something like:
  1406.    *
  1407.    * <p><pre>
  1408.    * CREATE TABLE T (A INT);
  1409.    * INSERT INTO T (A) VALUES (2);
  1410.    * BEGIN;
  1411.    * UPDATE T SET A = A + 1;
  1412.    * CREATE TABLE X (A INT);
  1413.    * SELECT A FROM T INTO X;
  1414.    * COMMIT;
  1415.    * </pre><p>
  1416.    *
  1417.    * does the CREATE TABLE call cause a commit?  The answer is no.  
  1418.    *
  1419.    * @return true if so
  1420.    * @exception SQLException if a database access error occurs
  1421.    */
  1422.   public boolean dataDefinitionCausesTransactionCommit() throws SQLException
  1423.   {
  1424.     return false;
  1425.   }
  1426.   
  1427.   /**
  1428.    * Is a data definition statement within a transaction ignored?
  1429.    * It seems to be (from experiment in previous method)
  1430.    *
  1431.    * @return true if so
  1432.    * @exception SQLException if a database access error occurs
  1433.    */
  1434.   public boolean dataDefinitionIgnoredInTransactions() throws SQLException
  1435.   {
  1436.     return true;
  1437.   }
  1438.   
  1439.   /**
  1440.    * Get a description of stored procedures available in a catalog
  1441.    * 
  1442.    * <p>Only procedure descriptions matching the schema and procedure
  1443.    * name criteria are returned.  They are ordered by PROCEDURE_SCHEM
  1444.    * and PROCEDURE_NAME
  1445.    *
  1446.    * <p>Each procedure description has the following columns:
  1447.    * <ol>
  1448.    * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
  1449.    * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
  1450.    * <li><b>PROCEDURE_NAME</b> String => procedure name
  1451.    * <li><b>Field 4</b> reserved (make it null)
  1452.    * <li><b>Field 5</b> reserved (make it null)
  1453.    * <li><b>Field 6</b> reserved (make it null)
  1454.    * <li><b>REMARKS</b> String => explanatory comment on the procedure
  1455.    * <li><b>PROCEDURE_TYPE</b> short => kind of procedure
  1456.    * <ul>
  1457.    *    <li> procedureResultUnknown - May return a result
  1458.    *  <li> procedureNoResult - Does not return a result
  1459.    * <li> procedureReturnsResult - Returns a result
  1460.    *    </ul>
  1461.    * </ol>
  1462.    *
  1463.    * @param catalog - a catalog name; "" retrieves those without a
  1464.    * catalog; null means drop catalog name from criteria
  1465.    * @param schemaParrern - a schema name pattern; "" retrieves those
  1466.    * without a schema - we ignore this parameter
  1467.    * @param procedureNamePattern - a procedure name pattern
  1468.    * @return ResultSet - each row is a procedure description
  1469.    * @exception SQLException if a database access error occurs
  1470.    */
  1471.   public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
  1472.   {
  1473.     // the field descriptors for the new ResultSet
  1474.     Field f[] = new Field[8];
  1475.     ResultSet r; // ResultSet for the SQL query that we need to do
  1476.     Vector v = new Vector(); // The new ResultSet tuple stuff
  1477.     
  1478.     byte remarks[] = defaultRemarks;
  1479.     
  1480.     f[0] = new Field(connection, "PROCEDURE_CAT",   iVarcharOid, 32);
  1481.     f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
  1482.     f[2] = new Field(connection, "PROCEDURE_NAME",  iVarcharOid, 32);
  1483.     f[3] = f[4] = f[5] = null; // reserved, must be null for now
  1484.     f[6] = new Field(connection, "REMARKS",    iVarcharOid, 8192);
  1485.     f[7] = new Field(connection, "PROCEDURE_TYPE", iInt2Oid, 2);
  1486.     
  1487.     // If the pattern is null, then set it to the default
  1488.     if(procedureNamePattern==null)
  1489.       procedureNamePattern="%";
  1490.     
  1491.     r = connection.ExecSQL("select proname, proretset from pg_proc where proname like '"+procedureNamePattern.toLowerCase()+"' order by proname");
  1492.     
  1493.     while (r.next())
  1494.       {
  1495. byte[][] tuple = new byte[8][0];
  1496. tuple[0] = null; // Catalog name
  1497. tuple[1] = null; // Schema name
  1498. tuple[2] = r.getBytes(1); // Procedure name
  1499. tuple[3] = tuple[4] = tuple[5] = null; // Reserved
  1500. tuple[6] = remarks; // Remarks
  1501. if (r.getBoolean(2))
  1502.   tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureReturnsResult).getBytes();
  1503. else
  1504.   tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureNoResult).getBytes();
  1505. v.addElement(tuple);
  1506.       }
  1507.     return new ResultSet(connection, f, v, "OK", 1);
  1508.   }
  1509.   
  1510.   /**
  1511.    * Get a description of a catalog's stored procedure parameters
  1512.    * and result columns.
  1513.    *
  1514.    * <p>Only descriptions matching the schema, procedure and parameter
  1515.    * name criteria are returned. They are ordered by PROCEDURE_SCHEM
  1516.    * and PROCEDURE_NAME. Within this, the return value, if any, is
  1517.    * first. Next are the parameter descriptions in call order. The
  1518.    * column descriptions follow in column number order.
  1519.    *
  1520.    * <p>Each row in the ResultSet is a parameter description or column 
  1521.    * description with the following fields:
  1522.    * <ol>
  1523.    * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
  1524.    * <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
  1525.    * <li><b>PROCEDURE_NAME</b> String => procedure name
  1526.    * <li><b>COLUMN_NAME</b> String => column/parameter name
  1527.    * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
  1528.    * <ul><li>procedureColumnUnknown - nobody knows
  1529.    * <li>procedureColumnIn - IN parameter
  1530.    * <li>procedureColumnInOut - INOUT parameter
  1531.    * <li>procedureColumnOut - OUT parameter
  1532.    * <li>procedureColumnReturn - procedure return value
  1533.    * <li>procedureColumnResult - result column in ResultSet
  1534.    * </ul>
  1535.    * <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
  1536.    * <li><b>TYPE_NAME</b> String => SQL type name
  1537.    * <li><b>PRECISION</b> int => precision
  1538.    * <li><b>LENGTH</b> int => length in bytes of data
  1539.    * <li><b>SCALE</b> short => scale
  1540.    * <li><b>RADIX</b> short => radix
  1541.    * <li><b>NULLABLE</b> short => can it contain NULL?
  1542.    * <ul><li>procedureNoNulls - does not allow NULL values
  1543.    * <li>procedureNullable - allows NULL values
  1544.    * <li>procedureNullableUnknown - nullability unknown
  1545.    * <li><b>REMARKS</b> String => comment describing parameter/column
  1546.    * </ol>
  1547.    * @param catalog This is ignored in postgresql, advise this is set to null
  1548.    * @param schemaPattern This is ignored in postgresql, advise this is set to null
  1549.    * @param procedureNamePattern a procedure name pattern
  1550.    * @param columnNamePattern a column name pattern
  1551.    * @return each row is a stored procedure parameter or column description
  1552.    * @exception SQLException if a database-access error occurs
  1553.    * @see #getSearchStringEscape
  1554.    */
  1555.   // Implementation note: This is required for Borland's JBuilder to work
  1556.   public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
  1557.   {
  1558.     if(procedureNamePattern==null)
  1559.       procedureNamePattern="%";
  1560.     
  1561.     if(columnNamePattern==null)
  1562.       columnNamePattern="%";
  1563.     
  1564.     // for now, this returns an empty result set.
  1565.     Field f[] = new Field[13];
  1566.     ResultSet r; // ResultSet for the SQL query that we need to do
  1567.     Vector v = new Vector(); // The new ResultSet tuple stuff
  1568.     
  1569.     f[0] = new Field(connection, new String("PROCEDURE_CAT"), iVarcharOid, 32);
  1570.     f[1] = new Field(connection, new String("PROCEDURE_SCHEM"), iVarcharOid, 32);
  1571.     f[2] = new Field(connection, new String("PROCEDURE_NAME"), iVarcharOid, 32);
  1572.     f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
  1573.     f[4] = new Field(connection, new String("COLUMN_TYPE"), iInt2Oid, 2);
  1574.     f[5] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
  1575.     f[6] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
  1576.     f[7] = new Field(connection, new String("PRECISION"), iInt4Oid, 4);
  1577.     f[8] = new Field(connection, new String("LENGTH"), iInt4Oid, 4);
  1578.     f[9] = new Field(connection, new String("SCALE"), iInt2Oid, 2);
  1579.     f[10] = new Field(connection, new String("RADIX"), iInt2Oid, 2);
  1580.     f[11] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
  1581.     f[12] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
  1582.     
  1583.     // add query loop here
  1584.     
  1585.     return new ResultSet(connection, f, v, "OK", 1);
  1586.   }
  1587.   
  1588.   /**
  1589.    * Get a description of tables available in a catalog.              
  1590.    *
  1591.    * <p>Only table descriptions matching the catalog, schema, table
  1592.    * name and type criteria are returned. They are ordered by
  1593.    * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.                      
  1594.    * 
  1595.    * <p>Each table description has the following columns:     
  1596.    *
  1597.    * <ol>
  1598.    * <li><b>TABLE_CAT</b> String => table catalog (may be null)      
  1599.    * <li><b>TABLE_SCHEM</b> String => table schema (may be null)         
  1600.    * <li><b>TABLE_NAME</b> String => table name
  1601.    * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
  1602.    * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
  1603.    * TEMPORARY", "ALIAS", "SYNONYM".                             
  1604.    * <li><b>REMARKS</b> String => explanatory comment on the table
  1605.    * </ol>
  1606.    *
  1607.    * <p>The valid values for the types parameter are:
  1608.    * "TABLE", "INDEX", "LARGE OBJECT", "SEQUENCE", "SYSTEM TABLE" and
  1609.    * "SYSTEM INDEX"
  1610.    *
  1611.    * @param catalog a catalog name; For postgresql, this is ignored, and
  1612.    * should be set to null
  1613.    * @param schemaPattern a schema name pattern; For postgresql, this is ignored, and
  1614.    * should be set to null
  1615.    * @param tableNamePattern a table name pattern. For all tables this should be "%"
  1616.    * @param types a list of table types to include; null returns
  1617.    * all types
  1618.    * @return each row is a table description      
  1619.    * @exception SQLException if a database-access error occurs.
  1620.    */
  1621.   public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
  1622.   {
  1623.     // Handle default value for types
  1624.     if(types==null)
  1625.       types = defaultTableTypes;
  1626.     
  1627.     if(tableNamePattern==null)
  1628.       tableNamePattern="%";
  1629.     
  1630.     // the field descriptors for the new ResultSet
  1631.     Field f[] = new Field[5];
  1632.     ResultSet r; // ResultSet for the SQL query that we need to do
  1633.     Vector v = new Vector(); // The new ResultSet tuple stuff
  1634.     
  1635.     f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
  1636.     f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
  1637.     f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
  1638.     f[3] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, 32);
  1639.     f[4] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
  1640.     
  1641.     // Now form the query
  1642.     StringBuffer sql = new StringBuffer("select relname,oid from pg_class where (");
  1643.     boolean notFirst=false;
  1644.     for(int i=0;i<types.length;i++) {
  1645.       if(notFirst)
  1646. sql.append(" or ");
  1647.       for(int j=0;j<getTableTypes.length;j++)
  1648. if(getTableTypes[j][0].equals(types[i])) {
  1649.   sql.append(getTableTypes[j][1]);
  1650.   notFirst=true;
  1651. }
  1652.     }
  1653.     
  1654.     // Added by Stefan Andreasen <stefan@linux.kapow.dk>
  1655.     // Now take the pattern into account
  1656.     sql.append(") and relname like '");
  1657.     sql.append(tableNamePattern.toLowerCase());
  1658.     sql.append("'");
  1659.     
  1660.     // Now run the query
  1661.     r = connection.ExecSQL(sql.toString());
  1662.     
  1663.     byte remarks[];
  1664.     
  1665.     while (r.next())
  1666.       {
  1667. byte[][] tuple = new byte[5][0];
  1668. // Fetch the description for the table (if any)
  1669. ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(2));
  1670. if(dr.getTupleCount()==1) {
  1671.   dr.next();
  1672.   remarks = dr.getBytes(1);
  1673. } else
  1674.   remarks = defaultRemarks;
  1675. dr.close();
  1676. tuple[0] = null; // Catalog name
  1677. tuple[1] = null; // Schema name
  1678. tuple[2] = r.getBytes(1); // Table name
  1679. tuple[3] = null; // Table type
  1680. tuple[4] = remarks; // Remarks
  1681. v.addElement(tuple);
  1682.       }
  1683.     r.close();
  1684.     return new ResultSet(connection, f, v, "OK", 1);
  1685.   }
  1686.   
  1687.   // This array contains the valid values for the types argument
  1688.   // in getTables().
  1689.   //
  1690.   // Each supported type consists of it's name, and the sql where
  1691.   // clause to retrieve that value.
  1692.   //
  1693.   // IMPORTANT: the query must be enclosed in ( )
  1694.   private static final String getTableTypes[][] = {
  1695.     {"TABLE", "(relkind='r' and relname !~ '^pg_' and relname !~ '^xinv')"},
  1696.     {"INDEX", "(relkind='i' and relname !~ '^pg_' and relname !~ '^xinx')"},
  1697.     {"LARGE OBJECT", "(relkind='r' and relname ~ '^xinv')"},
  1698.     {"SEQUENCE", "(relkind='S' and relname !~ '^pg_')"},
  1699.     {"SYSTEM TABLE", "(relkind='r' and relname ~ '^pg_')"},
  1700.     {"SYSTEM INDEX", "(relkind='i' and relname ~ '^pg_')"}
  1701.   };
  1702.   
  1703.   // These are the default tables, used when NULL is passed to getTables
  1704.   // The choice of these provide the same behaviour as psql's d
  1705.   private static final String defaultTableTypes[] = {
  1706.     "TABLE","INDEX","SEQUENCE"
  1707.   };
  1708.   
  1709.   /**
  1710.    * Get the schema names available in this database.  The results
  1711.    * are ordered by schema name.
  1712.    *
  1713.    * <P>The schema column is:
  1714.    *  <OL>
  1715.    * <LI><B>TABLE_SCHEM</B> String => schema name
  1716.    *  </OL>
  1717.    *
  1718.    * @return ResultSet each row has a single String column that is a
  1719.    * schema name
  1720.    */
  1721.   public java.sql.ResultSet getSchemas() throws SQLException
  1722.   {
  1723.     // We don't use schemas, so we simply return a single schema name "".
  1724.     //
  1725.     Field f[] = new Field[1];
  1726.     Vector v = new Vector();
  1727.     byte[][] tuple = new byte[1][0];
  1728.     f[0] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
  1729.     tuple[0] = "".getBytes();
  1730.     v.addElement(tuple);
  1731.     return new ResultSet(connection,f,v,"OK",1);
  1732.   }
  1733.   
  1734.   /**
  1735.    * Get the catalog names available in this database.  The results
  1736.    * are ordered by catalog name.
  1737.    *
  1738.    * <P>The catalog column is:
  1739.    *  <OL>
  1740.    * <LI><B>TABLE_CAT</B> String => catalog name
  1741.    *  </OL>
  1742.    *
  1743.    * @return ResultSet each row has a single String column that is a
  1744.    * catalog name
  1745.    */
  1746.   public java.sql.ResultSet getCatalogs() throws SQLException
  1747.   {
  1748.     // We don't use catalogs, so we simply return a single catalog name "".
  1749.     Field f[] = new Field[1];
  1750.     Vector v = new Vector();
  1751.     byte[][] tuple = new byte[1][0];
  1752.     f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
  1753.     tuple[0] = "".getBytes();
  1754.     v.addElement(tuple);
  1755.     return new ResultSet(connection,f,v,"OK",1);
  1756.   }
  1757.   
  1758.   /**
  1759.    * Get the table types available in this database.  The results
  1760.    * are ordered by table type.
  1761.    *
  1762.    * <P>The table type is:
  1763.    *  <OL>
  1764.    * <LI><B>TABLE_TYPE</B> String => table type.  Typical types are "TABLE",
  1765.    * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
  1766.    * "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
  1767.    *  </OL>
  1768.    *
  1769.    * @return ResultSet each row has a single String column that is a
  1770.    * table type
  1771.    */
  1772.   public java.sql.ResultSet getTableTypes() throws SQLException
  1773.   {
  1774.     Field f[] = new Field[1];
  1775.     Vector v = new Vector();
  1776.     byte[][] tuple = new byte[1][0];
  1777.     f[0] = new Field(connection,new String("TABLE_TYPE"),iVarcharOid,32);
  1778.     for(int i=0;i<getTableTypes.length;i++) {
  1779.       tuple[0] = getTableTypes[i][0].getBytes();
  1780.       v.addElement(tuple);
  1781.     }
  1782.     return new ResultSet(connection,f,v,"OK",1);
  1783.   }
  1784.   
  1785.   /**
  1786.    * Get a description of table columns available in a catalog.
  1787.    *
  1788.    * <P>Only column descriptions matching the catalog, schema, table
  1789.    * and column name criteria are returned.  They are ordered by
  1790.    * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
  1791.    *
  1792.    * <P>Each column description has the following columns:
  1793.    *  <OL>
  1794.    * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
  1795.    * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
  1796.    * <LI><B>TABLE_NAME</B> String => table name
  1797.    * <LI><B>COLUMN_NAME</B> String => column name
  1798.    * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
  1799.    * <LI><B>TYPE_NAME</B> String => Data source dependent type name
  1800.    * <LI><B>COLUMN_SIZE</B> int => column size.  For char or date
  1801.    *     types this is the maximum number of characters, for numeric or
  1802.    *     decimal types this is precision.
  1803.    * <LI><B>BUFFER_LENGTH</B> is not used.
  1804.    * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
  1805.    * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
  1806.    * <LI><B>NULLABLE</B> int => is NULL allowed?
  1807.    *      <UL>
  1808.    *      <LI> columnNoNulls - might not allow NULL values
  1809.    *      <LI> columnNullable - definitely allows NULL values
  1810.    *      <LI> columnNullableUnknown - nullability unknown
  1811.    *      </UL>
  1812.    * <LI><B>REMARKS</B> String => comment describing column (may be null)
  1813.    *  <LI><B>COLUMN_DEF</B> String => default value (may be null)
  1814.    * <LI><B>SQL_DATA_TYPE</B> int => unused
  1815.    * <LI><B>SQL_DATETIME_SUB</B> int => unused
  1816.    * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
  1817.    *       maximum number of bytes in the column
  1818.    * <LI><B>ORDINAL_POSITION</B> int => index of column in table
  1819.    *      (starting at 1)
  1820.    * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
  1821.    *      does not allow NULL values; "YES" means the column might
  1822.    *      allow NULL values.  An empty string means nobody knows.
  1823.    *  </OL>
  1824.    *
  1825.    * @param catalog a catalog name; "" retrieves those without a catalog
  1826.    * @param schemaPattern a schema name pattern; "" retrieves those
  1827.    * without a schema
  1828.    * @param tableNamePattern a table name pattern
  1829.    * @param columnNamePattern a column name pattern
  1830.    * @return ResultSet each row is a column description
  1831.    * @see #getSearchStringEscape
  1832.    */
  1833.   public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
  1834.   {
  1835.     // the field descriptors for the new ResultSet
  1836.     Field f[] = new Field[18];
  1837.     ResultSet r; // ResultSet for the SQL query that we need to do
  1838.     Vector v = new Vector(); // The new ResultSet tuple stuff
  1839.     
  1840.     f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
  1841.     f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
  1842.     f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
  1843.     f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
  1844.     f[4] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
  1845.     f[5] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
  1846.     f[6] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
  1847.     f[7] = new Field(connection, new String("BUFFER_LENGTH"), iVarcharOid, 32);
  1848.     f[8] = new Field(connection, new String("DECIMAL_DIGITS"), iInt4Oid, 4);
  1849.     f[9] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
  1850.     f[10] = new Field(connection, new String("NULLABLE"), iInt4Oid, 4);
  1851.     f[11] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
  1852.     f[12] = new Field(connection, new String("COLUMN_DEF"), iVarcharOid, 32);
  1853.     f[13] = new Field(connection, new String("SQL_DATA_TYPE"), iInt4Oid, 4);
  1854.     f[14] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
  1855.     f[15] = new Field(connection, new String("CHAR_OCTET_LENGTH"), iVarcharOid, 32);
  1856.     f[16] = new Field(connection, new String("ORDINAL_POSITION"), iInt4Oid,4);
  1857.     f[17] = new Field(connection, new String("IS_NULLABLE"), iVarcharOid, 32);
  1858.     
  1859.     // Added by Stefan Andreasen <stefan@linux.kapow.dk>
  1860.     // If the pattern are  null then set them to %
  1861.     if (tableNamePattern == null) tableNamePattern="%";
  1862.     if (columnNamePattern == null) columnNamePattern="%";
  1863.     
  1864.     // Now form the query
  1865.     // Modified by Stefan Andreasen <stefan@linux.kapow.dk>
  1866.     r = connection.ExecSQL("select a.oid,c.relname,a.attname,a.atttypid,a.attnum,a.attnotnull,a.attlen,a.atttypmod from pg_class c, pg_attribute a where a.attrelid=c.oid and c.relname like '"+tableNamePattern.toLowerCase()+"' and a.attname like '"+columnNamePattern.toLowerCase()+"' and a.attnum>0 order by c.relname,a.attnum");
  1867.     
  1868.     byte remarks[];
  1869.     
  1870.     while(r.next()) {
  1871. byte[][] tuple = new byte[18][0];
  1872. // Fetch the description for the table (if any)
  1873. ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(1));
  1874. if(dr.getTupleCount()==1) {
  1875.   dr.next();
  1876.   tuple[11] = dr.getBytes(1);
  1877. } else
  1878.   tuple[11] = defaultRemarks;
  1879. dr.close();
  1880. tuple[0] = "".getBytes(); // Catalog name
  1881. tuple[1] = "".getBytes(); // Schema name
  1882. tuple[2] = r.getBytes(2); // Table name
  1883. tuple[3] = r.getBytes(3); // Column name
  1884. dr = connection.ExecSQL("select typname from pg_type where oid = "+r.getString(4));
  1885. dr.next();
  1886. String typname=dr.getString(1);
  1887. dr.close();
  1888. tuple[4] = Integer.toString(Field.getSQLType(typname)).getBytes(); // Data type
  1889. tuple[5] = typname.getBytes(); // Type name
  1890. // Column size
  1891. // Looking at the psql source,
  1892. // I think the length of a varchar as specified when the table was created
  1893. // should be extracted from atttypmod which contains this length + sizeof(int32)
  1894. if (typname.equals("bpchar") || typname.equals("varchar")) {
  1895.   int atttypmod = r.getInt(8);
  1896.   tuple[6] = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0).getBytes();
  1897. } else
  1898.   tuple[6] = r.getBytes(7);
  1899. tuple[7] = null; // Buffer length
  1900. tuple[8] = "0".getBytes(); // Decimal Digits - how to get this?
  1901. tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
  1902. // tuple[10] is below
  1903. // tuple[11] is above
  1904. tuple[12] = null; // column default
  1905. tuple[13] = null; // sql data type (unused)
  1906. tuple[14] = null; // sql datetime sub (unused)
  1907. tuple[15] = tuple[6]; // char octet length
  1908. tuple[16] = r.getBytes(5); // ordinal position
  1909. String nullFlag = r.getString(6);
  1910. tuple[10] = Integer.toString(nullFlag.equals("f")?java.sql.DatabaseMetaData.columnNullable:java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
  1911. tuple[17] = (nullFlag.equals("f")?"YES":"NO").getBytes(); // is nullable
  1912. v.addElement(tuple);
  1913.       }
  1914.     r.close();
  1915.     return new ResultSet(connection, f, v, "OK", 1);
  1916.   }
  1917.   
  1918.   /**
  1919.    * Get a description of the access rights for a table's columns.
  1920.    *
  1921.    * <P>Only privileges matching the column name criteria are
  1922.    * returned.  They are ordered by COLUMN_NAME and PRIVILEGE.
  1923.    *
  1924.    * <P>Each privilige description has the following columns:
  1925.    *  <OL>
  1926.    * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
  1927.    * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
  1928.    * <LI><B>TABLE_NAME</B> String => table name
  1929.    * <LI><B>COLUMN_NAME</B> String => column name
  1930.    * <LI><B>GRANTOR</B> => grantor of access (may be null)
  1931.    * <LI><B>GRANTEE</B> String => grantee of access
  1932.    * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
  1933.    *      INSERT, UPDATE, REFRENCES, ...)
  1934.    * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
  1935.    *      to grant to others; "NO" if not; null if unknown
  1936.    *  </OL>
  1937.    *
  1938.    * @param catalog a catalog name; "" retrieves those without a catalog
  1939.    * @param schema a schema name; "" retrieves those without a schema
  1940.    * @param table a table name
  1941.    * @param columnNamePattern a column name pattern
  1942.    * @return ResultSet each row is a column privilege description
  1943.    * @see #getSearchStringEscape
  1944.    */
  1945.   public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
  1946.   {
  1947.     Field f[] = new Field[8];
  1948.     Vector v = new Vector();
  1949.     
  1950.     if(table==null)
  1951.       table="%";
  1952.     
  1953.     if(columnNamePattern==null)
  1954.       columnNamePattern="%";
  1955.     else
  1956.       columnNamePattern=columnNamePattern.toLowerCase();
  1957.     
  1958.     f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
  1959.     f[1] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
  1960.     f[2] = new Field(connection,new String("TABLE_NAME"),iVarcharOid,32);
  1961.     f[3] = new Field(connection,new String("COLUMN_NAME"),iVarcharOid,32);
  1962.     f[4] = new Field(connection,new String("GRANTOR"),iVarcharOid,32);
  1963.     f[5] = new Field(connection,new String("GRANTEE"),iVarcharOid,32);
  1964.     f[6] = new Field(connection,new String("PRIVILEGE"),iVarcharOid,32);
  1965.     f[7] = new Field(connection,new String("IS_GRANTABLE"),iVarcharOid,32);
  1966.     
  1967.     // This is taken direct from the psql source
  1968.     ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner and relname like '"+table.toLowerCase()+"' ORDER BY relname");
  1969.     while(r.next()) {
  1970.       byte[][] tuple = new byte[8][0];
  1971.       tuple[0] = tuple[1]= "".getBytes();
  1972.       DriverManager.println("relname=""+r.getString(1)+"" relacl=""+r.getString(2)+""");
  1973.       
  1974.       // For now, don't add to the result as relacl needs to be processed.
  1975.       //v.addElement(tuple);
  1976.     }
  1977.     
  1978.     return new ResultSet(connection,f,v,"OK",1);
  1979.   }
  1980.   
  1981.   /**
  1982.    * Get a description of the access rights for each table available
  1983.    * in a catalog.
  1984.    *
  1985.    * <P>Only privileges matching the schema and table name
  1986.    * criteria are returned.  They are ordered by TABLE_SCHEM,
  1987.    * TABLE_NAME, and PRIVILEGE.
  1988.    *
  1989.    * <P>Each privilige description has the following columns:
  1990.    *  <OL>
  1991.    * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
  1992.    * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
  1993.    * <LI><B>TABLE_NAME</B> String => table name
  1994.    * <LI><B>COLUMN_NAME</B> String => column name
  1995.    * <LI><B>GRANTOR</B> => grantor of access (may be null)
  1996.    * <LI><B>GRANTEE</B> String => grantee of access
  1997.    * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
  1998.    *      INSERT, UPDATE, REFRENCES, ...)
  1999.    * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
  2000.    *      to grant to others; "NO" if not; null if unknown
  2001.    *  </OL>
  2002.    *
  2003.    * @param catalog a catalog name; "" retrieves those without a catalog
  2004.    * @param schemaPattern a schema name pattern; "" retrieves those
  2005.    * without a schema
  2006.    * @param tableNamePattern a table name pattern
  2007.    * @return ResultSet each row is a table privilege description
  2008.    * @see #getSearchStringEscape
  2009.    */
  2010.   public java.sql.ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException
  2011.   {
  2012.     // XXX-Not Implemented
  2013.     return null;
  2014.   }
  2015.   
  2016.   /**
  2017.    * Get a description of a table's optimal set of columns that
  2018.    * uniquely identifies a row. They are ordered by SCOPE.
  2019.    *
  2020.    * <P>Each column description has the following columns:
  2021.    *  <OL>
  2022.    * <LI><B>SCOPE</B> short => actual scope of result
  2023.    *      <UL>
  2024.    *      <LI> bestRowTemporary - very temporary, while using row
  2025.    *      <LI> bestRowTransaction - valid for remainder of current transaction
  2026.    *      <LI> bestRowSession - valid for remainder of current session
  2027.    *      </UL>
  2028.    * <LI><B>COLUMN_NAME</B> String => column name
  2029.    * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
  2030.    * <LI><B>TYPE_NAME</B> String => Data source dependent type name
  2031.    * <LI><B>COLUMN_SIZE</B> int => precision
  2032.    * <LI><B>BUFFER_LENGTH</B> int => not used
  2033.    * <LI><B>DECIMAL_DIGITS</B> short  => scale
  2034.    * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
  2035.    *      like an Oracle ROWID
  2036.    *      <UL>
  2037.    *      <LI> bestRowUnknown - may or may not be pseudo column
  2038.    *      <LI> bestRowNotPseudo - is NOT a pseudo column
  2039.    *      <LI> bestRowPseudo - is a pseudo column
  2040.    *      </UL>
  2041.    *  </OL>
  2042.    *
  2043.    * @param catalog a catalog name; "" retrieves those without a catalog
  2044.    * @param schema a schema name; "" retrieves those without a schema
  2045.    * @param table a table name
  2046.    * @param scope the scope of interest; use same values as SCOPE
  2047.    * @param nullable include columns that are nullable?
  2048.    * @return ResultSet each row is a column description
  2049.    */
  2050.   // Implementation note: This is required for Borland's JBuilder to work
  2051.   public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
  2052.   {
  2053.     // for now, this returns an empty result set.
  2054.     Field f[] = new Field[8];
  2055.     ResultSet r; // ResultSet for the SQL query that we need to do
  2056.     Vector v = new Vector(); // The new ResultSet tuple stuff
  2057.     
  2058.     f[0] = new Field(connection, new String("SCOPE"), iInt2Oid, 2);
  2059.     f[1] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
  2060.     f[2] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
  2061.     f[3] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
  2062.     f[4] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
  2063.     f[5] = new Field(connection, new String("BUFFER_LENGTH"), iInt4Oid, 4);
  2064.     f[6] = new Field(connection, new String("DECIMAL_DIGITS"), iInt2Oid, 2);
  2065.     f[7] = new Field(connection, new String("PSEUDO_COLUMN"), iInt2Oid, 2);
  2066.     
  2067.     return new ResultSet(connection, f, v, "OK", 1);
  2068.   }
  2069.   
  2070.   /**
  2071.    * Get a description of a table's columns that are automatically
  2072.    * updated when any value in a row is updated.  They are
  2073.    * unordered.
  2074.    *
  2075.    * <P>Each column description has the following columns:
  2076.    *  <OL>
  2077.    * <LI><B>SCOPE</B> short => is not used
  2078.    * <LI><B>COLUMN_NAME</B> String => column name
  2079.    * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
  2080.    * <LI><B>TYPE_NAME</B> String => Data source dependent type name
  2081.    * <LI><B>COLUMN_SIZE</B> int => precision
  2082.    * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
  2083.    * <LI><B>DECIMAL_DIGITS</B> short  => scale
  2084.    * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
  2085.    *      like an Oracle ROWID
  2086.    *      <UL>
  2087.    *      <LI> versionColumnUnknown - may or may not be pseudo column
  2088.    *      <LI> versionColumnNotPseudo - is NOT a pseudo column
  2089.    *      <LI> versionColumnPseudo - is a pseudo column
  2090.    *      </UL>
  2091.    *  </OL>
  2092.    *
  2093.    * @param catalog a catalog name; "" retrieves those without a catalog
  2094.    * @param schema a schema name; "" retrieves those without a schema
  2095.    * @param table a table name
  2096.    * @return ResultSet each row is a column description
  2097.    */
  2098.  public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException
  2099.   {
  2100.     // XXX-Not Implemented
  2101.     return null;
  2102.   }
  2103.   
  2104.   /**
  2105.    * Get a description of a table's primary key columns.  They
  2106.    * are ordered by COLUMN_NAME.
  2107.    *
  2108.    * <P>Each column description has the following columns:
  2109.    *  <OL>
  2110.    * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
  2111.    * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
  2112.    * <LI><B>TABLE_NAME</B> String => table name
  2113.    * <LI><B>COLUMN_NAME</B> String => column name
  2114.    * <LI><B>KEY_SEQ</B> short => sequence number within primary key
  2115.    * <LI><B>PK_NAME</B> String => primary key name (may be null)
  2116.    *  </OL>
  2117.    *
  2118.    * @param catalog a catalog name; "" retrieves those without a catalog
  2119.    * @param schema a schema name pattern; "" retrieves those
  2120.    * without a schema
  2121.    * @param table a table name
  2122.    * @return ResultSet each row is a primary key column description
  2123.    */
  2124.   public java.sql.ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException
  2125.   {
  2126.     return connection.createStatement().executeQuery("SELECT " +
  2127.      "'' as TABLE_CAT," +
  2128.      "'' AS TABLE_SCHEM," +
  2129.      "bc.relname AS TABLE_NAME," +
  2130.      "ic.relname AS COLUMN_NAME," +
  2131.      "'1' as KEY_SEQ,"+ // -- fake it as a String for now
  2132.      "t.typname as PK_NAME " +
  2133.      " FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a, pg_type t " +
  2134.      " WHERE bc.relkind = 'r' " + //    -- not indices
  2135.      "  and bc.relname ~ '"+table+"'" +
  2136.      "  and i.indrelid = bc.oid" +
  2137.      "  and i.indexrelid = ic.oid" +
  2138.      "  and i.indkey[0] = a.attnum" +
  2139.      "  and i.indproc = '0'::oid" +
  2140.      "  and a.attrelid = bc.oid" +
  2141.      " ORDER BY TABLE_NAME, COLUMN_NAME;"
  2142.      );
  2143.   }
  2144.   
  2145.   /**
  2146.    * Get a description of the primary key columns that are
  2147.    * referenced by a table's foreign key columns (the primary keys
  2148.    * imported by a table).  They are ordered by PKTABLE_CAT,
  2149.    * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
  2150.    *
  2151.    * <P>Each primary key column description has the following columns:
  2152.    *  <OL>
  2153.    * <LI><B>PKTABLE_CAT</B> String => primary key table catalog
  2154.    *      being imported (may be null)
  2155.    * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
  2156.    *      being imported (may be null)
  2157.    * <LI><B>PKTABLE_NAME</B> String => primary key table name
  2158.    *      being imported
  2159.    * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
  2160.    *      being imported
  2161.    * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
  2162.    * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
  2163.    * <LI><B>FKTABLE_NAME</B> String => foreign key table name
  2164.    * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
  2165.    * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
  2166.    * <LI><B>UPDATE_RULE</B> short => What happens to
  2167.    *       foreign key when primary is updated:
  2168.    *      <UL>
  2169.    *      <LI> importedKeyCascade - change imported key to agree
  2170.    *               with primary key update
  2171.    *      <LI> importedKeyRestrict - do not allow update of primary
  2172.    *               key if it has been imported
  2173.    *      <LI> importedKeySetNull - change imported key to NULL if
  2174.    *               its primary key has been updated
  2175.    *      </UL>
  2176.    * <LI><B>DELETE_RULE</B> short => What happens to
  2177.    *      the foreign key when primary is deleted.
  2178.    *      <UL>
  2179.    *      <LI> importedKeyCascade - delete rows that import a deleted key
  2180.    *      <LI> importedKeyRestrict - do not allow delete of primary
  2181.    *               key if it has been imported
  2182.    *      <LI> importedKeySetNull - change imported key to NULL if
  2183.    *               its primary key has been deleted
  2184.    *      </UL>
  2185.    * <LI><B>FK_NAME</B> String => foreign key name (may be null)
  2186.    * <LI><B>PK_NAME</B> String => primary key name (may be null)
  2187.    *  </OL>
  2188.    *
  2189.    * @param catalog a catalog name; "" retrieves those without a catalog
  2190.    * @param schema a schema name pattern; "" retrieves those
  2191.    * without a schema
  2192.    * @param table a table name
  2193.    * @return ResultSet each row is a primary key column description
  2194.    * @see #getExportedKeys
  2195.    */
  2196.   public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
  2197.   {
  2198.     // XXX-Not Implemented
  2199.     return null;
  2200.   }
  2201.   
  2202.   /**
  2203.    * Get a description of a foreign key columns that reference a
  2204.    * table's primary key columns (the foreign keys exported by a
  2205.    * table).  They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
  2206.    * FKTABLE_NAME, and KEY_SEQ.
  2207.    *
  2208.    * <P>Each foreign key column description has the following columns:
  2209.    *  <OL>
  2210.    * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
  2211.    * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
  2212.    * <LI><B>PKTABLE_NAME</B> String => primary key table name
  2213.    * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
  2214.    * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
  2215.    *      being exported (may be null)
  2216.    * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
  2217.    *      being exported (may be null)
  2218.    * <LI><B>FKTABLE_NAME</B> String => foreign key table name
  2219.    *      being exported
  2220.    * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
  2221.    *      being exported
  2222.    * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
  2223.    * <LI><B>UPDATE_RULE</B> short => What happens to
  2224.    *       foreign key when primary is updated:
  2225.    *      <UL>
  2226.    *      <LI> importedKeyCascade - change imported key to agree
  2227.    *               with primary key update
  2228.    *      <LI> importedKeyRestrict - do not allow update of primary
  2229.    *               key if it has been imported
  2230.    *      <LI> importedKeySetNull - change imported key to NULL if
  2231.    *               its primary key has been updated
  2232.    *      </UL>
  2233.    * <LI><B>DELETE_RULE</B> short => What happens to
  2234.    *      the foreign key when primary is deleted.
  2235.    *      <UL>
  2236.    *      <LI> importedKeyCascade - delete rows that import a deleted key
  2237.    *      <LI> importedKeyRestrict - do not allow delete of primary
  2238.    *               key if it has been imported
  2239.    *      <LI> importedKeySetNull - change imported key to NULL if
  2240.    *               its primary key has been deleted
  2241.    *      </UL>
  2242.    * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
  2243.    * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
  2244.    *  </OL>
  2245.    *
  2246.    * @param catalog a catalog name; "" retrieves those without a catalog
  2247.    * @param schema a schema name pattern; "" retrieves those
  2248.    * without a schema
  2249.    * @param table a table name
  2250.    * @return ResultSet each row is a foreign key column description
  2251.    * @see #getImportedKeys
  2252.    */
  2253.   public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
  2254.   {
  2255.     // XXX-Not Implemented
  2256.     return null;
  2257.   }
  2258.   
  2259.   /**
  2260.    * Get a description of the foreign key columns in the foreign key
  2261.    * table that reference the primary key columns of the primary key
  2262.    * table (describe how one table imports another's key.) This
  2263.    * should normally return a single foreign key/primary key pair
  2264.    * (most tables only import a foreign key from a table once.)  They
  2265.    * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
  2266.    * KEY_SEQ.
  2267.    *
  2268.    * <P>Each foreign key column description has the following columns:
  2269.    *  <OL>
  2270.    * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
  2271.    * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
  2272.    * <LI><B>PKTABLE_NAME</B> String => primary key table name
  2273.    * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
  2274.    * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
  2275.    *      being exported (may be null)
  2276.    * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
  2277.    *      being exported (may be null)
  2278.    * <LI><B>FKTABLE_NAME</B> String => foreign key table name
  2279.    *      being exported
  2280.    * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
  2281.    *      being exported
  2282.    * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
  2283.    * <LI><B>UPDATE_RULE</B> short => What happens to
  2284.    *       foreign key when primary is updated:
  2285.    *      <UL>
  2286.    *      <LI> importedKeyCascade - change imported key to agree
  2287.    *               with primary key update
  2288.    *      <LI> importedKeyRestrict - do not allow update of primary
  2289.    *               key if it has been imported
  2290.    *      <LI> importedKeySetNull - change imported key to NULL if
  2291.    *               its primary key has been updated
  2292.    *      </UL>
  2293.    * <LI><B>DELETE_RULE</B> short => What happens to
  2294.    *      the foreign key when primary is deleted.
  2295.    *      <UL>
  2296.    *      <LI> importedKeyCascade - delete rows that import a deleted key
  2297.    *      <LI> importedKeyRestrict - do not allow delete of primary
  2298.    *               key if it has been imported
  2299.    *      <LI> importedKeySetNull - change imported key to NULL if
  2300.    *               its primary key has been deleted
  2301.    *      </UL>
  2302.    * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
  2303.    * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
  2304.    *  </OL>
  2305.    *
  2306.    * @param catalog a catalog name; "" retrieves those without a catalog
  2307.    * @param schema a schema name pattern; "" retrieves those
  2308.    * without a schema
  2309.    * @param table a table name
  2310.    * @return ResultSet each row is a foreign key column description
  2311.    * @see #getImportedKeys
  2312.    */
  2313.   public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
  2314.   {
  2315.     // XXX-Not Implemented
  2316.     return null;
  2317.   }
  2318.   
  2319.   /**
  2320.    * Get a description of all the standard SQL types supported by
  2321.    * this database. They are ordered by DATA_TYPE and then by how
  2322.    * closely the data type maps to the corresponding JDBC SQL type.
  2323.    *
  2324.    * <P>Each type description has the following columns:
  2325.    *  <OL>
  2326.    * <LI><B>TYPE_NAME</B> String => Type name
  2327.    * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
  2328.    * <LI><B>PRECISION</B> int => maximum precision
  2329.    * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
  2330.    *      (may be null)
  2331.    * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
  2332.    (may be null)
  2333.    * <LI><B>CREATE_PARAMS</B> String => parameters used in creating
  2334.    *      the type (may be null)
  2335.    * <LI><B>NULLABLE</B> short => can you use NULL for this type?
  2336.    *      <UL>
  2337.    *      <LI> typeNoNulls - does not allow NULL values
  2338.    *      <LI> typeNullable - allows NULL values
  2339.    *      <LI> typeNullableUnknown - nullability unknown
  2340.    *      </UL>
  2341.    * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
  2342.    * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
  2343.    *      <UL>
  2344.    *      <LI> typePredNone - No support
  2345.    *      <LI> typePredChar - Only supported with WHERE .. LIKE
  2346.    *      <LI> typePredBasic - Supported except for WHERE .. LIKE
  2347.    *      <LI> typeSearchable - Supported for all WHERE ..
  2348.    *      </UL>
  2349.    * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
  2350.    * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
  2351.    * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
  2352.    *      auto-increment value?
  2353.    * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
  2354.    *      (may be null)
  2355.    * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
  2356.    * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
  2357.    * <LI><B>SQL_DATA_TYPE</B> int => unused
  2358.    * <LI><B>SQL_DATETIME_SUB</B> int => unused
  2359.    * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
  2360.    *  </OL>
  2361.    *
  2362.    * @return ResultSet each row is a SQL type description
  2363.    */
  2364.   public java.sql.ResultSet getTypeInfo() throws SQLException
  2365.   {
  2366.     ResultSet rs = connection.ExecSQL("select typname from pg_type");
  2367.     if(rs!=null) {
  2368.       Field f[] = new Field[18];
  2369.       ResultSet r; // ResultSet for the SQL query that we need to do
  2370.       Vector v = new Vector(); // The new ResultSet tuple stuff
  2371.       
  2372.       f[0] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
  2373.       f[1] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
  2374.       f[2] = new Field(connection, new String("PRECISION"), iInt4Oid, 4);
  2375.       f[3] = new Field(connection, new String("LITERAL_PREFIX"), iVarcharOid, 32);
  2376.       f[4] = new Field(connection, new String("LITERAL_SUFFIX"), iVarcharOid, 32);
  2377.       f[5] = new Field(connection, new String("CREATE_PARAMS"), iVarcharOid, 32);
  2378.       f[6] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
  2379.       f[7] = new Field(connection, new String("CASE_SENSITIVE"), iBoolOid, 1);
  2380.       f[8] = new Field(connection, new String("SEARCHABLE"), iInt2Oid, 2);
  2381.       f[9] = new Field(connection, new String("UNSIGNED_ATTRIBUTE"), iBoolOid, 1);
  2382.       f[10] = new Field(connection, new String("FIXED_PREC_SCALE"), iBoolOid, 1);
  2383.       f[11] = new Field(connection, new String("AUTO_INCREMENT"), iBoolOid, 1);
  2384.       f[12] = new Field(connection, new String("LOCAL_TYPE_NAME"), iVarcharOid, 32);
  2385.       f[13] = new Field(connection, new String("MINIMUM_SCALE"), iInt2Oid, 2);
  2386.       f[14] = new Field(connection, new String("MAXIMUM_SCALE"), iInt2Oid, 2);
  2387.       f[15] = new Field(connection, new String("SQL_DATA_TYPE"), iInt4Oid, 4);
  2388.       f[16] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
  2389.       f[17] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
  2390.       
  2391.       // cache some results, this will keep memory useage down, and speed
  2392.       // things up a little.
  2393.       byte b9[]  = "9".getBytes();
  2394.       byte b10[] = "10".getBytes();
  2395.       byte bf[]  = "f".getBytes();
  2396.       byte bnn[] = Integer.toString(typeNoNulls).getBytes();
  2397.       byte bts[] = Integer.toString(typeSearchable).getBytes();
  2398.       
  2399.       while(rs.next()) {
  2400. byte[][] tuple = new byte[18][];
  2401. String typname=rs.getString(1);
  2402. tuple[0] = typname.getBytes();
  2403. tuple[1] = Integer.toString(Field.getSQLType(typname)).getBytes();
  2404. tuple[2] = b9; // for now
  2405. tuple[6] = bnn; // for now
  2406. tuple[7] = bf; // false for now - not case sensitive
  2407. tuple[8] = bts;
  2408. tuple[9] = bf; // false for now - it's signed
  2409. tuple[10] = bf; // false for now - must handle money
  2410. tuple[11] = bf; // false for now - handle autoincrement
  2411. // 12 - LOCAL_TYPE_NAME is null
  2412. // 13 & 14 ?
  2413. // 15 & 16 are unused so we return null
  2414. tuple[17] = b10; // everything is base 10
  2415. v.addElement(tuple);
  2416.       }
  2417.       rs.close();
  2418.       return new ResultSet(connection, f, v, "OK", 1);
  2419.     }
  2420.     
  2421.     return null;
  2422.   }
  2423.   
  2424.   /**
  2425.    * Get a description of a table's indices and statistics. They are
  2426.    * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
  2427.    *
  2428.    * <P>Each index column description has the following columns:
  2429.    *  <OL>
  2430.    * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
  2431.    * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
  2432.    * <LI><B>TABLE_NAME</B> String => table name
  2433.    * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
  2434.    *      false when TYPE is tableIndexStatistic
  2435.    * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
  2436.    *      null when TYPE is tableIndexStatistic
  2437.    * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
  2438.    *      tableIndexStatistic
  2439.    * <LI><B>TYPE</B> short => index type:
  2440.    *      <UL>
  2441.    *      <LI> tableIndexStatistic - this identifies table statistics that are
  2442.    *           returned in conjuction with a table's index descriptions
  2443.    *      <LI> tableIndexClustered - this is a clustered index
  2444.    *      <LI> tableIndexHashed - this is a hashed index
  2445.    *      <LI> tableIndexOther - this is some other style of index
  2446.    *      </UL>
  2447.    * <LI><B>ORDINAL_POSITION</B> short => column sequence number
  2448.    *      within index; zero when TYPE is tableIndexStatistic
  2449.    * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
  2450.    *      tableIndexStatistic
  2451.    * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending
  2452.    *      "D" => descending, may be null if sort sequence is not supported;
  2453.    *      null when TYPE is tableIndexStatistic
  2454.    * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
  2455.    *      this is the number of rows in the table; otherwise it is the
  2456.    *      number of unique values in the index.
  2457.    * <LI><B>PAGES</B> int => When TYPE is  tableIndexStatisic then
  2458.    *      this is the number of pages used for the table, otherwise it
  2459.    *      is the number of pages used for the current index.
  2460.    * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
  2461.    *      (may be null)
  2462.    *  </OL>
  2463.    *
  2464.    * @param catalog a catalog name; "" retrieves those without a catalog
  2465.    * @param schema a schema name pattern; "" retrieves those without a schema
  2466.    * @param table a table name
  2467.    * @param unique when true, return only indices for unique values;
  2468.    *     when false, return indices regardless of whether unique or not
  2469.    * @param approximate when true, result is allowed to reflect approximate
  2470.    *     or out of data values; when false, results are requested to be
  2471.    *     accurate
  2472.    * @return ResultSet each row is an index column description
  2473.    */
  2474.   // Implementation note: This is required for Borland's JBuilder to work
  2475.   public java.sql.ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException
  2476.   {
  2477.     // for now, this returns an empty result set.
  2478.     Field f[] = new Field[13];
  2479.     ResultSet r; // ResultSet for the SQL query that we need to do
  2480.     Vector v = new Vector(); // The new ResultSet tuple stuff
  2481.     
  2482.     f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
  2483.     f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
  2484.     f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
  2485.     f[3] = new Field(connection, new String("NON_UNIQUE"), iBoolOid, 1);
  2486.     f[4] = new Field(connection, new String("INDEX_QUALIFIER"), iVarcharOid, 32);
  2487.     f[5] = new Field(connection, new String("INDEX_NAME"), iVarcharOid, 32);
  2488.     f[6] = new Field(connection, new String("TYPE"), iInt2Oid, 2);
  2489.     f[7] = new Field(connection, new String("ORDINAL_POSITION"), iInt2Oid, 2);
  2490.     f[8] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
  2491.     f[9] = new Field(connection, new String("ASC_OR_DESC"), iVarcharOid, 32);
  2492.     f[10] = new Field(connection, new String("CARDINALITY"), iInt4Oid, 4);
  2493.     f[11] = new Field(connection, new String("PAGES"), iInt4Oid, 4);
  2494.     f[12] = new Field(connection, new String("FILTER_CONDITION"), iVarcharOid, 32);
  2495.     
  2496.     return new ResultSet(connection, f, v, "OK", 1);
  2497.   }
  2498. }