KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > Connection


1 /*
2    Copyright (C) 2002 MySQL AB
3
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8
9       This program is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12       GNU General Public License for more details.
13
14       You should have received a copy of the GNU General Public License
15       along with this program; if not, write to the Free Software
16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18  */

19 package com.mysql.jdbc;
20
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.Reader JavaDoc;
24 import java.io.UnsupportedEncodingException JavaDoc;
25
26 import java.math.BigDecimal JavaDoc;
27
28 import java.net.URL JavaDoc;
29
30 import java.sql.Clob JavaDoc;
31 import java.sql.Date JavaDoc;
32 import java.sql.ParameterMetaData JavaDoc;
33 import java.sql.Ref JavaDoc;
34 import java.sql.SQLException JavaDoc;
35 import java.sql.Savepoint JavaDoc;
36 import java.sql.Time JavaDoc;
37 import java.sql.Timestamp JavaDoc;
38
39 import java.util.ArrayList JavaDoc;
40 import java.util.Calendar JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.Properties JavaDoc;
46 import java.util.TimeZone JavaDoc;
47
48
49 /**
50  * A Connection represents a session with a specific database. Within the
51  * context of a Connection, SQL statements are executed and results are
52  * returned.
53  *
54  * <P>
55  * A Connection's database is able to provide information describing its
56  * tables, its supported SQL grammar, its stored procedures, the capabilities
57  * of this connection, etc. This information is obtained with the getMetaData
58  * method.
59  * </p>
60  *
61  * @author Mark Matthews
62  * @version $Id: Connection.java,v 1.31.2.55 2004/02/13 22:33:50 mmatthew Exp $
63  *
64  * @see java.sql.Connection
65  */

66 public class Connection implements java.sql.Connection JavaDoc {
67     // The command used to "ping" the database.
68
// Newer versions of MySQL server have a ping() command,
69
// but this works for everything
70
private static final String JavaDoc PING_COMMAND = "SELECT 1";
71
72     /**
73      * Map mysql transaction isolation level name to
74      * java.sql.Connection.TRANSACTION_XXX
75      */

76     private static Map JavaDoc mapTransIsolationName2Value = null;
77
78     /**
79      * The mapping between MySQL charset names and Java charset names.
80      * Initialized by loadCharacterSetMapping()
81      */

82     private static Map JavaDoc charsetMap;
83
84     /** Table of multi-byte charsets. Initialized by loadCharacterSetMapping() */
85     private static Map JavaDoc multibyteCharsetsMap;
86
87     /** Default socket factory classname */
88     private static final String JavaDoc DEFAULT_SOCKET_FACTORY = StandardSocketFactory.class
89         .getName();
90
91     static {
92         loadCharacterSetMapping();
93         mapTransIsolationName2Value = new HashMap JavaDoc(8);
94         mapTransIsolationName2Value.put("READ-UNCOMMITED",
95             new Integer JavaDoc(TRANSACTION_READ_UNCOMMITTED));
96         mapTransIsolationName2Value.put("READ-UNCOMMITTED",
97             new Integer JavaDoc(TRANSACTION_READ_UNCOMMITTED));
98         mapTransIsolationName2Value.put("READ-COMMITTED",
99             new Integer JavaDoc(TRANSACTION_READ_COMMITTED));
100         mapTransIsolationName2Value.put("REPEATABLE-READ",
101             new Integer JavaDoc(TRANSACTION_REPEATABLE_READ));
102         mapTransIsolationName2Value.put("SERIALIZABLE",
103             new Integer JavaDoc(TRANSACTION_SERIALIZABLE));
104     }
105
106     /**
107      * Marker for character set converter not being available (not written,
108      * multibyte, etc) Used to prevent multiple instantiation requests.
109      */

110     private final static Object JavaDoc CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object JavaDoc();
111
112     /** Internal DBMD to use for various database-version specific features */
113     private DatabaseMetaData dbmd = null;
114
115     /** The list of host(s) to try and connect to */
116     private List JavaDoc hostList = null;
117
118     /** A map of SQL to parsed prepared statement parameters. */
119     private Map JavaDoc cachedPreparedStatementParams;
120
121     /**
122      * Holds cached mappings to charset converters to avoid static
123      * synchronization and at the same time save memory (each charset
124      * converter takes approx 65K of static data).
125      */

126     private Map JavaDoc charsetConverterMap = new HashMap JavaDoc(CharsetMapping.JAVA_TO_MYSQL_CHARSET_MAP
127             .size());
128
129     /** A map of statements that have had setMaxRows() called on them */
130     private Map JavaDoc statementsUsingMaxRows;
131
132     /**
133      * The type map for UDTs (not implemented, but used by some third-party
134      * vendors, most notably IBM WebSphere)
135      */

136     private Map JavaDoc typeMap;
137
138     /** The I/O abstraction interface (network conn to MySQL server */
139     private MysqlIO io = null;
140
141     /** Mutex */
142     private final Object JavaDoc mutex = new Object JavaDoc();
143
144     /** The map of server variables that we retrieve at connection init. */
145     private Map JavaDoc serverVariables = null;
146
147     /** The driver instance that created us */
148     private NonRegisteringDriver myDriver;
149
150     /** Properties for this connection specified by user */
151     private Properties JavaDoc props = null;
152
153     /** The database we're currently using (called Catalog in JDBC terms). */
154     private String JavaDoc database = null;
155
156     /** If we're doing unicode character conversions, what encoding do we use? */
157     private String JavaDoc encoding = null;
158
159     /** The hostname we're connected to */
160     private String JavaDoc host = null;
161
162     /** The JDBC URL we're using */
163     private String JavaDoc myURL = null;
164
165     /** What does MySQL call this encoding? */
166     private String JavaDoc mysqlEncodingName = null;
167     private String JavaDoc negativeInfinityRep = MysqlDefs.MIN_DOUBLE_VAL_STRING;
168     private String JavaDoc notANumberRep = MysqlDefs.NAN_VAL_STRING;
169
170     /** The password we used */
171     private String JavaDoc password = null;
172     private String JavaDoc positiveInfinityRep = MysqlDefs.MAX_DOUBLE_VAL_STRING;
173
174     /** Classname for socket factory */
175     private String JavaDoc socketFactoryClassName = null;
176
177     /** The user we're connected as */
178     private String JavaDoc user = null;
179
180     /** Where was the connection _explicitly_ closed by the application? */
181     private Throwable JavaDoc explicitCloseLocation;
182
183     /** If the connection was forced closed, why was it forced closed? */
184     private Throwable JavaDoc forcedCloseReason;
185     private TimeZone JavaDoc defaultTimeZone;
186
187     /** The timezone of the server */
188     private TimeZone JavaDoc serverTimezone = null;
189
190     /** Allow LOAD LOCAL INFILE (defaults to true) */
191     private boolean allowLoadLocalInfile = true;
192
193     /** Should we clear the input stream each query? */
194     private boolean alwaysClearStream = false;
195
196     /** Are we in autoCommit mode? */
197     private boolean autoCommit = true;
198
199     /** SHould we cache the parsing of prepared statements? */
200     private boolean cachePreparedStatements = false;
201
202     /** Should we capitalize mysql types */
203     private boolean capitalizeDBMDTypes = false;
204
205     /** Should we clobber streaming results on new queries, or issue an error? */
206     private boolean clobberStreamingResults = false;
207
208     /**
209      * Should we continue processing batch commands if one fails. The JDBC spec
210      * allows either way, so we let the user choose
211      */

212     private boolean continueBatchOnError = true;
213
214     /** Should we do unicode character conversions? */
215     private boolean doUnicode = false;
216
217     /** Are we failed-over to a non-master host */
218     private boolean failedOver = false;
219
220     /** Does the server suuport isolation levels? */
221     private boolean hasIsolationLevels = false;
222
223     /** Does this version of MySQL support quoted identifiers? */
224     private boolean hasQuotedIdentifiers = false;
225
226     //
227
// This is for the high availability :) routines
228
//
229
private boolean highAvailability = false;
230
231     /** Ignore non-transactional table warning for rollback? */
232     private boolean ignoreNonTxTables = false;
233
234     /** Has this connection been closed? */
235     private boolean isClosed = true;
236
237     /** Should we tell MySQL that we're an interactive client? */
238     private boolean isInteractiveClient = false;
239
240     /** Is the server configured to use lower-case table names only? */
241     private boolean lowerCaseTableNames = false;
242
243     /** Has the max-rows setting been changed from the default? */
244     private boolean maxRowsChanged = false;
245     private boolean negativeInfinityRepIsClipped = true;
246     private boolean notANumberRepIsClipped = true;
247
248     /** Do we expose sensitive information in exception and error messages? */
249     private boolean paranoid = false;
250
251     /** Should we do 'extra' sanity checks? */
252     private boolean pedantic = false;
253     private boolean positiveInfinityRepIsClipped = true;
254
255     /** Should we retrieve 'info' messages from the server? */
256     private boolean readInfoMsg = false;
257
258     /** Are we in read-only mode? */
259     private boolean readOnly = false;
260
261     /**
262      * If autoReconnect == true, should we attempt to reconnect at transaction
263      * boundaries?
264      */

265     private boolean reconnectAtTxEnd = false;
266
267     /** Do we relax the autoCommit semantics? (For enhydra, for example) */
268     private boolean relaxAutoCommit = false;
269
270     /** Do we need to correct endpoint rounding errors */
271     private boolean strictFloatingPoint = false;
272
273     /** Do we check all keys for updatable result sets? */
274     private boolean strictUpdates = true;
275
276     /** Are transactions supported by the MySQL server we are connected to? */
277     private boolean transactionsSupported = false;
278
279     /** Has ANSI_QUOTES been enabled on the server? */
280     private boolean useAnsiQuotes = false;
281
282     /** Should we use compression? */
283     private boolean useCompression = false;
284
285     /** Can we use the "ping" command rather than a query? */
286     private boolean useFastPing = false;
287
288     /** Should we tack on hostname in DBMD.getTable/ColumnPrivileges()? */
289     private boolean useHostsInPrivileges = true;
290
291     /** Should we use SSL? */
292     private boolean useSSL = false;
293
294     /**
295      * Should we use stream lengths in prepared statements? (true by default ==
296      * JDBC compliant)
297      */

298     private boolean useStreamLengthsInPrepStmts = true;
299
300     /** Should we use timezone information? */
301     private boolean useTimezone = false;
302
303     /** Should we return PreparedStatements for UltraDev's stupid bug? */
304     private boolean useUltraDevWorkAround = false;
305     private boolean useUnbufferedInput = true;
306     private double initialTimeout = 2.0D;
307
308     /** How many hosts are in the host list? */
309     private int hostListSize = 0;
310
311     /** isolation level */
312     private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
313
314     /**
315      * The largest packet we can send (changed once we know what the server
316      * supports, we get this at connection init).
317      */

318     private int maxAllowedPacket = 65536;
319     private int maxReconnects = 3;
320
321     /**
322      * The max rows that a result set can contain. Defaults to -1, which
323      * according to the JDBC spec means "all".
324      */

325     private int maxRows = -1;
326     private int netBufferLength = 16384;
327
328     /** The port number we're connected to (defaults to 3306) */
329     private int port = 3306;
330
331     /**
332      * If prepared statement caching is enabled, what should the threshold
333      * length of the SQL to prepare should be in order to _not_ cache?
334      */

335     private int preparedStatementCacheMaxSqlSize = 256;
336
337     /** If prepared statement caching is enabled, how many should we cache? */
338     private int preparedStatementCacheSize = 25;
339
340     /**
341      * How many queries should we wait before we try to re-connect to the
342      * master, when we are failing over to replicated hosts Defaults to 50
343      */

344     private int queriesBeforeRetryMaster = 50;
345
346     /** What should we set the socket timeout to? */
347     private int socketTimeout = 0; // infinite
348

349     /** When did the last query finish? */
350     private long lastQueryFinishedTime = 0;
351
352     /** When did the master fail? */
353     private long masterFailTimeMillis = 0L;
354
355     /** Number of queries we've issued since the master failed */
356     private long queriesIssuedFailedOver = 0;
357
358     /**
359      * How many seconds should we wait before retrying to connect to the master
360      * if failed over? We fall back when either queriesBeforeRetryMaster or
361      * secondsBeforeRetryMaster is reached.
362      */

363     private long secondsBeforeRetryMaster = 30L;
364
365     /**
366      * Creates a connection to a MySQL Server.
367      *
368      * @param host the hostname of the database server
369      * @param port the port number the server is listening on
370      * @param info a Properties[] list holding the user and password
371      * @param database the database to connect to
372      * @param url the URL of the connection
373      * @param d the Driver instantation of the connection
374      *
375      * @exception java.sql.SQLException if a database access error occurs
376      * @throws SQLException DOCUMENT ME!
377      */

378     Connection(String JavaDoc host, int port, Properties JavaDoc info, String JavaDoc database,
379         String JavaDoc url, NonRegisteringDriver d) throws java.sql.SQLException JavaDoc {
380         if (Driver.TRACE) {
381             Object JavaDoc[] args = { host, new Integer JavaDoc(port), info, database, url, d };
382             Debug.methodCall(this, "constructor", args);
383         }
384
385         this.defaultTimeZone = TimeZone.getDefault();
386
387         this.serverVariables = new HashMap JavaDoc();
388
389         if (host == null) {
390             this.host = "localhost";
391             hostList = new ArrayList JavaDoc();
392             hostList.add(this.host);
393         } else if (host.indexOf(",") != -1) {
394             // multiple hosts separated by commas (failover)
395
hostList = StringUtils.split(host, ",", true);
396         } else {
397             this.host = host;
398             hostList = new ArrayList JavaDoc();
399             hostList.add(this.host);
400         }
401
402         hostListSize = hostList.size();
403         this.port = port;
404
405         if (database == null) {
406             throw new SQLException JavaDoc("Malformed URL '" + url + "'.",
407                 SQLError.SQL_STATE_GENERAL_ERROR);
408         }
409
410         this.database = database;
411         this.myURL = url;
412         this.myDriver = d;
413         this.user = info.getProperty("user");
414         this.password = info.getProperty("password");
415
416         if ((this.user == null) || this.user.equals("")) {
417             this.user = "nobody";
418         }
419
420         if (this.password == null) {
421             this.password = "";
422         }
423
424         this.props = info;
425         initializeDriverProperties(info);
426
427         if (Driver.DEBUG) {
428             System.out.println("Connect: " + this.user + " to " + this.database);
429         }
430
431         try {
432             createNewIO(false);
433             this.dbmd = new DatabaseMetaData(this, this.database);
434         } catch (java.sql.SQLException JavaDoc ex) {
435             cleanup(ex);
436
437             // don't clobber SQL exceptions
438
throw ex;
439         } catch (Exception JavaDoc ex) {
440             cleanup(ex);
441
442             StringBuffer JavaDoc mesg = new StringBuffer JavaDoc();
443
444             if (!useParanoidErrorMessages()) {
445                 mesg.append("Cannot connect to MySQL server on ");
446                 mesg.append(this.host);
447                 mesg.append(":");
448                 mesg.append(this.port);
449                 mesg.append(".\n\n");
450                 mesg.append("Make sure that there is a MySQL server ");
451                 mesg.append("running on the machine/port you are trying ");
452                 mesg.append(
453                     "to connect to and that the machine this software is "
454                     + "running on ");
455                 mesg.append("is able to connect to this host/port "
456                     + "(i.e. not firewalled). ");
457                 mesg.append(
458                     "Also make sure that the server has not been started "
459                     + "with the --skip-networking ");
460                 mesg.append("flag.\n\n");
461             } else {
462                 mesg.append("Unable to connect to database.");
463             }
464
465             mesg.append("Underlying exception: \n\n");
466             mesg.append(ex.getClass().getName());
467             throw new java.sql.SQLException JavaDoc(mesg.toString(),
468                 SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
469         }
470     }
471
472     /**
473      * If a connection is in auto-commit mode, than all its SQL statements will
474      * be executed and committed as individual transactions. Otherwise, its
475      * SQL statements are grouped into transactions that are terminated by
476      * either commit() or rollback(). By default, new connections are in
477      * auto- commit mode. The commit occurs when the statement completes or
478      * the next execute occurs, whichever comes first. In the case of
479      * statements returning a ResultSet, the statement completes when the last
480      * row of the ResultSet has been retrieved or the ResultSet has been
481      * closed. In advanced cases, a single statement may return multiple
482      * results as well as output parameter values. Here the commit occurs
483      * when all results and output param values have been retrieved.
484      *
485      * <p>
486      * <b>Note:</b> MySQL does not support transactions, so this method is a
487      * no-op.
488      * </p>
489      *
490      * @param autoCommit - true enables auto-commit; false disables it
491      *
492      * @exception java.sql.SQLException if a database access error occurs
493      * @throws SQLException DOCUMENT ME!
494      */

495     public void setAutoCommit(boolean autoCommit) throws java.sql.SQLException JavaDoc {
496         if (Driver.TRACE) {
497             Object JavaDoc[] args = { new Boolean JavaDoc(autoCommit) };
498             Debug.methodCall(this, "setAutoCommit", args);
499         }
500
501         checkClosed();
502
503         if (this.transactionsSupported) {
504             // this internal value must be set first as failover depends on it
505
// being set to true to fail over (which is done by most
506
// app servers and connection pools at the end of
507
// a transaction), and the driver issues an implicit set
508
// based on this value when it (re)-connects to a server
509
// so the value holds across connections
510
//
511
this.autoCommit = autoCommit;
512
513             //
514
// This is to catch the 'edge' case of
515
// autoCommit going from true -> false
516
//
517
if ((this.highAvailability || this.failedOver) && !this.autoCommit) {
518                 pingAndReconnect(true);
519             }
520
521             String JavaDoc sql = "SET autocommit=" + (autoCommit ? "1" : "0");
522             execSQL(sql, -1, this.database);
523         } else {
524             if ((autoCommit == false) && (this.relaxAutoCommit == false)) {
525                 throw new SQLException JavaDoc("MySQL Versions Older than 3.23.15 "
526                     + "do not support transactions",
527                     SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
528             } else {
529                 this.autoCommit = autoCommit;
530             }
531         }
532
533         return;
534     }
535
536     /**
537      * gets the current auto-commit state
538      *
539      * @return Current state of the auto-commit mode
540      *
541      * @exception java.sql.SQLException (why?)
542      *
543      * @see setAutoCommit
544      */

545     public boolean getAutoCommit() throws java.sql.SQLException JavaDoc {
546         if (Driver.TRACE) {
547             Object JavaDoc[] args = new Object JavaDoc[0];
548             Debug.methodCall(this, "getAutoCommit", args);
549             Debug.returnValue(this, "getAutoCommit",
550                 new Boolean JavaDoc(this.autoCommit));
551         }
552
553         return this.autoCommit;
554     }
555
556     /**
557      * A sub-space of this Connection's database may be selected by setting a
558      * catalog name. If the driver does not support catalogs, it will
559      * silently ignore this request
560      *
561      * <p>
562      * <b>Note:</b> MySQL's notion of catalogs are individual databases.
563      * </p>
564      *
565      * @param catalog the database for this connection to use
566      *
567      * @throws java.sql.SQLException if a database access error occurs
568      */

569     public void setCatalog(String JavaDoc catalog) throws java.sql.SQLException JavaDoc {
570         if (Driver.TRACE) {
571             Object JavaDoc[] args = { catalog };
572             Debug.methodCall(this, "setCatalog", args);
573         }
574
575         checkClosed();
576
577         String JavaDoc quotedId = this.dbmd.getIdentifierQuoteString();
578
579         if ((quotedId == null) || quotedId.equals(" ")) {
580             quotedId = "";
581         }
582
583         StringBuffer JavaDoc query = new StringBuffer JavaDoc("USE ");
584         query.append(quotedId);
585         query.append(catalog);
586         query.append(quotedId);
587
588         execSQL(query.toString(), -1, catalog);
589         this.database = catalog;
590     }
591
592     /**
593      * Return the connections current catalog name, or null if no catalog name
594      * is set, or we dont support catalogs.
595      *
596      * <p>
597      * <b>Note:</b> MySQL's notion of catalogs are individual databases.
598      * </p>
599      *
600      * @return the current catalog name or null
601      *
602      * @exception java.sql.SQLException if a database access error occurs
603      */

604     public String JavaDoc getCatalog() throws java.sql.SQLException JavaDoc {
605         if (Driver.TRACE) {
606             Object JavaDoc[] args = new Object JavaDoc[0];
607             Debug.methodCall(this, "getCatalog", args);
608             Debug.returnValue(this, "getCatalog", this.database);
609         }
610
611         return this.database;
612     }
613
614     /**
615      * Returns whether we clobber streaming results on new queries, or issue an
616      * error?
617      *
618      * @return true if we should implicitly close streaming result sets upon
619      * receiving a new query
620      */

621     public boolean getClobberStreamingResults() {
622         return this.clobberStreamingResults;
623     }
624
625     /**
626      * DOCUMENT ME!
627      *
628      * @return DOCUMENT ME!
629      */

630     public boolean isClosed() {
631         if (Driver.TRACE) {
632             Object JavaDoc[] args = new Object JavaDoc[0];
633             Debug.methodCall(this, "isClosed", args);
634             Debug.returnValue(this, "isClosed", new Boolean JavaDoc(this.isClosed));
635         }
636
637         return this.isClosed;
638     }
639
640     /**
641      * Returns the character encoding for this Connection
642      *
643      * @return the character encoding for this connection.
644      */

645     public String JavaDoc getEncoding() {
646         return this.encoding;
647     }
648
649     /**
650      * @see Connection#setHoldability(int)
651      */

652     public void setHoldability(int arg0) throws SQLException JavaDoc {
653         // do nothing
654
}
655
656     /**
657      * @see Connection#getHoldability()
658      */

659     public int getHoldability() throws SQLException JavaDoc {
660         return ResultSet.CLOSE_CURSORS_AT_COMMIT;
661     }
662
663     /**
664      * NOT JDBC-Compliant, but clients can use this method to determine how
665      * long this connection has been idle. This time (reported in
666      * milliseconds) is updated once a query has completed.
667      *
668      * @return number of ms that this connection has been idle, 0 if the driver
669      * is busy retrieving results.
670      */

671     public long getIdleFor() {
672         if (this.lastQueryFinishedTime == 0) {
673             return 0;
674         } else {
675             long now = System.currentTimeMillis();
676             long idleTime = now - this.lastQueryFinishedTime;
677
678             return idleTime;
679         }
680     }
681
682     /**
683      * Should we tell MySQL that we're an interactive client
684      *
685      * @return true if isInteractiveClient was set to true.
686      */

687     public boolean isInteractiveClient() {
688         return isInteractiveClient;
689     }
690
691     /**
692      * A connection's database is able to provide information describing its
693      * tables, its supported SQL grammar, its stored procedures, the
694      * capabilities of this connection, etc. This information is made
695      * available through a DatabaseMetaData object.
696      *
697      * @return a DatabaseMetaData object for this connection
698      *
699      * @exception java.sql.SQLException if a database access error occurs
700      */

701     public java.sql.DatabaseMetaData JavaDoc getMetaData() throws java.sql.SQLException JavaDoc {
702         checkClosed();
703
704         return new DatabaseMetaData(this, this.database);
705     }
706
707     /**
708      * DOCUMENT ME!
709      *
710      * @return
711      */

712     public String JavaDoc getNegativeInfinityRep() {
713         return negativeInfinityRep;
714     }
715
716     /**
717      * DOCUMENT ME!
718      *
719      * @return
720      */

721     public boolean isNegativeInfinityRepIsClipped() {
722         return negativeInfinityRepIsClipped;
723     }
724
725     /**
726      * DOCUMENT ME!
727      *
728      * @return
729      */

730     public String JavaDoc getNotANumberRep() {
731         return notANumberRep;
732     }
733
734     /**
735      * DOCUMENT ME!
736      *
737      * @return
738      */

739     public boolean isNotANumberRepIsClipped() {
740         return notANumberRepIsClipped;
741     }
742
743     /**
744      * DOCUMENT ME!
745      *
746      * @return
747      */

748     public String JavaDoc getPositiveInfinityRep() {
749         return positiveInfinityRep;
750     }
751
752     /**
753      * DOCUMENT ME!
754      *
755      * @return
756      */

757     public boolean isPositiveInfinityRepIsClipped() {
758         return positiveInfinityRepIsClipped;
759     }
760
761     /**
762      * Should the driver do profiling?
763      *
764      * @param flag set to true to enable profiling.
765      *
766      * @throws SQLException if the connection is closed.
767      */

768     public void setProfileSql(boolean flag) throws SQLException JavaDoc {
769         // For re-connection
770
this.props.setProperty("profileSql", String.valueOf(flag));
771         getIO().setProfileSql(flag);
772     }
773
774     /**
775      * You can put a connection in read-only mode as a hint to enable database
776      * optimizations <B>Note:</B> setReadOnly cannot be called while in the
777      * middle of a transaction
778      *
779      * @param readOnly - true enables read-only mode; false disables it
780      *
781      * @exception java.sql.SQLException if a database access error occurs
782      */

783     public void setReadOnly(boolean readOnly) throws java.sql.SQLException JavaDoc {
784         if (Driver.TRACE) {
785             Object JavaDoc[] args = { new Boolean JavaDoc(readOnly) };
786             Debug.methodCall(this, "setReadOnly", args);
787             Debug.returnValue(this, "setReadOnly", new Boolean JavaDoc(readOnly));
788         }
789
790         checkClosed();
791         this.readOnly = readOnly;
792     }
793
794     /**
795      * Tests to see if the connection is in Read Only Mode. Note that we
796      * cannot really put the database in read only mode, but we pretend we can
797      * by returning the value of the readOnly flag
798      *
799      * @return true if the connection is read only
800      *
801      * @exception java.sql.SQLException if a database access error occurs
802      */

803     public boolean isReadOnly() throws java.sql.SQLException JavaDoc {
804         if (Driver.TRACE) {
805             Object JavaDoc[] args = new Object JavaDoc[0];
806             Debug.methodCall(this, "isReadOnly", args);
807             Debug.returnValue(this, "isReadOnly", new Boolean JavaDoc(this.readOnly));
808         }
809
810         return this.readOnly;
811     }
812
813     /**
814      * @see Connection#setSavepoint()
815      */

816     public java.sql.Savepoint JavaDoc setSavepoint() throws SQLException JavaDoc {
817         throw new NotImplemented();
818     }
819
820     /**
821      * @see Connection#setSavepoint(String)
822      */

823     public java.sql.Savepoint JavaDoc setSavepoint(String JavaDoc arg0)
824         throws SQLException JavaDoc {
825         throw new NotImplemented();
826     }
827
828     /**
829      * DOCUMENT ME!
830      *
831      * @return DOCUMENT ME!
832      */

833     public TimeZone JavaDoc getServerTimezone() {
834         return this.serverTimezone;
835     }
836
837     /**
838      * DOCUMENT ME!
839      *
840      * @param level DOCUMENT ME!
841      *
842      * @throws java.sql.SQLException DOCUMENT ME!
843      * @throws SQLException DOCUMENT ME!
844      */

845     public void setTransactionIsolation(int level) throws java.sql.SQLException JavaDoc {
846         if (Driver.TRACE) {
847             Object JavaDoc[] args = { new Integer JavaDoc(level) };
848             Debug.methodCall(this, "setTransactionIsolation", args);
849         }
850
851         checkClosed();
852
853         if (this.hasIsolationLevels) {
854             StringBuffer JavaDoc sql = new StringBuffer JavaDoc(
855                     "SET SESSION TRANSACTION ISOLATION LEVEL ");
856
857             switch (level) {
858             case java.sql.Connection.TRANSACTION_NONE:
859                 throw new SQLException JavaDoc("Transaction isolation level "
860                     + "NONE not supported by MySQL");
861
862             case java.sql.Connection.TRANSACTION_READ_COMMITTED:
863                 sql.append("READ COMMITTED");
864
865                 break;
866
867             case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
868                 sql.append("READ UNCOMMITTED");
869
870                 break;
871
872             case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
873            &n