001: /*-------------------------------------------------------------------------
002: *
003: * Copyright (c) 2004-2005, PostgreSQL Global Development Group
004: *
005: * IDENTIFICATION
006: * $PostgreSQL: pgjdbc/org/postgresql/jdbc3/AbstractJdbc3Connection.java,v 1.17 2005/04/10 21:54:16 jurka Exp $
007: *
008: *-------------------------------------------------------------------------
009: */
010: package org.postgresql.jdbc3;
011:
012: import java.util.Properties;
013: import java.sql.*;
014:
015: import org.postgresql.util.PSQLException;
016: import org.postgresql.util.PSQLState;
017: import org.postgresql.util.GT;
018:
019: /**
020: * This class defines methods of the jdbc3 specification. This class extends
021: * org.postgresql.jdbc2.AbstractJdbc2Connection which provides the jdbc2
022: * methods. The real Connection class (for jdbc3) is org.postgresql.jdbc3.Jdbc3Connection
023: */
024: public abstract class AbstractJdbc3Connection extends
025: org.postgresql.jdbc2.AbstractJdbc2Connection {
026: private int rsHoldability = ResultSet.CLOSE_CURSORS_AT_COMMIT;
027: private int savepointId = 0;
028:
029: protected AbstractJdbc3Connection(String host, int port,
030: String user, String database, Properties info, String url)
031: throws SQLException {
032: super (host, port, user, database, info, url);
033: }
034:
035: /**
036: * Changes the holdability of <code>ResultSet</code> objects
037: * created using this <code>Connection</code> object to the given
038: * holdability.
039: *
040: * @param holdability a <code>ResultSet</code> holdability constant; one of
041: * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
042: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
043: * @throws SQLException if a database access occurs, the given parameter
044: * is not a <code>ResultSet</code> constant indicating holdability,
045: * or the given holdability is not supported
046: * @see #getHoldability
047: * @see ResultSet
048: * @since 1.4
049: */
050: public void setHoldability(int holdability) throws SQLException {
051: switch (holdability) {
052: case ResultSet.CLOSE_CURSORS_AT_COMMIT:
053: rsHoldability = holdability;
054: break;
055: case ResultSet.HOLD_CURSORS_OVER_COMMIT:
056: rsHoldability = holdability;
057: break;
058: default:
059: throw new PSQLException(GT.tr(
060: "Unknown ResultSet holdability setting: {0}.",
061: new Integer(holdability)),
062: PSQLState.INVALID_PARAMETER_VALUE);
063: }
064: }
065:
066: /**
067: * Retrieves the current holdability of <code>ResultSet</code> objects
068: * created using this <code>Connection</code> object.
069: *
070: * @return the holdability, one of
071: * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
072: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
073: * @throws SQLException if a database access occurs
074: * @see #setHoldability
075: * @see ResultSet
076: * @since 1.4
077: */
078: public int getHoldability() throws SQLException {
079: return rsHoldability;
080: }
081:
082: /**
083: * Creates an unnamed savepoint in the current transaction and
084: * returns the new <code>Savepoint</code> object that represents it.
085: *
086: * @return the new <code>Savepoint</code> object
087: * @exception SQLException if a database access error occurs
088: * or this <code>Connection</code> object is currently in
089: * auto-commit mode
090: * @see Savepoint
091: * @since 1.4
092: */
093: public Savepoint setSavepoint() throws SQLException {
094: if (!haveMinimumServerVersion("8.0"))
095: throw new PSQLException(
096: GT
097: .tr("Server versions prior to 8.0 do not support savepoints."),
098: PSQLState.NOT_IMPLEMENTED);
099: if (getAutoCommit())
100: throw new PSQLException(
101: GT
102: .tr("Cannot establish a savepoint in auto-commit mode."),
103: PSQLState.NO_ACTIVE_SQL_TRANSACTION);
104:
105: PSQLSavepoint savepoint = new PSQLSavepoint(savepointId++);
106:
107: // Note we can't use execSQLUpdate because we don't want
108: // to suppress BEGIN.
109: Statement stmt = createStatement();
110: stmt.executeUpdate("SAVEPOINT " + savepoint.getPGName());
111: stmt.close();
112:
113: return savepoint;
114: }
115:
116: /**
117: * Creates a savepoint with the given name in the current transaction
118: * and returns the new <code>Savepoint</code> object that represents it.
119: *
120: * @param name a <code>String</code> containing the name of the savepoint
121: * @return the new <code>Savepoint</code> object
122: * @exception SQLException if a database access error occurs
123: * or this <code>Connection</code> object is currently in
124: * auto-commit mode
125: * @see Savepoint
126: * @since 1.4
127: */
128: public Savepoint setSavepoint(String name) throws SQLException {
129: if (!haveMinimumServerVersion("8.0"))
130: throw new PSQLException(
131: GT
132: .tr("Server versions prior to 8.0 do not support savepoints."),
133: PSQLState.NOT_IMPLEMENTED);
134: if (getAutoCommit())
135: throw new PSQLException(
136: GT
137: .tr("Cannot establish a savepoint in auto-commit mode."),
138: PSQLState.NO_ACTIVE_SQL_TRANSACTION);
139:
140: PSQLSavepoint savepoint = new PSQLSavepoint(name);
141:
142: // Note we can't use execSQLUpdate because we don't want
143: // to suppress BEGIN.
144: Statement stmt = createStatement();
145: stmt.executeUpdate("SAVEPOINT " + savepoint.getPGName());
146: stmt.close();
147:
148: return savepoint;
149: }
150:
151: /**
152: * Undoes all changes made after the given <code>Savepoint</code> object
153: * was set.
154: * <P>
155: * This method should be used only when auto-commit has been disabled.
156: *
157: * @param savepoint the <code>Savepoint</code> object to roll back to
158: * @exception SQLException if a database access error occurs,
159: * the <code>Savepoint</code> object is no longer valid,
160: * or this <code>Connection</code> object is currently in
161: * auto-commit mode
162: * @see Savepoint
163: * @see #rollback
164: * @since 1.4
165: */
166: public void rollback(Savepoint savepoint) throws SQLException {
167: if (!haveMinimumServerVersion("8.0"))
168: throw new PSQLException(
169: GT
170: .tr("Server versions prior to 8.0 do not support savepoints."),
171: PSQLState.NOT_IMPLEMENTED);
172:
173: PSQLSavepoint pgSavepoint = (PSQLSavepoint) savepoint;
174: execSQLUpdate("ROLLBACK TO SAVEPOINT "
175: + pgSavepoint.getPGName());
176: }
177:
178: /**
179: * Removes the given <code>Savepoint</code> object from the current
180: * transaction. Any reference to the savepoint after it have been removed
181: * will cause an <code>SQLException</code> to be thrown.
182: *
183: * @param savepoint the <code>Savepoint</code> object to be removed
184: * @exception SQLException if a database access error occurs or
185: * the given <code>Savepoint</code> object is not a valid
186: * savepoint in the current transaction
187: * @since 1.4
188: */
189: public void releaseSavepoint(Savepoint savepoint)
190: throws SQLException {
191: if (!haveMinimumServerVersion("8.0"))
192: throw new PSQLException(
193: GT
194: .tr("Server versions prior to 8.0 do not support savepoints."),
195: PSQLState.NOT_IMPLEMENTED);
196:
197: PSQLSavepoint pgSavepoint = (PSQLSavepoint) savepoint;
198: execSQLUpdate("RELEASE SAVEPOINT " + pgSavepoint.getPGName());
199: pgSavepoint.invalidate();
200: }
201:
202: /**
203: * Creates a <code>Statement</code> object that will generate
204: * <code>ResultSet</code> objects with the given type, concurrency,
205: * and holdability.
206: * This method is the same as the <code>createStatement</code> method
207: * above, but it allows the default result set
208: * type, concurrency, and holdability to be overridden.
209: *
210: * @param resultSetType one of the following <code>ResultSet</code>
211: * constants:
212: * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
213: * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
214: * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
215: * @param resultSetConcurrency one of the following <code>ResultSet</code>
216: * constants:
217: * <code>ResultSet.CONCUR_READ_ONLY</code> or
218: * <code>ResultSet.CONCUR_UPDATABLE</code>
219: * @param resultSetHoldability one of the following <code>ResultSet</code>
220: * constants:
221: * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
222: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
223: * @return a new <code>Statement</code> object that will generate
224: * <code>ResultSet</code> objects with the given type,
225: * concurrency, and holdability
226: * @exception SQLException if a database access error occurs
227: * or the given parameters are not <code>ResultSet</code>
228: * constants indicating type, concurrency, and holdability
229: * @see ResultSet
230: * @since 1.4
231: */
232: public abstract Statement createStatement(int resultSetType,
233: int resultSetConcurrency, int resultSetHoldability)
234: throws SQLException;
235:
236: public Statement createStatement(int resultSetType,
237: int resultSetConcurrency) throws SQLException {
238: return createStatement(resultSetType, resultSetConcurrency,
239: getHoldability());
240: }
241:
242: /**
243: * Creates a <code>PreparedStatement</code> object that will generate
244: * <code>ResultSet</code> objects with the given type, concurrency,
245: * and holdability.
246: * <P>
247: * This method is the same as the <code>prepareStatement</code> method
248: * above, but it allows the default result set
249: * type, concurrency, and holdability to be overridden.
250: *
251: * @param sql a <code>String</code> object that is the SQL statement to
252: * be sent to the database; may contain one or more ? IN
253: * parameters
254: * @param resultSetType one of the following <code>ResultSet</code>
255: * constants:
256: * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
257: * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
258: * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
259: * @param resultSetConcurrency one of the following <code>ResultSet</code>
260: * constants:
261: * <code>ResultSet.CONCUR_READ_ONLY</code> or
262: * <code>ResultSet.CONCUR_UPDATABLE</code>
263: * @param resultSetHoldability one of the following <code>ResultSet</code>
264: * constants:
265: * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
266: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
267: * @return a new <code>PreparedStatement</code> object, containing the
268: * pre-compiled SQL statement, that will generate
269: * <code>ResultSet</code> objects with the given type,
270: * concurrency, and holdability
271: * @exception SQLException if a database access error occurs
272: * or the given parameters are not <code>ResultSet</code>
273: * constants indicating type, concurrency, and holdability
274: * @see ResultSet
275: * @since 1.4
276: */
277: public abstract PreparedStatement prepareStatement(String sql,
278: int resultSetType, int resultSetConcurrency,
279: int resultSetHoldability) throws SQLException;
280:
281: public PreparedStatement prepareStatement(String sql,
282: int resultSetType, int resultSetConcurrency)
283: throws SQLException {
284: return prepareStatement(sql, resultSetType,
285: resultSetConcurrency, getHoldability());
286: }
287:
288: /**
289: * Creates a <code>CallableStatement</code> object that will generate
290: * <code>ResultSet</code> objects with the given type and concurrency.
291: * This method is the same as the <code>prepareCall</code> method
292: * above, but it allows the default result set
293: * type, result set concurrency type and holdability to be overridden.
294: *
295: * @param sql a <code>String</code> object that is the SQL statement to
296: * be sent to the database; may contain on or more ? parameters
297: * @param resultSetType one of the following <code>ResultSet</code>
298: * constants:
299: * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
300: * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
301: * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
302: * @param resultSetConcurrency one of the following <code>ResultSet</code>
303: * constants:
304: * <code>ResultSet.CONCUR_READ_ONLY</code> or
305: * <code>ResultSet.CONCUR_UPDATABLE</code>
306: * @param resultSetHoldability one of the following <code>ResultSet</code>
307: * constants:
308: * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
309: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
310: * @return a new <code>CallableStatement</code> object, containing the
311: * pre-compiled SQL statement, that will generate
312: * <code>ResultSet</code> objects with the given type,
313: * concurrency, and holdability
314: * @exception SQLException if a database access error occurs
315: * or the given parameters are not <code>ResultSet</code>
316: * constants indicating type, concurrency, and holdability
317: * @see ResultSet
318: * @since 1.4
319: */
320: public abstract CallableStatement prepareCall(String sql,
321: int resultSetType, int resultSetConcurrency,
322: int resultSetHoldability) throws SQLException;
323:
324: public CallableStatement prepareCall(String sql, int resultSetType,
325: int resultSetConcurrency) throws SQLException {
326: return prepareCall(sql, resultSetType, resultSetConcurrency,
327: getHoldability());
328: }
329:
330: /**
331: * Creates a default <code>PreparedStatement</code> object that has
332: * the capability to retrieve auto-generated keys. The given constant
333: * tells the driver whether it should make auto-generated keys
334: * available for retrieval. This parameter is ignored if the SQL
335: * statement is not an <code>INSERT</code> statement.
336: * <P>
337: * <B>Note:</B> This method is optimized for handling
338: * parametric SQL statements that benefit from precompilation. If
339: * the driver supports precompilation,
340: * the method <code>prepareStatement</code> will send
341: * the statement to the database for precompilation. Some drivers
342: * may not support precompilation. In this case, the statement may
343: * not be sent to the database until the <code>PreparedStatement</code>
344: * object is executed. This has no direct effect on users; however, it does
345: * affect which methods throw certain SQLExceptions.
346: * <P>
347: * Result sets created using the returned <code>PreparedStatement</code>
348: * object will by default be type <code>TYPE_FORWARD_ONLY</code>
349: * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
350: *
351: * @param sql an SQL statement that may contain one or more '?' IN
352: * parameter placeholders
353: * @param autoGeneratedKeys a flag indicating whether auto-generated keys
354: * should be returned; one of the following <code>Statement</code>
355: * constants:
356: * <code>Statement.RETURN_GENERATED_KEYS</code> or
357: * <code>Statement.NO_GENERATED_KEYS</code>.
358: * @return a new <code>PreparedStatement</code> object, containing the
359: * pre-compiled SQL statement, that will have the capability of
360: * returning auto-generated keys
361: * @exception SQLException if a database access error occurs
362: * or the given parameter is not a <code>Statement</code>
363: * constant indicating whether auto-generated keys should be
364: * returned
365: * @since 1.4
366: */
367: public PreparedStatement prepareStatement(String sql,
368: int autoGeneratedKeys) throws SQLException {
369: if (autoGeneratedKeys != Statement.NO_GENERATED_KEYS)
370: throw new PSQLException(
371: GT
372: .tr("Returning autogenerated keys is not supported."),
373: PSQLState.NOT_IMPLEMENTED);
374: return prepareStatement(sql);
375: }
376:
377: /**
378: * Creates a default <code>PreparedStatement</code> object capable
379: * of returning the auto-generated keys designated by the given array.
380: * This array contains the indexes of the columns in the target
381: * table that contain the auto-generated keys that should be made
382: * available. This array is ignored if the SQL
383: * statement is not an <code>INSERT</code> statement.
384: * <P>
385: * An SQL statement with or without IN parameters can be
386: * pre-compiled and stored in a <code>PreparedStatement</code> object. This
387: * object can then be used to efficiently execute this statement
388: * multiple times.
389: * <P>
390: * <B>Note:</B> This method is optimized for handling
391: * parametric SQL statements that benefit from precompilation. If
392: * the driver supports precompilation,
393: * the method <code>prepareStatement</code> will send
394: * the statement to the database for precompilation. Some drivers
395: * may not support precompilation. In this case, the statement may
396: * not be sent to the database until the <code>PreparedStatement</code>
397: * object is executed. This has no direct effect on users; however, it does
398: * affect which methods throw certain SQLExceptions.
399: * <P>
400: * Result sets created using the returned <code>PreparedStatement</code>
401: * object will by default be type <code>TYPE_FORWARD_ONLY</code>
402: * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
403: *
404: * @param sql an SQL statement that may contain one or more '?' IN
405: * parameter placeholders
406: * @param columnIndexes an array of column indexes indicating the columns
407: * that should be returned from the inserted row or rows
408: * @return a new <code>PreparedStatement</code> object, containing the
409: * pre-compiled statement, that is capable of returning the
410: * auto-generated keys designated by the given array of column
411: * indexes
412: * @exception SQLException if a database access error occurs
413: *
414: * @since 1.4
415: */
416: public PreparedStatement prepareStatement(String sql,
417: int columnIndexes[]) throws SQLException {
418: if (columnIndexes.length != 0)
419: throw new PSQLException(
420: GT
421: .tr("Returning autogenerated keys is not supported."),
422: PSQLState.NOT_IMPLEMENTED);
423: return prepareStatement(sql);
424: }
425:
426: /**
427: * Creates a default <code>PreparedStatement</code> object capable
428: * of returning the auto-generated keys designated by the given array.
429: * This array contains the names of the columns in the target
430: * table that contain the auto-generated keys that should be returned.
431: * This array is ignored if the SQL
432: * statement is not an <code>INSERT</code> statement.
433: * <P>
434: * An SQL statement with or without IN parameters can be
435: * pre-compiled and stored in a <code>PreparedStatement</code> object. This
436: * object can then be used to efficiently execute this statement
437: * multiple times.
438: * <P>
439: * <B>Note:</B> This method is optimized for handling
440: * parametric SQL statements that benefit from precompilation. If
441: * the driver supports precompilation,
442: * the method <code>prepareStatement</code> will send
443: * the statement to the database for precompilation. Some drivers
444: * may not support precompilation. In this case, the statement may
445: * not be sent to the database until the <code>PreparedStatement</code>
446: * object is executed. This has no direct effect on users; however, it does
447: * affect which methods throw certain SQLExceptions.
448: * <P>
449: * Result sets created using the returned <code>PreparedStatement</code>
450: * object will by default be type <code>TYPE_FORWARD_ONLY</code>
451: * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
452: *
453: * @param sql an SQL statement that may contain one or more '?' IN
454: * parameter placeholders
455: * @param columnNames an array of column names indicating the columns
456: * that should be returned from the inserted row or rows
457: * @return a new <code>PreparedStatement</code> object, containing the
458: * pre-compiled statement, that is capable of returning the
459: * auto-generated keys designated by the given array of column
460: * names
461: * @exception SQLException if a database access error occurs
462: *
463: * @since 1.4
464: */
465: public PreparedStatement prepareStatement(String sql,
466: String columnNames[]) throws SQLException {
467: if (columnNames.length != 0)
468: throw new PSQLException(
469: GT
470: .tr("Returning autogenerated keys is not supported."),
471: PSQLState.NOT_IMPLEMENTED);
472: return prepareStatement(sql);
473: }
474:
475: }
|