1
package org.postgresql.jdbc2;
3
// IMPORTANT NOTE: This file implements the JDBC 2 version of the driver.
4
// If you make any modifications to this file, you must make sure that the
5
// changes are also made (if relevent) to the related JDBC 1 class in the
6
// org.postgresql.jdbc1 package.
11
import org.postgresql.Driver;
12
import org.postgresql.Field;
13
import org.postgresql.util.PSQLException;
16
* This class provides information about the database as a whole.
18
* $Id: DatabaseMetaData.java,v 1.48 2002/01/18 17:21:31 davec Exp $
20
* <p>Many of the methods here return lists of information in ResultSets. You
21
* can use the normal ResultSet methods such as getString and getInt to
22
* retrieve the data from these ResultSets. If a given form of metadata is
23
* not available, these methods should throw a SQLException.
25
* <p>Some of these methods take arguments that are String patterns. These
26
* arguments all have names such as fooPattern. Within a pattern String,
27
* "%" means match any substring of 0 or more characters, and "_" means
28
* match any one character. Only metadata entries matching the search
29
* pattern are returned. if a search pattern argument is set to a null
30
* ref, it means that argument's criteria should be dropped from the
33
* <p>A SQLException will be throws if a driver does not support a meta
34
* data method. In the case of methods that return a ResultSet, either
35
* a ResultSet (which may be empty) is returned or a SQLException is
38
* @see java.sql.DatabaseMetaData
40
public class DatabaseMetaData implements java.sql.DatabaseMetaData
42
Connection connection; // The connection association
44
// These define various OID's. Hopefully they will stay constant.
45
static final int iVarcharOid = 1043; // OID for varchar
46
static final int iBoolOid = 16; // OID for bool
47
static final int iInt2Oid = 21; // OID for int2
48
static final int iInt4Oid = 23; // OID for int4
49
static final int VARHDRSZ = 4; // length for int4
51
public DatabaseMetaData(Connection conn)
53
this.connection = conn;
57
* Can all the procedures returned by getProcedures be called
58
* by the current user?
61
* @exception SQLException if a database access error occurs
63
public boolean allProceduresAreCallable() throws SQLException
65
Driver.debug("allProceduresAreCallable");
66
return true; // For now...
70
* Can all the tables returned by getTable be SELECTed by
74
* @exception SQLException if a database access error occurs
76
public boolean allTablesAreSelectable() throws SQLException
78
Driver.debug("allTablesAreSelectable");
79
return true; // For now...
83
* What is the URL for this database?
85
* @return the url or null if it cannott be generated
86
* @exception SQLException if a database access error occurs
88
public String getURL() throws SQLException
90
String url = connection.getURL();
91
Driver.debug("getURL " + url);
96
* What is our user name as known to the database?
98
* @return our database user name
99
* @exception SQLException if a database access error occurs
101
public String getUserName() throws SQLException
103
String userName = connection.getUserName();
104
Driver.debug("getUserName " + userName);
109
* Is the database in read-only mode?
112
* @exception SQLException if a database access error occurs
114
public boolean isReadOnly() throws SQLException
116
boolean isReadOnly = connection.isReadOnly();
117
Driver.debug("isReadOnly " + isReadOnly);
122
* Are NULL values sorted high?
125
* @exception SQLException if a database access error occurs
127
public boolean nullsAreSortedHigh() throws SQLException
129
boolean nullSortedHigh = connection.haveMinimumServerVersion("7.2");
130
Driver.debug("nullsAreSortedHigh " + nullSortedHigh);
131
return nullSortedHigh;
135
* Are NULL values sorted low?
138
* @exception SQLException if a database access error occurs
140
public boolean nullsAreSortedLow() throws SQLException
142
Driver.debug("nullsAreSortedLow false");
147
* Are NULL values sorted at the start regardless of sort order?
150
* @exception SQLException if a database access error occurs
152
public boolean nullsAreSortedAtStart() throws SQLException
154
Driver.debug("nullsAreSortedAtStart false");
159
* Are NULL values sorted at the end regardless of sort order?
162
* @exception SQLException if a database access error occurs
164
public boolean nullsAreSortedAtEnd() throws SQLException
166
boolean nullsAreSortedAtEnd = ! connection.haveMinimumServerVersion("7.2");
167
Driver.debug("nullsAreSortedAtEnd " + nullsAreSortedAtEnd);
168
return nullsAreSortedAtEnd;
172
* What is the name of this database product - we hope that it is
173
* PostgreSQL, so we return that explicitly.
175
* @return the database product name
176
* @exception SQLException if a database access error occurs
178
public String getDatabaseProductName() throws SQLException
180
Driver.debug("getDatabaseProductName PostgresSQL");
185
* What is the version of this database product.
187
* @return the database version
188
* @exception SQLException if a database access error occurs
190
public String getDatabaseProductVersion() throws SQLException
192
String versionNumber = connection.getDBVersionNumber();
193
Driver.debug("getDatabaseProductVersion " + versionNumber);
194
return versionNumber;
198
* What is the name of this JDBC driver? If we don't know this
199
* we are doing something wrong!
201
* @return the JDBC driver name
202
* @exception SQLException why?
204
public String getDriverName() throws SQLException
206
String driverName = "PostgreSQL Native Driver";
207
Driver.debug("getDriverName" + driverName);
212
* What is the version string of this JDBC driver? Again, this is
215
* @return the JDBC driver name.
216
* @exception SQLException why?
218
public String getDriverVersion() throws SQLException
220
String driverVersion = connection.this_driver.getVersion();
221
Driver.debug("getDriverVersion " + driverVersion);
222
return driverVersion;
226
* What is this JDBC driver's major version number?
228
* @return the JDBC driver major version
230
public int getDriverMajorVersion()
232
int majorVersion = connection.this_driver.getMajorVersion();
233
Driver.debug("getMajorVersion " + majorVersion);
238
* What is this JDBC driver's minor version number?
240
* @return the JDBC driver minor version
242
public int getDriverMinorVersion()
244
int minorVersion = connection.this_driver.getMinorVersion();
245
Driver.debug("getMinorVersion " + minorVersion);
250
* Does the database store tables in a local file? No - it
251
* stores them in a file on the server.
254
* @exception SQLException if a database access error occurs
256
public boolean usesLocalFiles() throws SQLException
258
Driver.debug("usesLocalFiles " + false);
263
* Does the database use a file for each table? Well, not really,
264
* since it doesnt use local files.
267
* @exception SQLException if a database access error occurs
269
public boolean usesLocalFilePerTable() throws SQLException
271
Driver.debug("usesLocalFilePerTable " + false);
276
* Does the database treat mixed case unquoted SQL identifiers
277
* as case sensitive and as a result store them in mixed case?
278
* A JDBC-Compliant driver will always return false.
280
* <p>Predicament - what do they mean by "SQL identifiers" - if it
281
* means the names of the tables and columns, then the answers
282
* given below are correct - otherwise I don't know.
285
* @exception SQLException if a database access error occurs
287
public boolean supportsMixedCaseIdentifiers() throws SQLException
289
Driver.debug("supportsMixedCaseIdentifiers " + false);
294
* Does the database treat mixed case unquoted SQL identifiers as
295
* case insensitive and store them in upper case?
299
public boolean storesUpperCaseIdentifiers() throws SQLException
301
Driver.debug("storesUpperCaseIdentifiers " + false);
306
* Does the database treat mixed case unquoted SQL identifiers as
307
* case insensitive and store them in lower case?
311
public boolean storesLowerCaseIdentifiers() throws SQLException
313
Driver.debug("storesLowerCaseIdentifiers " + true);
318
* Does the database treat mixed case unquoted SQL identifiers as
319
* case insensitive and store them in mixed case?
323
public boolean storesMixedCaseIdentifiers() throws SQLException
325
Driver.debug("storesMixedCaseIdentifiers " + false);
330
* Does the database treat mixed case quoted SQL identifiers as
331
* case sensitive and as a result store them in mixed case? A
332
* JDBC compliant driver will always return true.
335
* @exception SQLException if a database access error occurs
337
public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException
339
Driver.debug("supportsMixedCaseQuotedIdentifiers " + true);
344
* Does the database treat mixed case quoted SQL identifiers as
345
* case insensitive and store them in upper case?
349
public boolean storesUpperCaseQuotedIdentifiers() throws SQLException
351
Driver.debug("storesUpperCaseQuotedIdentifiers " + false);
356
* Does the database treat mixed case quoted SQL identifiers as case
357
* insensitive and store them in lower case?
361
public boolean storesLowerCaseQuotedIdentifiers() throws SQLException
363
Driver.debug("storesLowerCaseQuotedIdentifiers " + false);
368
* Does the database treat mixed case quoted SQL identifiers as case
369
* insensitive and store them in mixed case?
373
public boolean storesMixedCaseQuotedIdentifiers() throws SQLException
375
Driver.debug("storesMixedCaseQuotedIdentifiers " + false);
380
* What is the string used to quote SQL identifiers? This returns
381
* a space if identifier quoting isn't supported. A JDBC Compliant
382
* driver will always use a double quote character.
384
* @return the quoting string
385
* @exception SQLException if a database access error occurs
387
public String getIdentifierQuoteString() throws SQLException
389
Driver.debug("getIdentifierQuoteString \"" );
394
* Get a comma separated list of all a database's SQL keywords that
395
* are NOT also SQL92 keywords.
397
* <p>Within PostgreSQL, the keywords are found in
398
* src/backend/parser/keywords.c
400
* <p>For SQL Keywords, I took the list provided at
401
* <a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
402
* http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
403
* which is for SQL3, not SQL-92, but it is close enough for
406
* @return a comma separated list of keywords we use
407
* @exception SQLException if a database access error occurs
409
public String getSQLKeywords() throws SQLException
411
Driver.debug("getSQLKeyWords");
412
return "abort,acl,add,aggregate,append,archive,arch_store,backward,binary,change,cluster,copy,database,delimiters,do,extend,explain,forward,heavy,index,inherits,isnull,light,listen,load,merge,nothing,notify,notnull,oids,purge,rename,replace,retrieve,returns,rule,recipe,setof,stdin,stdout,store,vacuum,verbose,version";
415
public String getNumericFunctions() throws SQLException
417
// XXX-Not Implemented
418
Driver.debug("getNumericFunctions");
422
public String getStringFunctions() throws SQLException
424
// XXX-Not Implemented
425
Driver.debug("getStringFunctions");
429
public String getSystemFunctions() throws SQLException
431
// XXX-Not Implemented
432
Driver.debug("getSystemFunctions");
436
public String getTimeDateFunctions() throws SQLException
438
// XXX-Not Implemented
439
Driver.debug("getTimeDateFunctions");
444
* This is the string that can be used to escape '_' and '%' in
445
* a search string pattern style catalog search parameters
447
* @return the string used to escape wildcard characters
448
* @exception SQLException if a database access error occurs
450
public String getSearchStringEscape() throws SQLException
452
Driver.debug("getSearchStringEscape");
457
* Get all the "extra" characters that can be used in unquoted
458
* identifier names (those beyond a-zA-Z0-9 and _)
460
* <p>From the file src/backend/parser/scan.l, an identifier is
461
* {letter}{letter_or_digit} which makes it just those listed
464
* @return a string containing the extra characters
465
* @exception SQLException if a database access error occurs
467
public String getExtraNameCharacters() throws SQLException
469
Driver.debug("getExtraNameCharacters");
474
* Is "ALTER TABLE" with an add column supported?
475
* Yes for PostgreSQL 6.1
478
* @exception SQLException if a database access error occurs
480
public boolean supportsAlterTableWithAddColumn() throws SQLException
482
Driver.debug("supportsAlterTableWithAddColumn " + true);
487
* Is "ALTER TABLE" with a drop column supported?
488
* Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
491
* @exception SQLException if a database access error occurs
493
public boolean supportsAlterTableWithDropColumn() throws SQLException
495
Driver.debug("supportsAlterTableWithDropColumn " + false);
500
* Is column aliasing supported?
502
* <p>If so, the SQL AS clause can be used to provide names for
503
* computed columns or to provide alias names for columns as
504
* required. A JDBC Compliant driver always returns true.
509
* select count(C) as C_COUNT from T group by C;
512
* should return a column named as C_COUNT instead of count(C)
515
* @exception SQLException if a database access error occurs
517
public boolean supportsColumnAliasing() throws SQLException
519
Driver.debug("supportsColumnAliasing " + true);
524
* Are concatenations between NULL and non-NULL values NULL? A
525
* JDBC Compliant driver always returns true
528
* @exception SQLException if a database access error occurs
530
public boolean nullPlusNonNullIsNull() throws SQLException
532
Driver.debug("nullPlusNonNullIsNull " + true);
536
public boolean supportsConvert() throws SQLException
538
// XXX-Not Implemented
539
Driver.debug("supportsConvert " + false);
543
public boolean supportsConvert(int fromType, int toType) throws SQLException
545
// XXX-Not Implemented
546
Driver.debug("supportsConvert " + false);
551
* Are table correlation names supported? A JDBC Compliant
552
* driver always returns true.
554
* @return true if so; false otherwise
555
* @exception SQLException - if a database access error occurs
557
public boolean supportsTableCorrelationNames() throws SQLException
559
Driver.debug("supportsTableCorrelationNames " + true);
564
* If table correlation names are supported, are they restricted to
565
* be different from the names of the tables?
567
* @return true if so; false otherwise
568
* @exception SQLException - if a database access error occurs
570
public boolean supportsDifferentTableCorrelationNames() throws SQLException
572
Driver.debug("supportsDifferentTableCorrelationNames " + false);
577
* Are expressions in "ORDER BY" lists supported?
579
* <br>e.g. select * from t order by a + b;
582
* @exception SQLException if a database access error occurs
584
public boolean supportsExpressionsInOrderBy() throws SQLException
586
Driver.debug("supportsExpressionsInOrderBy " + true);
591
* Can an "ORDER BY" clause use columns not in the SELECT?
594
* @exception SQLException if a database access error occurs
596
public boolean supportsOrderByUnrelated() throws SQLException
598
boolean supportsOrderByUnrelated = connection.haveMinimumServerVersion("6.4");
599
Driver.debug("supportsOrderByUnrelated " + supportsOrderByUnrelated);
600
return supportsOrderByUnrelated;
604
* Is some form of "GROUP BY" clause supported?
605
* I checked it, and yes it is.
608
* @exception SQLException if a database access error occurs
610
public boolean supportsGroupBy() throws SQLException
612
Driver.debug("supportsGroupBy " + true);
617
* Can a "GROUP BY" clause use columns not in the SELECT?
620
* @exception SQLException if a database access error occurs
622
public boolean supportsGroupByUnrelated() throws SQLException
624
boolean supportsGroupByUnrelated = connection.haveMinimumServerVersion("6.4");
625
Driver.debug("supportsGroupByUnrelated " + supportsGroupByUnrelated);
626
return supportsGroupByUnrelated;
630
* Can a "GROUP BY" clause add columns not in the SELECT provided
631
* it specifies all the columns in the SELECT? Does anyone actually
632
* understand what they mean here?
634
* (I think this is a subset of the previous function. -- petere)
637
* @exception SQLException if a database access error occurs
639
public boolean supportsGroupByBeyondSelect() throws SQLException
641
boolean supportsGroupByBeyondSelect = connection.haveMinimumServerVersion("6.4");
642
Driver.debug("supportsGroupByUnrelated " + supportsGroupByBeyondSelect);
643
return supportsGroupByBeyondSelect;
647
* Is the escape character in "LIKE" clauses supported? A
648
* JDBC compliant driver always returns true.
651
* @exception SQLException if a database access error occurs
653
public boolean supportsLikeEscapeClause() throws SQLException
655
boolean supportsLikeEscapeClause = connection.haveMinimumServerVersion("7.1");
656
Driver.debug("supportsLikeEscapeClause " + supportsLikeEscapeClause);
657
return supportsLikeEscapeClause;
661
* Are multiple ResultSets from a single execute supported?
662
* Well, I implemented it, but I dont think this is possible from
663
* the back ends point of view.
666
* @exception SQLException if a database access error occurs
668
public boolean supportsMultipleResultSets() throws SQLException
670
Driver.debug("supportsMultipleResultSets " + false);
675
* Can we have multiple transactions open at once (on different
677
* I guess we can have, since Im relying on it.
680
* @exception SQLException if a database access error occurs
682
public boolean supportsMultipleTransactions() throws SQLException
684
Driver.debug("supportsMultipleTransactions " + true);
689
* Can columns be defined as non-nullable. A JDBC Compliant driver
690
* always returns true.
692
* <p>This changed from false to true in v6.2 of the driver, as this
693
* support was added to the backend.
696
* @exception SQLException if a database access error occurs
698
public boolean supportsNonNullableColumns() throws SQLException
700
Driver.debug("supportsNonNullableColumns true");
705
* Does this driver support the minimum ODBC SQL grammar. This
706
* grammar is defined at:
708
* <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
710
* <p>In Appendix C. From this description, we seem to support the
711
* ODBC minimal (Level 0) grammar.
714
* @exception SQLException if a database access error occurs
716
public boolean supportsMinimumSQLGrammar() throws SQLException
718
Driver.debug("supportsMinimumSQLGrammar TRUE");
723
* Does this driver support the Core ODBC SQL grammar. We need
724
* SQL-92 conformance for this.
727
* @exception SQLException if a database access error occurs
729
public boolean supportsCoreSQLGrammar() throws SQLException
731
Driver.debug("supportsCoreSQLGrammar FALSE ");
736
* Does this driver support the Extended (Level 2) ODBC SQL
737
* grammar. We don't conform to the Core (Level 1), so we can't
738
* conform to the Extended SQL Grammar.
741
* @exception SQLException if a database access error occurs
743
public boolean supportsExtendedSQLGrammar() throws SQLException
745
Driver.debug("supportsExtendedSQLGrammar FALSE");
750
* Does this driver support the ANSI-92 entry level SQL grammar?
751
* All JDBC Compliant drivers must return true. We currently
752
* report false until 'schema' support is added. Then this
753
* should be changed to return true, since we will be mostly
754
* compliant (probably more compliant than many other databases)
755
* And since this is a requirement for all JDBC drivers we
756
* need to get to the point where we can return true.
759
* @exception SQLException if a database access error occurs
761
public boolean supportsANSI92EntryLevelSQL() throws SQLException
763
Driver.debug("supportsANSI92EntryLevelSQL false ");
768
* Does this driver support the ANSI-92 intermediate level SQL
772
* @exception SQLException if a database access error occurs
774
public boolean supportsANSI92IntermediateSQL() throws SQLException
776
Driver.debug("supportsANSI92IntermediateSQL false ");
781
* Does this driver support the ANSI-92 full SQL grammar?
784
* @exception SQLException if a database access error occurs
786
public boolean supportsANSI92FullSQL() throws SQLException
788
Driver.debug("supportsANSI92FullSQL false ");
793
* Is the SQL Integrity Enhancement Facility supported?
794
* I haven't seen this mentioned anywhere, so I guess not
797
* @exception SQLException if a database access error occurs
799
public boolean supportsIntegrityEnhancementFacility() throws SQLException
801
Driver.debug("supportsIntegrityEnhancementFacility false ");
806
* Is some form of outer join supported?
809
* @exception SQLException if a database access error occurs
811
public boolean supportsOuterJoins() throws SQLException
813
boolean supportsOuterJoins = connection.haveMinimumServerVersion("7.1");
814
Driver.debug("supportsOuterJoins " + supportsOuterJoins);
815
return supportsOuterJoins;
819
* Are full nexted outer joins supported?
822
* @exception SQLException if a database access error occurs
824
public boolean supportsFullOuterJoins() throws SQLException
826
boolean supportsFullOuterJoins = connection.haveMinimumServerVersion("7.1");
827
Driver.debug("supportsFullOuterJoins " + supportsFullOuterJoins);
828
return supportsFullOuterJoins;
832
* Is there limited support for outer joins?
835
* @exception SQLException if a database access error occurs
837
public boolean supportsLimitedOuterJoins() throws SQLException
839
boolean supportsLimitedOuterJoins = connection.haveMinimumServerVersion("7.1");
840
Driver.debug("supportsFullOuterJoins " + supportsLimitedOuterJoins);
841
return supportsLimitedOuterJoins;
845
* What is the database vendor's preferred term for "schema"?
846
* PostgreSQL doesn't have schemas, but when it does, we'll use the
849
* @return the vendor term
850
* @exception SQLException if a database access error occurs
852
public String getSchemaTerm() throws SQLException
854
Driver.debug("getSchemaTerm schema");
859
* What is the database vendor's preferred term for "procedure"?
860
* Traditionally, "function" has been used.
862
* @return the vendor term
863
* @exception SQLException if a database access error occurs
865
public String getProcedureTerm() throws SQLException
867
Driver.debug("getProcedureTerm function ");
872
* What is the database vendor's preferred term for "catalog"?
874
* @return the vendor term
875
* @exception SQLException if a database access error occurs
877
public String getCatalogTerm() throws SQLException
879
Driver.debug("getCatalogTerm database ");
884
* Does a catalog appear at the start of a qualified table name?
885
* (Otherwise it appears at the end).
888
* @exception SQLException if a database access error occurs
890
public boolean isCatalogAtStart() throws SQLException
892
// return true here; we return false for every other catalog function
893
// so it won't matter what we return here D.C.
894
Driver.debug("isCatalogAtStart not implemented");
899
* What is the Catalog separator.
901
* @return the catalog separator string
902
* @exception SQLException if a database access error occurs
904
public String getCatalogSeparator() throws SQLException
906
// Give them something to work with here
907
// everything else returns false so it won't matter what we return here D.C.
908
Driver.debug("getCatalogSeparator not implemented ");
913
* Can a schema name be used in a data manipulation statement? Nope.
916
* @exception SQLException if a database access error occurs
918
public boolean supportsSchemasInDataManipulation() throws SQLException
920
Driver.debug("supportsSchemasInDataManipulation false");
925
* Can a schema name be used in a procedure call statement? Nope.
928
* @exception SQLException if a database access error occurs
930
public boolean supportsSchemasInProcedureCalls() throws SQLException
932
Driver.debug("supportsSchemasInProcedureCalls false");
937
* Can a schema be used in a table definition statement? Nope.
940
* @exception SQLException if a database access error occurs
942
public boolean supportsSchemasInTableDefinitions() throws SQLException
944
Driver.debug("supportsSchemasInTableDefinitions false");
949
* Can a schema name be used in an index definition statement?
952
* @exception SQLException if a database access error occurs
954
public boolean supportsSchemasInIndexDefinitions() throws SQLException
956
Driver.debug("supportsSchemasInIndexDefinitions false");
961
* Can a schema name be used in a privilege definition statement?
964
* @exception SQLException if a database access error occurs
966
public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException
968
Driver.debug("supportsSchemasInPrivilegeDefinitions false");
973
* Can a catalog name be used in a data manipulation statement?
976
* @exception SQLException if a database access error occurs
978
public boolean supportsCatalogsInDataManipulation() throws SQLException
980
Driver.debug("supportsCatalogsInDataManipulation false");
985
* Can a catalog name be used in a procedure call statement?
988
* @exception SQLException if a database access error occurs
990
public boolean supportsCatalogsInProcedureCalls() throws SQLException
992
Driver.debug("supportsCatalogsInDataManipulation false");
997
* Can a catalog name be used in a table definition statement?
1000
* @exception SQLException if a database access error occurs
1002
public boolean supportsCatalogsInTableDefinitions() throws SQLException
1004
Driver.debug("supportsCatalogsInTableDefinitions false");
1009
* Can a catalog name be used in an index definition?
1011
* @return true if so
1012
* @exception SQLException if a database access error occurs
1014
public boolean supportsCatalogsInIndexDefinitions() throws SQLException
1016
Driver.debug("supportsCatalogsInIndexDefinitions false");
1021
* Can a catalog name be used in a privilege definition statement?
1023
* @return true if so
1024
* @exception SQLException if a database access error occurs
1026
public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException
1028
Driver.debug("supportsCatalogsInPrivilegeDefinitions false");
1033
* We support cursors for gets only it seems. I dont see a method
1034
* to get a positioned delete.
1036
* @return true if so
1037
* @exception SQLException if a database access error occurs
1039
public boolean supportsPositionedDelete() throws SQLException
1041
Driver.debug("supportsPositionedDelete false");
1042
return false; // For now...
1046
* Is positioned UPDATE supported?
1048
* @return true if so
1049
* @exception SQLException if a database access error occurs
1051
public boolean supportsPositionedUpdate() throws SQLException
1053
Driver.debug("supportsPositionedUpdate false");
1054
return false; // For now...
1058
* Is SELECT for UPDATE supported?
1060
* @return true if so; false otherwise
1061
* @exception SQLException - if a database access error occurs
1063
public boolean supportsSelectForUpdate() throws SQLException
1065
return connection.haveMinimumServerVersion("6.5");
1069
* Are stored procedure calls using the stored procedure escape
1072
* @return true if so; false otherwise
1073
* @exception SQLException - if a database access error occurs
1075
public boolean supportsStoredProcedures() throws SQLException
1081
* Are subqueries in comparison expressions supported? A JDBC
1082
* Compliant driver always returns true.
1084
* @return true if so; false otherwise
1085
* @exception SQLException - if a database access error occurs
1087
public boolean supportsSubqueriesInComparisons() throws SQLException
1093
* Are subqueries in 'exists' expressions supported? A JDBC
1094
* Compliant driver always returns true.
1096
* @return true if so; false otherwise
1097
* @exception SQLException - if a database access error occurs
1099
public boolean supportsSubqueriesInExists() throws SQLException
1105
* Are subqueries in 'in' statements supported? A JDBC
1106
* Compliant driver always returns true.
1108
* @return true if so; false otherwise
1109
* @exception SQLException - if a database access error occurs
1111
public boolean supportsSubqueriesInIns() throws SQLException
1117
* Are subqueries in quantified expressions supported? A JDBC
1118
* Compliant driver always returns true.
1120
* (No idea what this is, but we support a good deal of
1123
* @return true if so; false otherwise
1124
* @exception SQLException - if a database access error occurs
1126
public boolean supportsSubqueriesInQuantifieds() throws SQLException
1132
* Are correlated subqueries supported? A JDBC Compliant driver
1133
* always returns true.
1135
* (a.k.a. subselect in from?)
1137
* @return true if so; false otherwise
1138
* @exception SQLException - if a database access error occurs
1140
public boolean supportsCorrelatedSubqueries() throws SQLException
1142
return connection.haveMinimumServerVersion("7.1");
1146
* Is SQL UNION supported?
1148
* @return true if so
1149
* @exception SQLException if a database access error occurs
1151
public boolean supportsUnion() throws SQLException
1153
return true; // since 6.3
1157
* Is SQL UNION ALL supported?
1159
* @return true if so
1160
* @exception SQLException if a database access error occurs
1162
public boolean supportsUnionAll() throws SQLException
1164
return connection.haveMinimumServerVersion("7.1");
1168
* In PostgreSQL, Cursors are only open within transactions.
1170
* @return true if so
1171
* @exception SQLException if a database access error occurs
1173
public boolean supportsOpenCursorsAcrossCommit() throws SQLException
1179
* Do we support open cursors across multiple transactions?
1181
* @return true if so
1182
* @exception SQLException if a database access error occurs
1184
public boolean supportsOpenCursorsAcrossRollback() throws SQLException
1190
* Can statements remain open across commits? They may, but
1191
* this driver cannot guarentee that. In further reflection.
1192
* we are talking a Statement object here, so the answer is
1193
* yes, since the Statement is only a vehicle to ExecSQL()
1195
* @return true if they always remain open; false otherwise
1196
* @exception SQLException if a database access error occurs
1198
public boolean supportsOpenStatementsAcrossCommit() throws SQLException
1204
* Can statements remain open across rollbacks? They may, but
1205
* this driver cannot guarentee that. In further contemplation,
1206
* we are talking a Statement object here, so the answer is yes,
1207
* since the Statement is only a vehicle to ExecSQL() in Connection
1209
* @return true if they always remain open; false otherwise
1210
* @exception SQLException if a database access error occurs
1212
public boolean supportsOpenStatementsAcrossRollback() throws SQLException
1218
* How many hex characters can you have in an inline binary literal
1220
* @return the max literal length
1221
* @exception SQLException if a database access error occurs
1223
public int getMaxBinaryLiteralLength() throws SQLException
1225
return 0; // no limit
1229
* What is the maximum length for a character literal
1230
* I suppose it is 8190 (8192 - 2 for the quotes)
1232
* @return the max literal length
1233
* @exception SQLException if a database access error occurs
1235
public int getMaxCharLiteralLength() throws SQLException
1237
return 0; // no limit
1241
* Whats the limit on column name length. The description of
1242
* pg_class would say '32' (length of pg_class.relname) - we
1243
* should probably do a query for this....but....
1245
* @return the maximum column name length
1246
* @exception SQLException if a database access error occurs
1248
public int getMaxColumnNameLength() throws SQLException
1254
* What is the maximum number of columns in a "GROUP BY" clause?
1256
* @return the max number of columns
1257
* @exception SQLException if a database access error occurs
1259
public int getMaxColumnsInGroupBy() throws SQLException
1261
return 0; // no limit
1265
* What's the maximum number of columns allowed in an index?
1266
* 6.0 only allowed one column, but 6.1 introduced multi-column
1267
* indices, so, theoretically, its all of them.
1269
* @return max number of columns
1270
* @exception SQLException if a database access error occurs
1272
public int getMaxColumnsInIndex() throws SQLException
1274
return getMaxColumnsInTable();
1278
* What's the maximum number of columns in an "ORDER BY clause?
1280
* @return the max columns
1281
* @exception SQLException if a database access error occurs
1283
public int getMaxColumnsInOrderBy() throws SQLException
1285
return 0; // no limit
1289
* What is the maximum number of columns in a "SELECT" list?
1291
* @return the max columns
1292
* @exception SQLException if a database access error occurs
1294
public int getMaxColumnsInSelect() throws SQLException
1296
return 0; // no limit
1300
* What is the maximum number of columns in a table? From the
1301
* CREATE TABLE reference page...
1303
* <p>"The new class is created as a heap with no initial data. A
1304
* class can have no more than 1600 attributes (realistically,
1305
* this is limited by the fact that tuple sizes must be less than
1308
* @return the max columns
1309
* @exception SQLException if a database access error occurs
1311
public int getMaxColumnsInTable() throws SQLException
1317
* How many active connection can we have at a time to this
1318
* database? Well, since it depends on postmaster, which just
1319
* does a listen() followed by an accept() and fork(), its
1320
* basically very high. Unless the system runs out of processes,
1321
* it can be 65535 (the number of aux. ports on a TCP/IP system).
1322
* I will return 8192 since that is what even the largest system
1323
* can realistically handle,
1325
* @return the maximum number of connections
1326
* @exception SQLException if a database access error occurs
1328
public int getMaxConnections() throws SQLException
1334
* What is the maximum cursor name length (the same as all
1335
* the other F***** identifiers!)
1337
* @return max cursor name length in bytes
1338
* @exception SQLException if a database access error occurs
1340
public int getMaxCursorNameLength() throws SQLException
1346
* Retrieves the maximum number of bytes for an index, including all
1347
* of the parts of the index.
1349
* @return max index length in bytes, which includes the composite
1350
* of all the constituent parts of the index; a result of zero means
1351
* that there is no limit or the limit is not known
1352
* @exception SQLException if a database access error occurs
1354
public int getMaxIndexLength() throws SQLException
1356
return 0; // no limit (larger than an int anyway)
1359
public int getMaxSchemaNameLength() throws SQLException
1361
// XXX-Not Implemented
1366
* What is the maximum length of a procedure name?
1367
* (length of pg_proc.proname used) - again, I really
1368
* should do a query here to get it.
1370
* @return the max name length in bytes
1371
* @exception SQLException if a database access error occurs
1373
public int getMaxProcedureNameLength() throws SQLException
1378
public int getMaxCatalogNameLength() throws SQLException
1380
// XXX-Not Implemented
1385
* What is the maximum length of a single row?
1387
* @return max row size in bytes
1388
* @exception SQLException if a database access error occurs
1390
public int getMaxRowSize() throws SQLException
1392
if (connection.haveMinimumServerVersion("7.1"))
1393
return 1073741824; // 1 GB
1395
return 8192; // XXX could be altered
1399
* Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
1400
* blobs? We don't handle blobs yet
1402
* @return true if so
1403
* @exception SQLException if a database access error occurs
1405
public boolean doesMaxRowSizeIncludeBlobs() throws SQLException
1411
* What is the maximum length of a SQL statement?
1413
* @return max length in bytes
1414
* @exception SQLException if a database access error occurs
1416
public int getMaxStatementLength() throws SQLException
1418
if (connection.haveMinimumServerVersion("7.0"))
1419
return 0; // actually whatever fits in size_t
1425
* How many active statements can we have open at one time to
1426
* this database? Basically, since each Statement downloads
1427
* the results as the query is executed, we can have many. However,
1428
* we can only really have one statement per connection going
1429
* at once (since they are executed serially) - so we return
1432
* @return the maximum
1433
* @exception SQLException if a database access error occurs
1435
public int getMaxStatements() throws SQLException
1441
* What is the maximum length of a table name? This was found
1442
* from pg_class.relname length
1444
* @return max name length in bytes
1445
* @exception SQLException if a database access error occurs
1447
public int getMaxTableNameLength() throws SQLException
1453
* What is the maximum number of tables that can be specified
1456
* @return the maximum
1457
* @exception SQLException if a database access error occurs
1459
public int getMaxTablesInSelect() throws SQLException
1461
return 0; // no limit
1465
* What is the maximum length of a user name? Well, we generally
1466
* use UNIX like user names in PostgreSQL, so I think this would
1467
* be 8. However, showing the schema for pg_user shows a length
1468
* for username of 32.
1470
* @return the max name length in bytes
1471
* @exception SQLException if a database access error occurs
1473
public int getMaxUserNameLength() throws SQLException
1480
* What is the database's default transaction isolation level? We
1481
* do not support this, so all transactions are SERIALIZABLE.
1483
* @return the default isolation level
1484
* @exception SQLException if a database access error occurs
1487
public int getDefaultTransactionIsolation() throws SQLException
1489
return Connection.TRANSACTION_READ_COMMITTED;
1493
* Are transactions supported? If not, commit and rollback are noops
1494
* and the isolation level is TRANSACTION_NONE. We do support
1497
* @return true if transactions are supported
1498
* @exception SQLException if a database access error occurs
1500
public boolean supportsTransactions() throws SQLException
1506
* Does the database support the given transaction isolation level?
1507
* We only support TRANSACTION_SERIALIZABLE and TRANSACTION_READ_COMMITTED
1509
* @param level the values are defined in java.sql.Connection
1510
* @return true if so
1511
* @exception SQLException if a database access error occurs
1514
public boolean supportsTransactionIsolationLevel(int level) throws SQLException
1516
if (level == Connection.TRANSACTION_SERIALIZABLE ||
1517
level == Connection.TRANSACTION_READ_COMMITTED)
1524
* Are both data definition and data manipulation transactions
1527
* @return true if so
1528
* @exception SQLException if a database access error occurs
1530
public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException
1536
* Are only data manipulation statements withing a transaction
1539
* @return true if so
1540
* @exception SQLException if a database access error occurs
1542
public boolean supportsDataManipulationTransactionsOnly() throws SQLException
1548
* Does a data definition statement within a transaction force
1549
* the transaction to commit? I think this means something like:
1552
* CREATE TABLE T (A INT);
1553
* INSERT INTO T (A) VALUES (2);
1555
* UPDATE T SET A = A + 1;
1556
* CREATE TABLE X (A INT);
1557
* SELECT A FROM T INTO X;
1561
* does the CREATE TABLE call cause a commit? The answer is no.
1563
* @return true if so
1564
* @exception SQLException if a database access error occurs
1566
public boolean dataDefinitionCausesTransactionCommit() throws SQLException
1572
* Is a data definition statement within a transaction ignored?
1573
* It seems to be (from experiment in previous method)
1575
* @return true if so
1576
* @exception SQLException if a database access error occurs
1578
public boolean dataDefinitionIgnoredInTransactions() throws SQLException
1584
* Get a description of stored procedures available in a catalog
1586
* <p>Only procedure descriptions matching the schema and procedure
1587
* name criteria are returned. They are ordered by PROCEDURE_SCHEM
1588
* and PROCEDURE_NAME
1590
* <p>Each procedure description has the following columns:
1592
* <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
1593
* <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
1594
* <li><b>PROCEDURE_NAME</b> String => procedure name
1595
* <li><b>Field 4</b> reserved (make it null)
1596
* <li><b>Field 5</b> reserved (make it null)
1597
* <li><b>Field 6</b> reserved (make it null)
1598
* <li><b>REMARKS</b> String => explanatory comment on the procedure
1599
* <li><b>PROCEDURE_TYPE</b> short => kind of procedure
1601
* <li> procedureResultUnknown - May return a result
1602
* <li> procedureNoResult - Does not return a result
1603
* <li> procedureReturnsResult - Returns a result
1607
* @param catalog - a catalog name; "" retrieves those without a
1608
* catalog; null means drop catalog name from criteria
1609
* @param schemaParrern - a schema name pattern; "" retrieves those
1610
* without a schema - we ignore this parameter
1611
* @param procedureNamePattern - a procedure name pattern
1612
* @return ResultSet - each row is a procedure description
1613
* @exception SQLException if a database access error occurs
1615
public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
1617
// the field descriptors for the new ResultSet
1618
Field f[] = new Field[8];
1619
java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
1620
Vector v = new Vector(); // The new ResultSet tuple stuff
1622
f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
1623
f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
1624
f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
1625
f[3] = f[4] = f[5] = new Field(connection, "reserved", iVarcharOid, 32); // null; // reserved, must be null for now
1626
f[6] = new Field(connection, "REMARKS", iVarcharOid, 8192);
1627
f[7] = new Field(connection, "PROCEDURE_TYPE", iInt2Oid, 2);
1629
// If the pattern is null, then set it to the default
1630
if (procedureNamePattern == null)
1631
procedureNamePattern = "%";
1633
r = connection.ExecSQL("select proname, proretset from pg_proc where proname like '" + procedureNamePattern.toLowerCase() + "' order by proname");
1637
byte[][] tuple = new byte[8][0];
1639
tuple[0] = null; // Catalog name
1640
tuple[1] = null; // Schema name
1641
tuple[2] = r.getBytes(1); // Procedure name
1642
tuple[3] = tuple[4] = tuple[5] = null; // Reserved
1645
if (r.getBoolean(2))
1646
tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureReturnsResult).getBytes();
1648
tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureNoResult).getBytes();
1650
v.addElement(tuple);
1652
return new ResultSet(connection, f, v, "OK", 1);
1656
* Get a description of a catalog's stored procedure parameters
1657
* and result columns.
1659
* <p>Only descriptions matching the schema, procedure and parameter
1660
* name criteria are returned. They are ordered by PROCEDURE_SCHEM
1661
* and PROCEDURE_NAME. Within this, the return value, if any, is
1662
* first. Next are the parameter descriptions in call order. The
1663
* column descriptions follow in column number order.
1665
* <p>Each row in the ResultSet is a parameter description or column
1666
* description with the following fields:
1668
* <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
1669
* <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
1670
* <li><b>PROCEDURE_NAME</b> String => procedure name
1671
* <li><b>COLUMN_NAME</b> String => column/parameter name
1672
* <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
1673
* <ul><li>procedureColumnUnknown - nobody knows
1674
* <li>procedureColumnIn - IN parameter
1675
* <li>procedureColumnInOut - INOUT parameter
1676
* <li>procedureColumnOut - OUT parameter
1677
* <li>procedureColumnReturn - procedure return value
1678
* <li>procedureColumnResult - result column in ResultSet
1680
* <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
1681
* <li><b>TYPE_NAME</b> String => SQL type name
1682
* <li><b>PRECISION</b> int => precision
1683
* <li><b>LENGTH</b> int => length in bytes of data
1684
* <li><b>SCALE</b> short => scale
1685
* <li><b>RADIX</b> short => radix
1686
* <li><b>NULLABLE</b> short => can it contain NULL?
1687
* <ul><li>procedureNoNulls - does not allow NULL values
1688
* <li>procedureNullable - allows NULL values
1689
* <li>procedureNullableUnknown - nullability unknown
1690
* <li><b>REMARKS</b> String => comment describing parameter/column
1692
* @param catalog This is ignored in org.postgresql, advise this is set to null
1693
* @param schemaPattern This is ignored in org.postgresql, advise this is set to null
1694
* @param procedureNamePattern a procedure name pattern
1695
* @param columnNamePattern a column name pattern
1696
* @return each row is a stored procedure parameter or column description
1697
* @exception SQLException if a database-access error occurs
1698
* @see #getSearchStringEscape
1700
// Implementation note: This is required for Borland's JBuilder to work
1701
public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
1703
if (procedureNamePattern == null)
1704
procedureNamePattern = "%";
1706
if (columnNamePattern == null)
1707
columnNamePattern = "%";
1709
// for now, this returns an empty result set.
1710
Field f[] = new Field[13];
1711
ResultSet r; // ResultSet for the SQL query that we need to do
1712
Vector v = new Vector(); // The new ResultSet tuple stuff
1714
f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
1715
f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
1716
f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
1717
f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
1718
f[4] = new Field(connection, "COLUMN_TYPE", iInt2Oid, 2);
1719
f[5] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
1720
f[6] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
1721
f[7] = new Field(connection, "PRECISION", iInt4Oid, 4);
1722
f[8] = new Field(connection, "LENGTH", iInt4Oid, 4);
1723
f[9] = new Field(connection, "SCALE", iInt2Oid, 2);
1724
f[10] = new Field(connection, "RADIX", iInt2Oid, 2);
1725
f[11] = new Field(connection, "NULLABLE", iInt2Oid, 2);
1726
f[12] = new Field(connection, "REMARKS", iVarcharOid, 32);
1728
// add query loop here
1730
return new ResultSet(connection, f, v, "OK", 1);
1734
* Get a description of tables available in a catalog.
1736
* <p>Only table descriptions matching the catalog, schema, table
1737
* name and type criteria are returned. They are ordered by
1738
* TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1740
* <p>Each table description has the following columns:
1743
* <li><b>TABLE_CAT</b> String => table catalog (may be null)
1744
* <li><b>TABLE_SCHEM</b> String => table schema (may be null)
1745
* <li><b>TABLE_NAME</b> String => table name
1746
* <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
1747
* "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
1748
* TEMPORARY", "ALIAS", "SYNONYM".
1749
* <li><b>REMARKS</b> String => explanatory comment on the table
1752
* <p>The valid values for the types parameter are:
1753
* "TABLE", "INDEX", "SEQUENCE", "SYSTEM TABLE" and "SYSTEM INDEX"
1755
* @param catalog a catalog name; For org.postgresql, this is ignored, and
1756
* should be set to null
1757
* @param schemaPattern a schema name pattern; For org.postgresql, this is ignored, and
1758
* should be set to null
1759
* @param tableNamePattern a table name pattern. For all tables this should be "%"
1760
* @param types a list of table types to include; null returns
1762
* @return each row is a table description
1763
* @exception SQLException if a database-access error occurs.
1765
public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
1767
// Handle default value for types
1769
types = defaultTableTypes;
1771
if (tableNamePattern == null)
1772
tableNamePattern = "%";
1774
// the field descriptors for the new ResultSet
1775
Field f[] = new Field[5];
1776
java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
1777
Vector v = new Vector(); // The new ResultSet tuple stuff
1779
f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
1780
f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
1781
f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
1782
f[3] = new Field(connection, "TABLE_TYPE", iVarcharOid, 32);
1783
f[4] = new Field(connection, "REMARKS", iVarcharOid, 32);
1785
// Now form the query
1786
StringBuffer sql = new StringBuffer("select relname,oid,relkind from pg_class where (");
1788
boolean notFirst = false;
1789
for (int i = 0;i < types.length;i++)
1791
for (int j = 0;j < getTableTypes.length;j++)
1792
if (getTableTypes[j][0].equals(types[i]))
1796
sql.append(getTableTypes[j][1]);
1801
// Added by Stefan Andreasen <stefan@linux.kapow.dk>
1802
// Now take the pattern into account
1803
sql.append(") and relname like '");
1804
sql.append(tableNamePattern.toLowerCase());
1805
sql.append("' order by relkind, relname");
1807
// Now run the query
1808
r = connection.ExecSQL(sql.toString());
1812
byte[][] tuple = new byte[5][0];
1814
// Fetch the description for the table (if any)
1815
String getDescriptionStatement =
1816
connection.haveMinimumServerVersion("7.2") ?
1817
"select obj_description(" + r.getInt(2) + ",'pg_class')" :
1818
"select description from pg_description where objoid=" + r.getInt(2);
1820
java.sql.ResultSet dr = connection.ExecSQL(getDescriptionStatement);
1822
byte remarks[] = null;
1824
if (((org.postgresql.ResultSet)dr).getTupleCount() == 1)
1827
remarks = dr.getBytes(1);
1832
switch (r.getBytes(3)[0])
1841
relKind = "SEQUENCE";
1850
tuple[0] = null; // Catalog name
1851
tuple[1] = null; // Schema name
1852
tuple[2] = r.getBytes(1); // Table name
1853
tuple[3] = (relKind == null) ? null : relKind.getBytes(); // Table type
1854
tuple[4] = remarks; // Remarks
1855
v.addElement(tuple);
1858
return new ResultSet(connection, f, v, "OK", 1);
1861
// This array contains the valid values for the types argument
1864
// Each supported type consists of it's name, and the sql where
1865
// clause to retrieve that value.
1867
// IMPORTANT: the query must be enclosed in ( )
1868
private static final String getTableTypes[][] = {
1869
{"TABLE", "(relkind='r' and relhasrules='f' and relname !~ '^pg_' and relname !~ '^xinv')"},
1870
{"VIEW", "(relkind='v' and relname !~ '^pg_')"},
1871
{"INDEX", "(relkind='i' and relname !~ '^pg_')"},
1872
{"SEQUENCE", "(relkind='S' and relname !~ '^pg_')"},
1873
{"SYSTEM TABLE", "(relkind='r' and relname ~ '^pg_')"},
1874
{"SYSTEM INDEX", "(relkind='i' and relname ~ '^pg_')"}
1877
// These are the default tables, used when NULL is passed to getTables
1878
// The choice of these provide the same behaviour as psql's \d
1879
private static final String defaultTableTypes[] = {
1880
"TABLE", "VIEW", "INDEX", "SEQUENCE"
1884
* Get the schema names available in this database. The results
1885
* are ordered by schema name.
1887
* <P>The schema column is:
1889
* <LI><B>TABLE_SCHEM</B> String => schema name
1892
* @return ResultSet each row has a single String column that is a
1895
public java.sql.ResultSet getSchemas() throws SQLException
1897
// We don't use schemas, so we simply return a single schema name "".
1899
Field f[] = new Field[1];
1900
Vector v = new Vector();
1901
byte[][] tuple = new byte[1][0];
1902
f[0] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
1903
tuple[0] = "".getBytes();
1904
v.addElement(tuple);
1905
return new ResultSet(connection, f, v, "OK", 1);
1909
* Get the catalog names available in this database. The results
1910
* are ordered by catalog name.
1912
* <P>The catalog column is:
1914
* <LI><B>TABLE_CAT</B> String => catalog name
1917
* @return ResultSet each row has a single String column that is a
1920
public java.sql.ResultSet getCatalogs() throws SQLException
1922
return connection.createStatement().executeQuery("select datname as TABLE_CAT from pg_database;");
1926
* Get the table types available in this database. The results
1927
* are ordered by table type.
1929
* <P>The table type is:
1931
* <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1932
* "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1933
* "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1936
* @return ResultSet each row has a single String column that is a
1939
public java.sql.ResultSet getTableTypes() throws SQLException
1941
Field f[] = new Field[1];
1942
Vector v = new Vector();
1943
f[0] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, 32);
1944
for (int i = 0;i < getTableTypes.length;i++)
1946
byte[][] tuple = new byte[2][0];
1947
tuple[0] = getTableTypes[i][0].getBytes();
1948
v.addElement(tuple);
1950
return new ResultSet(connection, f, v, "OK", 1);
1954
* Get a description of table columns available in a catalog.
1956
* <P>Only column descriptions matching the catalog, schema, table
1957
* and column name criteria are returned. They are ordered by
1958
* TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1960
* <P>Each column description has the following columns:
1962
* <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1963
* <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1964
* <LI><B>TABLE_NAME</B> String => table name
1965
* <LI><B>COLUMN_NAME</B> String => column name
1966
* <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1967
* <LI><B>TYPE_NAME</B> String => Data source dependent type name
1968
* <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1969
* types this is the maximum number of characters, for numeric or
1970
* decimal types this is precision.
1971
* <LI><B>BUFFER_LENGTH</B> is not used.
1972
* <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1973
* <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1974
* <LI><B>NULLABLE</B> int => is NULL allowed?
1976
* <LI> columnNoNulls - might not allow NULL values
1977
* <LI> columnNullable - definitely allows NULL values
1978
* <LI> columnNullableUnknown - nullability unknown
1980
* <LI><B>REMARKS</B> String => comment describing column (may be null)
1981
* <LI><B>COLUMN_DEF</B> String => default value (may be null)
1982
* <LI><B>SQL_DATA_TYPE</B> int => unused
1983
* <LI><B>SQL_DATETIME_SUB</B> int => unused
1984
* <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1985
* maximum number of bytes in the column
1986
* <LI><B>ORDINAL_POSITION</B> int => index of column in table
1988
* <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1989
* does not allow NULL values; "YES" means the column might
1990
* allow NULL values. An empty string means nobody knows.
1993
* @param catalog a catalog name; "" retrieves those without a catalog
1994
* @param schemaPattern a schema name pattern; "" retrieves those
1996
* @param tableNamePattern a table name pattern
1997
* @param columnNamePattern a column name pattern
1998
* @return ResultSet each row is a column description
1999
* @see #getSearchStringEscape
2001
public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
2003
Vector v = new Vector(); // The new ResultSet tuple stuff
2004
Field f[] = new Field[18]; // The field descriptors for the new ResultSet
2006
f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
2007
f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
2008
f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
2009
f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
2010
f[4] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
2011
f[5] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
2012
f[6] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
2013
f[7] = new Field(connection, "BUFFER_LENGTH", iVarcharOid, 32);
2014
f[8] = new Field(connection, "DECIMAL_DIGITS", iInt4Oid, 4);
2015
f[9] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
2016
f[10] = new Field(connection, "NULLABLE", iInt4Oid, 4);
2017
f[11] = new Field(connection, "REMARKS", iVarcharOid, 32);
2018
f[12] = new Field(connection, "COLUMN_DEF", iVarcharOid, 32);
2019
f[13] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
2020
f[14] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
2021
f[15] = new Field(connection, "CHAR_OCTET_LENGTH", iVarcharOid, 32);
2022
f[16] = new Field(connection, "ORDINAL_POSITION", iInt4Oid, 4);
2023
f[17] = new Field(connection, "IS_NULLABLE", iVarcharOid, 32);
2025
StringBuffer sql = new StringBuffer(512);
2027
/* Build a >= 7.1 SQL statement to list all columns */
2028
sql.append("select " +
2029
(connection.haveMinimumServerVersion("7.2") ? "a.attrelid, " : "a.oid, ") +
2039
/* Use the new col_description in 7.2 or an additional outer join in 7.1 */
2040
(connection.haveMinimumServerVersion("7.2") ? "col_description(a.attrelid, a.attnum) " : "e.description ") +
2043
" (pg_class c inner join pg_attribute a on" +
2045
" a.attrelid=c.oid");
2047
if ((tableNamePattern != null) && ! tableNamePattern.equals("%"))
2049
sql.append(" and c.relname like \'" + tableNamePattern + "\'");
2052
if ((columnNamePattern != null) && ! columnNamePattern.equals("%"))
2054
sql.append(" and a.attname like \'" + columnNamePattern + "\'");
2058
" and a.attnum > 0" +
2060
" ) inner join pg_type t on" +
2062
" t.oid = a.atttypid" +
2065
" left outer join pg_attrdef d on" +
2067
" c.oid = d.adrelid" +
2068
" and a.attnum = d.adnum" +
2071
if (!connection.haveMinimumServerVersion("7.2"))
2075
" left outer join pg_description e on" +
2077
" e.objoid = a.oid" +
2081
sql.append("order by" +
2082
" c.relname, a.attnum");
2084
java.sql.ResultSet r = connection.ExecSQL(sql.toString());
2087
byte[][] tuple = new byte[18][0];
2089
String nullFlag = r.getString(6);
2090
String typname = r.getString(10);
2092
tuple[0] = null; // Catalog name, not supported
2093
tuple[1] = null; // Schema name, not supported
2094
tuple[2] = r.getBytes(2); // Table name
2095
tuple[3] = r.getBytes(3); // Column name
2096
tuple[4] = Integer.toString(connection.getSQLType(typname)).getBytes(); // Data type
2097
tuple[5] = typname.getBytes(); // Type name
2100
// Looking at the psql source,
2101
// I think the length of a varchar as specified when the table was created
2102
// should be extracted from atttypmod which contains this length + sizeof(int32)
2103
if (typname.equals("bpchar") || typname.equals("varchar"))
2105
int atttypmod = r.getInt(8);
2106
tuple[6] = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0).getBytes();
2110
tuple[6] = r.getBytes(7);
2113
tuple[7] = null; // Buffer length
2114
// Decimal digits = scale
2115
// From the source (see e.g. backend/utils/adt/numeric.c,
2116
// function numeric()) the scale and precision can be calculated
2117
// from the typmod value.
2118
if (typname.equals("numeric") || typname.equals("decimal"))
2120
int attypmod = r.getInt(8);
2122
Integer.toString((attypmod - VARHDRSZ) & 0xffff).getBytes();
2125
tuple[8] = "0".getBytes();
2126
tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
2127
tuple[10] = Integer.toString(nullFlag.equals("f") ?
2128
java.sql.DatabaseMetaData.columnNullable :
2129
java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
2130
tuple[11] = r.getBytes(11); // Description (if any)
2131
tuple[12] = r.getBytes(9); // Column default
2132
tuple[13] = null; // sql data type (unused)
2133
tuple[14] = null; // sql datetime sub (unused)
2134
tuple[15] = tuple[6]; // char octet length
2135
tuple[16] = r.getBytes(5); // ordinal position
2136
tuple[17] = (nullFlag.equals("f") ? "YES" : "NO").getBytes(); // Is nullable
2138
v.addElement(tuple);
2142
return new ResultSet(connection, f, v, "OK", 1);
2146
* Get a description of the access rights for a table's columns.
2148
* <P>Only privileges matching the column name criteria are
2149
* returned. They are ordered by COLUMN_NAME and PRIVILEGE.
2151
* <P>Each privilige description has the following columns:
2153
* <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2154
* <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2155
* <LI><B>TABLE_NAME</B> String => table name
2156
* <LI><B>COLUMN_NAME</B> String => column name
2157
* <LI><B>GRANTOR</B> => grantor of access (may be null)
2158
* <LI><B>GRANTEE</B> String => grantee of access
2159
* <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2160
* INSERT, UPDATE, REFRENCES, ...)
2161
* <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2162
* to grant to others; "NO" if not; null if unknown
2165
* @param catalog a catalog name; "" retrieves those without a catalog
2166
* @param schema a schema name; "" retrieves those without a schema
2167
* @param table a table name
2168
* @param columnNamePattern a column name pattern
2169
* @return ResultSet each row is a column privilege description
2170
* @see #getSearchStringEscape
2172
public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
2174
Field f[] = new Field[8];
2175
Vector v = new Vector();
2180
if (columnNamePattern == null)
2181
columnNamePattern = "%";
2183
columnNamePattern = columnNamePattern.toLowerCase();
2185
f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
2186
f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
2187
f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
2188
f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
2189
f[4] = new Field(connection, "GRANTOR", iVarcharOid, 32);
2190
f[5] = new Field(connection, "GRANTEE", iVarcharOid, 32);
2191
f[6] = new Field(connection, "PRIVILEGE", iVarcharOid, 32);
2192
f[7] = new Field(connection, "IS_GRANTABLE", iVarcharOid, 32);
2194
// This is taken direct from the psql source
2195
java.sql.ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner and relname like '" + table.toLowerCase() + "' ORDER BY relname");
2198
byte[][] tuple = new byte[8][0];
2199
tuple[0] = tuple[1] = "".getBytes();
2200
DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\"");
2202
// For now, don't add to the result as relacl needs to be processed.
2203
//v.addElement(tuple);
2206
return new ResultSet(connection, f, v, "OK", 1);
2210
* Get a description of the access rights for each table available
2213
* This method is currently unimplemented.
2215
* <P>Only privileges matching the schema and table name
2216
* criteria are returned. They are ordered by TABLE_SCHEM,
2217
* TABLE_NAME, and PRIVILEGE.
2219
* <P>Each privilige description has the following columns:
2221
* <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2222
* <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2223
* <LI><B>TABLE_NAME</B> String => table name
2224
* <LI><B>COLUMN_NAME</B> String => column name
2225
* <LI><B>GRANTOR</B> => grantor of access (may be null)
2226
* <LI><B>GRANTEE</B> String => grantee of access
2227
* <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2228
* INSERT, UPDATE, REFRENCES, ...)
2229
* <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2230
* to grant to others; "NO" if not; null if unknown
2233
* @param catalog a catalog name; "" retrieves those without a catalog
2234
* @param schemaPattern a schema name pattern; "" retrieves those
2236
* @param tableNamePattern a table name pattern
2237
* @return ResultSet each row is a table privilege description
2238
* @see #getSearchStringEscape
2240
public java.sql.ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException
2242
Field f[] = new Field[8];
2243
Vector v = new Vector();
2245
if (tableNamePattern == null)
2246
tableNamePattern = "%";
2248
f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
2249
f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
2250
f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
2251
f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
2252
f[4] = new Field(connection, "GRANTOR", iVarcharOid, 32);
2253
f[5] = new Field(connection, "GRANTEE", iVarcharOid, 32);
2254
f[6] = new Field(connection, "PRIVILEGE", iVarcharOid, 32);
2255
f[7] = new Field(connection, "IS_GRANTABLE", iVarcharOid, 32);
2257
// This is taken direct from the psql source
2258
java.sql.ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner and relname like '" + tableNamePattern.toLowerCase() + "' ORDER BY relname");
2261
byte[][] tuple = new byte[8][0];
2262
tuple[0] = tuple[1] = "".getBytes();
2263
DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\"");
2265
// For now, don't add to the result as relacl needs to be processed.
2266
//v.addElement(tuple);
2269
return new ResultSet(connection, f, v, "OK", 1);
2273
* Get a description of a table's optimal set of columns that
2274
* uniquely identifies a row. They are ordered by SCOPE.
2276
* This method is currently not implemented.
2278
* <P>Each column description has the following columns:
2280
* <LI><B>SCOPE</B> short => actual scope of result
2282
* <LI> bestRowTemporary - very temporary, while using row
2283
* <LI> bestRowTransaction - valid for remainder of current transaction
2284
* <LI> bestRowSession - valid for remainder of current session
2286
* <LI><B>COLUMN_NAME</B> String => column name
2287
* <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2288
* <LI><B>TYPE_NAME</B> String => Data source dependent type name
2289
* <LI><B>COLUMN_SIZE</B> int => precision
2290
* <LI><B>BUFFER_LENGTH</B> int => not used
2291
* <LI><B>DECIMAL_DIGITS</B> short => scale
2292
* <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2293
* like an Oracle ROWID
2295
* <LI> bestRowUnknown - may or may not be pseudo column
2296
* <LI> bestRowNotPseudo - is NOT a pseudo column
2297
* <LI> bestRowPseudo - is a pseudo column
2301
* @param catalog a catalog name; "" retrieves those without a catalog
2302
* @param schema a schema name; "" retrieves those without a schema
2303
* @param table a table name
2304
* @param scope the scope of interest; use same values as SCOPE
2305
* @param nullable include columns that are nullable?
2306
* @return ResultSet each row is a column description
2308
// Implementation note: This is required for Borland's JBuilder to work
2309
public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
2311
// for now, this returns an empty result set.
2312
Field f[] = new Field[8];
2313
ResultSet r; // ResultSet for the SQL query that we need to do
2314
Vector v = new Vector(); // The new ResultSet tuple stuff
2316
f[0] = new Field(connection, "SCOPE", iInt2Oid, 2);
2317
f[1] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
2318
f[2] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
2319
f[3] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
2320
f[4] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
2321
f[5] = new Field(connection, "BUFFER_LENGTH", iInt4Oid, 4);
2322
f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
2323
f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
2325
return new ResultSet(connection, f, v, "OK", 1);
2329
* Get a description of a table's columns that are automatically
2330
* updated when any value in a row is updated. They are
2333
* This method is currently unimplemented.
2335
* <P>Each column description has the following columns:
2337
* <LI><B>SCOPE</B> short => is not used
2338
* <LI><B>COLUMN_NAME</B> String => column name
2339
* <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2340
* <LI><B>TYPE_NAME</B> String => Data source dependent type name
2341
* <LI><B>COLUMN_SIZE</B> int => precision
2342
* <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
2343
* <LI><B>DECIMAL_DIGITS</B> short => scale
2344
* <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2345
* like an Oracle ROWID
2347
* <LI> versionColumnUnknown - may or may not be pseudo column
2348
* <LI> versionColumnNotPseudo - is NOT a pseudo column
2349
* <LI> versionColumnPseudo - is a pseudo column
2353
* @param catalog a catalog name; "" retrieves those without a catalog
2354
* @param schema a schema name; "" retrieves those without a schema
2355
* @param table a table name
2356
* @return ResultSet each row is a column description
2358
public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException
2360
throw org.postgresql.Driver.notImplemented();
2364
* Get a description of a table's primary key columns. They
2365
* are ordered by COLUMN_NAME.
2367
* <P>Each column description has the following columns:
2369
* <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2370
* <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2371
* <LI><B>TABLE_NAME</B> String => table name
2372
* <LI><B>COLUMN_NAME</B> String => column name
2373
* <LI><B>KEY_SEQ</B> short => sequence number within primary key
2374
* <LI><B>PK_NAME</B> String => primary key name (may be null)
2377
* @param catalog a catalog name; "" retrieves those without a catalog
2378
* @param schema a schema name pattern; "" retrieves those
2380
* @param table a table name
2381
* @return ResultSet each row is a primary key column description
2383
public java.sql.ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException
2385
return connection.createStatement().executeQuery("SELECT " +
2386
"'' as TABLE_CAT," +
2387
"'' AS TABLE_SCHEM," +
2388
"bc.relname AS TABLE_NAME," +
2389
"a.attname AS COLUMN_NAME," +
2390
"a.attnum as KEY_SEQ," +
2391
"ic.relname as PK_NAME " +
2392
" FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a" +
2393
" WHERE bc.relkind = 'r' " + // -- not indices
2394
" and upper(bc.relname) = upper('" + table + "')" +
2395
" and i.indrelid = bc.oid" +
2396
" and i.indexrelid = ic.oid" +
2397
" and ic.oid = a.attrelid" +
2398
" and i.indisprimary='t' " +
2399
" ORDER BY table_name, pk_name, key_seq"
2403
private java.sql.ResultSet getImportedExportedKeys(String catalog, String schema, String primaryTable, String foreignTable) throws SQLException
2405
Field f[] = new Field[14];
2407
f[0] = new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
2408
f[1] = new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
2409
f[2] = new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
2410
f[3] = new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
2411
f[4] = new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
2412
f[5] = new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
2413
f[6] = new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
2414
f[7] = new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
2415
f[8] = new Field(connection, "KEY_SEQ", iInt2Oid, 2);
2416
f[9] = new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
2417
f[10] = new Field(connection, "DELETE_RULE", iInt2Oid, 2);
2418
f[11] = new Field(connection, "FK_NAME", iVarcharOid, 32);
2419
f[12] = new Field(connection, "PK_NAME", iVarcharOid, 32);
2420
f[13] = new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
2422
java.sql.ResultSet rs = connection.ExecSQL("SELECT c.relname,c2.relname,"
2423
+ "t.tgconstrname,ic.relname,"
2424
+ "t.tgdeferrable,t.tginitdeferred,"
2425
+ "t.tgnargs,t.tgargs,p.proname "
2426
+ "FROM pg_trigger t,pg_class c,pg_class c2,"
2427
+ "pg_class ic,pg_proc p, pg_index i "
2428
+ "WHERE t.tgrelid=c.oid AND t.tgconstrrelid=c2.oid "
2429
+ "AND t.tgfoid=p.oid AND tgisconstraint "
2430
+ ((primaryTable != null) ? "AND c.relname='" + primaryTable + "' " : "")
2431
+ ((foreignTable != null) ? "AND c2.relname='" + foreignTable + "' " : "")
2432
+ "AND i.indrelid=c.oid "
2433
+ "AND i.indexrelid=ic.oid AND i.indisprimary "
2434
+ "ORDER BY c.relname,c2.relname"
2436
Vector tuples = new Vector();
2443
byte tuple[][] = new byte[14][0];
2444
for (int k = 0;k < 14;k++)
2447
String fKeyName = rs.getString(3);
2448
boolean foundRule = false;
2451
String proname = rs.getString(9);
2452
if (proname != null && proname.startsWith("RI_FKey_"))
2455
if (proname.endsWith("_upd"))
2456
col = 9; // UPDATE_RULE
2457
else if (proname.endsWith("_del"))
2458
col = 10; // DELETE_RULE
2461
String rule = proname.substring(8, proname.length() - 4);
2462
int action = importedKeyNoAction;
2463
if ("cascade".equals(rule))
2464
action = importedKeyCascade;
2465
else if ("setnull".equals(rule))
2466
action = importedKeySetNull;
2467
else if ("setdefault".equals(rule))
2468
action = importedKeySetDefault;
2469
tuple[col] = Integer.toString(action).getBytes();
2473
tuple[2] = rs.getBytes(1); //PKTABLE_NAME
2474
tuple[6] = rs.getBytes(2); //FKTABLE_NAME
2476
// Parse the tgargs data
2477
StringBuffer fkeyColumns = new StringBuffer();
2478
StringBuffer pkeyColumns = new StringBuffer();
2479
int numColumns = (rs.getInt(7) >> 1) - 2;
2480
String s = rs.getString(8);
2481
int pos = s.lastIndexOf("\\000");
2482
for (int c = 0;c < numColumns;c++)
2486
int pos2 = s.lastIndexOf("\\000", pos - 1);
2489
if (pkeyColumns.length() > 0)
2490
pkeyColumns.insert(0, ',');
2491
pkeyColumns.insert(0, s.substring(pos2 + 4, pos)); //PKCOLUMN_NAME
2492
pos = s.lastIndexOf("\\000", pos2 - 1);
2495
if (fkeyColumns.length() > 0)
2496
fkeyColumns.insert(0, ',');
2497
fkeyColumns.insert(0, s.substring(pos + 4, pos2)); //FKCOLUMN_NAME
2502
tuple[3] = pkeyColumns.toString().getBytes(); //PKCOLUMN_NAME
2503
tuple[7] = fkeyColumns.toString().getBytes(); //FKCOLUMN_NAME
2505
tuple[8] = Integer.toString(seq++).getBytes(); //KEY_SEQ
2506
tuple[11] = fKeyName.getBytes(); //FK_NAME
2507
tuple[12] = rs.getBytes(4); //PK_NAME
2510
int deferrability = importedKeyNotDeferrable;
2511
boolean deferrable = rs.getBoolean(5);
2512
boolean initiallyDeferred = rs.getBoolean(6);
2515
if (initiallyDeferred)
2516
deferrability = importedKeyInitiallyDeferred;
2518
deferrability = importedKeyInitiallyImmediate;
2520
tuple[13] = Integer.toString(deferrability).getBytes();
2527
while ((hasMore = rs.next()) && fKeyName.equals(rs.getString(3)));
2529
if(foundRule) tuples.addElement(tuple);
2535
return new ResultSet(connection, f, tuples, "OK", 1);
2539
* Get a description of the primary key columns that are
2540
* referenced by a table's foreign key columns (the primary keys
2541
* imported by a table). They are ordered by PKTABLE_CAT,
2542
* PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
2544
* <P>Each primary key column description has the following columns:
2546
* <LI><B>PKTABLE_CAT</B> String => primary key table catalog
2547
* being imported (may be null)
2548
* <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
2549
* being imported (may be null)
2550
* <LI><B>PKTABLE_NAME</B> String => primary key table name
2552
* <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2554
* <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2555
* <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2556
* <LI><B>FKTABLE_NAME</B> String => foreign key table name
2557
* <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2558
* <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2559
* <LI><B>UPDATE_RULE</B> short => What happens to
2560
* foreign key when primary is updated:
2562
* <LI> importedKeyCascade - change imported key to agree
2563
* with primary key update
2564
* <LI> importedKeyRestrict - do not allow update of primary
2565
* key if it has been imported
2566
* <LI> importedKeySetNull - change imported key to NULL if
2567
* its primary key has been updated
2569
* <LI><B>DELETE_RULE</B> short => What happens to
2570
* the foreign key when primary is deleted.
2572
* <LI> importedKeyCascade - delete rows that import a deleted key
2573
* <LI> importedKeyRestrict - do not allow delete of primary
2574
* key if it has been imported
2575
* <LI> importedKeySetNull - change imported key to NULL if
2576
* its primary key has been deleted
2578
* <LI><B>FK_NAME</B> String => foreign key name (may be null)
2579
* <LI><B>PK_NAME</B> String => primary key name (may be null)
2582
* @param catalog a catalog name; "" retrieves those without a catalog
2583
* @param schema a schema name pattern; "" retrieves those
2585
* @param table a table name
2586
* @return ResultSet each row is a primary key column description
2587
* @see #getExportedKeys
2589
public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
2591
return getImportedExportedKeys(catalog, schema, null, table);
2595
* Get a description of a foreign key columns that reference a
2596
* table's primary key columns (the foreign keys exported by a
2597
* table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
2598
* FKTABLE_NAME, and KEY_SEQ.
2600
* This method is currently unimplemented.
2602
* <P>Each foreign key column description has the following columns:
2604
* <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
2605
* <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
2606
* <LI><B>PKTABLE_NAME</B> String => primary key table name
2607
* <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2608
* <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2609
* being exported (may be null)
2610
* <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2611
* being exported (may be null)
2612
* <LI><B>FKTABLE_NAME</B> String => foreign key table name
2614
* <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2616
* <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2617
* <LI><B>UPDATE_RULE</B> short => What happens to
2618
* foreign key when primary is updated:
2620
* <LI> importedKeyCascade - change imported key to agree
2621
* with primary key update
2622
* <LI> importedKeyRestrict - do not allow update of primary
2623
* key if it has been imported
2624
* <LI> importedKeySetNull - change imported key to NULL if
2625
* its primary key has been updated
2627
* <LI><B>DELETE_RULE</B> short => What happens to
2628
* the foreign key when primary is deleted.
2630
* <LI> importedKeyCascade - delete rows that import a deleted key
2631
* <LI> importedKeyRestrict - do not allow delete of primary
2632
* key if it has been imported
2633
* <LI> importedKeySetNull - change imported key to NULL if
2634
* its primary key has been deleted
2636
* <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
2637
* <LI><B>PK_NAME</B> String => primary key identifier (may be null)
2640
* @param catalog a catalog name; "" retrieves those without a catalog
2641
* @param schema a schema name pattern; "" retrieves those
2643
* @param table a table name
2644
* @return ResultSet each row is a foreign key column description
2645
* @see #getImportedKeys
2647
public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
2649
return getImportedExportedKeys(catalog, schema, table, null);
2653
* Get a description of the foreign key columns in the foreign key
2654
* table that reference the primary key columns of the primary key
2655
* table (describe how one table imports another's key.) This
2656
* should normally return a single foreign key/primary key pair
2657
* (most tables only import a foreign key from a table once.) They
2658
* are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
2661
* This method is currently unimplemented.
2663
* <P>Each foreign key column description has the following columns:
2665
* <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
2666
* <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
2667
* <LI><B>PKTABLE_NAME</B> String => primary key table name
2668
* <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2669
* <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2670
* being exported (may be null)
2671
* <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2672
* being exported (may be null)
2673
* <LI><B>FKTABLE_NAME</B> String => foreign key table name
2675
* <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2677
* <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2678
* <LI><B>UPDATE_RULE</B> short => What happens to
2679
* foreign key when primary is updated:
2681
* <LI> importedKeyCascade - change imported key to agree
2682
* with primary key update
2683
* <LI> importedKeyRestrict - do not allow update of primary
2684
* key if it has been imported
2685
* <LI> importedKeySetNull - change imported key to NULL if
2686
* its primary key has been updated
2688
* <LI><B>DELETE_RULE</B> short => What happens to
2689
* the foreign key when primary is deleted.
2691
* <LI> importedKeyCascade - delete rows that import a deleted key
2692
* <LI> importedKeyRestrict - do not allow delete of primary
2693
* key if it has been imported
2694
* <LI> importedKeySetNull - change imported key to NULL if
2695
* its primary key has been deleted
2697
* <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
2698
* <LI><B>PK_NAME</B> String => primary key identifier (may be null)
2701
* @param catalog a catalog name; "" retrieves those without a catalog
2702
* @param schema a schema name pattern; "" retrieves those
2704
* @param table a table name
2705
* @return ResultSet each row is a foreign key column description
2706
* @see #getImportedKeys
2708
public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
2710
return getImportedExportedKeys(primaryCatalog, primarySchema, primaryTable, foreignTable);
2714
* Get a description of all the standard SQL types supported by
2715
* this database. They are ordered by DATA_TYPE and then by how
2716
* closely the data type maps to the corresponding JDBC SQL type.
2718
* <P>Each type description has the following columns:
2720
* <LI><B>TYPE_NAME</B> String => Type name
2721
* <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2722
* <LI><B>PRECISION</B> int => maximum precision
2723
* <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
2725
* <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
2727
* <LI><B>CREATE_PARAMS</B> String => parameters used in creating
2728
* the type (may be null)
2729
* <LI><B>NULLABLE</B> short => can you use NULL for this type?
2731
* <LI> typeNoNulls - does not allow NULL values
2732
* <LI> typeNullable - allows NULL values
2733
* <LI> typeNullableUnknown - nullability unknown
2735
* <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
2736
* <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
2738
* <LI> typePredNone - No support
2739
* <LI> typePredChar - Only supported with WHERE .. LIKE
2740
* <LI> typePredBasic - Supported except for WHERE .. LIKE
2741
* <LI> typeSearchable - Supported for all WHERE ..
2743
* <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
2744
* <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
2745
* <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
2746
* auto-increment value?
2747
* <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
2749
* <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
2750
* <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
2751
* <LI><B>SQL_DATA_TYPE</B> int => unused
2752
* <LI><B>SQL_DATETIME_SUB</B> int => unused
2753
* <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
2756
* @return ResultSet each row is a SQL type description
2758
public java.sql.ResultSet getTypeInfo() throws SQLException
2760
java.sql.ResultSet rs = connection.ExecSQL("select typname from pg_type");
2763
Field f[] = new Field[18];
2764
ResultSet r; // ResultSet for the SQL query that we need to do
2765
Vector v = new Vector(); // The new ResultSet tuple stuff
2767
f[0] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
2768
f[1] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
2769
f[2] = new Field(connection, "PRECISION", iInt4Oid, 4);
2770
f[3] = new Field(connection, "LITERAL_PREFIX", iVarcharOid, 32);
2771
f[4] = new Field(connection, "LITERAL_SUFFIX", iVarcharOid, 32);
2772
f[5] = new Field(connection, "CREATE_PARAMS", iVarcharOid, 32);
2773
f[6] = new Field(connection, "NULLABLE", iInt2Oid, 2);
2774
f[7] = new Field(connection, "CASE_SENSITIVE", iBoolOid, 1);
2775
f[8] = new Field(connection, "SEARCHABLE", iInt2Oid, 2);
2776
f[9] = new Field(connection, "UNSIGNED_ATTRIBUTE", iBoolOid, 1);
2777
f[10] = new Field(connection, "FIXED_PREC_SCALE", iBoolOid, 1);
2778
f[11] = new Field(connection, "AUTO_INCREMENT", iBoolOid, 1);
2779
f[12] = new Field(connection, "LOCAL_TYPE_NAME", iVarcharOid, 32);
2780
f[13] = new Field(connection, "MINIMUM_SCALE", iInt2Oid, 2);
2781
f[14] = new Field(connection, "MAXIMUM_SCALE", iInt2Oid, 2);
2782
f[15] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
2783
f[16] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
2784
f[17] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
2786
// cache some results, this will keep memory useage down, and speed
2787
// things up a little.
2788
byte b9[] = "9".getBytes();
2789
byte b10[] = "10".getBytes();
2790
byte bf[] = "f".getBytes();
2791
byte bnn[] = Integer.toString(typeNoNulls).getBytes();
2792
byte bts[] = Integer.toString(typeSearchable).getBytes();
2796
byte[][] tuple = new byte[18][];
2797
String typname = rs.getString(1);
2798
tuple[0] = typname.getBytes();
2799
tuple[1] = Integer.toString(connection.getSQLType(typname)).getBytes();
2800
tuple[2] = b9; // for now
2801
tuple[6] = bnn; // for now
2802
tuple[7] = bf; // false for now - not case sensitive
2804
tuple[9] = bf; // false for now - it's signed
2805
tuple[10] = bf; // false for now - must handle money
2806
tuple[11] = bf; // false for now - handle autoincrement
2807
// 12 - LOCAL_TYPE_NAME is null
2809
// 15 & 16 are unused so we return null
2810
tuple[17] = b10; // everything is base 10
2811
v.addElement(tuple);
2814
return new ResultSet(connection, f, v, "OK", 1);
2817
throw new PSQLException("postgresql.metadata.unavailable");
2821
* Get a description of a table's indices and statistics. They are
2822
* ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
2824
* <P>Each index column description has the following columns:
2826
* <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2827
* <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2828
* <LI><B>TABLE_NAME</B> String => table name
2829
* <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
2830
* false when TYPE is tableIndexStatistic
2831
* <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
2832
* null when TYPE is tableIndexStatistic
2833
* <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
2834
* tableIndexStatistic
2835
* <LI><B>TYPE</B> short => index type:
2837
* <LI> tableIndexStatistic - this identifies table statistics that are
2838
* returned in conjuction with a table's index descriptions
2839
* <LI> tableIndexClustered - this is a clustered index
2840
* <LI> tableIndexHashed - this is a hashed index
2841
* <LI> tableIndexOther - this is some other style of index
2843
* <LI><B>ORDINAL_POSITION</B> short => column sequence number
2844
* within index; zero when TYPE is tableIndexStatistic
2845
* <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
2846
* tableIndexStatistic
2847
* <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending
2848
* "D" => descending, may be null if sort sequence is not supported;
2849
* null when TYPE is tableIndexStatistic
2850
* <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
2851
* this is the number of rows in the table; otherwise it is the
2852
* number of unique values in the index.
2853
* <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
2854
* this is the number of pages used for the table, otherwise it
2855
* is the number of pages used for the current index.
2856
* <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
2860
* @param catalog a catalog name; "" retrieves those without a catalog
2861
* @param schema a schema name pattern; "" retrieves those without a schema
2862
* @param table a table name
2863
* @param unique when true, return only indices for unique values;
2864
* when false, return indices regardless of whether unique or not
2865
* @param approximate when true, result is allowed to reflect approximate
2866
* or out of data values; when false, results are requested to be
2868
* @return ResultSet each row is an index column description
2870
// Implementation note: This is required for Borland's JBuilder to work
2871
public java.sql.ResultSet getIndexInfo(String catalog, String schema, String tableName, boolean unique, boolean approximate) throws SQLException
2873
Field f[] = new Field[13];
2874
java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
2875
Vector v = new Vector(); // The new ResultSet tuple stuff
2877
f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
2878
f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
2879
f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
2880
f[3] = new Field(connection, "NON_UNIQUE", iBoolOid, 1);
2881
f[4] = new Field(connection, "INDEX_QUALIFIER", iVarcharOid, 32);
2882
f[5] = new Field(connection, "INDEX_NAME", iVarcharOid, 32);
2883
f[6] = new Field(connection, "TYPE", iInt2Oid, 2);
2884
f[7] = new Field(connection, "ORDINAL_POSITION", iInt2Oid, 2);
2885
f[8] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
2886
f[9] = new Field(connection, "ASC_OR_DESC", iVarcharOid, 32);
2887
f[10] = new Field(connection, "CARDINALITY", iInt4Oid, 4);
2888
f[11] = new Field(connection, "PAGES", iInt4Oid, 4);
2889
f[12] = new Field(connection, "FILTER_CONDITION", iVarcharOid, 32);
2891
r = connection.ExecSQL("select " +
2895
"x.indisclustered, " +
2901
"FROM pg_index x, pg_class c, pg_class i, pg_am a " +
2902
"WHERE ((c.relname = '" + tableName.toLowerCase() + "') " +
2903
" AND (c.oid = x.indrelid) " +
2904
" AND (i.oid = x.indexrelid) " +
2905
" AND (i.relam = a.oid)) " +
2906
"ORDER BY x.indisunique DESC, " +
2907
" x.indisclustered, a.amname, i.relname");
2910
// indkey is an array of column ordinals (integers). In the JDBC
2911
// interface, this has to be separated out into a separate
2912
// tuple for each indexed column. Also, getArray() is not yet
2913
// implemented for Postgres JDBC, so we parse by hand.
2914
String columnOrdinalString = r.getString(6);
2915
StringTokenizer stok = new StringTokenizer(columnOrdinalString);
2916
int [] columnOrdinals = new int[stok.countTokens()];
2918
while (stok.hasMoreTokens())
2920
columnOrdinals[o++] = Integer.parseInt(stok.nextToken());
2922
for (int i = 0; i < columnOrdinals.length; i++)
2924
byte [] [] tuple = new byte [13] [];
2925
tuple[0] = "".getBytes();
2926
tuple[1] = "".getBytes();
2927
tuple[2] = r.getBytes(1);
2928
tuple[3] = r.getBoolean(2) ? "false".getBytes() : "true".getBytes();
2930
tuple[5] = r.getBytes(3);
2931
tuple[6] = r.getBoolean(4) ?
2932
Integer.toString(tableIndexClustered).getBytes() :
2933
r.getString(5).equals("hash") ?
2934
Integer.toString(tableIndexHashed).getBytes() :
2935
Integer.toString(tableIndexOther).getBytes();
2936
tuple[7] = Integer.toString(i + 1).getBytes();
2937
java.sql.ResultSet columnNameRS = connection.ExecSQL("select a.attname FROM pg_attribute a WHERE (a.attnum = " + columnOrdinals[i] + ") AND (a.attrelid = " + r.getInt(9) + ")");
2938
if (columnNameRS.next())
2939
tuple[8] = columnNameRS.getBytes(1);
2941
tuple[8] = "".getBytes();
2942
tuple[8] = columnNameRS.getBytes(1);
2943
tuple[9] = null; // sort sequence ???
2944
tuple[10] = r.getBytes(7); // inexact
2945
tuple[11] = r.getBytes(8);
2947
v.addElement(tuple);
2951
return new ResultSet(connection, f, v, "OK", 1);
2955
// ** JDBC 2 Extensions **
2958
* Does the database support the given result set type?
2960
* @param type - defined in java.sql.ResultSet
2961
* @return true if so; false otherwise
2962
* @exception SQLException - if a database access error occurs
2964
public boolean supportsResultSetType(int type) throws SQLException
2966
// The only type we don't support
2967
return type != java.sql.ResultSet.TYPE_SCROLL_SENSITIVE;
2972
* Does the database support the concurrency type in combination
2973
* with the given result set type?
2975
* @param type - defined in java.sql.ResultSet
2976
* @param concurrency - type defined in java.sql.ResultSet
2977
* @return true if so; false otherwise
2978
* @exception SQLException - if a database access error occurs
2980
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException
2982
// These combinations are not supported!
2983
if (type == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE)
2986
// We don't yet support Updateable ResultSets
2987
if (concurrency == java.sql.ResultSet.CONCUR_UPDATABLE)
2990
// Everything else we do
2995
/* lots of unsupported stuff... */
2996
public boolean ownUpdatesAreVisible(int type) throws SQLException
3001
public boolean ownDeletesAreVisible(int type) throws SQLException
3006
public boolean ownInsertsAreVisible(int type) throws SQLException
3011
public boolean othersUpdatesAreVisible(int type) throws SQLException
3016
public boolean othersDeletesAreVisible(int i) throws SQLException
3021
public boolean othersInsertsAreVisible(int type) throws SQLException
3026
public boolean updatesAreDetected(int type) throws SQLException
3031
public boolean deletesAreDetected(int i) throws SQLException
3036
public boolean insertsAreDetected(int type) throws SQLException
3042
* Indicates whether the driver supports batch updates.
3044
public boolean supportsBatchUpdates() throws SQLException
3050
* Return user defined types in a schema
3052
public java.sql.ResultSet getUDTs(String catalog,
3053
String schemaPattern,
3054
String typeNamePattern,
3056
) throws SQLException
3058
throw org.postgresql.Driver.notImplemented();
3063
* Retrieves the connection that produced this metadata object.
3065
* @return the connection that produced this metadata object
3067
public java.sql.Connection getConnection() throws SQLException
3069
return (java.sql.Connection)connection;
3072
/* I don't find these in the spec!?! */
3074
public boolean rowChangesAreDetected(int type) throws SQLException
3079
public boolean rowChangesAreVisible(int type) throws SQLException