Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java


1   /*
2   
3      Derby - Class org.apache.derby.impl.jdbc.EmbedDatabaseMetaData
4   
5      Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.impl.jdbc;
22  
23  import org.apache.derby.iapi.services.info.ProductVersionHolder;
24  
25  import org.apache.derby.iapi.services.monitor.Monitor;
26  
27  import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
28  
29  import org.apache.derby.iapi.sql.dictionary.DataDictionary;
30  import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
31  
32  import org.apache.derby.iapi.error.StandardException;
33  
34  import org.apache.derby.impl.sql.execute.GenericConstantActionFactory;
35  import org.apache.derby.impl.sql.execute.GenericExecutionFactory;
36  
37  import org.apache.derby.iapi.reference.Limits;
38  import org.apache.derby.iapi.reference.JDBC20Translation;
39  import org.apache.derby.iapi.reference.JDBC30Translation;
40  
41  import java.util.Properties;
42  
43  import java.sql.DatabaseMetaData;
44  import java.sql.Connection;
45  import java.sql.PreparedStatement;
46  import java.sql.SQLException;
47  import java.sql.ResultSet;
48  import java.sql.Types;
49  
50  import java.io.IOException;
51  import java.io.InputStream;
52  
53  /**
54   * This class provides information about the database as a whole.
55   *
56   * <P>Many of the methods here return lists of information in ResultSets.
57   * You can use the normal ResultSet methods such as getString and getInt
58   * to retrieve the data from these ResultSets.  If a given form of
59   * metadata is not available, these methods should throw a SQLException.
60   *
61   * <P>Some of these methods take arguments that are String patterns.  These
62   * arguments all have names such as fooPattern.  Within a pattern String, "%"
63   * means match any substring of 0 or more characters, and "_" means match
64   * any one character. Only metadata entries matching the search pattern
65   * are returned. If a search pattern argument is set to a null ref, it means
66   * that argument's criteria should be dropped from the search.
67   *
68   * <P>A SQLException will be thrown if a driver does not support a meta
69   * data method.  In the case of methods that return a ResultSet,
70   * either a ResultSet (which may be empty) is returned or a
71   * SQLException is thrown.
72   * <p>
73   * This implementation gets instructions from the Database for how to satisfy
74   * most requests for information.  Each instruction is either a simple string
75   * containing the desired information, or the text of a query that may be
76   * executed on the database connection to gather the information.  We get the
77   * instructions via an "InstructionReader," which requires the database
78   * Connection for initialization.
79   * <p>
80   * Those few pieces of metadata that are related to the driver, rather than the
81   * database, come from a separate InstructionReader.  Note that in that case it
82   * probably doesn't make sense to allow an instruction to specify a query.
83   *
84   * @author ames
85   */
86  public class EmbedDatabaseMetaData extends ConnectionChild 
87    implements DatabaseMetaData, java.security.PrivilegedAction {
88  
89    /*
90    ** Property and values related to using
91    ** stored prepared statements for metatdata.
92    */
93  
94    private final String url;
95    
96    /*
97    ** Set to true if metadata is off
98    */
99  
100   private  GenericConstantActionFactory  constantActionFactory;
101 
102   //////////////////////////////////////////////////////////////
103   //
104   // CONSTRUCTORS
105   //
106   //////////////////////////////////////////////////////////////
107   /**
108       @exception SQLException on error
109    */
110   public EmbedDatabaseMetaData (EmbedConnection connection, String url) 
111     throws SQLException {
112 
113       super(connection);
114     this.url = url;
115 
116   }
117 
118   private static Properties queryDescriptions;
119   protected final Properties getQueryDescriptions() {
120     Properties p = EmbedDatabaseMetaData.queryDescriptions;
121     if (p != null)
122       return p;
123 
124     return (EmbedDatabaseMetaData.queryDescriptions = loadQueryDescriptions());
125   }
126 
127   private Properties PBloadQueryDescriptions() {
128     Properties p = new Properties();
129     try {
130 
131       // SECURITY PERMISSION - IP3
132       InputStream is = getClass().getResourceAsStream("metadata.properties");
133       
134       p.load(is);
135       is.close();
136     } catch (IOException ioe) {
137     }
138     return p;
139   }
140 
141   //////////////////////////////////////////////////////////////
142   //
143   // DatabaseMetaData interface
144   //
145   //////////////////////////////////////////////////////////////
146 
147     //----------------------------------------------------------------------
148   // First, a variety of minor information about the target database.
149 
150     /**
151      * Can all the procedures returned by getProcedures be called by the
152      * current user?
153      *
154      * @return true if so
155      */
156   public boolean allProceduresAreCallable() {
157     return true;
158   }
159 
160     /**
161      * Can all the tables returned by getTable be SELECTed by the
162      * current user?
163      *
164      * @return true if so
165      */
166   public boolean allTablesAreSelectable() {
167     return true;
168   }
169 
170     /**
171      * What's the url for this database?
172      *
173      * @return the url or null if it can't be generated
174      */
175   public final String getURL()  {
176 
177     if (url == null)
178       return url;
179     int attributeStart = url.indexOf(';');
180     if (attributeStart == -1)
181       return url;
182     else
183       return url.substring(0,attributeStart);
184   }
185 
186     /**
187      * What's our user name as known to the database?
188      *
189      * @return our database user name
190      */
191   public String getUserName() {
192     return (getEmbedConnection().getTR().getUserName());
193   }
194 
195     /**
196      * Is the database in read-only mode?
197      *
198      * @return true if so
199      */
200   public boolean isReadOnly() {
201     return getLanguageConnectionContext().getDatabase().isReadOnly();
202   }
203 
204     /**
205      * Are NULL values sorted high?
206      *
207      * @return true if so
208      */
209   public boolean nullsAreSortedHigh() {
210     return true;
211   }
212 
213     /**
214      * Are NULL values sorted low?
215      *
216      * @return true if so
217      */
218   public boolean nullsAreSortedLow() {
219     return false;
220   }
221 
222     /**
223      * Are NULL values sorted at the start regardless of sort order?
224      *
225      * @return true if so
226      */
227   public boolean nullsAreSortedAtStart() {
228     return false;
229   }
230 
231     /**
232      * Are NULL values sorted at the end regardless of sort order?
233      *
234      * @return true if so
235      */
236   public boolean nullsAreSortedAtEnd() {
237     return false;
238   }
239 
240     /**
241      * What's the name of this database product?
242      *
243      * @return database product name
244      */
245   public String getDatabaseProductName() {
246     return Monitor.getMonitor().getEngineVersion().getProductName();
247   }
248 
249     /**
250      * What's the version of this database product?
251      *
252      * @return database version
253      */
254   public String getDatabaseProductVersion() {
255     ProductVersionHolder myPVH = Monitor.getMonitor().getEngineVersion();
256 
257     return myPVH.getVersionBuildString(false);
258   }
259 
260     /**
261      * What's the name of this JDBC driver?
262      *
263      * @return JDBC driver name
264      */
265   public String getDriverName() {
266     return "Apache Derby Embedded JDBC Driver";
267   }
268 
269     /**
270      * What's the version of this JDBC driver?
271      *
272      * @return JDBC driver version
273      */
274   public String getDriverVersion()  {
275     return getDatabaseProductVersion();
276   }
277 
278     /**
279      * What's this JDBC driver's major version number?
280      *
281      * @return JDBC driver major version
282      */
283   public int getDriverMajorVersion() {
284     return getEmbedConnection().getLocalDriver().getMajorVersion();
285   }
286 
287     /**
288      * What's this JDBC driver's minor version number?
289      *
290      * @return JDBC driver minor version number
291      */
292   public int getDriverMinorVersion() {
293     return getEmbedConnection().getLocalDriver().getMinorVersion();
294   }
295 
296     /**
297      * Does the database store tables in a local file?
298      *
299      * @return true if so
300      */
301   public boolean usesLocalFiles() {
302     return true;
303   }
304 
305     /**
306      * Does the database use a file for each table?
307      *
308      * @return true if the database uses a local file for each table
309      */
310   public boolean usesLocalFilePerTable() {
311     return true;
312   }
313 
314     /**
315      * Does the database treat mixed case unquoted SQL identifiers as
316      * case sensitive and as a result store them in mixed case?
317      *
318      * A JDBC-Compliant driver will always return false.
319      *
320      * @return true if so
321      */
322   public boolean supportsMixedCaseIdentifiers() {
323     return false;
324   }
325 
326     /**
327      * Does the database treat mixed case unquoted SQL identifiers as
328      * case insensitive and store them in upper case?
329      *
330      * @return true if so
331      */
332   public boolean storesUpperCaseIdentifiers() {
333     return true;
334   }
335 
336     /**
337      * Does the database treat mixed case unquoted SQL identifiers as
338      * case insensitive and store them in lower case?
339      *
340      * @return true if so
341      */
342   public boolean storesLowerCaseIdentifiers() {
343     return false;
344   }
345 
346     /**
347      * Does the database treat mixed case unquoted SQL identifiers as
348      * case insensitive and store them in mixed case?
349      *
350      * @return true if so
351      */
352   public boolean storesMixedCaseIdentifiers() {
353     return false;
354   }
355 
356     /**
357      * Does the database treat mixed case quoted SQL identifiers as
358      * case sensitive and as a result store them in mixed case?
359      *
360      * A JDBC-Compliant driver will always return true.
361      *
362      * @return true if so
363      */
364   public boolean supportsMixedCaseQuotedIdentifiers() {
365     return true;
366   }
367 
368     /**
369      * Does the database treat mixed case quoted SQL identifiers as
370      * case insensitive and store them in upper case?
371      *
372      * @return true if so
373      */
374   public boolean storesUpperCaseQuotedIdentifiers() {
375     return false;
376   }
377 
378     /**
379      * Does the database treat mixed case quoted SQL identifiers as
380      * case insensitive and store them in lower case?
381      *
382      * @return true if so
383      */
384   public boolean storesLowerCaseQuotedIdentifiers() {
385     return false;
386   }
387 
388     /**
389      * Does the database treat mixed case quoted SQL identifiers as
390      * case insensitive and store them in mixed case?
391      *
392      * @return true if so
393      */
394   public boolean storesMixedCaseQuotedIdentifiers() {
395     return true;
396   }
397 
398     /**
399      * What's the string used to quote SQL identifiers?
400      * This returns a space " " if identifier quoting isn't supported.
401      *
402      * A JDBC-Compliant driver always uses a double quote character.
403      *
404      * @return the quoting string
405      */
406   public String getIdentifierQuoteString() {
407     return "\"";
408   }
409 
410     /**
411      * Get a comma separated list of all a database's SQL keywords
412      * that are NOT also SQL92 keywords.
413   includes reserved and non-reserved keywords.
414 
415      * @return the list
416      */
417   public String getSQLKeywords() {
418     return "ALIAS,BIGINT,BOOLEAN,CALL,CLASS,COPY,DB2J_DEBUG,EXECUTE,EXPLAIN,FILE,FILTER,"
419       +  "GETCURRENTCONNECTION,INDEX,INSTANCEOF,METHOD,NEW,OFF,PROPERTIES,PUBLICATION,RECOMPILE,"
420       +  "REFRESH,RENAME,RUNTIMESTATISTICS,STATEMENT,STATISTICS,TIMING,WAIT";
421   }
422 
423     /**
424      * Get a comma separated list of math functions.
425   getNumericFunctions lists "math functions" -- so built-in operators and
426   things like EXTRACT are not included.
427   FIXME: find a way to reference method aliases known to be "numeric"
428     *
429      * @return the list
430      */
431   public String getNumericFunctions() {
432     return "ABS,SQRT";
433   }
434 
435     /**
436      * Get a comma separated list of string functions.
437     REMIND, when they show up, something like this might appear here:
438     FIXME: find a way to reference method aliases known to be "string"
439      * @return the list
440      */
441   public String getStringFunctions() {
442     return "LENGTH,LOWER,LTRIM,RTRIM,SUBSTR,SUBSTRING,UPPER";
443   }
444 
445     /**
446      * Get a comma separated list of system functions.
447     FIXME: find a way to reference system functions on Database when/if
448     they are registered as aliases or include the Database object too.
449      * @return the list
450      */
451   public String getSystemFunctions()  {
452     return "CURRENT_USER,getCurrentConnection,runTimeStatistics,SESSION_USER,USER,CURRENT SCHEMA";
453   }
454 
455     /**
456      * Get a comma separated list of time and date functions.
457     not sure if this includes these built-ins or not, but here they are.
458     FIXME: find a way to reference method aliases known to be "date/time"
459      * @return the list
460      */
461   public String getTimeDateFunctions() {
462     return "CURDATE,CURTIME,CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,EXTRACT";
463   }
464 
465     /**
466      * This is the string that can be used to escape '_' or '%' in
467      * the string pattern style catalog search parameters.
468         we have no default escape value, so = is the end of the next line
469      * <P>The '_' character represents any single character.
470      * <P>The '%' character represents any sequence of zero or
471      * more characters.
472      * @return the string used to escape wildcard characters
473      */
474   public String getSearchStringEscape()  {
475     return "";
476   }
477 
478     /**
479      * Get all the "extra" characters that can be used in unquoted
480      * identifier names (those beyond a-z, A-Z, 0-9 and _).
481      *
482      * @return the string containing the extra characters
483      */
484   public String getExtraNameCharacters()  {
485     return "";
486   }
487 
488     //--------------------------------------------------------------------
489     // Functions describing which features are supported.
490 
491     /**
492      * Is "ALTER TABLE" with add column supported?
493      *
494      * @return true if so
495      */
496   public boolean supportsAlterTableWithAddColumn() {
497     return true;
498   }
499 
500     /**
501      * Is "ALTER TABLE" with drop column supported?
502      *
503      * @return true if so
504      */
505   public boolean supportsAlterTableWithDropColumn() {
506     return true;
507   }
508 
509     /**
510      * Is column aliasing supported?
511      *
512      * <P>If so, the SQL AS clause can be used to provide names for
513      * computed columns or to provide alias names for columns as
514      * required.
515      *
516      * A JDBC-Compliant driver always returns true.
517      *
518      * @return true if so
519      */
520   public boolean supportsColumnAliasing() {
521     return true;
522   }
523 
524     /**
525      * Are concatenations between NULL and non-NULL values NULL?
526      *
527      * A JDBC-Compliant driver always returns true.
528      *
529      * @return true if so
530      */
531   public boolean nullPlusNonNullIsNull()  {
532     return true;
533   }
534 
535     /**
536      * Is the CONVERT function between SQL types supported?
537      *
538      * @return true if so
539      */
540   public boolean supportsConvert() {
541     return true;
542   }
543 
544     /**
545      * Is CONVERT between the given SQL types supported?
546      *
547      * @param fromType the type to convert from
548      * @param toType the type to convert to
549      * @return true if so
550      * @see Types
551      */
552   public boolean supportsConvert(int fromType, int toType) {
553     /*
554      * at the moment we don't support CONVERT at all, so we take the easy
555      * way out.  Eventually we need to figure out how to handle this
556      * cleanly.
557      */
558     return false;
559   }
560 
561     /**
562      * Are table correlation names supported?
563      *
564      * A JDBC-Compliant driver always returns true.
565      *
566      * @return true if so
567      */
568   public boolean supportsTableCorrelationNames()  {
569     return true;
570   }
571 
572     /**
573      * If table correlation names are supported, are they restricted
574      * to be different from the names of the tables?
575      *
576      * @return true if so
577      */
578   public boolean supportsDifferentTableCorrelationNames() {
579     return true;
580   }
581 
582     /**
583      * Are expressions in "ORDER BY" lists supported?
584      *
585      * @return true if so
586      */
587   public boolean supportsExpressionsInOrderBy() {
588     return false;
589   }
590 
591     /**
592      * Can an "ORDER BY" clause use columns not in the SELECT?
593      *
594      * @return true if so
595      */
596   public boolean supportsOrderByUnrelated() {
597     return false;
598   }
599 
600     /**
601      * Is some form of "GROUP BY" clause supported?
602      *
603      * @return true if so
604      */
605   public boolean supportsGroupBy() {
606     return true;
607   }
608 
609     /**
610      * Can a "GROUP BY" clause use columns not in the SELECT?
611      *
612      * @return true if so
613      */
614   public boolean supportsGroupByUnrelated()  {
615     return true;
616   }
617 
618     /**
619      * Can a "GROUP BY" clause add columns not in the SELECT
620      * provided it specifies all the columns in the SELECT?
621      *
622      * @return true if so
623      */
624   public boolean supportsGroupByBeyondSelect() {
625     return true;
626   }
627 
628     /**
629      * Is the escape character in "LIKE" clauses supported?
630      *
631      * A JDBC-Compliant driver always returns true.
632      *
633      * @return true if so
634      */
635   public boolean supportsLikeEscapeClause() {
636     return true;
637   }
638 
639     /**
640      * Are multiple ResultSets from a single execute supported?
641      *
642      * @return true if so
643      */
644   public boolean supportsMultipleResultSets()  {
645     return true;
646   }
647 
648     /**
649      * Can we have multiple transactions open at once (on different
650      * connections)?
651      *
652      * @return true if so
653      */
654   public boolean supportsMultipleTransactions() {
655     return true;
656   }
657 
658     /**
659      * Can columns be defined as non-nullable?
660      *
661      * A JDBC-Compliant driver always returns true.
662      *
663      * @return true if so
664      */
665   public boolean supportsNonNullableColumns()  {
666     return true;
667   }
668 
669     /**
670      * Is the ODBC Minimum SQL grammar supported?
671      *
672      * All JDBC-Compliant drivers must return true.
673      *
674      * @return true if so
675      */
676   public boolean supportsMinimumSQLGrammar() {
677     return true;
678   }
679 
680     /**
681      * Is the ODBC Core SQL grammar supported?
682      *
683      * @return true if so
684      */
685   public boolean supportsCoreSQLGrammar() {
686     return false;
687   }
688 
689     /**
690      * Is the ODBC Extended SQL grammar supported?
691      *
692      * @return true if so
693      */
694   public boolean supportsExtendedSQLGrammar() {
695     return false;
696   }
697 
698     /**
699      * Is the ANSI92 entry level SQL grammar supported?
700      *
701      * All JDBC-Compliant drivers must return true.
702      *
703      * @return true if so
704      */
705   public boolean supportsANSI92EntryLevelSQL() {
706     return false;
707   }
708 
709     /**
710      * Is the ANSI92 intermediate SQL grammar supported?
711      *
712      * @return true if so
713    * 
714      */
715   public boolean supportsANSI92IntermediateSQL() {
716     return false;
717   }
718 
719     /**
720      * Is the ANSI92 full SQL grammar supported?
721      *
722      * @return true if so
723    * 
724      */
725   public boolean supportsANSI92FullSQL() {
726     return false;
727   }
728 
729     /**
730      * Is the SQL Integrity Enhancement Facility supported?
731      *
732      * @return true if so
733    * 
734      */
735   public boolean supportsIntegrityEnhancementFacility() {
736     return false;
737   }
738 
739     /**
740      * Is some form of outer join supported?
741      *
742      * @return true if so
743    * 
744      */
745   public boolean supportsOuterJoins() {
746     return true;
747   }
748 
749     /**
750      * Are full nested outer joins supported?
751      *
752      * @return true if so
753    * 
754      */
755   public boolean supportsFullOuterJoins()  {
756     return false;
757   }
758 
759     /**
760      * Is there limited support for outer joins?  (This will be true
761      * if supportFullOuterJoins is true.)
762      *
763      * @return true if so
764    * 
765      */
766   public boolean supportsLimitedOuterJoins() {
767     return true;
768   }
769 
770     /**
771      * What's the database vendor's preferred term for "schema"?
772      *
773      * @return the vendor term
774    * 
775      */
776   public String getSchemaTerm() {
777     return "SCHEMA";
778   }
779 
780     /**
781      * What's the database vendor's preferred term for "procedure"?
782      *
783      * @return the vendor term
784    * 
785      */
786   public String getProcedureTerm() {
787     return "PROCEDURE";
788   }
789 
790     /**
791      * What's the database vendor's preferred term for "catalog"?
792      *
793      * @return the vendor term
794    * 
795      */
796   public String getCatalogTerm() {
797     return "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 it appears at the start
805    * 
806      */
807   public boolean isCatalogAtStart() {
808     return false;
809   }
810 
811     /**
812      * What's the separator between catalog and table name?
813      *
814      * @return the separator string
815    * 
816      */
817   public String getCatalogSeparator() {
818     return "";
819   }
820 
821     /**
822      * Can a schema name be used in a data manipulation statement?
823      *
824      * @return true if so
825    * 
826      */
827   public boolean supportsSchemasInDataManipulation() {
828     return true;
829   }
830 
831     /**
832      * Can a schema name be used in a procedure call statement?
833      *
834      * @return true if so
835    * 
836      */
837   public boolean supportsSchemasInProcedureCalls() {
838     return true;
839   }
840 
841     /**
842      * Can a schema name be used in a table definition statement?
843      *
844      * @return true if so
845    * 
846      */
847   public boolean supportsSchemasInTableDefinitions() {
848     return true;
849   }
850 
851     /**
852      * Can a schema name be used in an index definition statement?
853      *
854      * @return true if so
855      */
856   public boolean supportsSchemasInIndexDefinitions() {
857     return true;
858   }
859 
860     /**
861      * Can a schema name be used in a privilege definition statement?
862      *
863      * @return true if so
864    * 
865      */
866   public boolean supportsSchemasInPrivilegeDefinitions() {
867     return true;
868   }
869 
870     /**
871      * Can a catalog name be used in a data manipulation statement?
872      *
873      * @return true if so
874    * 
875      */
876   public boolean supportsCatalogsInDataManipulation() {
877     return false;
878   }
879 
880     /**
881      * Can a catalog name be used in a procedure call statement?
882      *
883      * @return true if so
884    * 
885      */
886   public boolean supportsCatalogsInProcedureCalls() {
887     return false;
888   }
889 
890     /**
891      * Can a catalog name be used in a table definition statement?
892      *
893      * @return true if so
894    * 
895      */
896   public boolean supportsCatalogsInTableDefinitions() {
897     return false;
898   }
899 
900     /**
901      * Can a catalog name be used in an index definition statement?
902      *
903      * @return true if so
904      */
905   public boolean supportsCatalogsInIndexDefinitions() {
906     return false;
907   }
908 
909     /**
910      * Can a catalog name be used in a privilege definition statement?
911      *
912      * @return true if so
913      */
914   public boolean supportsCatalogsInPrivilegeDefinitions() {
915     return false;
916   }
917 
918 
919     /**
920      * Is positioned DELETE supported?
921      *
922      * @return true if so
923      */
924   public boolean supportsPositionedDelete() {
925     return true;
926   }
927 
928     /**
929      * Is positioned UPDATE supported?
930      *
931      * @return true if so
932      */
933   public boolean supportsPositionedUpdate() {
934     return true;
935   }
936 
937     /**
938      * Is SELECT for UPDATE supported?
939      *
940      * @return true if so
941      */
942   public boolean supportsSelectForUpdate() {
943     return true;
944   }
945 
946     /**
947      * Are stored procedure calls using the stored procedure escape
948      * syntax supported?
949      *
950      * @return true if so
951      */
952   public boolean supportsStoredProcedures() {
953     return true;
954   }
955 
956     /**
957      * Are subqueries in comparison expressions supported?
958      *
959      * A JDBC-Compliant driver always returns true.
960      *
961      * @return true if so
962      */
963   public boolean supportsSubqueriesInComparisons() {
964     return true;
965   }
966 
967     /**
968      * Are subqueries in 'exists' expressions supported?
969      *
970      * A JDBC-Compliant driver always returns true.
971      *
972      * @return true if so
973      */
974   public boolean supportsSubqueriesInExists() {
975     return true;
976   }
977 
978     /**
979      * Are subqueries in 'in' statements supported?
980      *
981      * A JDBC-Compliant driver always returns true.
982      *
983      * @return true if so
984      */
985   public boolean supportsSubqueriesInIns() {
986     return true;
987   }
988 
989     /**
990      * Are subqueries in quantified expressions supported?
991      *
992      * A JDBC-Compliant driver always returns true.
993      *
994      * @return true if so
995      */
996   public boolean supportsSubqueriesInQuantifieds() {
997     return true;
998   }
999 
1000    /**
1001     * Are correlated subqueries supported?
1002     *
1003     * A JDBC-Compliant driver always returns true.
1004     *
1005     * @return true if so
1006     */
1007  public boolean supportsCorrelatedSubqueries() {
1008    return true;
1009  }
1010
1011    /**
1012     * Is SQL UNION supported?
1013     *
1014     * @return true if so
1015     */
1016  public boolean supportsUnion() {
1017    return true;
1018  }
1019
1020    /**
1021     * Is SQL UNION ALL supported?
1022     *
1023     * @return true if so
1024     */
1025  public boolean supportsUnionAll() {
1026    return true;
1027  }
1028
1029    /**
1030     * Can cursors remain open across commits?
1031     *
1032     * @return true if cursors always remain open; false if they might not remain open
1033     */
1034  //returns false because Derby does not support cursors that are open across commits for XA transactions.
1035  public boolean supportsOpenCursorsAcrossCommit() {
1036    return false;
1037  }
1038
1039    /**
1040     * Can cursors remain open across rollbacks?
1041     *
1042     * @return true if cursors always remain open; false if they might not remain open
1043     */
1044  public boolean supportsOpenCursorsAcrossRollback() {
1045    return false;
1046  }
1047
1048    /**
1049     * Can statements remain open across commits?
1050     *
1051     * @return true if statements always remain open; false if they might not remain open
1052     */
1053  public boolean supportsOpenStatementsAcrossCommit() {
1054    return true;
1055  }
1056
1057    /**
1058     * Can statements remain open across rollbacks?
1059     *
1060     * @return true if statements always remain open; false if they might not remain open
1061     */
1062  public boolean supportsOpenStatementsAcrossRollback() {
1063    return false;
1064  }
1065
1066
1067
1068    //----------------------------------------------------------------------
1069    // The following group of methods exposes various limitations
1070    // based on the target database with the current driver.
1071    // Unless otherwise specified, a result of zero means there is no
1072    // limit, or the limit is not known.
1073
1074    /**
1075     * How many hex characters can you have in an inline binary literal?
1076     *
1077     * @return max literal length
1078     */
1079  public int getMaxBinaryLiteralLength() {
1080    return 0;
1081  }
1082
1083    /**
1084     * What's the max length for a character literal?
1085     *
1086     * @return max literal length
1087     */
1088  public int getMaxCharLiteralLength() {
1089    return 0;
1090  }
1091
1092    /**
1093     * What's the limit on column name length?
1094     *
1095     * @return max literal length
1096     */
1097  public int getMaxColumnNameLength() {
1098    return Limits.MAX_IDENTIFIER_LENGTH;
1099  }
1100
1101    /**
1102     * What's the maximum number of columns in a "GROUP BY" clause?
1103     *
1104     * @return max number of columns
1105     */
1106  public int getMaxColumnsInGroupBy() {
1107    return 0;
1108  }
1109
1110    /**
1111     * What's the maximum number of columns allowed in an index?
1112     *
1113     * @return max columns
1114     */
1115  public int getMaxColumnsInIndex() {
1116    return 0;
1117  }
1118
1119    /**
1120     * What's the maximum number of columns in an "ORDER BY" clause?
1121     *
1122     * @return max columns
1123     */
1124  public int getMaxColumnsInOrderBy() {
1125    return 0;
1126  }
1127
1128    /**
1129     * What's the maximum number of columns in a "SELECT" list?
1130     *
1131     * we don't have a limit...
1132     *
1133     * @return max columns
1134     */
1135  public int getMaxColumnsInSelect() {
1136    return 0;
1137  }
1138
1139    /**
1140     * What's the maximum number of columns in a table?
1141     *
1142     * @return max columns
1143     */
1144  public int getMaxColumnsInTable()  {
1145    return 0;
1146  }
1147
1148    /**
1149     * How many active connections can we have at a time to this database?
1150     *
1151     * @return max connections
1152     */
1153  public int getMaxConnections() {
1154    return 0;
1155  }
1156
1157    /**
1158     * What's the maximum cursor name length?
1159     *
1160     * @return max cursor name length in bytes
1161     */
1162  public int getMaxCursorNameLength() {
1163    return Limits.MAX_IDENTIFIER_LENGTH;
1164  }
1165
1166    /**
1167     * What's the maximum length of an index (in bytes)?
1168     *
1169     * @return max index length in bytes
1170     */
1171  public int getMaxIndexLength() {
1172    return 0;
1173  }
1174
1175    /**
1176     * What's the maximum length allowed for a schema name?
1177     *
1178     * @return max name length in bytes
1179     */
1180  public int getMaxSchemaNameLength()  {
1181    return Limits.MAX_IDENTIFIER_LENGTH;
1182  }
1183
1184    /**
1185     * What's the maximum length of a procedure name?
1186     *
1187     * @return max name length in bytes
1188     */
1189  public int getMaxProcedureNameLength() {
1190    return Limits.MAX_IDENTIFIER_LENGTH;
1191  }
1192
1193    /**
1194     * What's the maximum length of a catalog name?
1195     *
1196     * @return max name length in bytes
1197     */
1198  public int getMaxCatalogNameLength()  {
1199    return 0;
1200  }
1201
1202    /**
1203     * What's the maximum length of a single row?
1204     *
1205     * @return max row size in bytes
1206     */
1207  public int getMaxRowSize() {
1208    return 0;
1209  }
1210
1211    /**
1212     * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
1213     * blobs?
1214     *
1215     * @return true if so
1216     */
1217  public boolean doesMaxRowSizeIncludeBlobs() {
1218    return true;
1219  }
1220
1221    /**
1222     * What's the maximum length of a SQL statement?
1223     *
1224     * @return max length in bytes
1225     */
1226  public int getMaxStatementLength() {
1227    return 0;
1228  }
1229
1230    /**
1231     * How many active statements can we have open at one time to this
1232     * database?
1233     *
1234     * @return the maximum
1235     */
1236  public int getMaxStatements() {
1237    return 0;
1238  }
1239
1240    /**
1241     * What's the maximum length of a table name?
1242     *
1243     * @return max name length in bytes
1244     */
1245  public int getMaxTableNameLength() {
1246    return Limits.MAX_IDENTIFIER_LENGTH;
1247  }
1248
1249    /**
1250     * What's the maximum number of tables in a SELECT?
1251     *
1252     * @return the maximum
1253     */
1254  public int getMaxTablesInSelect() {
1255    return 0;
1256  }
1257
1258    /**
1259     * What's the maximum length of a user name?
1260     *
1261     * @return max name length  in bytes
1262     */
1263  public int getMaxUserNameLength() {
1264    return Limits.DB2_MAX_USERID_LENGTH;
1265  }
1266
1267    //----------------------------------------------------------------------
1268
1269    /**
1270     * What's the database's default transaction isolation level?  The
1271     * values are defined in java.sql.Connection.
1272     *
1273     * @return the default isolation level
1274     * @see Connection
1275     */
1276  public int getDefaultTransactionIsolation() {
1277    return java.sql.Connection.TRANSACTION_READ_COMMITTED;
1278  }
1279
1280    /**
1281     * Are transactions supported? If not, commit is a noop and the
1282     * isolation level is TRANSACTION_NONE.
1283     *
1284     * @return true if transactions are supported
1285     */
1286  public boolean supportsTransactions()  {
1287    return true;
1288  }
1289
1290    /**
1291     * Does the database support the given transaction isolation level?
1292   *
1293   * DatabaseMetaData.supportsTransactionIsolation() should return false for
1294   * isolation levels that are not supported even if a higher level can be
1295   * substituted.
1296     *
1297     * @param level the values are defined in java.sql.Connection
1298     * @return true if so
1299     * @see Connection
1300    */  
1301  public boolean supportsTransactionIsolationLevel(int level)
1302               {
1303    // REMIND: This is hard-coded for the moment because it doesn't nicely
1304    // fit within the framework we've set up for the rest of these values.
1305    // Part of the reason is that it has a parameter, so it's not just a
1306    // simple value look-up.  Some ideas for the future on how to make this
1307    // not hard-coded:
1308    //    - code it as a query: "select true from <something> where ? in
1309    //      (a,b,c)" where a,b,c are the supported isolation levels.  The
1310    //      parameter would be set to "level".  This seems awfully awkward.
1311    //    - somehow what you'd really like is to enable the instructions
1312    //      file to contain the list, or set, of supported isolation
1313    //      levels.  Something like:
1314    //          supportsTr...ionLevel=SERIALIZABLE | REPEATABLE_READ | ...
1315    //      That would take some more code that doesn't seem worthwhile at
1316    //      the moment for this one case.
1317
1318    /*
1319      REMIND: this could be moved into a query that is e.g.
1320      VALUES ( ? in (8,...) )
1321      so that database could control the list of supported
1322      isolations.  For now, it's hard coded, and just the one.
1323     */
1324
1325    return (level == Connection.TRANSACTION_SERIALIZABLE    ||
1326            level == Connection.TRANSACTION_REPEATABLE_READ ||
1327          level == Connection.TRANSACTION_READ_COMMITTED  ||
1328          level == Connection.TRANSACTION_READ_UNCOMMITTED);
1329  }
1330
1331    /**
1332     * Are both data definition and data manipulation statements
1333     * within a transaction supported?
1334     *
1335     * @return true if so
1336     */
1337  public boolean supportsDataDefinitionAndDataManipulationTransactions() {
1338       return true;
1339  }
1340    /**
1341     * Are only data manipulation statements within a transaction
1342     * supported?
1343     *
1344     * @return true if so
1345     */
1346  public boolean supportsDataManipulationTransactionsOnly()
1347  {
1348       return false;
1349  }
1350    /**
1351     * Does a data definition statement within a transaction force the
1352     * transaction to commit?
1353     *
1354     * @return true if so
1355   * 
1356     */
1357  public boolean dataDefinitionCausesTransactionCommit() {
1358    return false;
1359  }
1360    /**
1361     * Is a data definition statement within a transaction ignored?
1362     *
1363     * @return true if so
1364   * 
1365     */
1366  public boolean dataDefinitionIgnoredInTransactions(){
1367    return false;
1368  }
1369
1370
1371    /**
1372     * Get a description of stored procedures available in a
1373     * catalog.
1374     *
1375     * <P>Only procedure descriptions matching the schema and
1376     * procedure name criteria are returned.  They are ordered by
1377     * PROCEDURE_SCHEM, and PROCEDURE_NAME.
1378     *
1379     * <P>Each procedure description has the the following columns:
1380     *  <OL>
1381     *  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1382     *  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1383     *  <LI><B>PROCEDURE_NAME</B> String => procedure name
1384     *  <LI> reserved for future use
1385     *  <LI> reserved for future use
1386     *  <LI> reserved for future use
1387     *  <LI><B>REMARKS</B> String => explanatory comment on the procedure
1388     *  <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
1389     *      <UL>
1390     *      <LI> procedureResultUnknown - May return a result
1391     *      <LI> procedureNoResult - Does not return a result
1392     *      <LI> procedureReturnsResult - Returns a result
1393     *      </UL>
1394     *  </OL>
1395     *
1396     * @param catalog a catalog name; "" retrieves those without a
1397     * catalog; null means drop catalog name from the selection criteria
1398     * @param schemaPattern a schema name pattern; "" retrieves those
1399     * without a schema
1400     * @param procedureNamePattern a procedure name pattern
1401     * @return ResultSet - each row is a procedure description
1402     * @see #getSearchStringEscape
1403   * @exception SQLException thrown on failure.
1404     */
1405  public ResultSet getProcedures(String catalog, String schemaPattern,
1406      String procedureNamePattern) throws SQLException {
1407
1408    return doGetProcs(catalog, schemaPattern,
1409      procedureNamePattern, "getProcedures");
1410  }
1411
1412  /**
1413   * Get a description of stored procedures available in a
1414   * catalog.  Same as getProcedures() above, except that
1415   * the result set will conform to ODBC specifications.
1416   */
1417  public ResultSet getProceduresForODBC(String catalog, String schemaPattern,
1418      String procedureNamePattern) throws SQLException {
1419
1420    return doGetProcs(catalog, schemaPattern,
1421      procedureNamePattern, "odbc_getProcedures");
1422  }
1423
1424  /**
1425   * Does the actual work for the getProcedures metadata calls.
1426   * See getProcedures() method above for parameter descriptions.
1427   * @param queryName Name of the query to execute; is used
1428   *  to determine whether the result set should conform to
1429   *  JDBC or ODBC specifications.
1430   */
1431  private ResultSet doGetProcs(String catalog, String schemaPattern,
1432    String procedureNamePattern, String queryName)
1433    throws SQLException {
1434
1435    PreparedStatement s = getPreparedQuery(queryName);
1436    s.setString(1, swapNull(catalog));
1437    s.setString(2, swapNull(schemaPattern));
1438    s.setString(3, swapNull(procedureNamePattern));
1439    return s.executeQuery();
1440  }
1441
1442    /**
1443     * Get a description of a catalog's stored procedure parameters
1444     * and result columns.
1445     *
1446     * <P>Only descriptions matching the schema, procedure and
1447     * parameter name criteria are returned.  They are ordered by
1448     * PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
1449     * if any, is first. Next are the parameter descriptions in call
1450     * order. The column descriptions follow in column number order.
1451     *
1452     * <P>Each row in the ResultSet is a parameter description or
1453     * column description with the following fields:
1454     *  <OL>
1455     *  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1456     *  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1457     *  <LI><B>PROCEDURE_NAME</B> String => procedure name
1458     *  <LI><B>COLUMN_NAME</B> String => column/parameter name
1459     *  <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
1460     *      <UL>
1461     *      <LI> procedureColumnUnknown - nobody knows
1462     *      <LI> procedureColumnIn - IN parameter
1463     *      <LI> procedureColumnInOut - INOUT parameter
1464     *      <LI> procedureColumnOut - OUT parameter
1465     *      <LI> procedureColumnReturn - procedure return value
1466     *      <LI> procedureColumnResult - result column in ResultSet
1467     *      </UL>
1468     *  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1469     *  <LI><B>TYPE_NAME</B> String => SQL type name
1470     *  <LI><B>PRECISION</B> int => precision
1471     *  <LI><B>LENGTH</B> int => length in bytes of data
1472     *  <LI><B>SCALE</B> short => scale
1473     *  <LI><B>RADIX</B> short => radix
1474     *  <LI><B>NULLABLE</B> short => can it contain NULL?
1475     *      <UL>
1476     *      <LI> procedureNoNulls - does not allow NULL values
1477     *      <LI> procedureNullable - allows NULL values
1478     *      <LI> procedureNullableUnknown - nullability unknown
1479     *      </UL>
1480     *  <LI><B>REMARKS</B> String => comment describing parameter/column
1481     *  </OL>
1482     *
1483     * <P><B>Note:</B> Some databases may not return the column
1484     * descriptions for a procedure. Additional columns beyond
1485     * REMARKS can be defined by the database.
1486     *
1487     * @param catalog a catalog name; "" retrieves those without a
1488     * catalog; null means drop catalog name from the selection criteria
1489     * @param schemaPattern a schema name pattern; "" retrieves those
1490     * without a schema
1491     * @param procedureNamePattern a procedure name pattern
1492     * @param columnNamePattern a column name pattern
1493     * @return ResultSet - each row is a stored procedure parameter or
1494     *      column description
1495     * @see #getSearchStringEscape
1496   * @exception SQLException thrown on failure.
1497     */
1498  public ResultSet getProcedureColumns(String catalog,
1499      String schemaPattern,
1500      String procedureNamePattern,
1501      String columnNamePattern) throws SQLException {
1502
1503    return doGetProcCols(catalog, schemaPattern,
1504      procedureNamePattern, columnNamePattern,
1505      "getProcedureColumns");
1506  }
1507
1508  /**
1509   * Get a description of a catalog's stored procedure parameters
1510   * and result columns.  Same as getProcedureColumns() above,
1511   * except that the result set will conform to ODBC specifications.
1512   */
1513  public ResultSet getProcedureColumnsForODBC(String catalog,
1514      String schemaPattern, String procedureNamePattern,
1515      String columnNamePattern) throws SQLException {
1516
1517    return doGetProcCols(catalog, schemaPattern,
1518      procedureNamePattern, columnNamePattern,
1519      "odbc_getProcedureColumns");
1520  }
1521
1522  /**
1523   * Does the actual work for the getProcedureColumns metadata
1524   * calls. See getProcedureColumns() method above for parameter
1525   * descriptions.
1526   * @param queryName Name of the query to execute; is used
1527   *  to determine whether the result set should conform to
1528   *  JDBC or ODBC specifications.
1529   */
1530  private ResultSet doGetProcCols(String catalog, String schemaPattern,
1531      String procedureNamePattern, String columnNamePattern,
1532      String queryName) throws SQLException {
1533
1534    PreparedStatement s = getPreparedQuery(queryName);
1535    // 
1536                // catalog is not part of the query
1537                //
1538    s.setString(1, swapNull(schemaPattern));
1539    s.setString(2, swapNull(procedureNamePattern));
1540    s.setString(3, swapNull(columnNamePattern));
1541    return s.executeQuery();
1542  }
1543
1544    /**
1545     * Get a description of tables available in a catalog.
1546     *
1547     * <P>Only table descriptions matching the catalog, schema, table
1548     * name and type criteria are returned.  They are ordered by
1549     * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1550     *
1551     * <P>Each table description has the following columns:
1552     *  <OL>
1553     *  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1554     *  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1555     *  <LI><B>TABLE_NAME</B> String => table name
1556     *  <LI><B>TABLE_TYPE</B> String => table type.  Typical types are "TABLE",
1557     *      "VIEW",  "SYSTEM TABLE", "GLOBAL TEMPORARY",
1558     *      "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1559     *  <LI><B>REMARKS</B> String => explanatory comment on the table
1560     *  </OL>
1561     *
1562     * <P><B>Note:</B> Some databases may not return information for
1563     * all tables.
1564     *
1565     * @param catalog a catalog name; "" retrieves those without a
1566     * catalog; null means drop catalog name from the selection criteria
1567     * @param schemaPattern a schema name pattern; "" retrieves those
1568     * without a schema
1569     * @param tableNamePattern a table name pattern
1570     * @param types a list of table types to include; null returns all types
1571     * @return ResultSet - each row is a table description
1572     * @see #getSearchStringEscape
1573   * @exception SQLException thrown on failure.
1574     */
1575  public ResultSet getTables(String catalog, String schemaPattern,
1576    String tableNamePattern, String types[]) throws SQLException {
1577    synchronized (getConnectionSynchronization()) {
1578                        setupContextStack();
1579      ResultSet rs = null;
1580      try {
1581      
1582      String queryText = getQueryDescriptions().getProperty("getTables");
1583
1584      /*
1585       * The query text is assumed to end with a "where" clause, so
1586       * that we can safely append
1587       * "and table_Type in ('xxx','yyy','zzz', ...)" and
1588       * have it become part of the where clause.
1589       *
1590       * Let's assume for now that the table type first char corresponds
1591       * to JBMS table type identifiers.
1592       */
1593      StringBuffer whereClauseTail = new StringBuffer(queryText);
1594
1595      if (types != null  &&  types.length >= 1) {
1596        whereClauseTail.append(" AND TABLETYPE IN ('");
1597        whereClauseTail.append(types[0].substring(0, 1));
1598
1599        for (int i=1; i<types.length; i++) {
1600          whereClauseTail.append("','");
1601          whereClauseTail.append(types[i].substring(0, 1));
1602        }
1603        whereClauseTail.append("')");
1604      }
1605      // Add the order by clause after the 'in' list.
1606      whereClauseTail.append(
1607        " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME");
1608
1609      PreparedStatement s =
1610        getEmbedConnection().prepareMetaDataStatement(whereClauseTail.toString());
1611
1612      s.setString(1, swapNull(catalog));
1613      s.setString(2, swapNull(schemaPattern));
1614      s.setString(3, swapNull(tableNamePattern));
1615
1616      rs = s.executeQuery();
1617        } catch (Throwable t) {
1618        throw handleException(t);
1619      } finally {
1620          restoreContextStack();
1621      }
1622
1623      return rs;
1624    }
1625  }
1626
1627    /**
1628     * Get the schema names available in this database.  The results
1629     * are ordered by schema name.
1630     *
1631     * <P>The schema column is:
1632     *  <OL>
1633     *  <LI><B>TABLE_SCHEM</B> String => schema name
1634     *  </OL>
1635     *
1636     * @return ResultSet - each row has a single String column that is a
1637     * schema name
1638   * @exception SQLException thrown on failure.
1639     */
1640  public ResultSet getSchemas() throws SQLException {
1641    return getSimpleQuery("getSchemas");
1642  }
1643
1644    /**
1645     * Get the catalog names available in this database.  The results
1646     * are ordered by catalog name.
1647     *
1648     * <P>The catalog column is:
1649     *  <OL>
1650     *  <LI><B>TABLE_CAT</B> String => catalog name
1651     *  </OL>
1652     *
1653     * @return ResultSet - each row has a single String column that is a
1654     * catalog name
1655   * @exception SQLException thrown on failure.
1656     */
1657  public ResultSet getCatalogs() throws SQLException {
1658    return getSimpleQuery("getCatalogs");
1659  }
1660
1661    /**
1662     * Get the table types available in this database.  The results
1663     * are ordered by table type.
1664     *
1665     * <P>The table type is:
1666     *  <OL>
1667     *  <LI><B>TABLE_TYPE</B> String => table type.  Typical types are "TABLE",
1668     *      "VIEW",  "SYSTEM TABLE", "GLOBAL TEMPORARY",
1669     *      "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1670     *  </OL>
1671     *
1672     * @return ResultSet - each row has a single String column that is a
1673     * table type
1674   * @exception SQLException thrown on failure.
1675     */
1676  public ResultSet getTableTypes() throws SQLException {
1677    return getSimpleQuery("getTableTypes");
1678  }
1679
1680    /**
1681     * Get a description of table columns available in a catalog.
1682     *
1683     * <P>Only column descriptions matching the catalog, schema, table
1684     * and column name criteria are returned.  They are ordered by
1685     * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1686     *
1687     * <P>Each column description has the following columns:
1688     *  <OL>
1689     *  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1690     *  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1691     *  <LI><B>TABLE_NAME</B> String => table name
1692     *  <LI><B>COLUMN_NAME</B> String => column name
1693     *  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1694     *  <LI><B>TYPE_NAME</B> String => Data source dependent type name
1695     *  <LI><B>COLUMN_SIZE</B> int => column size.  For char or date
1696     *      types this is the maximum number of characters, for numeric or
1697     *      decimal types this is precision.
1698     *  <LI><B>BUFFER_LENGTH</B> is not used.
1699     *  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1700     *  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1701     *  <LI><B>NULLABLE</B> int => is NULL allowed?
1702     *      <UL>
1703     *      <LI> columnNoNulls - might not allow NULL values
1704     *      <LI> columnNullable - definitely allows NULL values
1705     *      <LI> columnNullableUnknown - nullability unknown
1706     *      </UL>
1707     *  <LI><B>REMARKS</B> String => comment describing column (may be null)
1708     *   <LI><B>COLUMN_DEF</B> String => default value (may be null)
1709     *  <LI><B>SQL_DATA_TYPE</B> int => unused
1710     *  <LI><B>SQL_DATETIME_SUB</B> int => unused
1711     *  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1712     *       maximum number of bytes in the column
1713     *  <LI><B>ORDINAL_POSITION</B> int  => index of column in table
1714     *      (starting at 1)
1715     *  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1716     *      does not allow NULL values; "YES" means the column might
1717     *      allow NULL values.  An empty string means nobody knows.
1718     *  </OL>
1719     *
1720     * @param catalog a catalog name; "" retrieves those without a
1721     * catalog; null means drop catalog name from the selection criteria
1722     * @param schem