]> granicus.if.org Git - postgresql/blob - src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
Tue Jan 30 22:24:00 GMT 2001 peter@retep.org.uk
[postgresql] / src / interfaces / jdbc / org / postgresql / jdbc2 / Connection.java
1 package org.postgresql.jdbc2;
2
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.
7
8 import java.io.*;
9 import java.lang.*;
10 import java.lang.reflect.*;
11 import java.net.*;
12 import java.util.*;
13 import java.sql.*;
14 import org.postgresql.Field;
15 import org.postgresql.fastpath.*;
16 import org.postgresql.largeobject.*;
17 import org.postgresql.util.*;
18
19 /**
20  * $Id: Connection.java,v 1.6 2001/01/31 08:26:02 peter Exp $
21  *
22  * A Connection represents a session with a specific database.  Within the
23  * context of a Connection, SQL statements are executed and results are
24  * returned.
25  *
26  * <P>A Connection's database is able to provide information describing
27  * its tables, its supported SQL grammar, its stored procedures, the
28  * capabilities of this connection, etc.  This information is obtained
29  * with the getMetaData method.
30  *
31  * <p><B>Note:</B> By default, the Connection automatically commits changes
32  * after executing each statement.  If auto-commit has been disabled, an
33  * explicit commit must be done or database changes will not be saved.
34  *
35  * @see java.sql.Connection
36  */
37 public class Connection extends org.postgresql.Connection implements java.sql.Connection
38 {
39   // This is a cache of the DatabaseMetaData instance for this connection
40   protected DatabaseMetaData metadata;
41
42   protected java.util.Map typemap;
43
44   /**
45    * SQL statements without parameters are normally executed using
46    * Statement objects.  If the same SQL statement is executed many
47    * times, it is more efficient to use a PreparedStatement
48    *
49    * @return a new Statement object
50    * @exception SQLException passed through from the constructor
51    */
52   public java.sql.Statement createStatement() throws SQLException
53   {
54     // The spec says default of TYPE_FORWARD_ONLY but everyone is used to
55     // using TYPE_SCROLL_INSENSITIVE
56     return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
57   }
58
59   /**
60    * SQL statements without parameters are normally executed using
61    * Statement objects.  If the same SQL statement is executed many
62    * times, it is more efficient to use a PreparedStatement
63    *
64    * @param resultSetType to use
65    * @param resultSetCuncurrency to use
66    * @return a new Statement object
67    * @exception SQLException passed through from the constructor
68    */
69   public java.sql.Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException
70   {
71     Statement s = new Statement(this);
72     s.setResultSetType(resultSetType);
73     s.setResultSetConcurrency(resultSetConcurrency);
74     return s;
75   }
76
77
78   /**
79    * A SQL statement with or without IN parameters can be pre-compiled
80    * and stored in a PreparedStatement object.  This object can then
81    * be used to efficiently execute this statement multiple times.
82    *
83    * <B>Note:</B> This method is optimized for handling parametric
84    * SQL statements that benefit from precompilation if the drivers
85    * supports precompilation.  PostgreSQL does not support precompilation.
86    * In this case, the statement is not sent to the database until the
87    * PreparedStatement is executed.  This has no direct effect on users;
88    * however it does affect which method throws certain SQLExceptions
89    *
90    * @param sql a SQL statement that may contain one or more '?' IN
91    *    parameter placeholders
92    * @return a new PreparedStatement object containing the pre-compiled
93    *    statement.
94    * @exception SQLException if a database access error occurs.
95    */
96   public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
97   {
98     return prepareStatement(sql,java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
99   }
100
101   public java.sql.PreparedStatement prepareStatement(String sql,int resultSetType,int resultSetConcurrency) throws SQLException
102   {
103     PreparedStatement s = new PreparedStatement(this,sql);
104     s.setResultSetType(resultSetType);
105     s.setResultSetConcurrency(resultSetConcurrency);
106     return s;
107   }
108
109   /**
110    * A SQL stored procedure call statement is handled by creating a
111    * CallableStatement for it.  The CallableStatement provides methods
112    * for setting up its IN and OUT parameters and methods for executing
113    * it.
114    *
115    * <B>Note:</B> This method is optimised for handling stored procedure
116    * call statements.  Some drivers may send the call statement to the
117    * database when the prepareCall is done; others may wait until the
118    * CallableStatement is executed.  This has no direct effect on users;
119    * however, it does affect which method throws certain SQLExceptions
120    *
121    * @param sql a SQL statement that may contain one or more '?' parameter
122    *    placeholders.  Typically this statement is a JDBC function call
123    *    escape string.
124    * @return a new CallableStatement object containing the pre-compiled
125    *    SQL statement
126    * @exception SQLException if a database access error occurs
127    */
128   public java.sql.CallableStatement prepareCall(String sql) throws SQLException
129   {
130     return prepareCall(sql,java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
131   }
132
133   public java.sql.CallableStatement prepareCall(String sql,int resultSetType,int resultSetConcurrency) throws SQLException
134   {
135     throw new PSQLException("postgresql.con.call");
136     //CallableStatement s = new CallableStatement(this,sql);
137     //s.setResultSetType(resultSetType);
138     //s.setResultSetConcurrency(resultSetConcurrency);
139     //return s;
140   }
141
142
143   /**
144    * A driver may convert the JDBC sql grammar into its system's
145    * native SQL grammar prior to sending it; nativeSQL returns the
146    * native form of the statement that the driver would have sent.
147    *
148    * @param sql a SQL statement that may contain one or more '?'
149    *    parameter placeholders
150    * @return the native form of this statement
151    * @exception SQLException if a database access error occurs
152    */
153   public String nativeSQL(String sql) throws SQLException
154   {
155     return sql;
156   }
157
158   /**
159    * If a connection is in auto-commit mode, than all its SQL
160    * statements will be executed and committed as individual
161    * transactions.  Otherwise, its SQL statements are grouped
162    * into transactions that are terminated by either commit()
163    * or rollback().  By default, new connections are in auto-
164    * commit mode.  The commit occurs when the statement completes
165    * or the next execute occurs, whichever comes first.  In the
166    * case of statements returning a ResultSet, the statement
167    * completes when the last row of the ResultSet has been retrieved
168    * or the ResultSet has been closed.  In advanced cases, a single
169    * statement may return multiple results as well as output parameter
170    * values.  Here the commit occurs when all results and output param
171    * values have been retrieved.
172    *
173    * @param autoCommit - true enables auto-commit; false disables it
174    * @exception SQLException if a database access error occurs
175    */
176   public void setAutoCommit(boolean autoCommit) throws SQLException
177   {
178     if (this.autoCommit == autoCommit)
179       return;
180     if (autoCommit)
181       ExecSQL("end");
182     else
183       ExecSQL("begin");
184     this.autoCommit = autoCommit;
185   }
186
187   /**
188    * gets the current auto-commit state
189    *
190    * @return Current state of the auto-commit mode
191    * @exception SQLException (why?)
192    * @see setAutoCommit
193    */
194   public boolean getAutoCommit() throws SQLException
195   {
196     return this.autoCommit;
197   }
198
199   /**
200    * The method commit() makes all changes made since the previous
201    * commit/rollback permanent and releases any database locks currently
202    * held by the Connection.  This method should only be used when
203    * auto-commit has been disabled.  (If autoCommit == true, then we
204    * just return anyhow)
205    *
206    * @exception SQLException if a database access error occurs
207    * @see setAutoCommit
208    */
209   public void commit() throws SQLException
210   {
211     if (autoCommit)
212       return;
213     ExecSQL("commit");
214     autoCommit = true;
215     ExecSQL("begin");
216     autoCommit = false;
217   }
218
219   /**
220    * The method rollback() drops all changes made since the previous
221    * commit/rollback and releases any database locks currently held by
222    * the Connection.
223    *
224    * @exception SQLException if a database access error occurs
225    * @see commit
226    */
227   public void rollback() throws SQLException
228   {
229     if (autoCommit)
230       return;
231     ExecSQL("rollback");
232     autoCommit = true;
233     ExecSQL("begin");
234     autoCommit = false;
235   }
236
237   /**
238    * In some cases, it is desirable to immediately release a Connection's
239    * database and JDBC resources instead of waiting for them to be
240    * automatically released (cant think why off the top of my head)
241    *
242    * <B>Note:</B> A Connection is automatically closed when it is
243    * garbage collected.  Certain fatal errors also result in a closed
244    * connection.
245    *
246    * @exception SQLException if a database access error occurs
247    */
248   public void close() throws SQLException
249   {
250     if (pg_stream != null)
251       {
252         try
253           {
254             pg_stream.close();
255           } catch (IOException e) {}
256           pg_stream = null;
257       }
258   }
259
260   /**
261    * Tests to see if a Connection is closed
262    *
263    * @return the status of the connection
264    * @exception SQLException (why?)
265    */
266   public boolean isClosed() throws SQLException
267   {
268     // If the stream is gone, then close() was called
269     if(pg_stream == null)
270       return true;
271
272     // ok, test the connection
273     try {
274       // by sending an empty query. If we are dead, then an SQLException should
275       // be thrown
276       java.sql.ResultSet rs = ExecSQL(" ");
277       if(rs!=null)
278         rs.close();
279
280       // By now, we must be alive
281       return false;
282     } catch(SQLException se) {
283       // Why throw an SQLException as this may fail without throwing one,
284       // ie isClosed() is called incase the connection has died, and we don't
285       // want to find out by an Exception, so instead we return true, as its
286       // most likely why it was thrown in the first place.
287       return true;
288     }
289   }
290
291   /**
292    * A connection's database is able to provide information describing
293    * its tables, its supported SQL grammar, its stored procedures, the
294    * capabilities of this connection, etc.  This information is made
295    * available through a DatabaseMetaData object.
296    *
297    * @return a DatabaseMetaData object for this connection
298    * @exception SQLException if a database access error occurs
299    */
300   public java.sql.DatabaseMetaData getMetaData() throws SQLException
301   {
302     if(metadata==null)
303       metadata = new DatabaseMetaData(this);
304     return metadata;
305   }
306
307   /**
308    * You can put a connection in read-only mode as a hunt to enable
309    * database optimizations
310    *
311    * <B>Note:</B> setReadOnly cannot be called while in the middle
312    * of a transaction
313    *
314    * @param readOnly - true enables read-only mode; false disables it
315    * @exception SQLException if a database access error occurs
316    */
317   public void setReadOnly (boolean readOnly) throws SQLException
318   {
319     this.readOnly = readOnly;
320   }
321
322   /**
323    * Tests to see if the connection is in Read Only Mode.  Note that
324    * we cannot really put the database in read only mode, but we pretend
325    * we can by returning the value of the readOnly flag
326    *
327    * @return true if the connection is read only
328    * @exception SQLException if a database access error occurs
329    */
330   public boolean isReadOnly() throws SQLException
331   {
332     return readOnly;
333   }
334
335   /**
336    * A sub-space of this Connection's database may be selected by
337    * setting a catalog name.  If the driver does not support catalogs,
338    * it will silently ignore this request
339    *
340    * @exception SQLException if a database access error occurs
341    */
342   public void setCatalog(String catalog) throws SQLException
343   {
344     // No-op
345   }
346
347   /**
348    * Return the connections current catalog name, or null if no
349    * catalog name is set, or we dont support catalogs.
350    *
351    * @return the current catalog name or null
352    * @exception SQLException if a database access error occurs
353    */
354   public String getCatalog() throws SQLException
355   {
356     return null;
357   }
358
359   /**
360    * You can call this method to try to change the transaction
361    * isolation level using one of the TRANSACTION_* values.
362    *
363    * <B>Note:</B> setTransactionIsolation cannot be called while
364    * in the middle of a transaction
365    *
366    * @param level one of the TRANSACTION_* isolation values with
367    *    the exception of TRANSACTION_NONE; some databases may
368    *    not support other values
369    * @exception SQLException if a database access error occurs
370    * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
371    */
372   public void setTransactionIsolation(int level) throws SQLException
373   {
374     String q = "SET TRANSACTION ISOLATION LEVEL";
375
376     switch(level) {
377
378       case java.sql.Connection.TRANSACTION_READ_COMMITTED:
379         ExecSQL(q + " READ COMMITTED");
380         return;
381
382       case java.sql.Connection.TRANSACTION_SERIALIZABLE:
383         ExecSQL(q + " SERIALIZABLE");
384         return;
385
386       default:
387         throw new PSQLException("postgresql.con.isolevel",new Integer(level));
388     }
389   }
390
391   /**
392    * Get this Connection's current transaction isolation mode.
393    *
394    * @return the current TRANSACTION_* mode value
395    * @exception SQLException if a database access error occurs
396    */
397   public int getTransactionIsolation() throws SQLException
398   {
399       ExecSQL("show xactisolevel");
400
401       SQLWarning w = getWarnings();
402       if (w != null) {
403           if (w.getMessage().indexOf("READ COMMITTED") != -1) return java.sql.Connection.TRANSACTION_READ_COMMITTED; else
404               if (w.getMessage().indexOf("READ UNCOMMITTED") != -1) return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; else
405                   if (w.getMessage().indexOf("REPEATABLE READ") != -1) return java.sql.Connection.TRANSACTION_REPEATABLE_READ; else
406                       if (w.getMessage().indexOf("SERIALIZABLE") != -1) return java.sql.Connection.TRANSACTION_SERIALIZABLE;
407       }
408       return java.sql.Connection.TRANSACTION_READ_COMMITTED;
409   }
410
411   /**
412    * The first warning reported by calls on this Connection is
413    * returned.
414    *
415    * <B>Note:</B> Sebsequent warnings will be changed to this
416    * SQLWarning
417    *
418    * @return the first SQLWarning or null
419    * @exception SQLException if a database access error occurs
420    */
421   public SQLWarning getWarnings() throws SQLException
422   {
423     return firstWarning;
424   }
425
426   /**
427    * After this call, getWarnings returns null until a new warning
428    * is reported for this connection.
429    *
430    * @exception SQLException if a database access error occurs
431    */
432   public void clearWarnings() throws SQLException
433   {
434     firstWarning = null;
435   }
436
437     /**
438      * This overides the method in org.postgresql.Connection and returns a
439      * ResultSet.
440      */
441     protected java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat,Field[] fields, Vector tuples, String status, int updateCount, int insertOID) throws SQLException
442     {
443       // In 7.1 we now test concurrency to see which class to return. If we are not working with a
444       // Statement then default to a normal ResultSet object.
445       if(stat!=null) {
446         if(stat.getResultSetConcurrency()==java.sql.ResultSet.CONCUR_UPDATABLE)
447           return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn,fields,tuples,status,updateCount,insertOID);
448       }
449
450       return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn,fields,tuples,status,updateCount,insertOID);
451     }
452
453     // *****************
454     // JDBC 2 extensions
455     // *****************
456
457     public java.util.Map getTypeMap() throws SQLException
458     {
459       // new in 7.1
460       return typemap;
461     }
462
463
464     public void setTypeMap(java.util.Map map) throws SQLException
465     {
466       // new in 7.1
467       typemap=map;
468     }
469
470     /**
471      * This overides the standard internal getObject method so that we can
472      * check the jdbc2 type map first
473      *
474      * @return PGobject for this type, and set to value
475      * @exception SQLException if value is not correct for this type
476      * @see org.postgresql.util.Serialize
477      */
478     public Object getObject(String type,String value) throws SQLException
479     {
480       if(typemap!=null) {
481         SQLData d = (SQLData) typemap.get(type);
482         if(d!=null) {
483           // Handle the type (requires SQLInput & SQLOutput classes to be implemented)
484           throw org.postgresql.Driver.notImplemented();
485         }
486       }
487
488       // Default to the original method
489       return super.getObject(type,value);
490     }
491 }
492
493 // ***********************************************************************
494