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.services.sanity.SanityManager; |
28 | |
29 | import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; |
30 | |
31 | import org.apache.derby.iapi.sql.dictionary.DataDictionary; |
32 | import org.apache.derby.iapi.sql.dictionary.SPSDescriptor; |
33 | |
34 | import org.apache.derby.iapi.error.StandardException; |
35 | |
36 | import org.apache.derby.impl.sql.execute.GenericConstantActionFactory; |
37 | import org.apache.derby.impl.sql.execute.GenericExecutionFactory; |
38 | |
39 | import org.apache.derby.iapi.reference.Limits; |
40 | import org.apache.derby.iapi.reference.JDBC20Translation; |
41 | import org.apache.derby.iapi.reference.JDBC30Translation; |
42 | |
43 | import java.util.Properties; |
44 | |
45 | import java.sql.DatabaseMetaData; |
46 | import java.sql.Connection; |
47 | import java.sql.PreparedStatement; |
48 | import java.sql.SQLException; |
49 | import java.sql.ResultSet; |
50 | import java.sql.Types; |
51 | |
52 | import java.io.IOException; |
53 | import java.io.InputStream; |
54 | |
55 | /** |
56 | * This class provides information about the database as a whole. |
57 | * |
58 | * <P>Many of the methods here return lists of information in ResultSets. |
59 | * You can use the normal ResultSet methods such as getString and getInt |
60 | * to retrieve the data from these ResultSets. If a given form of |
61 | * metadata is not available, these methods should throw a SQLException. |
62 | * |
63 | * <P>Some of these methods take arguments that are String patterns. These |
64 | * arguments all have names such as fooPattern. Within a pattern String, "%" |
65 | * means match any substring of 0 or more characters, and "_" means match |
66 | * any one character. Only metadata entries matching the search pattern |
67 | * are returned. If a search pattern argument is set to a null ref, it means |
68 | * that argument's criteria should be dropped from the search. |
69 | * |
70 | * <P>A SQLException will be thrown if a driver does not support a meta |
71 | * data method. In the case of methods that return a ResultSet, |
72 | * either a ResultSet (which may be empty) is returned or a |
73 | * SQLException is thrown. |
74 | * <p> |
75 | * This implementation gets instructions from the Database for how to satisfy |
76 | * most requests for information. Each instruction is either a simple string |
77 | * containing the desired information, or the text of a query that may be |
78 | * executed on the database connection to gather the information. We get the |
79 | * instructions via an "InstructionReader," which requires the database |
80 | * Connection for initialization. |
81 | * <p> |
82 | * Those few pieces of metadata that are related to the driver, rather than the |
83 | * database, come from a separate InstructionReader. Note that in that case it |
84 | * probably doesn't make sense to allow an instruction to specify a query. |
85 | * |
86 | * @author ames |
87 | */ |
88 | public class EmbedDatabaseMetaData extends ConnectionChild |
89 | implements DatabaseMetaData, java.security.PrivilegedAction { |
90 | |
91 | /* |
92 | ** Property and values related to using |
93 | ** stored prepared statements for metatdata. |
94 | */ |
95 | |
96 | private final String url; |
97 | |
98 | /* |
99 | ** Set to true if metadata is off |
100 | */ |
101 | |
102 | private GenericConstantActionFactory constantActionFactory; |
103 | |
104 | ////////////////////////////////////////////////////////////// |
105 | // |
106 | // CONSTRUCTORS |
107 | // |
108 | ////////////////////////////////////////////////////////////// |
109 | /** |
110 | @exception SQLException on error |
111 | */ |
112 | public EmbedDatabaseMetaData (EmbedConnection connection, String url) |
113 | throws SQLException { |
114 | |
115 | super(connection); |
116 | this.url = url; |
117 | |
118 | } |
119 | |
120 | /** Cached query descriptions from metadata.properties. */ |
121 | private static Properties queryDescriptions; |
122 | /** Cached query descriptions from metadata_net.properties. */ |
123 | private static Properties queryDescriptions_net; |
124 | /** |
125 | * Return all queries found in either metadata.properties or |
126 | * metadata_net.properties. |
127 | * |
128 | * @param net if <code>true</code>, read metadata_net.properties; |
129 | * otherwise, read metadata.properties. |
130 | * @return a <code>Properties</code> value with the queries |
131 | */ |
132 | private Properties getQueryDescriptions(boolean net) { |
133 | Properties p = net ? queryDescriptions_net : queryDescriptions; |
134 | if (p != null) { |
135 | return p; |
136 | } |
137 | loadQueryDescriptions(); |
138 | return net ? queryDescriptions_net : queryDescriptions; |
139 | } |
140 | |
141 | /** |
142 | * Read the query descriptions from metadata.properties and |
143 | * metadata_net.properties. This method must be invoked from |
144 | * within a privileged block. |
145 | */ |
146 | private void PBloadQueryDescriptions() { |
147 | String[] files = { |
148 | "metadata.properties", |
149 | "/org/apache/derby/impl/sql/catalog/metadata_net.properties" |
150 | }; |
151 | Properties[] props = new Properties[files.length]; |
152 | for (int i = 0; i < files.length; ++i) { |
153 | try { |
154 | props[i] = new Properties(); |
155 | // SECURITY PERMISSION - IP3 |
156 | InputStream is = getClass().getResourceAsStream(files[i]); |
157 | props[i].load(is); |
158 | is.close(); |
159 | } catch (IOException ioe) { |
160 | if (SanityManager.DEBUG) { |
161 | SanityManager.THROWASSERT("Error reading " + files[i], ioe); |
162 | } |
163 | } |
164 | } |
165 | queryDescriptions = props[0]; |
166 | queryDescriptions_net = props[1]; |
167 | } |
168 | |
169 | ////////////////////////////////////////////////////////////// |
170 | // |
171 | // DatabaseMetaData interface |
172 | // |
173 | ////////////////////////////////////////////////////////////// |
174 | |
175 | //---------------------------------------------------------------------- |
176 | // First, a variety of minor information about the target database. |
177 | |
178 | /** |
179 | * Can all the procedures returned by getProcedures be called by the |
180 | * current user? |
181 | * |
182 | * @return true if so |
183 | */ |
184 | public boolean allProceduresAreCallable() { |
185 | return true; |
186 | } |
187 | |
188 | /** |
189 | * Can all the tables returned by getTable be SELECTed by the |
190 | * current user? |
191 | * |
192 | * @return true if so |
193 | */ |
194 | public boolean allTablesAreSelectable() { |
195 | return true; |
196 | } |
197 | |
198 | /** |
199 | * What's the url for this database? |
200 | * |
201 | * @return the url or null if it can't be generated |
202 | */ |
203 | public final String getURL() { |
204 | |
205 | if (url == null) |
206 | return url; |
207 | int attributeStart = url.indexOf(';'); |
208 | if (attributeStart == -1) |
209 | return url; |
210 | else |
211 | return url.substring(0,attributeStart); |
212 | } |
213 | |
214 | /** |
215 | * What's our user name as known to the database? |
216 | * |
217 | * @return our database user name |
218 | */ |
219 | public String getUserName() { |
220 | return (getEmbedConnection().getTR().getUserName()); |
221 | } |
222 | |
223 | /** |
224 | * Is the database in read-only mode? |
225 | * |
226 | * @return true if so |
227 | */ |
228 | public boolean isReadOnly() { |
229 | return getLanguageConnectionContext().getDatabase().isReadOnly(); |
230 | } |
231 | |
232 | /** |
233 | * Are NULL values sorted high? |
234 | * |
235 | * @return true if so |
236 | */ |
237 | public boolean nullsAreSortedHigh() { |
238 | return true; |
239 | } |
240 | |
241 | /** |
242 | * Are NULL values sorted low? |
243 | * |
244 | * @return true if so |
245 | */ |
246 | public boolean nullsAreSortedLow() { |
247 | return false; |
248 | } |
249 | |
250 | /** |
251 | * Are NULL values sorted at the start regardless of sort order? |
252 | * |
253 | * @return true if so |
254 | */ |
255 | public boolean nullsAreSortedAtStart() { |
256 | return false; |
257 | } |
258 | |
259 | /** |
260 | * Are NULL values sorted at the end regardless of sort order? |
261 | * |
262 | * @return true if so |
263 | */ |
264 | public boolean nullsAreSortedAtEnd() { |
265 | return false; |
266 | } |
267 | |
268 | /** |
269 | * What's the name of this database product? |
270 | * |
271 | * @return database product name |
272 | */ |
273 | public String getDatabaseProductName() { |
274 | return Monitor.getMonitor().getEngineVersion().getProductName(); |
275 | } |
276 | |
277 | /** |
278 | * What's the version of this database product? |
279 | * |
280 | * @return database version |
281 | */ |
282 | public String getDatabaseProductVersion() { |
283 | ProductVersionHolder myPVH = Monitor.getMonitor().getEngineVersion(); |
284 | |
285 | return myPVH.getVersionBuildString(false); |
286 | } |
287 | |
288 | /** |
289 | * What's the name of this JDBC driver? |
290 | * |
291 | * @return JDBC driver name |
292 | */ |
293 | public String getDriverName() { |
294 | return "Apache Derby Embedded JDBC Driver"; |
295 | } |
296 | |
297 | /** |
298 | * What's the version of this JDBC driver? |
299 | * |
300 | * @return JDBC driver version |
301 | */ |
302 | public String getDriverVersion() { |
303 | return getDatabaseProductVersion(); |
304 | } |
305 | |
306 | /** |
307 | * What's this JDBC driver's major version number? |
308 | * |
309 | * @return JDBC driver major version |
310 | */ |
311 | public int getDriverMajorVersion() { |
312 | return getEmbedConnection().getLocalDriver().getMajorVersion(); |
313 | } |
314 | |
315 | /** |
316 | * What's this JDBC driver's minor version number? |
317 | * |
318 | * @return JDBC driver minor version number |
319 | */ |
320 | public int getDriverMinorVersion() { |
321 | return getEmbedConnection().getLocalDriver().getMinorVersion(); |
322 | } |
323 | |
324 | /** |
325 | * Does the database store tables in a local file? |
326 | * |
327 | * @return true if so |
328 | */ |
329 | public boolean usesLocalFiles() { |
330 | return true; |
331 | } |
332 | |
333 | /** |
334 | * Does the database use a file for each table? |
335 | * |
336 | * @return true if the database uses a local file for each table |
337 | */ |
338 | public boolean usesLocalFilePerTable() { |
339 | return true; |
340 | } |
341 | |
342 | /** |
343 | * Does the database treat mixed case unquoted SQL identifiers as |
344 | * case sensitive and as a result store them in mixed case? |
345 | * |
346 | * A JDBC-Compliant driver will always return false. |
347 | * |
348 | * @return true if so |
349 | */ |
350 | public boolean supportsMixedCaseIdentifiers() { |
351 | return false; |
352 | } |
353 | |
354 | /** |
355 | * Does the database treat mixed case unquoted SQL identifiers as |
356 | * case insensitive and store them in upper case? |
357 | * |
358 | * @return true if so |
359 | */ |
360 | public boolean storesUpperCaseIdentifiers() { |
361 | return true; |
362 | } |
363 | |
364 | /** |
365 | * Does the database treat mixed case unquoted SQL identifiers as |
366 | * case insensitive and store them in lower case? |
367 | * |
368 | * @return true if so |
369 | */ |
370 | public boolean storesLowerCaseIdentifiers() { |
371 | return false; |
372 | } |
373 | |
374 | /** |
375 | * Does the database treat mixed case unquoted SQL identifiers as |
376 | * case insensitive and store them in mixed case? |
377 | * |
378 | * @return true if so |
379 | */ |
380 | public boolean storesMixedCaseIdentifiers() { |
381 | return false; |
382 | } |
383 | |
384 | /** |
385 | * Does the database treat mixed case quoted SQL identifiers as |
386 | * case sensitive and as a result store them in mixed case? |
387 | * |
388 | * A JDBC-Compliant driver will always return true. |
389 | * |
390 | * @return true if so |
391 | */ |
392 | public boolean supportsMixedCaseQuotedIdentifiers() { |
393 | return true; |
394 | } |
395 | |
396 | /** |
397 | * Does the database treat mixed case quoted SQL identifiers as |
398 | * case insensitive and store them in upper case? |
399 | * |
400 | * @return true if so |
401 | */ |
402 | public boolean storesUpperCaseQuotedIdentifiers() { |
403 | return false; |
404 | } |
405 | |
406 | /** |
407 | * Does the database treat mixed case quoted SQL identifiers as |
408 | * case insensitive and store them in lower case? |
409 | * |
410 | * @return true if so |
411 | */ |
412 | public boolean storesLowerCaseQuotedIdentifiers() { |
413 | return false; |
414 | } |
415 | |
416 | /** |
417 | * Does the database treat mixed case quoted SQL identifiers as |
418 | * case insensitive and store them in mixed case? |
419 | * |
420 | * @return true if so |
421 | */ |
422 | public boolean storesMixedCaseQuotedIdentifiers() { |
423 | return true; |
424 | } |
425 | |
426 | /** |
427 | * What's the string used to quote SQL identifiers? |
428 | * This returns a space " " if identifier quoting isn't supported. |
429 | * |
430 | * A JDBC-Compliant driver always uses a double quote character. |
431 | * |
432 | * @return the quoting string |
433 | */ |
434 | public String getIdentifierQuoteString() { |
435 | return "\""; |
436 | } |
437 | |
438 | /** |
439 | * Get a comma separated list of all a database's SQL keywords |
440 | * that are NOT also SQL92 keywords. |
441 | includes reserved and non-reserved keywords. |
442 | |
443 | * @return the list |
444 | */ |
445 | public String getSQLKeywords() { |
446 | return "ALIAS,BIGINT,BOOLEAN,CALL,CLASS,COPY,DB2J_DEBUG,EXECUTE,EXPLAIN,FILE,FILTER," |
447 | + "GETCURRENTCONNECTION,INDEX,INSTANCEOF,METHOD,NEW,OFF,PROPERTIES,PUBLICATION,RECOMPILE," |
448 | + "REFRESH,RENAME,RUNTIMESTATISTICS,STATEMENT,STATISTICS,TIMING,WAIT"; |
449 | } |
450 | |
451 | /** |
452 | * Get a comma separated list of JDBC escaped numeric functions. |
453 | * Must be a complete or sub set of functions in appendix C.1 |
454 | * @return the list |
455 | */ |
456 | public String getNumericFunctions() { |
457 | return "ABS,ACOS,ASIN,ATAN,CEILING,COS,DEGREES,EXP,FLOOR,LOG,LOG10,MOD,PI,RADIANS,SIN,SQRT,TAN"; |
458 | } |
459 | |
460 | /** |
461 | * Get a comma separated list of JDBC escaped string functions. |
462 | * Must be a complete or sub set of functions in appendix C.2 |
463 | * of JDBC 3.0 specification. |
464 | * @return the list |
465 | */ |
466 | public String getStringFunctions() { |
467 | return "CONCAT,LENGTH,LCASE,LOCATE,LTRIM,RTRIM,SUBSTRING,UCASE"; |
468 | } |
469 | |
470 | /** |
471 | * Get a comma separated list of JDBC escaped system functions. |
472 | * Must be a complete or sub set of functions in appendix C.4 |
473 | * of JDBC 3.0 specification. |
474 | * @return the list |
475 | */ |
476 | public String getSystemFunctions() { |
477 | return "USER"; |
478 | } |
479 | |
480 | /** |
481 | * Get a comma separated list of JDBC escaped time date functions. |
482 | * Must be a complete or sub set of functions in appendix C.3 |
483 | * of JDBC 3.0 specification. |
484 | * @return the list |
485 | */ |
486 | public String getTimeDateFunctions() { |
487 | return "CURDATE,CURTIME,HOUR,MINUTE,MONTH,SECOND,TIMESTAMPADD,TIMESTAMPDIFF,YEAR"; |
488 | } |
489 | |
490 | /** |
491 | * This is the string that can be used to escape '_' or '%' in |
492 | * the string pattern style catalog search parameters. |
493 | we have no default escape value, so = is the end of the next line |
494 | * <P>The '_' character represents any single character. |
495 | * <P>The '%' character represents any sequence of zero or |
496 | * more characters. |
497 | * @return the string used to escape wildcard characters |
498 | */ |
499 | public String getSearchStringEscape() { |
500 | return ""; |
501 | } |
502 | |
503 | /** |
504 | * Get all the "extra" characters that can be used in unquoted |
505 | * identifier names (those beyond a-z, A-Z, 0-9 and _). |
506 | * |
507 | * @return the string containing the extra characters |
508 | */ |
509 | public String getExtraNameCharacters() { |
510 | return ""; |
511 | } |
512 | |
513 | //-------------------------------------------------------------------- |
514 | // Functions describing which features are supported. |
515 | |
516 | /** |
517 | * Is "ALTER TABLE" with add column supported? |
518 | * |
519 | * @return true if so |
520 | */ |
521 | public boolean supportsAlterTableWithAddColumn() { |
522 | return true; |
523 | } |
524 | |
525 | /** |
526 | * Is "ALTER TABLE" with drop column supported? |
527 | * |
528 | * @return true if so |
529 | */ |
530 | public boolean supportsAlterTableWithDropColumn() { |
531 | return true; |
532 | } |
533 | |
534 | /** |
535 | * Is column aliasing supported? |
536 | * |
537 | * <P>If so, the SQL AS clause can be used to provide names for |
538 | * computed columns or to provide alias names for columns as |
539 | * required. |
540 | * |
541 | * A JDBC-Compliant driver always returns true. |
542 | * |
543 | * @return true if so |
544 | */ |
545 | public boolean supportsColumnAliasing() { |
546 | return true; |
547 | } |
548 | |
549 | /** |
550 | * Are concatenations between NULL and non-NULL values NULL? |
551 | * |
552 | * A JDBC-Compliant driver always returns true. |
553 | * |
554 | * @return true if so |
555 | */ |
556 | public boolean nullPlusNonNullIsNull() { |
557 | return true; |
558 | } |
559 | |
560 | /** |
561 | * Is the CONVERT function between SQL types supported? |
562 | * |
563 | * @return true if so |
564 | */ |
565 | public boolean supportsConvert() { |
566 | return true; |
567 | } |
568 | |
569 | /** |
570 | * Is CONVERT between the given SQL types supported? |
571 | * |
572 | * @param fromType the type to convert from |
573 | * @param toType the type to convert to |
574 | * @return true if so |
575 | * @see Types |
576 | */ |
577 | public boolean supportsConvert(int fromType, int toType) { |
578 | /* |
579 | * at the moment we don't support CONVERT at all, so we take the easy |
580 | * way out. Eventually we need to figure out how to handle this |
581 | * cleanly. |
582 | */ |
583 | return false; |
584 | } |
585 | |
586 | /** |
587 | * Are table correlation names supported? |
588 | * |
589 | * A JDBC-Compliant driver always returns true. |
590 | * |
591 | * @return true if so |
592 | */ |
593 | public boolean supportsTableCorrelationNames() { |
594 | return true; |
595 | } |
596 | |
597 | /** |
598 | * If table correlation names are supported, are they restricted |
599 | * to be different from the names of the tables? |
600 | * |
601 | * @return true if so |
602 | */ |
603 | public boolean supportsDifferentTableCorrelationNames() { |
604 | return true; |
605 | } |
606 | |
607 | /** |
608 | * Are expressions in "ORDER BY" lists supported? |
609 | * |
610 | * @return true if so |
611 | */ |
612 | public boolean supportsExpressionsInOrderBy() { |
613 | return false; |
614 | } |
615 | |
616 | /** |
617 | * Can an "ORDER BY" clause use columns not in the SELECT? |
618 | * |
619 | * @return true if so |
620 | */ |
621 | public boolean supportsOrderByUnrelated() { |
622 | return false; |
623 | } |
624 | |
625 | /** |
626 | * Is some form of "GROUP BY" clause supported? |
627 | * |
628 | * @return true if so |
629 | */ |
630 | public boolean supportsGroupBy() { |
631 | return true; |
632 | } |
633 | |
634 | /** |
635 | * Can a "GROUP BY" clause use columns not in the SELECT? |
636 | * |
637 | * @return true if so |
638 | */ |
639 | public boolean supportsGroupByUnrelated() { |
640 | return true; |
641 | } |
642 | |
643 | /** |
644 | * Can a "GROUP BY" clause add columns not in the SELECT |
645 | * provided it specifies all the columns in the SELECT? |
646 | * |
647 | * @return true if so |
648 | */ |
649 | public boolean supportsGroupByBeyondSelect() { |
650 | return true; |
651 | } |
652 | |
653 | /** |
654 | * Is the escape character in "LIKE" clauses supported? |
655 | * |
656 | * A JDBC-Compliant driver always returns true. |
657 | * |
658 | * @return true if so |
659 | */ |
660 | public boolean supportsLikeEscapeClause() { |
661 | return true; |
662 | } |
663 | |
664 | /** |
665 | * Are multiple ResultSets from a single execute supported? |
666 | * |
667 | * @return true if so |
668 | */ |
669 | public boolean supportsMultipleResultSets() { |
670 | return true; |
671 | } |
672 | |
673 | /** |
674 | * Can we have multiple transactions open at once (on different |
675 | * connections)? |
676 | * |
677 | * @return true if so |
678 | */ |
679 | public boolean supportsMultipleTransactions() { |
680 | return true; |
681 | } |
682 | |
683 | /** |
684 | * Can columns be defined as non-nullable? |
685 | * |
686 | * A JDBC-Compliant driver always returns true. |
687 | * |
688 | * @return true if so |
689 | */ |
690 | public boolean supportsNonNullableColumns() { |
691 | return true; |
692 | } |
693 | |
694 | /** |
695 | * Is the ODBC Minimum SQL grammar supported? |
696 | * |
697 | * All JDBC-Compliant drivers must return true. |
698 | * |
699 | * @return true if so |
700 | */ |
701 | public boolean supportsMinimumSQLGrammar() { |
702 | return true; |
703 | } |
704 | |
705 | /** |
706 | * Is the ODBC Core SQL grammar supported? |
707 | * |
708 | * @return true if so |
709 | */ |
710 | public boolean supportsCoreSQLGrammar() { |
711 | return false; |
712 | } |
713 | |
714 | /** |
715 | * Is the ODBC Extended SQL grammar supported? |
716 | * |
717 | * @return true if so |
718 | */ |
719 | public boolean supportsExtendedSQLGrammar() { |
720 | return false; |
721 | } |
722 | |
723 | /** |
724 | * Is the ANSI92 entry level SQL grammar supported? |
725 | * |
726 | * All JDBC-Compliant drivers must return true. |
727 | * |
728 | * @return true if so |
729 | */ |
730 | public boolean supportsANSI92EntryLevelSQL() { |
731 | return false; |
732 | } |
733 | |
734 | /** |
735 | * Is the ANSI92 intermediate SQL grammar supported? |
736 | * |
737 | * @return true if so |
738 | * |
739 | */ |
740 | public boolean supportsANSI92IntermediateSQL() { |
741 | return false; |
742 | } |
743 | |
744 | /** |
745 | * Is the ANSI92 full SQL grammar supported? |
746 | * |
747 | * @return true if so |
748 | * |
749 | */ |
750 | public boolean supportsANSI92FullSQL() { |
751 | return false; |
752 | } |
753 | |
754 | /** |
755 | * Is the SQL Integrity Enhancement Facility supported? |
756 | * |
757 | * @return true if so |
758 | * |
759 | */ |
760 | public boolean supportsIntegrityEnhancementFacility() { |
761 | return false; |
762 | } |
763 | |
764 | /** |
765 | * Is some form of outer join supported? |
766 | * |
767 | * @return true if so |
768 | * |
769 | */ |
770 | public boolean supportsOuterJoins() { |
771 | return true; |
772 | } |
773 | |
774 | /** |
775 | * Are full nested outer joins supported? |
776 | * |
777 | * @return true if so |
778 | * |
779 | */ |
780 | public boolean supportsFullOuterJoins() { |
781 | return false; |
782 | } |
783 | |
784 | /** |
785 | * Is there limited support for outer joins? (This will be true |
786 | * if supportFullOuterJoins is true.) |
787 | * |
788 | * @return true if so |
789 | * |
790 | */ |
791 | public boolean supportsLimitedOuterJoins() { |
792 | return true; |
793 | } |
794 | |
795 | /** |
796 | * What's the database vendor's preferred term for "schema"? |
797 | * |
798 | * @return the vendor term |
799 | * |
800 | */ |
801 | public String getSchemaTerm() { |
802 | return "SCHEMA"; |
803 | } |
804 | |
805 | /** |
806 | * What's the database vendor's preferred term for "procedure"? |
807 | * |
808 | * @return the vendor term |
809 | * |
810 | */ |
811 | public String getProcedureTerm() { |
812 | return "PROCEDURE"; |
813 | } |
814 | |
815 | /** |
816 | * What's the database vendor's preferred term for "catalog"? |
817 | * |
818 | * @return the vendor term |
819 | * |
820 | */ |
821 | public String getCatalogTerm() { |
822 | return "CATALOG"; |
823 | } |
824 | |
825 | /** |
826 | * Does a catalog appear at the start of a qualified table name? |
827 | * (Otherwise it appears at the end) |
828 | * |
829 | * @return true if it appears at the start |
830 | * |
831 | */ |
832 | public boolean isCatalogAtStart() { |
833 | return false; |
834 | } |
835 | |
836 | /** |
837 | * What's the separator between catalog and table name? |
838 | * |
839 | * @return the separator string |
840 | * |
841 | */ |
842 | public String getCatalogSeparator() { |
843 | return ""; |
844 | } |
845 | |
846 | /** |
847 | * Can a schema name be used in a data manipulation statement? |
848 | * |
849 | * @return true if so |
850 | * |
851 | */ |
852 | public boolean supportsSchemasInDataManipulation() { |
853 | return true; |
854 | } |
855 | |
856 | /** |
857 | * Can a schema name be used in a procedure call statement? |
858 | * |
859 | * @return true if so |
860 | * |
861 | */ |
862 | public boolean supportsSchemasInProcedureCalls() { |
863 | return true; |
864 | } |
865 | |
866 | /** |
867 | * Can a schema name be used in a table definition statement? |
868 | * |
869 | * @return true if so |
870 | * |
871 | */ |
872 | public boolean supportsSchemasInTableDefinitions() { |
873 | return true; |
874 | } |
875 | |
876 | /** |
877 | * Can a schema name be used in an index definition statement? |
878 | * |
879 | * @return true if so |
880 | */ |
881 | public boolean supportsSchemasInIndexDefinitions() { |
882 | return true; |
883 | } |
884 | |
885 | /** |
886 | * Can a schema name be used in a privilege definition statement? |
887 | * |
888 | * @return true if so |
889 | * |
890 | */ |
891 | public boolean supportsSchemasInPrivilegeDefinitions() { |
892 | return true; |
893 | } |
894 | |
895 | /** |
896 | * Can a catalog name be used in a data manipulation statement? |
897 | * |
898 | * @return true if so |
899 | * |
900 | */ |
901 | public boolean supportsCatalogsInDataManipulation() { |
902 | return false; |
903 | } |
904 | |
905 | /** |
906 | * Can a catalog name be used in a procedure call statement? |
907 | * |
908 | * @return true if so |
909 | * |
910 | */ |
911 | public boolean supportsCatalogsInProcedureCalls() { |
912 | return false; |
913 | } |
914 | |
915 | /** |
916 | * Can a catalog name be used in a table definition statement? |
917 | * |
918 | * @return true if so |
919 | * |
920 | */ |
921 | public boolean supportsCatalogsInTableDefinitions() { |
922 | return false; |
923 | } |
924 | |
925 | /** |
926 | * Can a catalog name be used in an index definition statement? |
927 | * |
928 | * @return true if so |
929 | */ |
930 | public boolean supportsCatalogsInIndexDefinitions() { |
931 | return false; |
932 | } |
933 | |
934 | /** |
935 | * Can a catalog name be used in a privilege definition statement? |
936 | * |
937 | * @return true if so |
938 | */ |
939 | public boolean supportsCatalogsInPrivilegeDefinitions() { |
940 | return false; |
941 | } |
942 | |
943 | |
944 | /** |
945 | * Is positioned DELETE supported? |
946 | * |
947 | * @return true if so |
948 | */ |
949 | public boolean supportsPositionedDelete() { |
950 | return true; |
951 | } |
952 | |
953 | /** |
954 | * Is positioned UPDATE supported? |
955 | * |
956 | * @return true if so |
957 | */ |
958 | public boolean supportsPositionedUpdate() { |
959 | return true; |
960 | } |
961 | |
962 | /** |
963 | * Is SELECT for UPDATE supported? |
964 | * |
965 | * @return true if so |
966 | */ |
967 | public boolean supportsSelectForUpdate() { |
968 | return true; |
969 | } |
970 | |
971 | /** |
972 | * Are stored procedure calls using the stored procedure escape |
973 | * syntax supported? |
974 | * |
975 | * @return true if so |
976 | */ |
977 | public boolean supportsStoredProcedures() { |
978 | return true; |
979 | } |
980 | |
981 | /** |
982 | * Are subqueries in comparison expressions supported? |
983 | * |
984 | * A JDBC-Compliant driver always returns true. |
985 | * |
986 | * @return true if so |
987 | */ |
988 | public boolean supportsSubqueriesInComparisons() { |
989 | return true; |
990 | } |
991 | |
992 | /** |
993 | * Are subqueries in 'exists' expressions supported? |
994 | * |
995 | * A JDBC-Compliant driver always returns true. |
996 | * |
997 | * @return true if so |
998 | */ |
999 | public boolean supportsSubqueriesInExists() { |
1000 | return true; |
1001 | } |
1002 | |
1003 | /** |
1004 | * Are subqueries in 'in' statements supported? |
1005 | * |
1006 | * A JDBC-Compliant driver always returns true. |
1007 | * |
1008 | * @return true if so |
1009 | */ |
1010 | public boolean supportsSubqueriesInIns() { |
1011 | return true; |
1012 | } |
1013 | |
1014 | /** |
1015 | * Are subqueries in quantified expressions supported? |
1016 | * |
1017 | * A JDBC-Compliant driver always returns true. |
1018 | * |
1019 | * @return true if so |
1020 | */ |
1021 | public boolean supportsSubqueriesInQuantifieds() { |
1022 | return true; |
1023 | } |
1024 | |
1025 | /** |
1026 | * Are correlated subqueries supported? |
1027 | * |
1028 | * A JDBC-Compliant driver always returns true. |
1029 | * |
1030 | * @return true if so |
1031 | */ |
1032 | public boolean supportsCorrelatedSubqueries() { |
1033 | return true; |
1034 | } |
1035 | |
1036 | /** |
1037 | * Is SQL UNION supported? |
1038 | * |
1039 | * @return true if so |
1040 | */ |
1041 | public boolean supportsUnion() { |
1042 | return true; |
1043 | } |
1044 | |
1045 | /** |
1046 | * Is SQL UNION ALL supported? |
1047 | * |
1048 | * @return true if so |
1049 | */ |
1050 | public boolean supportsUnionAll() { |
1051 | return true; |
1052 | } |
1053 | |
1054 | /** |
1055 | * Can cursors remain open across commits? |
1056 | * |
1057 | * @return true if cursors always remain open; false if they might not remain open |
1058 | */ |
1059 | //returns false because Derby does not support cursors that are open across commits for XA transactions. |
1060 | public boolean supportsOpenCursorsAcrossCommit() { |
1061 | return false; |
1062 | } |
1063 | |
1064 | /** |
1065 | * Can cursors remain open across rollbacks? |
1066 | * |
1067 | * @return true if cursors always remain open; false if they might not remain open |
1068 | */ |
1069 | public boolean supportsOpenCursorsAcrossRollback() { |
1070 | return false; |
1071 | } |
1072 | |
1073 | /** |
1074 | * Can statements remain open across commits? |
1075 | * |
1076 | * @return true if statements always remain open; false if they might not remain open |
1077 | */ |
1078 | public boolean supportsOpenStatementsAcrossCommit() { |
1079 | return true; |
1080 | } |
1081 | |
1082 | /** |
1083 | * Can statements remain open across rollbacks? |
1084 | * |
1085 | * @return true if statements always remain open; false if they might not remain open |
1086 | */ |
1087 | public boolean supportsOpenStatementsAcrossRollback() { |
1088 | return false; |
1089 | } |
1090 | |
1091 | |
1092 | |
1093 | //---------------------------------------------------------------------- |
1094 | // The following group of methods exposes various limitations |
1095 | // based on the target database with the current driver. |
1096 | // Unless otherwise specified, a result of zero means there is no |
1097 | // limit, or the limit is not known. |
1098 | |
1099 | /** |
1100 | * How many hex characters can you have in an inline binary literal? |
1101 | * |
1102 | * @return max literal length |
1103 | */ |
1104 | public int getMaxBinaryLiteralLength() { |
1105 | return 0; |
1106 | } |
1107 | |
1108 | /** |
1109 | * What's the max length for a character literal? |
1110 | * |
1111 | * @return max literal length |
1112 | */ |
1113 | public int getMaxCharLiteralLength() { |
1114 | return 0; |
1115 | } |
1116 | |
1117 | /** |
1118 | * What's the limit on column name length? |
1119 | * |
1120 | * @return max literal length |
1121 | */ |
1122 | public int getMaxColumnNameLength() { |
1123 | return Limits.MAX_IDENTIFIER_LENGTH; |
1124 | } |
1125 | |
1126 | /** |
1127 | * What's the maximum number of columns in a "GROUP BY" clause? |
1128 | * |
1129 | * @return max number of columns |
1130 | */ |
1131 | public int getMaxColumnsInGroupBy() { |
1132 | return 0; |
1133 | } |
1134 | |
1135 | /** |
1136 | * What's the maximum number of columns allowed in an index? |
1137 | * |
1138 | * @return max columns |
1139 | */ |
1140 | public int getMaxColumnsInIndex() { |
1141 | return 0; |
1142 | } |
1143 | |
1144 | /** |
1145 | * What's the maximum number of columns in an "ORDER BY" clause? |
1146 | * |
1147 | * @return max columns |
1148 | */ |
1149 | public int getMaxColumnsInOrderBy() { |
1150 | return 0; |
1151 | } |
1152 | |
1153 | /** |
1154 | * What's the maximum number of columns in a "SELECT" list? |
1155 | * |
1156 | * we don't have a limit... |
1157 | * |
1158 | * @return max columns |
1159 | */ |
1160 | public int getMaxColumnsInSelect() { |
1161 | return 0; |
1162 | } |
1163 | |
1164 | /** |
1165 | * What's the maximum number of columns in a table? |
1166 | * |
1167 | * @return max columns |
1168 | */ |
1169 | public int getMaxColumnsInTable() { |
1170 | return 0; |
1171 | } |
1172 | |
1173 | /** |
1174 | * How many active connections can we have at a time to this database? |
1175 | * |
1176 | * @return max connections |
1177 | */ |
1178 | public int getMaxConnections() { |
1179 | return 0; |
1180 | } |
1181 | |
1182 | /** |
1183 | * What's the maximum cursor name length? |
1184 | * |
1185 | * @return max cursor name length in bytes |
1186 | */ |
1187 | public int getMaxCursorNameLength() { |
1188 | return Limits.MAX_IDENTIFIER_LENGTH; |
1189 | } |
1190 | |
1191 | /** |
1192 | * What's the maximum length of an index (in bytes)? |
1193 | * |
1194 | * @return max index length in bytes |
1195 | */ |
1196 | public int getMaxIndexLength() { |
1197 | return 0; |
1198 | } |
1199 | |
1200 | /** |
1201 | * What's the maximum length allowed for a schema name? |
1202 | * |
1203 | * @return max name length in bytes |
1204 | */ |
1205 | public int getMaxSchemaNameLength() { |
1206 | return Limits.MAX_IDENTIFIER_LENGTH; |
1207 | } |
1208 | |
1209 | /** |
1210 | * What's the maximum length of a procedure name? |
1211 | * |
1212 | * @return max name length in bytes |
1213 | */ |
1214 | public int getMaxProcedureNameLength() { |
1215 | return Limits.MAX_IDENTIFIER_LENGTH; |
1216 | } |
1217 | |
1218 | /** |
1219 | * What's the maximum length of a catalog name? |
1220 | * |
1221 | * @return max name length in bytes |
1222 | */ |
1223 | public int getMaxCatalogNameLength() { |
1224 | return 0; |
1225 | } |
1226 | |
1227 | /** |
1228 | * What's the maximum length of a single row? |
1229 | * |
1230 | * @return max row size in bytes |
1231 | */ |
1232 | public int getMaxRowSize() { |
1233 | return 0; |
1234 | } |
1235 | |
1236 | /** |
1237 | * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY |
1238 | * blobs? |
1239 | * |
1240 | * @return true if so |
1241 | */ |
1242 | public boolean doesMaxRowSizeIncludeBlobs() { |
1243 | return true; |
1244 | } |
1245 | |
1246 | /** |
1247 | * What's the maximum length of a SQL statement? |
1248 | * |
1249 | * @return max length in bytes |
1250 | */ |
1251 | public int getMaxStatementLength() { |
1252 | return 0; |
1253 | } |
1254 | |
1255 | /** |
1256 | * How many active statements can we have open at one time to this |
1257 | * database? |
1258 | * |
1259 | * @return the maximum |
1260 | */ |
1261 | public int getMaxStatements() { |
1262 | return 0; |
1263 | } |
1264 | |
1265 | /** |
1266 | * What's the maximum length of a table name? |
1267 | * |
1268 | * @return max name length in bytes |
1269 | */ |
1270 | public int getMaxTableNameLength() { |
1271 | return Limits.MAX_IDENTIFIER_LENGTH; |
1272 | } |
1273 | |
1274 | /** |
1275 | * What's the maximum number of tables in a SELECT? |
1276 | * |
1277 | * @return the maximum |
1278 | */ |
1279 | public int getMaxTablesInSelect() { |
1280 | return 0; |
1281 | } |
1282 | |
1283 | /** |
1284 | * What's the maximum length of a user name? |
1285 | * |
1286 | * @return max name length in bytes |
1287 | */ |
1288 | public int getMaxUserNameLength() { |
1289 | return Limits.DB2_MAX_USERID_LENGTH; |
1290 | } |
1291 | |
1292 | //---------------------------------------------------------------------- |
1293 | |
1294 | /** |
1295 | * What's the database's default transaction isolation level? The |
1296 | * values are defined in java.sql.Connection. |
1297 | * |
1298 | * @return the default isolation level |
1299 | * @see Connection |
1300 | */ |
1301 | public int getDefaultTransactionIsolation() { |
1302 | return java.sql.Connection.TRANSACTION_READ_COMMITTED; |
1303 | } |
1304 | |
1305 | /** |
1306 | * Are transactions supported? If not, commit is a noop and the |
1307 | * isolation level is TRANSACTION_NONE. |
1308 | * |
1309 | * @return true if transactions are supported |
1310 | */ |
1311 | public boolean supportsTransactions() { |
1312 | return true; |
1313 | } |
1314 | |
1315 | /** |
1316 | * Does the database support the given transaction isolation level? |
1317 | * |
1318 | * DatabaseMetaData.supportsTransactionIsolation() should return false for |
1319 | * isolation levels that are not supported even if a higher level can be |
1320 | * substituted. |
1321 | * |
1322 | * @param level the values are defined in java.sql.Connection |
1323 | * @return true if so |
1324 | * @see Connection |
1325 | */ |
1326 | public boolean supportsTransactionIsolationLevel(int level) |
1327 | { |
1328 | // REMIND: This is hard-coded for the moment because it doesn't nicely |
1329 | // fit within the framework we've set up for the rest of these values. |
1330 | // Part of the reason is that it has a parameter, so it's not just a |
1331 | // simple value look-up. Some ideas for the future on how to make this |
1332 | // not hard-coded: |
1333 | // - code it as a query: "select true from <something> where ? in |
1334 | // (a,b,c)" where a,b,c are the supported isolation levels. The |
1335 | // parameter would be set to "level". This seems awfully awkward. |
1336 | // - somehow what you'd really like is to enable the instructions |
1337 | // file to contain the list, or set, of supported isolation |
1338 | // levels. Something like: |
1339 | // supportsTr...ionLevel=SERIALIZABLE | REPEATABLE_READ | ... |
1340 | // That would take some more code that doesn't seem worthwhile at |
1341 | // the moment for this one case. |
1342 | |
1343 | /* |
1344 | REMIND: this could be moved into a query that is e.g. |
1345 | VALUES ( ? in (8,...) ) |
1346 | so that database could control the list of supported |
1347 | isolations. For now, it's hard coded, and just the one. |
1348 | */ |
1349 | |
1350 | return (level == Connection.TRANSACTION_SERIALIZABLE || |
1351 | level == Connection.TRANSACTION_REPEATABLE_READ || |
1352 | level == Connection.TRANSACTION_READ_COMMITTED || |
1353 | level == Connection.TRANSACTION_READ_UNCOMMITTED); |
1354 | } |
1355 | |
1356 | /** |
1357 | * Are both data definition and data manipulation statements |
1358 | * within a transaction supported? |
1359 | * |
1360 | * @return true if so |
1361 | */ |
1362 | public boolean supportsDataDefinitionAndDataManipulationTransactions() { |
1363 | return true; |
1364 | } |
1365 | /** |
1366 | * Are only data manipulation statements within a transaction |
1367 | * supported? |
1368 | * |
1369 | * @return true if so |
1370 | */ |
1371 | public boolean supportsDataManipulationTransactionsOnly() |
1372 | { |
1373 | return false; |
1374 | } |
1375 | /** |
1376 | * Does a data definition statement within a transaction force the |
1377 | * transaction to commit? |
1378 | * |
1379 | * @return true if so |
1380 | * |
1381 | */ |
1382 | public boolean dataDefinitionCausesTransactionCommit() { |
1383 | return false; |
1384 | } |
1385 | /** |
1386 | * Is a data definition statement within a transaction ignored? |
1387 | * |
1388 | * @return true if so |
1389 | * |
1390 | */ |
1391 | public boolean dataDefinitionIgnoredInTransactions(){ |
1392 | return false; |
1393 | } |
1394 | |
1395 | |
1396 | /** |
1397 | * Get a description of stored procedures available in a |
1398 | * catalog. |
1399 | * |
1400 | * <P>Only procedure descriptions matching the schema and |
1401 | * procedure name criteria are returned. They are ordered by |
1402 | * PROCEDURE_SCHEM, and PROCEDURE_NAME. |
1403 | * |
1404 | * <P>Each procedure description has the the following columns: |
1405 | * <OL> |
1406 | * <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null) |
1407 | * <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null) |
1408 | * <LI><B>PROCEDURE_NAME</B> String => procedure name |
1409 | * <LI> reserved for future use |
1410 | * <LI> reserved for future use |
1411 | * <LI> reserved for future use |
1412 | * <LI><B>REMARKS</B> String => explanatory comment on the procedure |
1413 | * <LI><B>PROCEDURE_TYPE</B> short => kind of procedure: |
1414 | * <UL> |
1415 | * <LI> procedureResultUnknown - May return a result |
1416 | * <LI> procedureNoResult - Does not return a result |
1417 | * <LI> procedureReturnsResult - Returns a result |
1418 | * </UL> |
1419 | * <LI><B>SPECIFIC_NAME</B> String => The name which uniquely |
1420 | * identifies this procedure within its schema (since JDBC 4.0) |
1421 | * </OL> |
1422 | * |
1423 | * @param catalog a catalog name; "" retrieves those without a |
1424 | * catalog; null means drop catalog name from the selection criteria |
1425 | * @param schemaPattern a schema name pattern; "" retrieves those |
1426 | * without a schema |
1427 | * @param procedureNamePattern a procedure name pattern |
1428 | * @return ResultSet - each row is a procedure description |
1429 | * @see #getSearchStringEscape |
1430 | * @exception SQLException thrown on failure. |
1431 | */ |
1432 | public ResultSet getProcedures(String catalog, String schemaPattern, |
1433 | String procedureNamePattern) throws SQLException { |
1434 | |
1435 | // Using the new JDBC 4.0 version of the query here. The query |
1436 | // was given a new name to allow the old query to |
1437 | // be used by ODBCMetaDataGenerator. |
1438 | return doGetProcs(catalog, schemaPattern, |
1439 | procedureNamePattern, "getProcedures40"); |
1440 | } |
1441 | |
1442 | /** |
1443 | * Get a description of stored procedures available in a |
1444 | * catalog. Same as getProcedures() above, except that |
1445 | * the result set will conform to ODBC specifications. |
1446 | */ |
1447 | public ResultSet getProceduresForODBC(String catalog, String schemaPattern, |
1448 | String procedureNamePattern) throws SQLException { |
1449 | |
1450 | // For ODBC we still use the transformed version of the JDBC |
1451 | // 3.0 query, (may change in the future). |
1452 | return doGetProcs(catalog, schemaPattern, |
1453 | procedureNamePattern, "odbc_getProcedures"); |
1454 | } |
1455 | |
1456 | /** |
1457 | * Implements DatabaseMetaData.getFunctions() for an embedded |
1458 | * database. Queries the database to get information about |
1459 | * functions (procedures returning values). Executes the |
1460 | * 'getFunctions' query from metadata.properties to obtain the |
1461 | * ResultSet to return.<p> Compatibility: This is a new method in |
1462 | * the API which is only available with with Derby versions > 10.1 and |
1463 | * JDK versions >= 1.6 <p>Upgrade: Since this is a new query it |
1464 | * does not have an SPS, and will be available as soon as any |
1465 | * database, new or old, is booted with the new version of Derby, |
1466 | * (in <b>soft and hard</b> upgrade). |
1467 | * @param catalog limit the search to functions in this catalog |
1468 | * (not used) |
1469 | * @param schemaPattern limit the search to functions in schemas |
1470 | * matching this pattern |
1471 | * @param functionNamePattern limit the search to functions |
1472 | * matching this pattern |
1473 | * @return a ResultSet with metadata information |
1474 | * @throws SQLException if any of the underlying jdbc methods fail |
1475 | */ |
1476 | public ResultSet getFunctions(java.lang.String catalog, |
1477 | java.lang.String schemaPattern, |
1478 | java.lang.String functionNamePattern) |
1479 | throws SQLException |
1480 | { |
1481 | return doGetProcs(catalog, schemaPattern, |
1482 | functionNamePattern, "getFunctions"); |
1483 | } |
1484 | |
1485 | /** |
1486 | * Does the actual work for the getProcedures and getFunctions |
1487 | * metadata calls. See getProcedures() method above for parameter |
1488 | * descriptions. |
1489 | * @param queryName Name of the query to execute; is used |
1490 | * to determine whether the result set should conform to |
1491 | * JDBC or ODBC specifications. |
1492 | */ |
1493 | private ResultSet doGetProcs(String catalog, String schemaPattern, |
1494 | String procedureNamePattern, String queryName) |
1495 | throws SQLException { |
1496 | |
1497 | PreparedStatement s = getPreparedQuery(queryName); |
1498 | s.setString(1, swapNull(catalog)); |
1499 | s.setString(2, swapNull(schemaPattern)); |
1500 | s.setString(3, swapNull(procedureNamePattern)); |
1501 | return s.executeQuery(); |
1502 | } |
1503 | |
1504 | /** |
1505 | * Get a description of a catalog's stored procedure parameters |
1506 | * and result columns. |
1507 | * |
1508 | * <P>Only descriptions matching the schema, procedure and |
1509 | * parameter name criteria are returned. They are ordered by |
1510 | * PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value, |
1511 | * if any, is first. Next are the parameter descriptions in call |
1512 | * order. The column descriptions follow in column number order. |
1513 | * |
1514 | * <P>Each row in the ResultSet is a parameter description or |
1515 | * column description with the following fields: |
1516 | * <OL> |
1517 | * <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null) |
1518 | * <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null) |
1519 | * <LI><B>PROCEDURE_NAME</B> String => procedure name |
1520 | * <LI><B>COLUMN_NAME</B> String => column/parameter name |
1521 | * <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter: |
1522 | * <UL> |
1523 | * <LI> procedureColumnUnknown - nobody knows |
1524 | * <LI> procedureColumnIn - IN parameter |
1525 | * <LI> procedureColumnInOut - INOUT parameter |
1526 | * <LI> procedureColumnOut - OUT parameter |
1527 | * <LI> procedureColumnReturn - procedure return value |
1528 | * <LI> procedureColumnResult - result column in ResultSet |
1529 | * </UL> |
1530 | * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types |
1531 | * <LI><B>TYPE_NAME</B> String => SQL type name |
1532 | * <LI><B>PRECISION</B> int => precision |
1533 | * <LI><B>LENGTH</B> int => length in bytes of data |
1534 | * <LI><B>SCALE</B> short => scale |
1535 | * <LI><B>RADIX</B> short => radix |
1536 | * <LI><B>NULLABLE</B> short => can it contain NULL? |
1537 | * <UL> |
1538 | * <LI> procedureNoNulls - does not allow NULL values |
1539 | * <LI> procedureNullable - allows NULL values |
1540 | * <LI> procedureNullableUnknown - nullability unknown |
1541 | * </UL> |
1542 | * <LI><B>REMARKS</B> String => comment describing parameter/column |
1543 | * <LI><B>COLUMN_DEF</B> String |
1544 | * <LI><B>SQL_DATA_TYPE</B> int |
1545 | * <LI><B>SQL_DATETIME_SUB</B> int |
1546 | * <LI><B>CHAR_OCTET_LENGTH</B> int |
1547 | * <LI><B>ORDINAL_POSITION</B> int |
1548 | * <LI><B>IS_NULLABLE</B> String |
1549 | * <LI><B>SPECIFIC_NAME</B> String |
1550 | * </OL> |
1551 | * |
1552 | * <P><B>Note:</B> Some databases may not return the column |
1553 | * descriptions for a procedure. Additional columns beyond |
1554 | * SPECIFIC_NAME can be defined by the database. |
1555 | * |
1556 | * @param catalog a catalog name; "" retrieves those without a |
1557 | * catalog; null means drop catalog name from the selection criteria |
1558 | * @param schemaPattern a schema name pattern; "" retrieves those |
1559 | * without a schema |
1560 | * @param procedureNamePattern a procedure name pattern |
1561 | * @param columnNamePattern a column name pattern |
1562 | * @return ResultSet - each row is a stored procedure parameter or |
1563 | * column description |
1564 | * @see #getSearchStringEscape |
1565 | * @exception SQLException thrown on failure. |
1566 | */ |
1567 | public ResultSet getProcedureColumns(String catalog, |
1568 | String schemaPattern, |
1569 | String procedureNamePattern, |
1570 | String columnNamePattern) throws SQLException { |
1571 | |
1572 | // Using the new JDBC 4.0 version of the query here. The query |
1573 | // was given a new name to allow the old query to |
1574 | // be used by ODBCMetaDataGenerator. |
1575 | return doGetProcCols(catalog, schemaPattern, |
1576 | procedureNamePattern, columnNamePattern, |
1577 | "getProcedureColumns40"); |
1578 | } |
1579 | |
1580 | /** |
1581 | * Get a description of a catalog's stored procedure parameters |
1582 | * and result columns. Same as getProcedureColumns() above, |
1583 | * except that the result set will conform to ODBC specifications. |
1584 | */ |
1585 | public ResultSet getProcedureColumnsForODBC(String catalog, |
1586 | String schemaPattern, String procedureNamePattern, |
1587 | String columnNamePattern) throws SQLException { |
1588 | |
1589 | // For ODBC we still use the transformed version of the JDBC |
1590 | // 3.0 query, (may change in the future). |
1591 | return doGetProcCols(catalog, schemaPattern, |
1592 | procedureNamePattern, columnNamePattern, |
1593 | "odbc_getProcedureColumns"); |
1594 | } |
1595 | |
1596 | /** |
1597 | * Implements DatabaseMetaData.getFunctionParameters() for an embedded |
1598 | * database. Queries the database to get information about |
1599 | * function parameters. Executes the |
1600 | * 'getFunctionParameters' query from metadata.properties to obtain the |
1601 | * ResultSet.<p> Compatibility: This is a new method in |
1602 | * the API which is only available with with Derby versions > 10.1 and |
1603 | * JDK versions >= 1.6 <p>Upgrade: Since this is a new query it |
1604 | * does not have an SPS, and will be available as soon as any |
1605 | * database, new or old, is booted with the new version of Derby, |
1606 | * (in <b>soft and hard</b> upgrade). |
1607 | * @param catalog limit the search to functions in this catalog |
1608 | * (not used) |
1609 | * @param schemaPattern limit the search to functions in schemas |
1610 | * matching this pattern |
1611 | * @param functionNamePattern limit the search to functions |
1612 | * matching this pattern |
1613 | * @param parameterNamePattern limit the search parameters |
1614 | * matching this pattern |
1615 | * @return a ResultSet with metadata information |
1616 | * @throws SQLException if a database error occurs |
1617 | */ |
1618 | public ResultSet getFunctionParameters(String catalog, |
1619 | String schemaPattern, |
1620 | String functionNamePattern, |
1621 | String parameterNamePattern) |
1622 | throws SQLException { |
1623 | PreparedStatement s = getPreparedQuery("getFunctionParameters"); |
1624 | |
1625 | // Cannot use doGetProcCols() because our query requires |
1626 | // parameterNamePattern twice, because both LIKE and = is |
1627 | // required to select parameters with an empty parameter |
1628 | // name. That is, WHERE paramName LIKE ? will not match an |
1629 | // empty paramName, but WHERE paramName LIKE ? OR paramName = |
1630 | // ? will. |
1631 | s.setString(1, swapNull(schemaPattern)); |
1632 | s.setString(2, swapNull(functionNamePattern)); |
1633 | s.setString(3, swapNull(parameterNamePattern)); |
1634 | s.setString(4, swapNull(parameterNamePattern)); |
1635 | return s.executeQuery(); |
1636 | } |
1637 | |
1638 | /** |
1639 | * Does the actual work for the getProcedureColumns metadata |
1640 | * calls. See getProcedureColumns() method above for parameter |
1641 | * descriptions. |
1642 | * @param queryName Name of the query to execute; is used |
1643 | * to determine whether the result set should conform to |
1644 | * JDBC or ODBC specifications. |
1645 | */ |
1646 | private ResultSet doGetProcCols(String catalog, String schemaPattern, |
1647 | String procedureNamePattern, String columnNamePattern, |
1648 | String queryName) throws SQLException { |
1649 | |
1650 | PreparedStatement s = getPreparedQuery(queryName); |
1651 | // |
1652 | // catalog is not part of the query |
1653 | // |
1654 | s.setString(1, swapNull(schemaPattern)); |
1655 | s.setString(2, swapNull(procedureNamePattern)); |
1656 | s.setString(3, swapNull(columnNamePattern)); |
1657 | return s.executeQuery(); |
1658 | } |
1659 | |
1660 | /** |
1661 | * Get a description of tables available in a catalog. |
1662 | * |
1663 | * <P>Only table descriptions matching the catalog, schema, table |
1664 | * name and type criteria are returned. They are ordered by |
1665 | * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME. |
1666 | * |
1667 | * <P>Each table description has the following columns: |
1668 | * <OL> |
1669 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
1670 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
1671 | * <LI><B>TABLE_NAME</B> String => table name |
1672 | * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE", |
1673 | * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", |
1674 | * "LOCAL TEMPORARY", "ALIAS", "SYNONYM". |
1675 | * <LI><B>REMARKS</B> String => explanatory comment on the table |
1676 | * </OL> |
1677 | * |
1678 | * <P><B>Note:</B> Some databases may not return information for |
1679 | * all tables. |
1680 | * |
1681 | * @param catalog a catalog name; "" retrieves those without a |
1682 | * catalog; null means drop catalog name from the selection criteria |
1683 | * @param schemaPattern a schema name pattern; "" retrieves those |
1684 | * without a schema |
1685 | * @param tableNamePattern a table name pattern |
1686 | * @param types a list of table types to include; null returns all types |
1687 | * @return ResultSet - each row is a table description |
1688 | * @see #getSearchStringEscape |
1689 | * @exception SQLException thrown on failure. |
1690 | */ |
1691 | public ResultSet getTables(String catalog, String schemaPattern, |
1692 | String tableNamePattern, String types[]) throws SQLException { |
1693 | synchronized (getConnectionSynchronization()) { |
1694 | setupContextStack(); |
1695 | ResultSet rs = null; |
1696 | try { |
1697 | |
1698 | String queryText = |
1699 | getQueryDescriptions(false).getProperty("getTables"); |
1700 | |
1701 | /* |
1702 | * The query text is assumed to end with a "where" clause, so |
1703 | * that we can safely append |
1704 | * "and table_Type in ('xxx','yyy','zzz', ...)" and |
1705 | * have it become part of the where clause. |
1706 | * |
1707 | * Let's assume for now that the table type first char corresponds |
1708 | * to JBMS table type identifiers. |
1709 | */ |
1710 | StringBuffer whereClauseTail = new StringBuffer(queryText); |
1711 | |
1712 | if (types != null && types.length >= 1) { |
1713 | whereClauseTail.append(" AND TABLETYPE IN ('"); |
1714 | whereClauseTail.append(types[0].substring(0, 1)); |
1715 | |
1716 | for (int i=1; i<types.length; i++) { |
1717 | whereClauseTail.append("','"); |
1718 | whereClauseTail.append(types[i].substring(0, 1)); |
1719 | } |
1720 | whereClauseTail.append("')"); |
1721 | } |
1722 | // Add the order by clause after the 'in' list. |
1723 | whereClauseTail.append( |
1724 | " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME"); |
1725 | |
1726 | PreparedStatement s = |
1727 | getEmbedConnection().prepareMetaDataStatement(whereClauseTail.toString()); |
1728 | |
1729 | s.setString(1, swapNull(catalog)); |
1730 | s.setString(2, swapNull(schemaPattern)); |
1731 | s.setString(3, swapNull(tableNamePattern)); |
1732 | |
1733 | rs = s.executeQuery(); |
1734 | } catch (Throwable t) { |
1735 | throw handleException(t); |
1736 | } finally { |
1737 | restoreContextStack(); |
1738 | } |
1739 | |
1740 | return rs; |
1741 | } |
1742 | } |
1743 | |
1744 | /** |
1745 | * Get the schema names available in this database. The results |
1746 | * are ordered by schema name. |
1747 | * |
1748 | * <P>The schema columns are: |
1749 | * <OL> |
1750 | * <li><strong>TABLE_SCHEM</strong> String => schema name</li> |
1751 | * <li><strong>TABLE_CATALOG</strong> String => catalog name |
1752 | * (may be <code>null</code>)</li> |
1753 | * </OL> |
1754 | * |
1755 | * @return ResultSet - each row is a schema description |
1756 | * @exception SQLException thrown on failure. |
1757 | */ |
1758 | public ResultSet getSchemas() throws SQLException { |
1759 | return getSchemas(null, null); |
1760 | } |
1761 | |
1762 | /** |
1763 | * Get the catalog names available in this database. The results |
1764 | * are ordered by catalog name. |
1765 | * |
1766 | * <P>The catalog column is: |
1767 | * <OL> |
1768 | * <LI><B>TABLE_CAT</B> String => catalog name |
1769 | * </OL> |
1770 | * |
1771 | * @return ResultSet - each row has a single String column that is a |
1772 | * catalog name |
1773 | * @exception SQLException thrown on failure. |
1774 | */ |
1775 | public ResultSet getCatalogs() throws SQLException { |
1776 | return getSimpleQuery("getCatalogs"); |
1777 | } |
1778 | |
1779 | /** |
1780 | * Get the table types available in this database. The results |
1781 | * are ordered by table type. |
1782 | * |
1783 | * <P>The table type is: |
1784 | * <OL> |
1785 | * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE", |
1786 | * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", |
1787 | * "LOCAL TEMPORARY", "ALIAS", "SYNONYM". |
1788 | * </OL> |
1789 | * |
1790 | * @return ResultSet - each row has a single String column that is a |
1791 | * table type |
1792 | * @exception SQLException thrown on failure. |
1793 | */ |
1794 | public ResultSet getTableTypes() throws SQLException { |
1795 | return getSimpleQuery("getTableTypes"); |
1796 | } |
1797 | |
1798 | /** |
1799 | * Get a description of table columns available in a catalog. |
1800 | * |
1801 | * <P>Only column descriptions matching the catalog, schema, table |
1802 | * and column name criteria are returned. They are ordered by |
1803 | * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION. |
1804 | * |
1805 | * <P>Each column description has the following columns: |
1806 | * <OL> |
1807 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
1808 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
1809 | * <LI><B>TABLE_NAME</B> String => table name |
1810 | * <LI><B>COLUMN_NAME</B> String => column name |
1811 | * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types |
1812 | * <LI><B>TYPE_NAME</B> String => Data source dependent type name |
1813 | * <LI><B>COLUMN_SIZE</B> int => column size. For char or date |
1814 | * types this is the maximum number of characters, for numeric or |
1815 | * decimal types this is precision. |
1816 | * <LI><B>BUFFER_LENGTH</B> is not used. |
1817 | * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits |
1818 | * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) |
1819 | * <LI><B>NULLABLE</B> int => is NULL allowed? |
1820 | * <UL> |
1821 | * <LI> columnNoNulls - might not allow NULL values |
1822 | * <LI> columnNullable - definitely allows NULL values |
1823 | * <LI> columnNullableUnknown - nullability unknown |
1824 | * </UL> |
1825 | * <LI><B>REMARKS</B> String => comment describing column (may be null) |
1826 | * <LI><B>COLUMN_DEF</B> String => default value (may be null) |
1827 | * <LI><B>SQL_DATA_TYPE</B> int => unused |
1828 | * <LI><B>SQL_DATETIME_SUB</B> int => unused |
1829 | * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the |
1830 | * maximum number of bytes in the column |
1831 | * <LI><B>ORDINAL_POSITION</B> int => index of column in table |
1832 | * (starting at 1) |
1833 | * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely |
1834 | * does not allow NULL values; "YES" means the column might |
1835 | * allow NULL values. An empty string means nobody knows. |
1836 | * </OL> |
1837 | * |
1838 | * @param catalog a catalog name; "" retrieves those without a |
1839 | * catalog; null means drop catalog name from the selection criteria |
1840 | * @param schemaPattern a schema name pattern; "" retrieves those |
1841 | * without a schema |
1842 | * @param tableNamePattern a table name pattern |
1843 | * @param columnNamePattern a column name pattern |
1844 | * @return ResultSet - each row is a column description |
1845 | * @see #getSearchStringEscape |
1846 | * @exception SQLException thrown on failure. |
1847 | */ |
1848 | public ResultSet getColumns(String catalog, String schemaPattern, |
1849 | String tableNamePattern, String columnNamePattern) |
1850 | throws SQLException { |
1851 | |
1852 | return doGetCols(catalog, schemaPattern, tableNamePattern, |
1853 | columnNamePattern, "getColumns"); |
1854 | } |
1855 | |
1856 | /** |
1857 | * Get a description of table columns available in a catalog. |
1858 | * Same as getColumns() above, except that the result set |
1859 | * will conform to ODBC specifications. |
1860 | */ |
1861 | public ResultSet getColumnsForODBC(String catalog, String schemaPattern, |
1862 | String tableNamePattern, String columnNamePattern) |
1863 | throws SQLException { |
1864 | |
1865 | return doGetCols(catalog, schemaPattern, tableNamePattern, |
1866 | columnNamePattern, "odbc_getColumns"); |
1867 | } |
1868 | |
1869 | /** |
1870 | * Does the actual work for the getColumns metadata calls. |
1871 | * See getColumns() method above for parameter descriptions. |
1872 | * @param queryName Name of the query to execute; is used |
1873 | * to determine whether the result set should conform to |
1874 | * JDBC or ODBC specifications. |
1875 | */ |
1876 | private ResultSet doGetCols(String catalog, String schemaPattern, |
1877 | String tableNamePattern, String columnNamePattern, |
1878 | String queryName) throws SQLException { |
1879 | |
1880 | PreparedStatement s = getPreparedQuery(queryName); |
1881 | s.setString(1, swapNull(catalog)); |
1882 | s.setString(2, swapNull(schemaPattern)); |
1883 | s.setString(3, swapNull(tableNamePattern)); |
1884 | s.setString(4, swapNull(columnNamePattern)); |
1885 | return s.executeQuery(); |
1886 | } |
1887 | |
1888 | /** |
1889 | * Get a description of the access rights for a table's columns. |
1890 | * |
1891 | * <P>Only privileges matching the column name criteria are |
1892 | * returned. They are ordered by COLUMN_NAME and PRIVILEGE. |
1893 | * |
1894 | * <P>Each privilige description has the following columns: |
1895 | * <OL> |
1896 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
1897 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
1898 | * <LI><B>TABLE_NAME</B> String => table name |
1899 | * <LI><B>COLUMN_NAME</B> String => column name |
1900 | * <LI><B>GRANTOR</B> => grantor of access (may be null) |
1901 | * <LI><B>GRANTEE</B> String => grantee of access |
1902 | * <LI><B>PRIVILEGE</B> String => name of access (SELECT, |
1903 | * INSERT, UPDATE, REFRENCES, ...) |
1904 | * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted |
1905 | * to grant to others; "NO" if not; null if unknown |
1906 | * </OL> |
1907 | * |
1908 | * @param catalog a catalog name; "" retrieves those without a |
1909 | * catalog; null means drop catalog name from the selection criteria |
1910 | * @param schema a schema name; "" retrieves those without a schema |
1911 | * @param table a table name |
1912 | * @param columnNamePattern a column name pattern |
1913 | * @return ResultSet - each row is a column privilege description |
1914 | * @see #getSearchStringEscape |
1915 | * @exception SQLException thrown on failure. |
1916 | */ |
1917 | public ResultSet getColumnPrivileges(String catalog, String schema, |
1918 | String table, String columnNamePattern) throws SQLException { |
1919 | PreparedStatement s = getPreparedQuery("getColumnPrivileges"); |
1920 | s.setString(1, swapNull(catalog)); |
1921 | s.setString(2, swapNull(schema)); |
1922 | s.setString(3, swapNull(table)); |
1923 | s.setString(4, swapNull(columnNamePattern)); |
1924 | return s.executeQuery(); |
1925 | } |
1926 | |
1927 | /** |
1928 | * Get a description of the access rights for each table available |
1929 | * in a catalog. Note that a table privilege applies to one or |
1930 | * more columns in the table. It would be wrong to assume that |
1931 | * this priviledge applies to all columns (this may be true for |
1932 | * some systems but is not true for all.) |
1933 | * |
1934 | * <P>Only privileges matching the schema and table name |
1935 | * criteria are returned. They are ordered by TABLE_SCHEM, |
1936 | * TABLE_NAME, and PRIVILEGE. |
1937 | * |
1938 | * <P>Each privilige description has the following columns: |
1939 | * <OL> |
1940 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
1941 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
1942 | * <LI><B>TABLE_NAME</B> String => table name |
1943 | * <LI><B>GRANTOR</B> => grantor of access (may be null) |
1944 | * <LI><B>GRANTEE</B> String => grantee of access |
1945 | * <LI><B>PRIVILEGE</B> String => name of access (SELECT, |
1946 | * INSERT, UPDATE, REFRENCES, ...) |
1947 | * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted |
1948 | * to grant to others; "NO" if not; null if unknown |
1949 | * </OL> |
1950 | * |
1951 | * @param catalog a catalog name; "" retrieves those without a |
1952 | * catalog; null means drop catalog name from the selection criteria |
1953 | * @param schemaPattern a schema name pattern; "" retrieves those |
1954 | * without a schema |
1955 | * @param tableNamePattern a table name pattern |
1956 | * @return ResultSet - each row is a table privilege description |
1957 | * @see #getSearchStringEscape |
1958 | * @exception SQLException thrown on failure. |
1959 | */ |
1960 | public ResultSet getTablePrivileges(String catalog, String schemaPattern, |
1961 | String tableNamePattern) throws SQLException { |
1962 | PreparedStatement s = getPreparedQuery("getTablePrivileges"); |
1963 | s.setString(1, swapNull(catalog)); |
1964 | s.setString(2, swapNull(schemaPattern)); |
1965 | s.setString(3, swapNull(tableNamePattern)); |
1966 | return s.executeQuery(); |
1967 | } |
1968 | |
1969 | /** |
1970 | * Get a description of a table's optimal set of columns that |
1971 | * uniquely identifies a row. They are ordered by SCOPE. |
1972 | * |
1973 | * <P>Each column description has the following columns: |
1974 | * <OL> |
1975 | * <LI><B>SCOPE</B> short => actual scope of result |
1976 | * <UL> |
1977 | * <LI> bestRowTemporary - very temporary, while using row |
1978 | * <LI> bestRowTransaction - valid for remainder of current transaction |
1979 | * <LI> bestRowSession - valid for remainder of current session |
1980 | * </UL> |
1981 | * <LI><B>COLUMN_NAME</B> String => column name |
1982 | * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types |
1983 | * <LI><B>TYPE_NAME</B> String => Data source dependent type name |
1984 | * <LI><B>COLUMN_SIZE</B> int => precision |
1985 | * <LI><B>BUFFER_LENGTH</B> int => not used |
1986 | * <LI><B>DECIMAL_DIGITS</B> short => scale |
1987 | * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column |
1988 | * like an Oracle ROWID |
1989 | * <UL> |
1990 | * <LI> bestRowUnknown - may or may not be pseudo column |
1991 | * <LI> bestRowNotPseudo - is NOT a pseudo column |
1992 | * <LI> bestRowPseudo - is a pseudo column |
1993 | * </UL> |
1994 | * </OL> |
1995 | * |
1996 | * @param catalogPattern a catalog name; "" retrieves those without a |
1997 | * catalog; null means drop catalog name from the selection criteria |
1998 | * @param schemaPattern a schema name; "" retrieves those without a schema |
1999 | * @param tablePattern a table name |
2000 | * @param scope the scope of interest; use same values as SCOPE |
2001 | * @param nullable include columns that are nullable? |
2002 | * @return ResultSet - each row is a column description |
2003 | * @exception SQLException thrown on failure. |
2004 | */ |
2005 | public ResultSet getBestRowIdentifier |
2006 | ( |
2007 | String catalogPattern, |
2008 | String schemaPattern, |
2009 | String tablePattern, |
2010 | int scope, |
2011 | boolean nullable |
2012 | ) throws SQLException |
2013 | { |
2014 | return doGetBestRowId(catalogPattern, schemaPattern, tablePattern, |
2015 | scope, nullable, ""); |
2016 | } |
2017 | |
2018 | /** |
2019 | * Get a description of a table's optimal set of columns that |
2020 | * uniquely identifies a row. They are ordered by SCOPE. |
2021 | * Same as getBestRowIdentifier() above, except that the result |
2022 | * set will conform to ODBC specifications. |
2023 | */ |
2024 | public ResultSet getBestRowIdentifierForODBC(String catalogPattern, |
2025 | String schemaPattern, String tablePattern, int scope, |
2026 | boolean nullable) throws SQLException { |
2027 | |
2028 | return doGetBestRowId(catalogPattern, schemaPattern, tablePattern, |
2029 | scope, nullable, "odbc_"); |
2030 | } |
2031 | |
2032 | /** |
2033 | * Does the actual work for the getBestRowIdentifier metadata |
2034 | * calls. See getBestRowIdentifier() method above for parameter |
2035 | * descriptions. |
2036 | * @param queryPrefix Prefix to be appended to the names of |
2037 | * the queries used in this method. This is used |
2038 | * to determine whether the result set should conform to |
2039 | * JDBC or ODBC specifications. |
2040 | */ |
2041 | private ResultSet doGetBestRowId(String catalogPattern, |
2042 | String schemaPattern, String tablePattern, int scope, |
2043 | boolean nullable, String queryPrefix) throws SQLException { |
2044 | |
2045 | int nullableInIntForm = 0; |
2046 | if (nullable) |
2047 | nullableInIntForm = 1; |
2048 | |
2049 | if (catalogPattern == null) |
2050 | { |
2051 | catalogPattern = "%"; |
2052 | } |
2053 | if (schemaPattern == null) |
2054 | { |
2055 | schemaPattern = "%"; |
2056 | } |
2057 | if (tablePattern == null) |
2058 | { |
2059 | tablePattern = "%"; |
2060 | } |
2061 | |
2062 | PreparedStatement ps; |
2063 | boolean done; |
2064 | |
2065 | // scope value is bad, return an empty result |
2066 | if (scope < 0 || scope > 2) { |
2067 | ps = getPreparedQuery("getBestRowIdentifierEmpty"); |
2068 | return ps.executeQuery(); |
2069 | } |
2070 | |
2071 | // see if there is a primary key, use it. |
2072 | ps = getPreparedQuery("getBestRowIdentifierPrimaryKey"); |
2073 | ps.setString(1,catalogPattern); |
2074 | ps.setString(2,schemaPattern); |
2075 | ps.setString(3,tablePattern); |
2076 | |
2077 | ResultSet rs = ps.executeQuery(); |
2078 | done = rs.next(); |
2079 | String constraintId = ""; |
2080 | if (done) { |
2081 | constraintId = rs.getString(1); |
2082 | } |
2083 | |
2084 | rs.close(); |
2085 | ps.close(); |
2086 | |
2087 | if (done) |
2088 | { |
2089 | // this one's it, do the real thing and return it. |
2090 | // we don't need to check catalog, schema, table name |
2091 | // or scope again. |
2092 | ps = getPreparedQuery(queryPrefix + "getBestRowIdentifierPrimaryKeyColumns"); |
2093 | ps.setString(1,constraintId); |
2094 | ps.setString(2,constraintId); |
2095 | // note, primary key columns aren't nullable, |
2096 | // so we skip the nullOk parameter. |
2097 | return ps.executeQuery(); |
2098 | } |
2099 | |
2100 | // get the unique constraint with the fewest columns. |
2101 | ps = getPreparedQuery("getBestRowIdentifierUniqueConstraint"); |
2102 | ps.setString(1,catalogPattern); |
2103 | ps.setString(2,schemaPattern); |
2104 | ps.setString(3,tablePattern); |
2105 | |
2106 | rs = ps.executeQuery(); |
2107 | done = rs.next(); |
2108 | if (done) { |
2109 | constraintId = rs.getString(1); |
2110 | } |
2111 | // REMIND: we need to actually check for null columns |
2112 | // and toss out constraints with null columns if they aren't |
2113 | // desired... recode this as a WHILE returning at the |
2114 | // first match or falling off the end. |
2115 | |
2116 | rs.close(); |
2117 | ps.close(); |
2118 | if (done) |
2119 | { |
2120 | // this one's it, do the real thing and return it. |
2121 | ps = getPreparedQuery(queryPrefix + "getBestRowIdentifierUniqueKeyColumns"); |
2122 | ps.setString(1,constraintId); |
2123 | ps.setString(2,constraintId); |
2124 | ps.setInt(3,nullableInIntForm); |
2125 | return ps.executeQuery(); |
2126 | } |
2127 | |
2128 | |
2129 | // second-to last try -- unique index with minimal # columns |
2130 | // (only non null columns if so required) |
2131 | ps = getPreparedQuery("getBestRowIdentifierUniqueIndex"); |
2132 | ps.setString(1,catalogPattern); |
2133 | ps.setString(2,schemaPattern); |
2134 | ps.setString(3,tablePattern); |
2135 | |
2136 | rs = ps.executeQuery(); |
2137 | done = rs.next(); |
2138 | long indexNum = 0; |
2139 | if (done) { |
2140 | indexNum = rs.getLong(1); |
2141 | } |
2142 | // REMIND: we need to actually check for null columns |
2143 | // and toss out constraints with null columns if they aren't |
2144 | // desired... recode this as a WHILE returning at the |
2145 | // first match or falling off the end. |
2146 | |
2147 | rs.close(); |
2148 | ps.close(); |
2149 | if (done) { |
2150 | // this one's it, do the real thing and return it. |
2151 | ps = getPreparedQuery(queryPrefix + "getBestRowIdentifierUniqueIndexColumns"); |
2152 | ps.setLong(1,indexNum); |
2153 | ps.setInt(2,nullableInIntForm); |
2154 | return ps.executeQuery(); |
2155 | } |
2156 | |
2157 | // last try -- just return all columns of the table |
2158 | // the not null ones if that restriction is upon us. |
2159 | ps = getPreparedQuery(queryPrefix + "getBestRowIdentifierAllColumns"); |
2160 | ps.setString(1,catalogPattern); |
2161 | ps.setString(2,schemaPattern); |
2162 | ps.setString(3,tablePattern); |
2163 | ps.setInt(4,scope); |
2164 | ps.setInt(5,nullableInIntForm); |
2165 | return ps.executeQuery(); |
2166 | } |
2167 | |
2168 | /** |
2169 | * Get a description of a table's columns that are automatically |
2170 | * updated when any value in a row is updated. They are |
2171 | * unordered. |
2172 | * |
2173 | * <P>Each column description has the following columns: |
2174 | * <OL> |
2175 | * <LI><B>SCOPE</B> short => is not used |
2176 | * <LI><B>COLUMN_NAME</B> String => column name |
2177 | * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types |
2178 | * <LI><B>TYPE_NAME</B> String => Data source dependent type name |
2179 | * <LI><B>COLUMN_SIZE</B> int => precision |
2180 | * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes |
2181 | * <LI><B>DECIMAL_DIGITS</B> short => scale |
2182 | * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column |
2183 | * like an Oracle ROWID |
2184 | * <UL> |
2185 | * <LI> versionColumnUnknown - may or may not be pseudo column |
2186 | * <LI> versionColumnNotPseudo - is NOT a pseudo column |
2187 | * <LI> versionColumnPseudo - is a pseudo column |
2188 | * </UL> |
2189 | * </OL> |
2190 | * |
2191 | * @param catalog a catalog name; "" retrieves those without a |
2192 | * catalog; null means drop catalog name from the selection criteria |
2193 | * @param schema a schema name; "" retrieves those without a schema |
2194 | * @param table a table name |
2195 | * @return ResultSet - each row is a column description |
2196 | * @exception SQLException thrown on failure. |
2197 | */ |
2198 | public ResultSet getVersionColumns(String catalog, String schema, |
2199 | String table) throws SQLException { |
2200 | return doGetVersionCols(catalog, schema, table, "getVersionColumns"); |
2201 | } |
2202 | |
2203 | /** |
2204 | * Get a description of a table's columns that are automatically |
2205 | * updated when any value in a row is updated. They are |
2206 | * unordered. Same as getVersionColumns() above, except that |
2207 | * the result set will conform to ODBC specifications. |
2208 | */ |
2209 | public ResultSet getVersionColumnsForODBC(String catalog, String schema, |
2210 | String table) throws SQLException { |
2211 | return doGetVersionCols(catalog, schema, table, "odbc_getVersionColumns"); |
2212 | } |
2213 | |
2214 | /** |
2215 | * Does the actual work for the getVersionColumns metadata |
2216 | * calls. See getVersionColumns() method above for parameter |
2217 | * descriptions. |
2218 | * @param queryName Name of the query to execute; is used |
2219 | * to determine whether the result set should conform to |
2220 | * JDBC or ODBC specifications. |
2221 | */ |
2222 | private ResultSet doGetVersionCols(String catalog, String schema, |
2223 | String table, String queryName) throws SQLException { |
2224 | |
2225 | PreparedStatement s = getPreparedQuery(queryName); |
2226 | s.setString(1, swapNull(catalog)); |
2227 | s.setString(2, swapNull(schema)); |
2228 | s.setString(3, swapNull(table)); |
2229 | return s.executeQuery(); |
2230 | } |
2231 | |
2232 | /** |
2233 | * check if the dictionary is at the same version as the engine. If not, |
2234 | * then that means stored versions of the JDBC database metadata queries |
2235 | * may not be compatible with this version of the software. |
2236 | * This can happen if we are in soft upgrade mode. Since in soft upgrade |
2237 | * mode, we can't change these stored metadata queries in a backward |
2238 | * incompatible way, engine needs to read the metadata sql from |
2239 | * metadata.properties or metadata_net.properties file rather than |
2240 | * rely on system tables. |
2241 | * |
2242 | * @return true if we are not in soft upgrade mode |
2243 | * @throws SQLException |
2244 | */ |
2245 | private boolean notInSoftUpgradeMode() |
2246 | throws SQLException { |
2247 | if ( getEmbedConnection().isClosed()) |
2248 | throw Util.noCurrentConnection(); |
2249 | |
2250 | boolean notInSoftUpgradeMode; |
2251 | try { |
2252 | notInSoftUpgradeMode = |
2253 | getLanguageConnectionContext().getDataDictionary().checkVersion( |
2254 | DataDictionary.DD_VERSION_CURRENT,null); |
2255 | } catch (Throwable t) { |
2256 | throw handleException(t); |
2257 | } |
2258 | return notInSoftUpgradeMode; |
2259 | } |
2260 | |
2261 | |
2262 | /** |
2263 | * Get a description of a table's primary key columns. They |
2264 | * are ordered by COLUMN_NAME. |
2265 | * |
2266 | * <P>Each primary key column description has the following columns: |
2267 | * <OL> |
2268 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
2269 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
2270 | * <LI><B>TABLE_NAME</B> String => table name |
2271 | * <LI><B>COLUMN_NAME</B> String => column name |
2272 | * <LI><B>KEY_SEQ</B> short => sequence number within primary key |
2273 | * <LI><B>PK_NAME</B> String => primary key name (may be null) |
2274 | * </OL> |
2275 | * |
2276 | * @param catalog a catalog name; "" retrieves those without a |
2277 | * catalog; null means drop catalog name from the selection criteria |
2278 | * @param schema a schema name pattern; "" retrieves those |
2279 | * without a schema |
2280 | * @param table a table name |
2281 | * @return ResultSet - each row is a primary key column description |
2282 | * @exception SQLException thrown on failure. |
2283 | */ |
2284 | public ResultSet getPrimaryKeys(String catalog, String schema, |
2285 | String table) throws SQLException { |
2286 | return doGetPrimaryKeys(catalog, schema, table, "getPrimaryKeys"); |
2287 | } |
2288 | |
2289 | /** |
2290 | * Get a description of a table's primary key columns. They |
2291 | * are ordered by COLUMN_NAME. Same as getPrimaryKeys above, |
2292 | * except that the result set will conform to ODBC specifications. |
2293 | */ |
2294 | public ResultSet getPrimaryKeysForODBC(String catalog, String schema, |
2295 | String table) throws SQLException { |
2296 | return doGetPrimaryKeys(catalog, schema, table, "odbc_getPrimaryKeys"); |
2297 | } |
2298 | |
2299 | /** |
2300 | * Does the actual work for the getPrimaryKeys metadata |
2301 | * calls. See getPrimaryKeys() method above for parameter |
2302 | * descriptions. |
2303 | * @param queryName Name of the query to execute; is used |
2304 | * to determine whether the result set should conform to |
2305 | * JDBC or ODBC specifications. |
2306 | */ |
2307 | private ResultSet doGetPrimaryKeys(String catalog, String schema, |
2308 | String table, String queryName) throws SQLException { |
2309 | |
2310 | PreparedStatement s = getPreparedQuery(queryName); |
2311 | s.setString(1, swapNull(catalog)); |
2312 | s.setString(2, swapNull(schema)); |
2313 | s.setString(3, swapNull(table)); |
2314 | return s.executeQuery(); |
2315 | } |
2316 | |
2317 | /** |
2318 | * Get a description of the primary key columns that are |
2319 | * referenced by a table's foreign key columns (the primary keys |
2320 | * imported by a table). They are ordered by PKTABLE_CAT, |
2321 | * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ. |
2322 | * |
2323 | * <P>Each primary key column description has the following columns: |
2324 | * <OL> |
2325 | * <LI><B>PKTABLE_CAT</B> String => primary key table catalog |
2326 | * being imported (may be null) |
2327 | * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema |
2328 | * being imported (may be null) |
2329 | * <LI><B>PKTABLE_NAME</B> String => primary key table name |
2330 | * being imported |
2331 | * <LI><B>PKCOLUMN_NAME</B> String => primary key column name |
2332 | * being imported |
2333 | * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) |
2334 | * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) |
2335 | * <LI><B>FKTABLE_NAME</B> String => foreign key table name |
2336 | * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name |
2337 | * <LI><B>KEY_SEQ</B> short => sequence number within foreign key |
2338 | * <LI><B>UPDATE_RULE</B> short => What happens to |
2339 | * foreign key when primary is updated: |
2340 | * <UL> |
2341 | * <LI> importedNoAction - do not allow update of primary |
2342 | * key if it has been imported |
2343 | * <LI> importedKeyCascade - change imported key to agree |
2344 | * with primary key update |
2345 | * <LI> importedKeySetNull - change imported key to NULL if |
2346 | * its primary key has been updated |
2347 | * <LI> importedKeySetDefault - change imported key to default values |
2348 | * if its primary key has been updated |
2349 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2350 | * (for ODBC 2.x compatibility) |
2351 | * </UL> |
2352 | * <LI><B>DELETE_RULE</B> short => What happens to |
2353 | * the foreign key when primary is deleted. |
2354 | * <UL> |
2355 | * <LI> importedKeyNoAction - do not allow delete of primary |
2356 | * key if it has been imported |
2357 | * <LI> importedKeyCascade - delete rows that import a deleted key |
2358 | * <LI> importedKeySetNull - change imported key to NULL if |
2359 | * its primary key has been deleted |
2360 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2361 | * (for ODBC 2.x compatibility) |
2362 | * <LI> importedKeySetDefault - change imported key to default if |
2363 | * its primary key has been deleted |
2364 | * </UL> |
2365 | * <LI><B>FK_NAME</B> String => foreign key name (may be null) |
2366 | * <LI><B>PK_NAME</B> String => primary key name (may be null) |
2367 | * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key |
2368 | * constraints be deferred until commit |
2369 | * <UL> |
2370 | * <LI> importedKeyInitiallyDeferred - see SQL92 for definition |
2371 | * <LI> importedKeyInitiallyImmediate - see SQL92 for definition |
2372 | * <LI> importedKeyNotDeferrable - see SQL92 for definition |
2373 | * </UL> |
2374 | * </OL> |
2375 | * |
2376 | * @param catalog a catalog name; "" retrieves those without a |
2377 | * catalog; null means drop catalog name from the selection criteria |
2378 | * @param schema a schema name pattern; "" retrieves those |
2379 | * without a schema |
2380 | * @param table a table name |
2381 | * @return ResultSet - each row is a primary key column description |
2382 | * @see #getExportedKeys |
2383 | * @exception SQLException thrown on failure. |
2384 | */ |
2385 | public ResultSet getImportedKeys(String catalog, String schema, |
2386 | String table) throws SQLException { |
2387 | PreparedStatement s = getPreparedQuery("getImportedKeys"); |
2388 | s.setString(1, swapNull(catalog)); |
2389 | s.setString(2, swapNull(schema)); |
2390 | s.setString(3, swapNull(table)); |
2391 | return s.executeQuery(); |
2392 | } |
2393 | |
2394 | |
2395 | /** |
2396 | * Get a description of the foreign key columns that reference a |
2397 | * table's primary key columns (the foreign keys exported by a |
2398 | * table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM, |
2399 | * FKTABLE_NAME, and KEY_SEQ. |
2400 | * |
2401 | * <P>Each foreign key column description has the following columns: |
2402 | * <OL> |
2403 | * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) |
2404 | * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) |
2405 | * <LI><B>PKTABLE_NAME</B> String => primary key table name |
2406 | * <LI><B>PKCOLUMN_NAME</B> String => primary key column name |
2407 | * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) |
2408 | * being exported (may be null) |
2409 | * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) |
2410 | * being exported (may be null) |
2411 | * <LI><B>FKTABLE_NAME</B> String => foreign key table name |
2412 | * being exported |
2413 | * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name |
2414 | * being exported |
2415 | * <LI><B>KEY_SEQ</B> short => sequence number within foreign key |
2416 | * <LI><B>UPDATE_RULE</B> short => What happens to |
2417 | * foreign key when primary is updated: |
2418 | * <UL> |
2419 | * <LI> importedNoAction - do not allow update of primary |
2420 | * key if it has been imported |
2421 | * <LI> importedKeyCascade - change imported key to agree |
2422 | * with primary key update |
2423 | * <LI> importedKeySetNull - change imported key to NULL if |
2424 | * its primary key has been updated |
2425 | * <LI> importedKeySetDefault - change imported key to default values |
2426 | * if its primary key has been updated |
2427 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2428 | * (for ODBC 2.x compatibility) |
2429 | * </UL> |
2430 | * <LI><B>DELETE_RULE</B> short => What happens to |
2431 | * the foreign key when primary is deleted. |
2432 | * <UL> |
2433 | * <LI> importedKeyNoAction - do not allow delete of primary |
2434 | * key if it has been imported |
2435 | * <LI> importedKeyCascade - delete rows that import a deleted key |
2436 | * <LI> importedKeySetNull - change imported key to NULL if |
2437 | * its primary key has been deleted |
2438 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2439 | * (for ODBC 2.x compatibility) |
2440 | * <LI> importedKeySetDefault - change imported key to default if |
2441 | * its primary key has been deleted |
2442 | * </UL> |
2443 | * <LI><B>FK_NAME</B> String => foreign key name (may be null) |
2444 | * <LI><B>PK_NAME</B> String => primary key name (may be null) |
2445 | * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key |
2446 | * constraints be deferred until commit |
2447 | * <UL> |
2448 | * <LI> importedKeyInitiallyDeferred - see SQL92 for definition |
2449 | * <LI> importedKeyInitiallyImmediate - see SQL92 for definition |
2450 | * <LI> importedKeyNotDeferrable - see SQL92 for definition |
2451 | * </UL> |
2452 | * </OL> |
2453 | * |
2454 | * @param catalog a catalog name; "" retrieves those without a |
2455 | * catalog; null means drop catalog name from the selection criteria |
2456 | * @param schema a schema name pattern; "" retrieves those |
2457 | * without a schema |
2458 | * @param table a table name |
2459 | * @return ResultSet - each row is a foreign key column description |
2460 | * @see #getImportedKeys |
2461 | * @exception SQLException thrown on failure. |
2462 | */ |
2463 | public ResultSet getExportedKeys(String catalog, String schema, |
2464 | String table) throws SQLException { |
2465 | PreparedStatement s = getPreparedQuery("getCrossReference"); |
2466 | s.setString(1, swapNull(catalog)); |
2467 | s.setString(2, swapNull(schema)); |
2468 | s.setString(3, swapNull(table)); |
2469 | s.setString(4, swapNull(null)); |
2470 | s.setString(5, swapNull(null)); |
2471 | s.setString(6, swapNull(null)); |
2472 | return s.executeQuery(); |
2473 | } |
2474 | |
2475 | /** |
2476 | * Get a description of the foreign key columns in the foreign key |
2477 | * table that reference the primary key columns of the primary key |
2478 | * table (describe how one table imports another's key.) This |
2479 | * should normally return a single foreign key/primary key pair |
2480 | * (most tables only import a foreign key from a table once.) They |
2481 | * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and |
2482 | * KEY_SEQ. |
2483 | * |
2484 | * <P>Each foreign key column description has the following columns: |
2485 | * <OL> |
2486 | * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null) |
2487 | * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null) |
2488 | * <LI><B>PKTABLE_NAME</B> String => primary key table name |
2489 | * <LI><B>PKCOLUMN_NAME</B> String => primary key column name |
2490 | * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null) |
2491 | * being exported (may be null) |
2492 | * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null) |
2493 | * being exported (may be null) |
2494 | * <LI><B>FKTABLE_NAME</B> String => foreign key table name |
2495 | * being exported |
2496 | * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name |
2497 | * being exported |
2498 | * <LI><B>KEY_SEQ</B> short => sequence number within foreign key |
2499 | * <LI><B>UPDATE_RULE</B> short => What happens to |
2500 | * foreign key when primary is updated: |
2501 | * <UL> |
2502 | * <LI> importedNoAction - do not allow update of primary |
2503 | * key if it has been imported |
2504 | * <LI> importedKeyCascade - change imported key to agree |
2505 | * with primary key update |
2506 | * <LI> importedKeySetNull - change imported key to NULL if |
2507 | * its primary key has been updated |
2508 | * <LI> importedKeySetDefault - change imported key to default values |
2509 | * if its primary key has been updated |
2510 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2511 | * (for ODBC 2.x compatibility) |
2512 | * </UL> |
2513 | * <LI><B>DELETE_RULE</B> short => What happens to |
2514 | * the foreign key when primary is deleted. |
2515 | * <UL> |
2516 | * <LI> importedKeyNoAction - do not allow delete of primary |
2517 | * key if it has been imported |
2518 | * <LI> importedKeyCascade - delete rows that import a deleted key |
2519 | * <LI> importedKeySetNull - change imported key to NULL if |
2520 | * its primary key has been deleted |
2521 | * <LI> importedKeyRestrict - same as importedKeyNoAction |
2522 | * (for ODBC 2.x compatibility) |
2523 | * <LI> importedKeySetDefault - change imported key to default if |
2524 | * its primary key has been deleted |
2525 | * </UL> |
2526 | * <LI><B>FK_NAME</B> String => foreign key name (may be null) |
2527 | * <LI><B>PK_NAME</B> String => primary key name (may be null) |
2528 | * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key |
2529 | * constraints be deferred until commit |
2530 | * <UL> |
2531 | * <LI> importedKeyInitiallyDeferred - see SQL92 for definition |
2532 | * <LI> importedKeyInitiallyImmediate - see SQL92 for definition |
2533 | * <LI> importedKeyNotDeferrable - see SQL92 for definition |
2534 | * </UL> |
2535 | * </OL> |
2536 | * |
2537 | * @param primaryCatalog a catalog name; "" retrieves those without a |
2538 | * catalog; null means drop catalog name from the selection criteria |
2539 | * @param primarySchema a schema name pattern; "" retrieves those |
2540 | * without a schema |
2541 | * @param primaryTable the table name that exports the key |
2542 | * @param foreignCatalog a catalog name; "" retrieves those without a |
2543 | * catalog; null means drop catalog name from the selection criteria |
2544 | * @param foreignSchema a schema name pattern; "" retrieves those |
2545 | * without a schema |
2546 | * @param foreignTable the table name that imports the key |
2547 | * @return ResultSet - each row is a foreign key column description |
2548 | * @see #getImportedKeys |
2549 | * @exception SQLException thrown on failure. |
2550 | */ |
2551 | public ResultSet getCrossReference( |
2552 | String primaryCatalog, String primarySchema, String primaryTable, |
2553 | String foreignCatalog, String foreignSchema, String foreignTable |
2554 | ) throws SQLException { |
2555 | PreparedStatement s = getPreparedQuery("getCrossReference"); |
2556 | s.setString(1, swapNull(primaryCatalog)); |
2557 | s.setString(2, swapNull(primarySchema)); |
2558 | s.setString(3, swapNull(primaryTable)); |
2559 | s.setString(4, swapNull(foreignCatalog)); |
2560 | s.setString(5, swapNull(foreignSchema)); |
2561 | s.setString(6, swapNull(foreignTable)); |
2562 | return s.executeQuery(); |
2563 | } |
2564 | |
2565 | /** |
2566 | * Get a description of all the standard SQL types supported by |
2567 | * this database. They are ordered by DATA_TYPE and then by how |
2568 | * closely the data type maps to the corresponding JDBC SQL type. |
2569 | * |
2570 | * <P>Each type description has the following columns: |
2571 | * <OL> |
2572 | * <LI><B>TYPE_NAME</B> String => Type name |
2573 | * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types |
2574 | * <LI><B>PRECISION</B> int => maximum precision |
2575 | * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal |
2576 | * (may be null) |
2577 | * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal |
2578 | (may be null) |
2579 | * <LI><B>CREATE_PARAMS</B> String => parameters used in creating |
2580 | * the type (may be null) |
2581 | * <LI><B>NULLABLE</B> short => can you use NULL for this type? |
2582 | * <UL> |
2583 | * <LI> typeNoNulls - does not allow NULL values |
2584 | * <LI> typeNullable - allows NULL values |
2585 | * <LI> typeNullableUnknown - nullability unknown |
2586 | * </UL> |
2587 | * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive? |
2588 | * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type: |
2589 | * <UL> |
2590 | * <LI> typePredNone - No support |
2591 | * <LI> typePredChar - Only supported with WHERE .. LIKE |
2592 | * <LI> typePredBasic - Supported except for WHERE .. LIKE |
2593 | * <LI> typeSearchable - Supported for all WHERE .. |
2594 | * </UL> |
2595 | * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned? |
2596 | * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value? |
2597 | * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an |
2598 | * auto-increment value? |
2599 | * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name |
2600 | * (may be null) |
2601 | * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported |
2602 | * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported |
2603 | * <LI><B>SQL_DATA_TYPE</B> int => unused |
2604 | * <LI><B>SQL_DATETIME_SUB</B> int => unused |
2605 | * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10 |
2606 | * </OL> |
2607 | * |
2608 | * @return ResultSet - each row is a SQL type description |
2609 | * @exception SQLException thrown on failure. |
2610 | */ |
2611 | public ResultSet getTypeInfo() throws SQLException { |
2612 | return getSimpleQuery("getTypeInfo"); |
2613 | } |
2614 | |
2615 | /** |
2616 | * Get a description of all the standard SQL types supported by |
2617 | * this database. They are ordered by DATA_TYPE and then by how |
2618 | * closely the data type maps to the corresponding JDBC SQL type. |
2619 | * Same as getTypeInfo above, except that the result set will |
2620 | * conform to ODBC specifications. |
2621 | */ |
2622 | public ResultSet getTypeInfoForODBC() throws SQLException { |
2623 | return getSimpleQuery("odbc_getTypeInfo"); |
2624 | } |
2625 | |
2626 | /** |
2627 | * Get a description of a table's indices and statistics. They are |
2628 | * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION. |
2629 | * |
2630 | * <P>Each index column description has the following columns: |
2631 | * <OL> |
2632 | * <LI><B>TABLE_CAT</B> String => table catalog (may be null) |
2633 | * <LI><B>TABLE_SCHEM</B> String => table schema (may be null) |
2634 | * <LI><B>TABLE_NAME</B> String => table name |
2635 | * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique? |
2636 | * false when TYPE is tableIndexStatistic |
2637 | * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null); |
2638 | * null when TYPE is tableIndexStatistic |
2639 | * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is |
2640 | * tableIndexStatistic |
2641 | * <LI><B>TYPE</B> short => index type: |
2642 | * <UL> |
2643 | * <LI> tableIndexStatistic - this identifies table statistics that are |
2644 | * returned in conjuction with a table's index descriptions |
2645 | * <LI> tableIndexClustered - this is a clustered index |
2646 | * <LI> tableIndexHashed - this is a hashed index |
2647 | * <LI> tableIndexOther - this is some other style of index |
2648 | * </UL> |
2649 | * <LI><B>ORDINAL_POSITION</B> short => column sequence number |
2650 | * within index; zero when TYPE is tableIndexStatistic |
2651 | * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is |
2652 | * tableIndexStatistic |
2653 | * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending, |
2654 | * "D" => descending, may be null if sort sequence is not supported; |
2655 | * null when TYPE is tableIndexStatistic |
2656 | * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then |
2657 | * this is the number of rows in the table; otherwise, it is the |
2658 | * number of unique values in the index. |
2659 | * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then |
2660 | * this is the number of pages used for the table, otherwise it |
2661 | * is the number of pages used for the current index. |
2662 | * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any. |
2663 | * (may be null) |
2664 | * </OL> |
2665 | * |
2666 | * @param catalog a catalog name; "" retrieves those without a |
2667 | * catalog; null means drop catalog name from the selection criteria |
2668 | * @param schema a schema name pattern; "" retrieves those without a schema |
2669 | * @param table a table name |
2670 | * @param unique when true, return only indices for unique values; |
2671 | * when false, return indices regardless of whether unique or not |
2672 | * @param approximate when true, result is allowed to reflect approximate |
2673 | * or out of data values; when false, results are requested to be |
2674 | * accurate |
2675 | * @return ResultSet - each row is an index column description |
2676 | * @exception SQLException thrown on failure. |
2677 | */ |
2678 | public ResultSet getIndexInfo(String catalog, String schema, String table, |
2679 | boolean unique, boolean approximate) |
2680 | throws SQLException { |
2681 | return doGetIndexInfo(catalog, schema, table, unique, approximate, "getIndexInfo"); |
2682 | } |
2683 | |
2684 | /** |
2685 | * Get a description of a table's indices and statistics. They are |
2686 | * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION. |
2687 | * Same as getIndexInfo above, except that the result set will |
2688 | * conform to ODBC specifications. |
2689 | */ |
2690 | public ResultSet getIndexInfoForODBC(String catalog, String schema, String table, |
2691 | boolean unique, boolean approximate) throws SQLException |
2692 | { |
2693 | return doGetIndexInfo(catalog, schema, table, unique, approximate, "odbc_getIndexInfo"); |
2694 | } |
2695 | |
2696 | /** |
2697 | * Does the actual work for the getIndexInfo metadata |
2698 | * calls. See getIndexInfo() method above for parameter |
2699 | * descriptions. |
2700 | * @param queryName Name of the query to execute; is used |
2701 | * to determine whether the result set should conform to |
2702 | * JDBC or ODBC specifications. |
2703 | */ |
2704 | private ResultSet doGetIndexInfo(String catalog, String schema, String table, |
2705 | boolean unique, boolean approximate, String queryName) |
2706 | throws SQLException { |
2707 | |
2708 | int approximateInInt = 0; |
2709 | if (approximate) approximateInInt = 1; |
2710 | PreparedStatement s = getPreparedQuery(queryName); |
2711 | s.setString(1, swapNull(catalog)); |
2712 | s.setString(2, swapNull(schema)); |
2713 | s.setString(3, swapNull(table)); |
2714 | s.setBoolean(4, unique); |
2715 | s.setInt(5, approximateInInt); |
2716 | return s.executeQuery(); |
2717 | } |
2718 | |
2719 | ///////////////////////////////////////////////////////////////////////// |
2720 | // |
2721 | // JDBC 2.0 - New public methods |
2722 | // |
2723 | ///////////////////////////////////////////////////////////////////////// |
2724 | |
2725 | /** |
2726 | * JDBC 2.0 |
2727 | * |
2728 | * Does the database support the given result set type? |
2729 | * |
2730 | * @param type defined in java.sql.ResultSet |
2731 | * @return true if so |
2732 | * @see Connection |
2733 | */ |
2734 | public boolean supportsResultSetType(int type) { |
2735 | if ((type == JDBC20Translation.TYPE_FORWARD_ONLY) || |
2736 | (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE)) { |
2737 | return true; |
2738 | } |
2739 | //we don't support TYPE_SCROLL_SENSITIVE yet. |
2740 | return false; |
2741 | } |
2742 | |
2743 | /** |
2744 | * JDBC 2.0 |
2745 | * |
2746 | * Does the database support the concurrency type in combination |
2747 | * with the given result set type? |
2748 | * |
2749 | * @param type defined in java.sql.ResultSet |
2750 | * @param concurrency type defined in java.sql.ResultSet |
2751 | * @return true if so |
2752 | * @see Connection |
2753 | */ |
2754 | public boolean supportsResultSetConcurrency(int type, int concurrency) { |
2755 | if (type == JDBC20Translation.TYPE_SCROLL_SENSITIVE) { |
2756 | // (TYPE_SCROLL_SENSITIVE, *) |
2757 | return false; |
2758 | } else { |
2759 | // (FORWARD_ONLY, CONCUR_UPDATABLE) |
2760 | // (FORWARD_ONLY, CONCUR_READ_ONLY) |
2761 | // (TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE) |
2762 | // (TYPE_SCROLL_INSENSITIVE, READ_ONLY) |
2763 | return true; |
2764 | } |
2765 | } |
2766 | |
2767 | /** |
2768 | * JDBC 2.0 |
2769 | * |
2770 | * Determine whether a result set's updates are visible. |
2771 | * |
2772 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2773 | * @return true if updates are visible for the result set type |
2774 | */ |
2775 | public boolean ownUpdatesAreVisible(int type) { |
2776 | if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) { |
2777 | return true; |
2778 | } else { |
2779 | return false; |
2780 | } |
2781 | } |
2782 | |
2783 | /** |
2784 | * JDBC 2.0 |
2785 | * |
2786 | * Determine whether a result set's deletes are visible. |
2787 | * |
2788 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2789 | * @return true if deletes are visible for the result set type |
2790 | */ |
2791 | public boolean ownDeletesAreVisible(int type) { |
2792 | if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) { |
2793 | return true; |
2794 | } else { |
2795 | return false; |
2796 | } |
2797 | } |
2798 | |
2799 | /** |
2800 | * JDBC 2.0 |
2801 | * |
2802 | * Determine whether a result set's inserts are visible. |
2803 | * |
2804 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2805 | * @return true if inserts are visible for the result set type |
2806 | */ |
2807 | public boolean ownInsertsAreVisible(int type) { |
2808 | return false; |
2809 | } |
2810 | |
2811 | // Since Derby materializes a forward only ResultSet incrementally, it is |
2812 | // possible to see changes made by others and hence following 3 metadata |
2813 | // calls will return true for forward only ResultSets. |
2814 | |
2815 | /** |
2816 | * JDBC 2.0 |
2817 | * |
2818 | * Determine whether updates made by others are visible. |
2819 | * |
2820 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2821 | * @return true if updates are visible for the result set type |
2822 | */ |
2823 | public boolean othersUpdatesAreVisible(int type) { |
2824 | if (type == JDBC20Translation.TYPE_FORWARD_ONLY) |
2825 | return true; |
2826 | return false; |
2827 | } |
2828 | |
2829 | /** |
2830 | * JDBC 2.0 |
2831 | * |
2832 | * Determine whether deletes made by others are visible. |
2833 | * |
2834 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2835 | * @return true if deletes are visible for the result set type |
2836 | */ |
2837 | public boolean othersDeletesAreVisible(int type) { |
2838 | if (type == JDBC20Translation.TYPE_FORWARD_ONLY) |
2839 | return true; |
2840 | return false; |
2841 | } |
2842 | |
2843 | /** |
2844 | * JDBC 2.0 |
2845 | * |
2846 | * Determine whether inserts made by others are visible. |
2847 | * |
2848 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2849 | * @return true if inserts are visible for the result set type |
2850 | */ |
2851 | public boolean othersInsertsAreVisible(int type) { |
2852 | if (type == JDBC20Translation.TYPE_FORWARD_ONLY) |
2853 | return true; |
2854 | return false; |
2855 | } |
2856 | |
2857 | /** |
2858 | * JDBC 2.0 |
2859 | * |
2860 | * Determine whether or not a visible row update can be detected by |
2861 | * calling ResultSet.rowUpdated(). |
2862 | * |
2863 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2864 | * @return true if updates are detected by the resultset type |
2865 | */ |
2866 | public boolean updatesAreDetected(int type) { |
2867 | if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) { |
2868 | return true; |
2869 | } else { |
2870 | // For forward only resultsets, we move to before the next |
2871 | // row after a update and that is why updatesAreDetected |
2872 | // returns false. |
2873 | return false; |
2874 | } |
2875 | } |
2876 | |
2877 | /** |
2878 | * JDBC 2.0 |
2879 | * |
2880 | * Determine whether or not a visible row delete can be detected by |
2881 | * calling ResultSet.rowDeleted(). If deletesAreDetected() |
2882 | * returns false, then deleted rows are removed from the result set. |
2883 | * |
2884 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2885 | * @return true if deletes are detected by the resultset type |
2886 | */ |
2887 | public boolean deletesAreDetected(int type) { |
2888 | if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) { |
2889 | return true; |
2890 | } else { |
2891 | // For forward only resultsets, we move to before the next |
2892 | // row after a delete and that is why deletesAreDetected |
2893 | // returns false |
2894 | return false; |
2895 | } |
2896 | } |
2897 | |
2898 | /** |
2899 | * JDBC 2.0 |
2900 | * |
2901 | * Determine whether or not a visible row insert can be detected |
2902 | * by calling ResultSet.rowInserted(). |
2903 | * |
2904 | * @param type result set type, i.e. ResultSet.TYPE_XXX |
2905 | * @return true if inserts are detected by the resultset type |
2906 | */ |
2907 | public boolean insertsAreDetected(int type) { |
2908 | return false; |
2909 | } |
2910 | |
2911 | /** |
2912 | * JDBC 2.0 |
2913 | * |
2914 | * Return true if the driver supports batch updates, else return false. |
2915 | * |
2916 | */ |
2917 | public boolean supportsBatchUpdates() { |
2918 | return true; |
2919 | } |
2920 | |
2921 | /** |
2922 | * JDBC 2.0 |
2923 | * |
2924 | * Get a description of the user-defined types defined in a particular |
2925 | * schema. Schema specific UDTs may have type JAVA_OBJECT, STRUCT, |
2926 | * or DISTINCT. |
2927 | * |
2928 | * <P>Only types matching the catalog, schema, type name and type |
2929 | * criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM |
2930 | * and TYPE_NAME. The type name parameter may be a fully qualified |
2931 | * name. In this case, the catalog and schemaPattern parameters are |
2932 | * ignored. |
2933 | * |
2934 | * <P>Each type description has the following columns: |
2935 | * <OL> |
2936 | * <LI><B>TYPE_CAT</B> String => the type's catalog (may be null) |
2937 | * <LI><B>TYPE_SCHEM</B> String => type's schema (may be null) |
2938 | * <LI><B>TYPE_NAME</B> String => type name |
2939 | * <LI><B>CLASS_NAME</B> String => Java class name |
2940 | * <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types. |
2941 | * One of JAVA_OBJECT, STRUCT, or DISTINCT |
2942 | * <LI><B>REMARKS</B> String => explanatory comment on the type |
2943 | * </OL> |
2944 | * |
2945 | * <P><B>Note:</B> If the driver does not support UDTs then an empty |
2946 | * result set is returned. |
2947 | * |
2948 | * @param catalog a catalog name; "" retrieves those without a |
2949 | * catalog; null means drop catalog name from the selection criteria |
2950 | * @param schemaPattern a schema name pattern; "" retrieves those |
2951 | * without a schema |
2952 | * @param typeNamePattern a type name pattern; may be a fully qualified |
2953 | * name |
2954 | * @param types a list of user-named types to include (JAVA_OBJECT, |
2955 | * STRUCT, or DISTINCT); null returns all types |
2956 | * @return ResultSet - each row is a type description |
2957 | * @exception SQLException if a database-access error occurs. |
2958 | */ |
2959 | public ResultSet getUDTs(String catalog, String schemaPattern, |
2960 | String typeNamePattern, int[] types) |
2961 | throws SQLException { |
2962 | //we don't have support for catalog names |
2963 | //we don't have java class types per schema, instead it's per database and hence |
2964 | //we ignore schemapattern. |
2965 | //the only type of user-named types we support are JAVA_OBJECT |
2966 | synchronized (getConnectionSynchronization()) { |
2967 | setupContextStack(); |
2968 | ResultSet rs = null; |
2969 | int getClassTypes = 0; |
2970 | try { |
2971 | String queryText = getQueryDescriptions(false).getProperty("getUDTs"); |
2972 | |
2973 | if (types != null && types.length >= 1) { |
2974 | for (int i=0; i<types.length; i++){ |
2975 | if (types[i] == java.sql.Types.JAVA_OBJECT) |
2976 | getClassTypes = 1; |
2977 | } |
2978 | } else |
2979 | getClassTypes = 1; |
2980 | |
2981 | PreparedStatement s = |
2982 | getEmbedConnection().prepareMetaDataStatement(queryText); |
2983 | |
2984 | s.setInt(1, java.sql.Types.JAVA_OBJECT); |
2985 | s.setString(2, catalog); |
2986 | s.setString(3, schemaPattern); |
2987 | s.setString(4, swapNull(typeNamePattern)); |
2988 | s.setInt(5, getClassTypes); |
2989 | |
2990 | rs = s.executeQuery(); |
2991 | } finally { |
2992 | restoreContextStack(); |
2993 | } |
2994 | return rs; |
2995 | } |
2996 | } |
2997 | |
2998 | /** |
2999 | * JDBC 2.0 |
3000 | * |
3001 | * Return the connection that produced this metadata object. |
3002 | * |
3003 | */ |
3004 | public Connection getConnection() { |
3005 | return getEmbedConnection().getApplicationConnection(); |
3006 | } |
3007 | |
3008 | /** |
3009 | Following methods are for the new JDBC 3.0 methods in java.sql.DatabaseMetaData |
3010 | (see the JDBC 3.0 spec). We have the JDBC 3.0 methods in Local20 |
3011 | package, so we don't have to have a new class in Local30. |
3012 | The new JDBC 3.0 methods don't make use of any new JDBC3.0 classes and |
3013 | so this will work fine in jdbc2.0 configuration. |
3014 | */ |
3015 | |
3016 | ///////////////////////////////////////////////////////////////////////// |
3017 | // |
3018 | // JDBC 3.0 - New public methods |
3019 | // |
3020 | ///////////////////////////////////////////////////////////////////////// |
3021 | |
3022 | /** |
3023 | * JDBC 3.0 |
3024 | * |
3025 | * Retrieves whether this database supports statement pooling. |
3026 | * |
3027 | * @return true if statement pooling is supported; false otherwise |
3028 | */ |
3029 | public boolean supportsStatementPooling() |
3030 | { |
3031 | return false; |
3032 | } |
3033 | |
3034 | /** |
3035 | * JDBC 3.0 |
3036 | * |
3037 | * Retrieves whether this database supports savepoints. |
3038 | * |
3039 | * @return true if savepoints are supported; false otherwise |
3040 | */ |
3041 | public boolean supportsSavepoints() |
3042 | { |
3043 | return true; |
3044 | } |
3045 | |
3046 | /** |
3047 | * JDBC 3.0 |
3048 | * |
3049 | * Retrieves whether this database supports named parameters to callable statements. |
3050 | * |
3051 | * @return true if named parameters are supported; false otherwise |
3052 | */ |
3053 | public boolean supportsNamedParameters() |
3054 | { |
3055 | return false; |
3056 | } |
3057 | |
3058 | /** |
3059 | * JDBC 3.0 |
3060 | * |
3061 | * Retrieves whether it is possible to have multiple ResultSet objects returned from a |
3062 | * CallableStatement object simultaneously. |
3063 | * |
3064 | * @return true if a CallableStatement object can return multiple ResultSet objects |
3065 | * simultaneously; false otherwise |
3066 | */ |
3067 | public boolean supportsMultipleOpenResults() |
3068 | { |
3069 | return true; |
3070 | } |
3071 | |
3072 | /** |
3073 | * JDBC 3.0 |
3074 | * |
3075 | * Retrieves whether auto-generated keys can be retrieved after a statement |
3076 | * has been executed. |
3077 | * |
3078 | * @return true if auto-generated keys can be retrieved after a statement has |
3079 | * executed; false otherwise |
3080 | */ |
3081 | public boolean supportsGetGeneratedKeys() |
3082 | { |
3083 | /* |
3084 | * Currently reverting the returned value to false until there |
3085 | * is more support for autogenerated keys in Derby. |
3086 | * (such as support for specifying the returned columns for |
3087 | * the autogenerated key) |
3088 | */ |
3089 | return false; |
3090 | } |
3091 | |
3092 | /** |
3093 | * JDBC 3.0 |
3094 | * |
3095 | * Retrieves whether this database supports the given result set holdability. |
3096 | * |
3097 | * @param holdability - one of the following constants: |
3098 | * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT |
3099 | * @return true if so; false otherwise |
3100 | * executed; false otherwise |
3101 | */ |
3102 | public boolean supportsResultSetHoldability(int holdability) |
3103 | { |
3104 | return true; |
3105 | } |
3106 | |
3107 | /** |
3108 | * JDBC 3.0 |
3109 | * |
3110 | * Retrieves the default holdability of this ResultSet object. |
3111 | * |
3112 | * @return the default holdability which is ResultSet.HOLD_CURSORS_OVER_COMMIT |
3113 | */ |
3114 | public int getResultSetHoldability() |
3115 | { |
3116 | return JDBC30Translation.HOLD_CURSORS_OVER_COMMIT; |
3117 | } |
3118 | |
3119 | /** |
3120 | * JDBC 3.0 |
3121 | * |
3122 | * Retrieves the major version number of the underlying database. |
3123 | * |
3124 | * @return the underlying database's major version |
3125 | */ |
3126 | public int getDatabaseMajorVersion() |
3127 | { |
3128 | ProductVersionHolder pvh = Monitor.getMonitor().getEngineVersion(); |
3129 | if (pvh == null) |
3130 | { |
3131 | return -1; |
3132 | } |
3133 | return pvh.getMajorVersion(); |
3134 | } |
3135 | |
3136 | /** |
3137 | * JDBC 3.0 |
3138 | * |
3139 | * Retrieves the minor version number of the underlying database. |
3140 | * |
3141 | * @return the underlying database's minor version |
3142 | */ |
3143 | public int getDatabaseMinorVersion() |
3144 | { |
3145 | ProductVersionHolder pvh = Monitor.getMonitor().getEngineVersion(); |
3146 | if (pvh == null) |
3147 | { |
3148 | return -1; |
3149 | } |
3150 | return pvh.getMinorVersion(); |
3151 | } |
3152 | |
3153 | /** |
3154 | * JDBC 3.0 |
3155 | * |
3156 | * Retrieves the major JDBC version number for this driver. |
3157 | * |
3158 | * @return JDBC version major number |
3159 | */ |
3160 | public int getJDBCMajorVersion() |
3161 | { |
3162 | return 3; |
3163 | } |
3164 | |
3165 | /** |
3166 | * JDBC 3.0 |
3167 | * |
3168 | * Retrieves the minor JDBC version number for this driver. |
3169 | * |
3170 | * @return JDBC version minor number |
3171 | */ |
3172 | public int getJDBCMinorVersion() |
3173 | { |
3174 | return 0; |
3175 | } |
3176 | |
3177 | /** |
3178 | * JDBC 3.0 |
3179 | * |
3180 | * Indicates whether the SQLSTATEs returned by SQLException.getSQLState |
3181 | * is X/Open (now known as Open Group) SQL CLI or SQL99. |
3182 | * |
3183 | * @return the type of SQLSTATEs, one of: sqlStateXOpen or sqlStateSQL99 |
3184 | */ |
3185 | public int getSQLStateType() |
3186 | { |
3187 | return JDBC30Translation.SQL_STATE_SQL99; |
3188 | } |
3189 | |
3190 | /** |
3191 | * JDBC 3.0 |
3192 | * |
3193 | * Indicates whether updates made to a LOB are made on a copy or |
3194 | * directly to the LOB. |
3195 | * |
3196 | * @return true if updates are made to a copy of the LOB; false if |
3197 | * updates are made directly to the LOB |
3198 | * @exception SQLException Feature not implemented for now. |
3199 | */ |
3200 | public boolean locatorsUpdateCopy() |
3201 | throws SQLException |
3202 | { |
3203 | return false; |
3204 | } |
3205 | |
3206 | /** |
3207 | * JDBC 3.0 |
3208 | * |
3209 | * Retrieves a description of the user-defined type (UDT) hierarchies defined |
3210 | * in a particular schema in this database. Only the immediate super type/ sub type |
3211 | * relationship is modeled. |
3212 | * |
3213 | * @param catalog - a catalog name; "" retrieves those without a catalog; |
3214 | * null means drop catalog name from the selection criteria |
3215 | * @param schemaPattern - a schema name pattern; "" retrieves those without a schema |
3216 | * @param typeNamePattern - a UDT name pattern; may be a fully-qualified name |
3217 | * @return a ResultSet object in which a row gives information about the designated UDT |
3218 | * @exception SQLException Feature not implemented for now. |
3219 | */ |
3220 | public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) |
3221 | throws SQLException |
3222 | { |
3223 | return getSimpleQuery("getSuperTypes"); |
3224 | } |
3225 | |
3226 | /** |
3227 | * JDBC 3.0 |
3228 | * |
3229 | * Retrieves a description of the table hierarchies defined in a particular |
3230 | * schema in this database. |
3231 | * |
3232 | * @param catalog - a catalog name; "" retrieves those without a catalog; |
3233 | * null means drop catalog name from the selection criteria |
3234 | * @param schemaPattern - a schema name pattern; "" retrieves those without a schema |
3235 | * @param typeNamePattern - a UDT name pattern; may be a fully-qualified name |
3236 | * @return a ResultSet object in which each row is a type description |
3237 | * @exception SQLException if a database access error occurs |
3238 | */ |
3239 | public ResultSet getSuperTables(String catalog, String schemaPattern, String typeNamePattern) |
3240 | throws SQLException |
3241 | { |
3242 | return getSimpleQuery("getSuperTables"); |
3243 | } |
3244 | |
3245 | /** |
3246 | * JDBC 3.0 |
3247 | * |
3248 | * Retrieves a description of the given attribute of the given type for a |
3249 | * user-defined type (UDT) that is available in the given schema and catalog. |
3250 | * |
3251 | * @param catalog - a catalog name; must match the catalog name as it is |
3252 | * stored in the database; "" retrieves those without a catalog; null means that |
3253 | * the catalog name should not be used to narrow the search |
3254 | * @param schemaPattern - a schema name pattern; "" retrieves those without a schema; |
3255 | * null means that the schema name should not be used to narrow the search |
3256 | * @param typeNamePattern - a type name pattern; must match the type name as it is |
3257 | * stored in the database |
3258 | * @param attributeNamePattern - an attribute name pattern; must match the attribute |
3259 | * name as it is declared in the database |
3260 | * @return a ResultSet object in which each row is a type description |
3261 | * @exception SQLException if a database access error occurs. |
3262 | */ |
3263 | public ResultSet getAttributes(String catalog, String schemaPattern, |
3264 | String typeNamePattern, String attributeNamePattern) |
3265 | throws SQLException |
3266 | { |
3267 | return getSimpleQuery("getAttributes"); |
3268 | } |
3269 | |
3270 | ///////////////////////////////////////////////////////////////////////// |
3271 | // |
3272 | // JDBC 4.0 - New public methods |
3273 | // |
3274 | ///////////////////////////////////////////////////////////////////////// |
3275 | |
3276 | /** |
3277 | * JDBC 4.0 |
3278 | * |
3279 | * <p>Returns a list of the client info properties supported by |
3280 | * the driver. The result set contains the following columns: |
3281 | * |
3282 | * <p> |
3283 | * <ol> |
3284 | * <li>NAME String=> The name of the client info property.</li> |
3285 | * <li>MAX_LEN int=> The maximum length of the value for the |
3286 | * property.</li> |
3287 | * <li>DEFAULT_VALUE String=> The default value of the property.</li> |
3288 | * <li>DESCRIPTION String=> A description of the property.</li> |
3289 | * </ol> |
3290 | * |
3291 | * <p>The <code>ResultSet</code> is sorted by the NAME column. |
3292 | * |
3293 | * @return A <code>ResultSet</code> object; each row is a |
3294 | * supported client info property |
3295 | * @exception SQLException if an error occurs |
3296 | */ |
3297 | public ResultSet getClientInfoProperties() throws SQLException { |
3298 | return getSimpleQuery("getClientInfoProperties"); |
3299 | } |
3300 | |
3301 | /** |
3302 | * JDBC 4.0 |
3303 | * |
3304 | * <p>Get the schema names available in this database. The results |
3305 | * are ordered by schema name. |
3306 | * |
3307 | * <p>The schema columns are: |
3308 | * <ol> |
3309 | * <li><strong>TABLE_SCHEM</strong> String => schema name</li> |
3310 | * <li><strong>TABLE_CATALOG</strong> String => catalog name |
3311 | * (may be <code>null</code>)</li> |
3312 | * </ol> |
3313 | * |
3314 | * @param catalog catalog name used to narrow down the search; "" |
3315 | * means no catalog, <code>null</code> means any catalog |
3316 | * @param schemaPattern schema name used to narrow down the |
3317 | * search, <code>null</code> means schema name should not be used |
3318 | * to narrow down search |
3319 | * @return a <code>ResultSet</code> object in which each row is a |
3320 | * schema description |
3321 | * @exception SQLException if a database error occurs |
3322 | */ |
3323 | public ResultSet getSchemas(String catalog, String schemaPattern) |
3324 | throws SQLException |
3325 | { |
3326 | PreparedStatement s = getPreparedQuery("getSchemas"); |
3327 | s.setString(1, swapNull(catalog)); |
3328 | s.setString(2, swapNull(schemaPattern)); |
3329 | return s.executeQuery(); |
3330 | } |
3331 | |
3332 | ////////////////////////////////////////////////////////////// |
3333 | // |
3334 | // MISC |
3335 | // |
3336 | ////////////////////////////////////////////////////////////// |
3337 | |
3338 | /** |
3339 | * Get metadata that the client driver will cache. The metadata is |
3340 | * fetched using SYSIBM.METADATA (found in metadata_net.properties). |
3341 | * |
3342 | * @return the result set returned by SYSIBM.METADATA |
3343 | * @exception SQLException if a database error occurs |
3344 | */ |
3345 | public ResultSet getClientCachedMetaData() throws SQLException { |
3346 | return getSimpleQuery("METADATA", true); |
3347 | } |
3348 | |
3349 | /* |
3350 | * utility helper routines: |
3351 | */ |
3352 | |
3353 | /** |
3354 | * Execute a query in metadata.properties (or SPS in the SYS |
3355 | * schema) or metadata_net.properties (or SPS in the SYSIBM |
3356 | * schema). |
3357 | * |
3358 | * @param nameKey the name of the query |
3359 | * @param net if <code>true</code>, execute a query in |
3360 | * metadata_net.properties; otherwise, execute a query in |
3361 | * metadata.properties |
3362 | * @return a <code>ResultSet</code> value |
3363 | * @exception SQLException if a database error occurs |
3364 | */ |
3365 | private ResultSet getSimpleQuery(String nameKey, boolean net) |
3366 | throws SQLException |
3367 | { |
3368 | PreparedStatement ps = getPreparedQuery(nameKey, net); |
3369 | if (ps == null) |
3370 | return null; |
3371 | |
3372 | return ps.executeQuery(); |
3373 | } |
3374 | |
3375 | /** |
3376 | * Execute a query in metadata.properties, or an SPS in the SYS |
3377 | * schema. |
3378 | * |
3379 | * @param nameKey the name of the query |
3380 | * @return a <code>ResultSet</code> value |
3381 | * @exception SQLException if a database error occurs |
3382 | */ |
3383 | protected ResultSet getSimpleQuery(String nameKey) throws SQLException { |
3384 | return getSimpleQuery(nameKey, false); |
3385 | } |
3386 | |
3387 | /** |
3388 | * Get a stored prepared statement from the system tables. |
3389 | * |
3390 | * @param nameKey the name of the query |
3391 | * @param net if <code>true</code>, find query in SYSIBM schema; |
3392 | * otherwise, find query in SYS schema |
3393 | * @return a <code>PreparedStatement</code> value |
3394 | * @exception SQLException if a database error occurs |
3395 | */ |
3396 | private PreparedStatement getPreparedQueryUsingSystemTables(String nameKey, |
3397 | boolean net) |
3398 | throws SQLException |
3399 | { |
3400 | synchronized (getConnectionSynchronization()) |
3401 | { |
3402 | setupContextStack(); |
3403 | PreparedStatement ps = null; |
3404 | |
3405 | try |
3406 | { |
3407 | String queryText = |
3408 | getQueryDescriptions(net).getProperty(nameKey); |
3409 | if (queryText == null) |
3410 | { |
3411 | throw Util.notImplemented(nameKey); |
3412 | } |
3413 | |
3414 | ps = prepareSPS(nameKey, queryText, net); |
3415 | } |
3416 | |
3417 | catch (Throwable t) |
3418 | { |
3419 | throw handleException(t); |
3420 | } |
3421 | |
3422 | finally |
3423 | { |
3424 | restoreContextStack(); |
3425 | } |
3426 | return ps; |
3427 | } |
3428 | } |
3429 | |
3430 | /** |
3431 | * Either get the prepared query for the metadata call from the |
3432 | * system tables, or from the metadata.properties or |
3433 | * metadata_net.properties file. |
3434 | * In soft upgrade mode, the queries stored in the system tables |
3435 | * might not be upto date with the Derby engine release because |
3436 | * system tables can't be modified in backward incompatible way in |
3437 | * soft upgrade mode. Because of this, if the database is in |
3438 | * soft upgrade mode, get the queries from metadata.properties |
3439 | * file rather than from the system tables. |
3440 | * |
3441 | * Getting queries from metadata(_net).properties might cause problems |
3442 | * if system catalogs have been changed between versions either by |
3443 | * addition of columns or have new catalogs. To continue |
3444 | * to support soft upgrade from older versions of database, find |
3445 | * query that most closely matches database dictionary version. |
3446 | * |
3447 | * @param queryName Name of the metadata query for which we need |
3448 | * a prepared statement |
3449 | * @param net if <code>true</code>, use metadata_net.properties |
3450 | * instead of metadata.properties |
3451 | * @return PreparedStatement |
3452 | * @exception SQLException if a database error occurs |
3453 | */ |
3454 | private PreparedStatement getPreparedQuery(String queryName, |
3455 | boolean net) |
3456 | throws SQLException { |
3457 | PreparedStatement s; |
3458 | //We can safely goto system table since we are not in soft upgrade |
3459 | //mode and hence metadata sql in system tables are uptodate |
3460 | //with this Derby release. |
3461 | if (notInSoftUpgradeMode()) |
3462 | s = getPreparedQueryUsingSystemTables(queryName, net); |
3463 | else { |
3464 | try { |
3465 | //Can't use stored prepared statements because we are in soft upgrade |
3466 | //mode and hence need to get metadata sql from metadata.properties file |
3467 | //or metadata_net.properties |
3468 | String queryText = getQueryFromDescription(queryName, net); |
3469 | s = getEmbedConnection().prepareMetaDataStatement(queryText); |
3470 | } catch (Throwable t) { |
3471 | throw handleException(t); |
3472 | } |
3473 | } |
3474 | return s; |
3475 | } |
3476 | |
3477 | /** |
3478 | * Get a prepared query from system tables or metadata.properties. |
3479 | * |
3480 | * @param queryName name of the query |
3481 | * @return a <code>PreparedStatement</code> value |
3482 | * @exception SQLException if a database error occurs |
3483 | */ |
3484 | protected PreparedStatement getPreparedQuery(String queryName) |
3485 | throws SQLException |
3486 | { |
3487 | return getPreparedQuery(queryName, false); |
3488 | } |
3489 | |
3490 | /** |
3491 | * Given a queryName, find closest match in queryDescriptions. This method |
3492 | * should be called in soft-upgrade mode only, where current software version |
3493 | * doesn't match dictionary version. For these cases, there may be |
3494 | * multiple entries in queryDescriptions for given queryName. Find a |
3495 | * version of the query that closely matches dictionary version. |
3496 | * |
3497 | * This method is currently coded to handle two specific queries, |
3498 | * getColumnPrivileges and getTablePrivileges. Derby databases that are 10.1 |
3499 | * or earlier will not have new system tables added for 10.2 for privileges. |
3500 | * |
3501 | * It should be possible to automate finding closest match by generating |
3502 | * all Major_Minor versions between software version and dictionary version |
3503 | * and try each one from Dictionary version to current version. Since only |
3504 | * needed for two queries, overhead may not be worth it yet. |
3505 | * |
3506 | * @param queryName name of the query |
3507 | * @param net if <code>true</code>, get the query from |
3508 | * metadata_net.properties instead of metadata.properties |
3509 | * @return the query text |
3510 | * @exception StandardException if an error occurs |
3511 | */ |
3512 | private String getQueryFromDescription(String queryName, boolean net) |
3513 | throws StandardException |
3514 | { |
3515 | DataDictionary dd = getLanguageConnectionContext().getDataDictionary(); |
3516 | |
3517 | // If dictionary version is below 10.2, special case |
3518 | // getColumnPrivileges and getTablePrivileges since new system tables |
3519 | // for privileges wouldn't be present. |
3520 | if (!dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_2, null)) |
3521 | { |
3522 | if (queryName.equals("getColumnPrivileges")) |
3523 | queryName = "getColumnPrivileges_10_1"; |
3524 | |
3525 | if (queryName.equals("getTablePrivileges")) |
3526 | queryName = "getTablePrivileges_10_1"; |
3527 | } |
3528 | |
3529 | return getQueryDescriptions(net).getProperty(queryName); |
3530 | } |
3531 | |
3532 | /* |
3533 | ** Given a SPS name and a query text it returns a |
3534 | ** java.sql.PreparedStatement for the SPS. If the SPS |
3535 | ** doeesn't exist is created. |
3536 | ** |
3537 | */ |
3538 | private PreparedStatement prepareSPS(String spsName, |
3539 | String spsText, |
3540 | boolean net) |
3541 | throws StandardException, SQLException |
3542 | { |
3543 | |
3544 | LanguageConnectionContext lcc = getLanguageConnectionContext(); |
3545 | |
3546 | /* We now need to do this in sub transaction because we could possibly recompile SPS |
3547 | * later, and the recompile is in a sub transaction, and will update the SYSSTATEMENTS |
3548 | * entry. Don't want to block. |
3549 | */ |
3550 | lcc.beginNestedTransaction(true); |
3551 | |
3552 | DataDictionary dd = getLanguageConnectionContext().getDataDictionary(); |
3553 | SPSDescriptor spsd = dd.getSPSDescriptor( |
3554 | spsName, |
3555 | net ? dd.getSysIBMSchemaDescriptor() : |
3556 | dd.getSystemSchemaDescriptor()); |
3557 | lcc.commitNestedTransaction(); |
3558 | |
3559 | if (spsd == null) |
3560 | { |
3561 | throw Util.notImplemented(spsName); |
3562 | } |
3563 | |
3564 | /* manish: |
3565 | There should be a nicer way of getting a |
3566 | java.sql.PreparedStatement from an SPS descriptor! |
3567 | */ |
3568 | /* |
3569 | ** It is unnecessarily expensive to get the |
3570 | ** the statement, and then send an EXECUTE |
3571 | ** statement, but we have no (easy) way of turning |
3572 | ** the statement into a java.sql.PreparedStatement. |
3573 | */ |
3574 | String queryText = |
3575 | "EXECUTE STATEMENT " + (net ? "SYSIBM" : "SYS") + |
3576 | ".\"" + spsName + "\""; |
3577 | return getEmbedConnection().prepareMetaDataStatement(queryText); |
3578 | |
3579 | } |
3580 | |
3581 | static final protected String swapNull(String s) { |
3582 | return (s == null ? "%" : s); |
3583 | } |
3584 | |
3585 | /** |
3586 | * Gets the constant action factory |
3587 | * |
3588 | * @return the constant action factory. |
3589 | * |
3590 | * @exception StandardException Thrown on failur4e |
3591 | */ |
3592 | private GenericConstantActionFactory getGenericConstantActionFactory() |
3593 | throws StandardException |
3594 | { |
3595 | if ( constantActionFactory == null ) |
3596 | { |
3597 | GenericExecutionFactory execFactory = (GenericExecutionFactory) |
3598 | getLanguageConnectionContext().getLanguageConnectionFactory().getExecutionFactory(); |
3599 | constantActionFactory = execFactory.getConstantActionFactory(); |
3600 | } |
3601 | |
3602 | return constantActionFactory; |
3603 | } |
3604 | |
3605 | /** |
3606 | * Gets the LanguageConnectionContext for this connection. |
3607 | * |
3608 | * @return the lcc for this connection |
3609 | * |
3610 | */ |
3611 | private LanguageConnectionContext getLanguageConnectionContext() |
3612 | { |
3613 | return getEmbedConnection().getLanguageConnection(); |
3614 | } |
3615 | |
3616 | /* |
3617 | ** Priv block code, moved out of the old Java2 version. |
3618 | */ |
3619 | |
3620 | /** |
3621 | * Loads the query descriptions from metadata.properties and |
3622 | * metadata_net.properties into <code>queryDescriptions</code> and |
3623 | * <code>queryDescriptions_net</code>. |
3624 | */ |
3625 | private void loadQueryDescriptions() { |
3626 | java.security.AccessController.doPrivileged(this); |
3627 | } |
3628 | |
3629 | /** |
3630 | * Performs a privileged action. Reads the query descriptions. |
3631 | * |
3632 | * @return <code>null</code> |
3633 | */ |
3634 | public final Object run() { |
3635 | // SECURITY PERMISSION - IP3 |
3636 | PBloadQueryDescriptions(); |
3637 | return null; |
3638 | } |
3639 | |
3640 | } |