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

数据库系统

开发平台:

Unix_Linux

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