Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/mysql/jdbc/Connection.java


1   /*
2    Copyright (C) 2002-2004 MySQL AB
3   
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of version 2 of the GNU General Public License as
6    published by the Free Software Foundation.
7    
8   
9    There are special exceptions to the terms and conditions of the GPL 
10   as it is applied to this software. View the full text of the 
11   exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
12   software distribution.
13  
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23   */
24  package com.mysql.jdbc;
25  
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.Reader;
29  import java.io.UnsupportedEncodingException;
30  import java.math.BigDecimal;
31  import java.net.URL;
32  import java.sql.CallableStatement;
33  import java.sql.Clob;
34  import java.sql.Date;
35  import java.sql.ParameterMetaData;
36  import java.sql.Ref;
37  import java.sql.SQLException;
38  import java.sql.Savepoint;
39  import java.sql.Time;
40  import java.sql.Timestamp;
41  import java.util.ArrayList;
42  import java.util.Calendar;
43  import java.util.HashMap;
44  import java.util.Iterator;
45  import java.util.List;
46  import java.util.Map;
47  import java.util.Properties;
48  import java.util.TimeZone;
49  import java.util.TreeMap;
50  
51  
52  /**
53   * A Connection represents a session with a specific database.  Within the
54   * context of a Connection, SQL statements are executed and results are
55   * returned.
56   * 
57   * <P>
58   * A Connection's database is able to provide information describing its
59   * tables, its supported SQL grammar, its stored procedures, the capabilities
60   * of this connection, etc.  This information is obtained with the getMetaData
61   * method.
62   * </p>
63   *
64   * @author Mark Matthews
65   * @version $Id: Connection.java,v 1.31.2.85 2004/11/15 00:23:07 mmatthew Exp $
66   *
67   * @see java.sql.Connection
68   */
69  public class Connection implements java.sql.Connection {
70      // The command used to "ping" the database.
71      // Newer versions of MySQL server have a ping() command,
72      // but this works for everything
73      private static final String PING_COMMAND = "SELECT 1";
74  
75      /**
76       * Map mysql transaction isolation level name to
77       * java.sql.Connection.TRANSACTION_XXX
78       */
79      private static Map mapTransIsolationName2Value = null;
80  
81      /**
82       * The mapping between MySQL charset names and Java charset names.
83       * Initialized by loadCharacterSetMapping()
84       */
85      private static Map charsetMap;
86  
87      /** Table of multi-byte charsets. Initialized by loadCharacterSetMapping() */
88      private static Map multibyteCharsetsMap;
89  
90      /** Default socket factory classname */
91      private static final String DEFAULT_SOCKET_FACTORY = StandardSocketFactory.class
92          .getName();
93  
94      static {
95          loadCharacterSetMapping();
96          mapTransIsolationName2Value = new HashMap(8);
97          mapTransIsolationName2Value.put("READ-UNCOMMITED",
98              new Integer(TRANSACTION_READ_UNCOMMITTED));
99          mapTransIsolationName2Value.put("READ-UNCOMMITTED",
100             new Integer(TRANSACTION_READ_UNCOMMITTED));
101         mapTransIsolationName2Value.put("READ-COMMITTED",
102             new Integer(TRANSACTION_READ_COMMITTED));
103         mapTransIsolationName2Value.put("REPEATABLE-READ",
104             new Integer(TRANSACTION_REPEATABLE_READ));
105         mapTransIsolationName2Value.put("SERIALIZABLE",
106             new Integer(TRANSACTION_SERIALIZABLE));
107     }
108 
109     /**
110      * Marker for character set converter not being available (not written,
111      * multibyte, etc)  Used to prevent multiple instantiation requests.
112      */
113     private final static Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object();
114     boolean parserKnowsUnicode = false;
115 
116     /** Internal DBMD to use for various database-version specific features */
117     private DatabaseMetaData dbmd = null;
118 
119     /** The list of host(s) to try and connect to */
120     private List hostList = null;
121 
122     /** A map of SQL to parsed prepared statement parameters. */
123     private Map cachedPreparedStatementParams;
124 
125     /**
126      * Holds cached mappings to charset converters to avoid static
127      * synchronization and at the same time save memory (each charset
128      * converter takes approx 65K of static data).
129      */
130     private Map charsetConverterMap = new HashMap(CharsetMapping.JAVA_TO_MYSQL_CHARSET_MAP
131             .size());
132 
133     /** A map of statements that have had setMaxRows() called on them */
134     private Map statementsUsingMaxRows;
135 
136     /**
137      * The type map for UDTs (not implemented, but used by some third-party
138      * vendors, most notably IBM WebSphere)
139      */
140     private Map typeMap;
141 
142     /** The I/O abstraction interface (network conn to MySQL server */
143     private MysqlIO io = null;
144 
145     /** Mutex */
146     private final Object mutex = new Object();
147 
148     /** The map of server variables that we retrieve at connection init. */
149     private Map serverVariables = null;
150 
151     /** The driver instance that created us */
152     private NonRegisteringDriver myDriver;
153 
154     /** Properties for this connection specified by user */
155     private Properties props = null;
156 
157     /** The database we're currently using (called Catalog in JDBC terms). */
158     private String database = null;
159 
160     /** If we're doing unicode character conversions, what encoding do we use? */
161     private String encoding = null;
162 
163     /** The hostname we're connected to */
164     private String host = null;
165 
166     /** The JDBC URL we're using */
167     private String myURL = null;
168 
169     /** What does MySQL call this encoding? */
170     private String mysqlEncodingName = null;
171     private String negativeInfinityRep = MysqlDefs.MIN_DOUBLE_VAL_STRING;
172     private String notANumberRep = MysqlDefs.NAN_VAL_STRING;
173 
174     /** The password we used */
175     private String password = null;
176     private String positiveInfinityRep = MysqlDefs.MAX_DOUBLE_VAL_STRING;
177 
178     /** Classname for socket factory */
179     private String socketFactoryClassName = null;
180 
181     /** The user we're connected as */
182     private String user = null;
183 
184     /** Where was the connection _explicitly_ closed by the application? */
185     private Throwable explicitCloseLocation;
186 
187     /** If the connection was forced closed, why was it  forced closed? */
188     private Throwable forcedCloseReason;
189     private TimeZone defaultTimeZone;
190 
191     /** The timezone of the server */
192     private TimeZone serverTimezone = null;
193 
194     /**
195      * We need this 'bootstrapped', because 4.1 and newer will send fields back
196      * with this even before we fill this dynamically from the server.
197      */
198     private String[] indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
199 
200     /** Allow LOAD LOCAL INFILE (defaults to true) */
201     private boolean allowLoadLocalInfile = true;
202 
203     /** Should we clear the input stream each query? */
204     private boolean alwaysClearStream = false;
205 
206     /** Are we in autoCommit mode? */
207     private boolean autoCommit = true;
208 
209     /** SHould we cache the parsing of prepared statements? */
210     private boolean cachePreparedStatements = false;
211 
212     /** Should we capitalize mysql types */
213     private boolean capitalizeDBMDTypes = false;
214 
215     /** Should we clobber streaming results on new queries, or issue an error? */
216     private boolean clobberStreamingResults = false;
217 
218     /**
219      * Should we continue processing batch commands if one fails. The JDBC spec
220      * allows either way, so we let the user choose
221      */
222     private boolean continueBatchOnError = true;
223 
224     /** Should we do unicode character conversions? */
225     private boolean doUnicode = false;
226 
227     /** When failed-over, set connection to read-only? */
228     private boolean failOverReadOnly = true;
229 
230     /** Are we failed-over to a non-master host */
231     private boolean failedOver = false;
232 
233     /** Does the server suuport isolation levels? */
234     private boolean hasIsolationLevels = false;
235 
236     /** Does this version of MySQL support quoted identifiers? */
237     private boolean hasQuotedIdentifiers = false;
238 
239     //
240     // This is for the high availability :) routines
241     //
242     private boolean highAvailability = false;
243 
244     /** Ignore non-transactional table warning for rollback? */
245     private boolean ignoreNonTxTables = false;
246 
247     /** Has this connection been closed? */
248     private boolean isClosed = true;
249 
250     /** Should we tell MySQL that we're an interactive client? */
251     private boolean isInteractiveClient = false;
252 
253     /** Is the server configured to use lower-case table names only? */
254     private boolean lowerCaseTableNames = false;
255 
256     /** Has the max-rows setting been changed from the default? */
257     private boolean maxRowsChanged = false;
258     private boolean needsPing = false;
259     private boolean negativeInfinityRepIsClipped = true;
260     private boolean notANumberRepIsClipped = true;
261 
262     /** Do we expose sensitive information in exception and error messages? */
263     private boolean paranoid = false;
264 
265     /** Should we do 'extra' sanity checks? */
266     private boolean pedantic = false;
267     private boolean positiveInfinityRepIsClipped = true;
268 
269     /** Should we retrieve 'info' messages from the server? */
270     private boolean readInfoMsg = false;
271 
272     /** Are we in read-only mode? */
273     private boolean readOnly = false;
274 
275     /**
276      * If autoReconnect == true, should we attempt to reconnect at transaction
277      * boundaries?
278      */
279     private boolean reconnectAtTxEnd = false;
280 
281     /** Do we relax the autoCommit semantics? (For enhydra, for example) */
282     private boolean relaxAutoCommit = false;
283 
284     /** Do we need to correct endpoint rounding errors */
285     private boolean strictFloatingPoint = false;
286 
287     /** Do we check all keys for updatable result sets? */
288     private boolean strictUpdates = true;
289 
290     /** Are transactions supported by the MySQL server we are connected to? */
291     private boolean transactionsSupported = false;
292 
293     /** Has ANSI_QUOTES been enabled on the server? */
294     private boolean useAnsiQuotes = false;
295 
296     /** Should we use compression? */
297     private boolean useCompression = false;
298 
299     /** Can we use the "ping" command rather than a query? */
300     private boolean useFastPing = false;
301 
302     /** Should we tack on hostname in DBMD.getTable/ColumnPrivileges()? */
303     private boolean useHostsInPrivileges = true;
304     
305     /** Should we only use the error message from the server when reporting
306      * errors?
307      */
308     private boolean useOnlyServerErrorMessages = true;
309 
310     /** Should we use SSL? */
311     private boolean useSSL = false;
312 
313     /**
314      * Should we use stream lengths in prepared statements? (true by default ==
315      * JDBC compliant)
316      */
317     private boolean useStreamLengthsInPrepStmts = true;
318 
319     /** Should we use timezone information? */
320     private boolean useTimezone = false;
321 
322     /** Should we return PreparedStatements for UltraDev's stupid bug? */
323     private boolean useUltraDevWorkAround = false;
324     private boolean useUnbufferedInput = true;
325     private double initialTimeout = 2.0D;
326 
327     /** How many hosts are in the host list? */
328     private int hostListSize = 0;
329 
330     /** isolation level */
331     private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
332 
333     /**
334      * The largest packet we can send (changed once we know what the server
335      * supports, we get this at connection init).
336      */
337     private int maxAllowedPacket = 65536;
338     private int maxReconnects = 3;
339 
340     /**
341      * The max rows that a result set can contain. Defaults to -1, which
342      * according to the JDBC spec means "all".
343      */
344     private int maxRows = -1;
345     private int netBufferLength = 16384;
346 
347     /** The port number we're connected to (defaults to 3306) */
348     private int port = 3306;
349 
350     /**
351      * If prepared statement caching is enabled, what should the threshold
352      * length of the SQL to prepare should be in order to _not_ cache?
353      */
354     private int preparedStatementCacheMaxSqlSize = 256;
355 
356     /** If prepared statement caching is enabled, how many should we cache? */
357     private int preparedStatementCacheSize = 25;
358 
359     /**
360      * How many queries should we wait before we try to re-connect to the
361      * master, when we are failing over to replicated hosts Defaults to 50
362      */
363     private int queriesBeforeRetryMaster = 50;
364 
365     /** What should we set the socket timeout to? */
366     private int socketTimeout = 0; // infinite
367 
368     /** When did the last query finish? */
369     private long lastQueryFinishedTime = 0;
370 
371     /** When did the master fail? */
372     private long masterFailTimeMillis = 0L;
373 
374     /** Number of queries we've issued since the master failed */
375     private long queriesIssuedFailedOver = 0;
376 
377     /**
378      * How many seconds should we wait before retrying to connect to the master
379      * if failed over? We fall back when either queriesBeforeRetryMaster or
380      * secondsBeforeRetryMaster is reached.
381      */
382     private long secondsBeforeRetryMaster = 30L;
383 
384     /**
385      * Creates a connection to a MySQL Server.
386      *
387      * @param host the hostname of the database server
388      * @param port the port number the server is listening on
389      * @param info a Properties[] list holding the user and password
390      * @param database the database to connect to
391      * @param url the URL of the connection
392      * @param d the Driver instantation of the connection
393      *
394      * @exception java.sql.SQLException if a database access error occurs
395      * @throws SQLException DOCUMENT ME!
396      */
397     Connection(String host, int port, Properties info, String database,
398         String url, NonRegisteringDriver d) throws java.sql.SQLException {
399         if (Driver.TRACE) {
400             Object[] args = { host, new Integer(port), info, database, url, d };
401             Debug.methodCall(this, "constructor", args);
402         }
403 
404         this.defaultTimeZone = TimeZone.getDefault();
405 
406         this.serverVariables = new HashMap();
407 
408         if (host == null) {
409             this.host = "localhost";
410             hostList = new ArrayList();
411             hostList.add(this.host);
412         } else if (host.indexOf(",") != -1) {
413             // multiple hosts separated by commas (failover)
414             hostList = StringUtils.split(host, ",", true);
415         } else {
416             this.host = host;
417             hostList = new ArrayList();
418             hostList.add(this.host);
419         }
420 
421         hostListSize = hostList.size();
422         this.port = port;
423 
424         if (database == null) {
425             database = "";
426         }
427 
428         this.database = database;
429         this.myURL = url;
430         this.myDriver = d;
431         this.user = info.getProperty("user");
432         this.password = info.getProperty("password");
433 
434         if ((this.user == null) || this.user.equals("")) {
435             this.user = "nobody";
436         }
437 
438         if (this.password == null) {
439             this.password = "";
440         }
441 
442         this.props = info;
443         initializeDriverProperties(info);
444 
445         if (Driver.DEBUG) {
446             System.out.println("Connect: " + this.user + " to " + this.database);
447         }
448 
449         try {
450             createNewIO(false);
451             this.dbmd = new DatabaseMetaData(this, this.database);
452         } catch (java.sql.SQLException ex) {
453             cleanup(ex);
454 
455             // don't clobber SQL exceptions
456             throw ex;
457         } catch (Exception ex) {
458             cleanup(ex);
459 
460             StringBuffer mesg = new StringBuffer();
461 
462             if (!useParanoidErrorMessages()) {
463                 mesg.append("Cannot connect to MySQL server on ");
464                 mesg.append(this.host);
465                 mesg.append(":");
466                 mesg.append(this.port);
467                 mesg.append(".\n\n");
468                 mesg.append("Make sure that there is a MySQL server ");
469                 mesg.append("running on the machine/port you are trying ");
470                 mesg.append(
471                     "to connect to and that the machine this software is "
472                     + "running on ");
473                 mesg.append("is able to connect to this host/port "
474                     + "(i.e. not firewalled). ");
475                 mesg.append(
476                     "Also make sure that the server has not been started "
477                     + "with the --skip-networking ");
478                 mesg.append("flag.\n\n");
479             } else {
480                 mesg.append("Unable to connect to database.");
481             }
482 
483             mesg.append("Underlying exception: \n\n");
484             mesg.append(ex.getClass().getName());
485 
486             if (!this.paranoid) {
487                 mesg.append(Util.stackTraceToString(ex));
488             }
489 
490             throw new java.sql.SQLException(mesg.toString(),
491                 SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
492         }
493     }
494 
495     /**
496      * If a connection is in auto-commit mode, than all its SQL statements will
497      * be executed and committed as individual transactions.  Otherwise, its
498      * SQL statements are grouped into transactions that are terminated by
499      * either commit() or rollback().  By default, new connections are in
500      * auto- commit mode.  The commit occurs when the statement completes or
501      * the next execute occurs, whichever comes first.  In the case of
502      * statements returning a ResultSet, the statement completes when the last
503      * row of the ResultSet has been retrieved or the ResultSet has been
504      * closed.  In advanced cases, a single statement may return multiple
505      * results as well as output parameter values.  Here the commit occurs
506      * when all results and output param values have been retrieved.
507      * 
508      * <p>
509      * <b>Note:</b> MySQL does not support transactions, so this method is a
510      * no-op.
511      * </p>
512      *
513      * @param autoCommit - true enables auto-commit; false disables it
514      *
515      * @exception java.sql.SQLException if a database access error occurs
516      * @throws SQLException DOCUMENT ME!
517      */
518     public void setAutoCommit(boolean autoCommit) throws java.sql.SQLException {
519         if (Driver.TRACE) {
520             Object[] args = { new Boolean(autoCommit) };
521             Debug.methodCall(this, "setAutoCommit", args);
522         }
523 
524         checkClosed();
525 
526         if (this.transactionsSupported) {
527             // this internal value must be set first as failover depends on it
528             // being set to true to fail over (which is done by most
529             // app servers and connection pools at the end of
530             // a transaction), and the driver issues an implicit set
531             // based on this value when it (re)-connects to a server
532             // so the value holds across connections
533             //
534             this.autoCommit = autoCommit;
535 
536             //
537             // This is to catch the 'edge' case of
538             // autoCommit going from true -> false
539             //
540             if ((this.highAvailability || this.failedOver) && !this.autoCommit
541                     && this.needsPing) {
542                 pingAndReconnect(true);
543             }
544 
545             String sql = "SET autocommit=" + (autoCommit ? "1" : "0");
546             execSQL(sql, -1, this.database);
547         } else {
548             if ((autoCommit == false) && (this.relaxAutoCommit == false)) {
549                 throw new SQLException("MySQL Versions Older than 3.23.15 "
550                     + "do not support transactions",
551                     SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
552             } else {
553                 this.autoCommit = autoCommit;
554             }
555         }
556 
557         return;
558     }
559 
560     /**
561      * gets the current auto-commit state
562      *
563      * @return Current state of the auto-commit mode
564      *
565      * @exception java.sql.SQLException (why?)
566      *
567      * @see setAutoCommit
568      */
569     public boolean getAutoCommit() throws java.sql.SQLException {
570         if (Driver.TRACE) {
571             Object[] args = new Object[0];
572             Debug.methodCall(this, "getAutoCommit", args);
573             Debug.returnValue(this, "getAutoCommit",
574                 new Boolean(this.autoCommit));
575         }
576 
577         return this.autoCommit;
578     }
579 
580     /**
581      * A sub-space of this Connection's database may be selected by setting a
582      * catalog name.  If the driver does not support catalogs, it will
583      * silently ignore this request
584      * 
585      * <p>
586      * <b>Note:</b> MySQL's notion of catalogs are individual databases.
587      * </p>
588      *
589      * @param catalog the database for this connection to use
590      *
591      * @throws java.sql.SQLException if a database access error occurs
592      */
593     public void setCatalog(String catalog) throws java.sql.SQLException {
594         if (Driver.TRACE) {
595             Object[] args = { catalog };
596             Debug.methodCall(this, "setCatalog", args);
597         }
598 
599         checkClosed();
600 
601         String quotedId = this.dbmd.getIdentifierQuoteString();
602 
603         if ((quotedId == null) || quotedId.equals(" ")) {
604             quotedId = "";
605         }
606 
607         StringBuffer query = new StringBuffer("USE ");
608         query.append(quotedId);
609         query.append(catalog);
610         query.append(quotedId);
611 
612         execSQL(query.toString(), -1, catalog);
613         this.database = catalog;
614     }
615 
616     /**
617      * Return the connections current catalog name, or null if no catalog name
618      * is set, or we dont support catalogs.
619      * 
620      * <p>
621      * <b>Note:</b> MySQL's notion of catalogs are individual databases.
622      * </p>
623      *
624      * @return the current catalog name or null
625      *
626      * @exception java.sql.SQLException if a database access error occurs
627      */
628     public String getCatalog() throws java.sql.SQLException {
629         if (Driver.TRACE) {
630             Object[] args = new Object[0];
631             Debug.methodCall(this, "getCatalog", args);
632             Debug.returnValue(this, "getCatalog", this.database);
633         }
634 
635         return this.database;
636     }
637 
638     /**
639      * Returns whether we clobber streaming results on new queries, or issue an
640      * error?
641      *
642      * @return true if we should implicitly close streaming result sets upon
643      *         receiving a new query
644      */
645     public boolean getClobberStreamingResults() {
646         return this.clobberStreamingResults;
647     }
648 
649     /**
650      * DOCUMENT ME!
651      *
652      * @return DOCUMENT ME!
653      */
654     public boolean isClosed() {
655         if (Driver.TRACE) {
656             Object[] args = new Object[0];
657             Debug.methodCall(this, "isClosed", args);
658             Debug.returnValue(this, "isClosed", new Boolean(this.isClosed));
659         }
660 
661         return this.isClosed;
662     }
663 
664     /**
665      * Returns the character encoding for this Connection
666      *
667      * @return the character encoding for this connection.
668      */
669     public String getEncoding() {
670         return this.encoding;
671     }
672 
673     /**
674      * @see Connection#setHoldability(int)
675      */
676     public void setHoldability(int arg0) throws SQLException {
677         // do nothing
678     }
679 
680     /**
681      * @see Connection#getHoldability()
682      */
683     public int getHoldability() throws SQLException {
684         return ResultSet.CLOSE_CURSORS_AT_COMMIT;
685     }
686 
687     /**
688      * NOT JDBC-Compliant, but clients can use this method to determine how
689      * long this connection has been idle. This time (reported in
690      * milliseconds) is updated once a query has completed.
691      *
692      * @return number of ms that this connection has been idle, 0 if the driver
693      *         is busy retrieving results.
694      */
695     public long getIdleFor() {
696         if (this.lastQueryFinishedTime == 0) {
697             return 0;
698         } else {
699             long now = System.currentTimeMillis();
700             long idleTime = now - this.lastQueryFinishedTime;
701 
702             return idleTime;
703         }
704     }
705 
706     /**
707      * Should we tell MySQL that we're an interactive client
708      *
709      * @return true if isInteractiveClient was set to true.
710      */
711     public boolean isInteractiveClient() {
712         return isInteractiveClient;
713     }
714 
715     /**
716      * A connection's database is able to provide information describing its
717      * tables, its supported SQL grammar, its stored procedures, the
718      * capabilities of this connection, etc.  This information is made
719      * available through a DatabaseMetaData object.
720      *
721      * @return a DatabaseMetaData object for this connection
722      *
723      * @exception java.sql.SQLException if a database access error occurs
724      */
725     public java.sql.DatabaseMetaData getMetaData() throws java.sql.SQLException {
726         checkClosed();
727 
728         return new DatabaseMetaData(this, this.database);
729     }
730 
731     /**
732      * DOCUMENT ME!
733      *
734      * @return
735      */
736     public String getNegativeInfinityRep() {
737         return negativeInfinityRep;
738     }
739 
740     /**
741      * DOCUMENT ME!
742      *
743      * @return
744      */
745     public boolean isNegativeInfinityRepIsClipped() {
746         return negativeInfinityRepIsClipped;
747     }
748 
749     /**
750      * DOCUMENT ME!
751      *
752      * @return
753      */
754     public String getNotANumberRep() {
755         return notANumberRep;
756     }
757 
758     /**
759      * DOCUMENT ME!
760      *
761      * @return
762      */
763     public boolean isNotANumberRepIsClipped() {
764         return notANumberRepIsClipped;
765     }
766 
767     /**
768      * DOCUMENT ME!
769      *
770      * @return
771      */
772     public String getPositiveInfinityRep() {
773         return positiveInfinityRep;
774     }
775 
776     /**
777      * DOCUMENT ME!
778      *
779      * @return
780      */
781     public boolean isPositiveInfinityRepIsClipped() {
782         return positiveInfinityRepIsClipped;
783     }
784 
785     /**
786      * Should the driver do profiling?
787      *
788      * @param flag set to true to enable profiling.
789      *
790      * @throws SQLException if the connection is closed.
791      */
792     public void setProfileSql(boolean flag) throws SQLException {
793         // For re-connection
794         this.props.setProperty("profileSql", String.valueOf(flag));
795         getIO().setProfileSql(flag);
796     }
797 
798     /**
799      * You can put a connection in read-only mode as a hint to enable database
800      * optimizations <B>Note:</B> setReadOnly cannot be called while in the
801      * middle of a transaction
802      *
803      * @param readOnly - true enables read-only mode; false disables it
804      *
805      * @exception java.sql.SQLException if a database access error occurs
806      */
807     public void setReadOnly(boolean readOnly) throws java.sql.SQLException {
808         if (Driver.TRACE) {
809             Object[] args = { new Boolean(readOnly) };
810             Debug.methodCall(this, "setReadOnly", args);
811             Debug.returnValue(this, "setReadOnly", new Boolean(readOnly));
812         }
813 
814         checkClosed();
815         this.readOnly = readOnly;
816     }
817 
818     /**
819      * Tests to see if the connection is in Read Only Mode.  Note that we
820      * cannot really put the database in read only mode, but we pretend we can
821      * by returning the value of the readOnly flag
822      *
823      * @return true if the connection is read only
824      *
825      * @exception java.sql.SQLException if a database access error occurs
826      */
827     public boolean isReadOnly() throws java.sql.SQLException {
828         if (Driver.TRACE) {
829             Object[] args = new Object[0];
830             Debug.methodCall(this, "isReadOnly", args);
831             Debug.returnValue(this, "isReadOnly", new Boolean(this.readOnly));
832         }
833 
834         return this.readOnly;
835     }
836 
837     /**
838      * @see Connection#setSavepoint()
839      */
840     public java.sql.Savepoint setSavepoint() throws SQLException {
841         throw new NotImplemented();
842     }
843 
844     /**
845      * @see Connection#setSavepoint(String)
846      */
847     public java.sql.Savepoint setSavepoint(String arg0)
848         throws SQLException {
849         throw new NotImplemented();
850     }
851 
852     /**
853      * DOCUMENT ME!
854      *
855      * @return DOCUMENT ME!
856      */
857     public TimeZone getServerTimezone() {
858         return this.serverTimezone;
859     }
860 
861     /**
862      * DOCUMENT ME!
863      *
864      * @param level DOCUMENT ME!
865      *
866      * @throws java.sql.SQLException DOCUMENT ME!
867      * @throws SQLException DOCUMENT ME!
868      */
869     public void setTransactionIsolation(int level) throws java.sql.SQLException {
870         if (Driver.TRACE) {
871             Object[] args = { new Integer(level) };
872             Debug.methodCall(this, "setTransactionIsolation", args);
873         }
874 
875         checkClosed();
876 
877         if (this.hasIsolationLevels) {
878             StringBuffer sql = new StringBuffer(
879                     "SET SESSION TRANSACTION ISOLATION LEVEL ");
880 
881             switch (level) {
882             case java.sql.Connection.TRANSACTION_NONE:
883                 throw new SQLException("Transaction isolation level "
884                     + "NONE not supported by MySQL");
885 
886             case java.sql.Connection.TRANSACTION_READ_COMMITTED:
887                 sql.append("READ COMMITTED");
888 
889                 break;
890 
891             case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
892                 sql.append("READ UNCOMMITTED");
893 
894                 break;
895 
896             case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
897                 sql.append("REPEATABLE READ");
898 
899                 break;
900 
901             case java.sql.Connection.TRANSACTION_SERIALIZABLE:
902                 sql.append("SERIALIZABLE");
903 
904                 break;
905 
906             default:
907                 throw new SQLException("Unsupported transaction "
908                     + "isolation level '" + level + "'", "S1C00");
909             }
910 
911             execSQL(sql.toString(), -1, this.database);
912             isolationLevel = level;
913         } else {
914             throw new java.sql.SQLException("Transaction Isolation Levels are "
915                 + "not supported on MySQL versions older than 3.23.36.", "S1C00");
916         }
917     }
918 
919     /**
920      * Get this Connection's current transaction isolation mode.
921      *
922      * @return the current TRANSACTION_ mode value
923      *
924      * @exception java.sql.SQLException if a database access error occurs
925      * @throws SQLException DOCUMENT ME!
926      */
927     public int getTransactionIsolation() throws java.sql.SQLException {
928         if (Driver.TRACE) {
929             Object[] args = new Object[0];
930             Debug.methodCall(this, "getTransactionIsolation", args);
931             Debug.returnValue(this, "getTransactionIsolation",
932                 new Integer(isolationLevel));
933         }
934 
935         if (this.hasIsolationLevels) {
936             java.sql.Statement stmt = null;
937             java.sql.ResultSet rs = null;
938 
939             try {
940                 stmt = this.createStatement();
941 
942                 if (stmt.getMaxRows() != 0) {
943                     stmt.setMaxRows(0);
944                 }
945 
946                 String query = null;
947 
948                 if (this.io.versionMeetsMinimum(4, 0, 3)) {
949                     query = "SHOW VARIABLES LIKE 'tx_isolation'";
950                 } else {
951                     query = "SHOW VARIABLES LIKE 'transaction_isolation'";
952                 }
953 
954                 rs = stmt.executeQuery(query);
955 
956                 if (rs.next()) {
957                     String s = rs.getString(2);
958 
959                     if (s != null) {
960                         Integer intTI = (Integer) mapTransIsolationName2Value
961                             .get(s);
962 
963                         if (intTI != null) {
964                             return intTI.intValue();
965                         }
966                     }
967 
968                     throw new SQLException(
969                         "Could not map transaction isolation '" + s
970                         + " to a valid JDBC level.",
971                         SQLError.SQL_STATE_GENERAL_ERROR);
972                 } else {
973                     throw new SQLException("Could not retrieve transaction isolation level from server",
974                         SQLError.SQL_STATE_GENERAL_ERROR);
975                 }
976             } finally {
977                 if (rs != null) {
978                     try {
979                         rs.close();
980                     } catch (Exception ex) {
981                         // ignore
982                     }
983 
984                     rs = null;
985                 }
986 
987                 if (stmt != null) {
988                     try {
989                         stmt.close();
990                     } catch (Exception ex) {
991                         // ignore
992                     }
993 
994                     stmt = null;
995                 }
996             }
997         }
998 
999         return isolationLevel;
1000    }
1001
1002    /**
1003     * JDBC 2.0 Install a type-map object as the default type-map for this
1004     * connection
1005     *
1006     * @param map the type mapping
1007     *
1008     * @throws SQLException if a database error occurs.
1009     */
1010    public void setTypeMap(java.util.Map map) throws SQLException {
1011        this.typeMap = map;
1012    }
1013
1014    /**
1015     * JDBC 2.0 Get the type-map object associated with this connection. By
1016     * default, the map returned is empty.
1017     *
1018     * @return the type map
1019     *
1020     * @throws SQLException if a database error occurs
1021     */
1022    public synchronized java.util.Map getTypeMap() throws SQLException {
1023        if (this.typeMap == null) {
1024            this.typeMap = new HashMap();
1025        }
1026
1027        return this.typeMap;
1028    }
1029
1030    /**
1031     * The first warning reported by calls on this Connection is returned.
1032     * <B>Note:</B> Sebsequent warnings will be changed to this
1033     * java.sql.SQLWarning
1034     *
1035     * @return the first java.sql.SQLWarning or null
1036     *
1037     * @exception java.sql.SQLException if a database access error occurs
1038     */
1039    public java.sql.SQLWarning getWarnings() throws java.sql.SQLException {
1040        if (Driver.TRACE) {
1041            Object[] args = new Object[0];
1042            Debug.methodCall(this, "getWarnings", args);
1043            Debug.returnValue(this, "getWarnings", null);
1044        }
1045
1046        return null;
1047    }
1048
1049    /**
1050     * Allow use of LOAD LOCAL INFILE?
1051     *
1052     * @return true if allowLoadLocalInfile was set to true.
1053     */
1054    public boolean allowLoadLocalInfile() {
1055        return this.allowLoadLocalInfile;
1056    }
1057
1058    /**
1059     * DOCUMENT ME!
1060     *
1061     * @return DOCUMENT ME!
1062     */
1063    public boolean capitalizeDBMDTypes() {
1064        return this.capitalizeDBMDTypes;
1065    }
1066
1067    /**
1068     * Changes the user on this connection by performing a re-authentication.
1069     * If authentication fails, the connection will remain under the context
1070     * of the current user.
1071     *
1072     * @param userName the username to authenticate with
1073     * @param newPassword the password to authenticate with
1074     *
1075     * @throws SQLException if authentication fails, or some other error occurs
1076     *         while performing the command.
1077     */
1078    public void changeUser(String userName, String newPassword)
1079        throws SQLException {
1080        if ((userName == null) || userName.equals("")) {
1081            userName = "";
1082        }
1083
1084        if (newPassword == null) {
1085            newPassword = "";
1086        }
1087
1088        this.io.changeUser(userName, newPassword, this.database);
1089        this.user = userName;
1090        this.password = newPassword;
1091        
1092        if (this.io.versionMeetsMinimum(4, 1, 0)) {
1093          configureClientCharacterSet();
1094        }
1095    }
1096
1097    /**
1098     * After this call, getWarnings returns null until a new warning is
1099     * reported for this connection.
1100     *
1101     * @exception java.sql.SQLException if a database access error occurs
1102     */
1103    public void clearWarnings() throws java.sql.SQLException {
1104        if (Driver.TRACE) {
1105            Object[] args = new Object[0];
1106            Debug.methodCall(this, "clearWarnings", args);
1107        }
1108
1109        // firstWarning = null;
1110    }
1111
1112    /**
1113     * In some cases, it is desirable to immediately release a Connection's
1114     * database and JDBC resources instead of waiting for them to be
1115     * automatically released (cant think why off the top of my head)
1116     * <B>Note:</B> A Connection is automatically closed when it is garbage
1117     * collected.  Certain fatal errors also result in a closed connection.
1118     *
1119     * @exception java.sql.SQLException if a database access error occurs
1120     */
1121    public void close() throws java.sql.SQLException {
1122        if (this.explicitCloseLocation == null) {
1123            this.explicitCloseLocation = new Throwable();
1124        }
1125
1126        realClose(true, true);
1127    }
1128
1129    /**
1130     * The method commit() makes all changes made since the previous
1131     * commit/rollback permanent and releases any database locks currently
1132     * held by the Connection.  This method should only be used when
1133     * auto-commit has been disabled.
1134     *
1135     * @exception java.sql.SQLException if a database access error occurs
1136     *
1137     * @see setAutoCommit
1138     */
1139    public void commit() throws java.sql.SQLException {
1140        if (Driver.TRACE) {
1141            Object[] args = new Object[0];
1142            Debug.methodCall(this, "commit", args);
1143        }
1144
1145        checkClosed();
1146
1147        try {
1148            // no-op if _relaxAutoCommit == true
1149            if (this.autoCommit && !this.relaxAutoCommit) {
1150                throw new SQLException("Can't call commit when autocommit=true",
1151                    SQLError.SQL_STATE_GENERAL_ERROR);
1152            } else if (this.transactionsSupported) {
1153                execSQL("commit", -1, this.database);
1154            }
1155        } finally {
1156            if (this.reconnectAtTxEnd) {
1157                pingAndReconnect(true);
1158            }
1159        }
1160
1161        return;
1162    }
1163
1164    //--------------------------JDBC 2.0-----------------------------
1165
1166    /**
1167     * JDBC 2.0 Same as createStatement() above, but allows the default result
1168     * set type and result set concurrency type to be overridden.
1169     *
1170     * @param resultSetType a result set type, see ResultSet.TYPE_XXX
1171     * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
1172     *
1173     * @return a new Statement object
1174     *
1175     * @exception SQLException if a database-access error occurs.
1176     */
1177    public java.sql.Statement createStatement(int resultSetType,
1178        int resultSetConcurrency) throws SQLException {
1179        checkClosed();
1180
1181        Statement stmt = new com.mysql.jdbc.Statement(this, this.database);
1182        stmt.setResultSetType(resultSetType);
1183        stmt.setResultSetConcurrency(resultSetConcurrency);
1184
1185        return stmt;
1186    }
1187
1188    /**
1189     * SQL statements without parameters are normally executed using Statement
1190     * objects.  If the same SQL statement is executed many times, it is more
1191     * efficient to use a PreparedStatement
1192     *
1193     * @return a new Statement object
1194     *
1195     * @throws SQLException passed through from the constructor
1196     */
1197    public java.sql.Statement createStatement() throws SQLException {
1198        return createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
1199            java.sql.ResultSet.CONCUR_READ_ONLY);
1200    }
1201
1202    /**
1203     * @see Connection#createStatement(int, int, int)
1204     */
1205    public java.sql.Statement createStatement(int resultSetType,
1206        int resultSetConcurrency, int resultSetHoldability)
1207        throws SQLException {
1208        if (this.pedantic) {
1209            if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
1210                throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
1211                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1212            }
1213        }
1214
1215        return createStatement(resultSetType, resultSetConcurrency);
1216    }
1217
1218    /**
1219     * Cleanup the connection.
1220     *
1221     * @throws Throwable if an error occurs during cleanup.
1222     */
1223    protected void finalize() throws Throwable {
1224        cleanup(null);
1225    }
1226
1227    /**
1228     * Is the server configured to use lower-case table names only?
1229     *
1230     * @return true if lower_case_table_names is 'on'
1231     */
1232    public boolean lowerCaseTableNames() {
1233        return this.lowerCaseTableNames;
1234    }
1235
1236    /**
1237     * A driver may convert the JDBC sql grammar into its system's native SQL
1238     * grammar prior to sending it; nativeSQL returns the native form of the
1239     * statement that the driver would have sent.
1240     *
1241     * @param sql a SQL statement that may contain one or more '?' parameter
1242     *        placeholders
1243     *
1244     * @return the native form of this statement
1245     *
1246     * @exception java.sql.SQLException if a database access error occurs
1247     */
1248    public String nativeSQL(String sql) throws java.sql.SQLException {
1249        if (Driver.TRACE) {
1250            Object[] args = { sql };
1251            Debug.methodCall(this, "nativeSQL", args);
1252            Debug.returnValue(this, "nativeSQL", sql);
1253        }
1254
1255        return EscapeProcessor.escapeSQL(sql,
1256            getIO().versionMeetsMinimum(4, 0, 2));
1257    }
1258
1259    /**
1260     * DOCUMENT ME!
1261     *
1262     * @return DOCUMENT ME!
1263     */
1264    public boolean parserKnowsUnicode() {
1265        return this.parserKnowsUnicode;
1266    }
1267
1268    /**
1269     * DOCUMENT ME!
1270     *
1271     * @param sql DOCUMENT ME!
1272     *
1273     * @return DOCUMENT ME!
1274     *
1275     * @throws java.sql.SQLException DOCUMENT ME!
1276     */
1277    public java.sql.CallableStatement prepareCall(String sql)
1278        throws java.sql.SQLException {
1279        if (this.getUseUltraDevWorkAround()) {
1280            return new UltraDevWorkAround(prepareStatement(sql));
1281        } else {
1282            throw new java.sql.SQLException("Callable statments not "
1283                + "supported.", "S1C00");
1284        }
1285    }
1286
1287    /**
1288     * JDBC 2.0 Same as prepareCall() above, but allows the default result set
1289     * type and result set concurrency type to be overridden.
1290     *
1291     * @param sql the SQL representing the callable statement
1292     * @param resultSetType a result set type, see ResultSet.TYPE_XXX
1293     * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
1294     *
1295     * @return a new CallableStatement object containing the pre-compiled SQL
1296     *         statement
1297     *
1298     * @exception SQLException if a database-access error occurs.
1299     */
1300    public java.sql.CallableStatement prepareCall(String sql,
1301        int resultSetType, int resultSetConcurrency) throws SQLException {
1302        return prepareCall(sql);
1303    }
1304
1305    /**
1306     * @see Connection#prepareCall(String, int, int, int)
1307     */
1308    public java.sql.CallableStatement prepareCall(String sql,
1309        int resultSetType, int resultSetConcurrency, int resultSetHoldability)
1310        throws SQLException {
1311        if (this.pedantic) {
1312            if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
1313                throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
1314                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1315            }
1316        }
1317
1318        throw new NotImplemented();
1319    }
1320
1321    /**
1322     * A SQL statement with or without IN parameters can be pre-compiled and
1323     * stored in a PreparedStatement object.  This object can then be used to
1324     * efficiently execute this statement multiple times.
1325     * 
1326     * <p>
1327     * <B>Note:</B> This method is optimized for handling parametric SQL
1328     * statements that benefit from precompilation if the driver supports
1329     * precompilation. In this case, the statement is not sent to the database
1330     * until the PreparedStatement is executed.  This has no direct effect on
1331     * users; however it does affect which method throws certain
1332     * java.sql.SQLExceptions
1333     * </p>
1334     * 
1335     * <p>
1336     * MySQL does not support precompilation of statements, so they are handled
1337     * by the driver.
1338     * </p>
1339     *
1340     * @param sql a SQL statement that may contain one or more '?' IN parameter
1341     *        placeholders
1342     *
1343     * @return a new PreparedStatement object containing the pre-compiled
1344     *         statement.
1345     *
1346     * @exception java.sql.SQLException if a database access error occurs.
1347     */
1348    public java.sql.PreparedStatement prepareStatement(String sql)
1349        throws java.sql.SQLException {
1350        return prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,
1351            java.sql.ResultSet.CONCUR_READ_ONLY);
1352    }
1353
1354    /**
1355     * JDBC 2.0 Same as prepareStatement() above, but allows the default result
1356     * set type and result set concurrency type to be overridden.
1357     *
1358     * @param sql the SQL query containing place holders
1359     * @param resultSetType a result set type, see ResultSet.TYPE_XXX
1360     * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
1361     *
1362     * @return a new PreparedStatement object containing the pre-compiled SQL
1363     *         statement
1364     *
1365     * @exception SQLException if a database-access error occurs.
1366     */
1367    public synchronized java.sql.PreparedStatement prepareStatement(
1368        String sql, int resultSetType, int resultSetConcurrency)
1369        throws SQLException {
1370        checkClosed();
1371
1372        PreparedStatement pStmt = null;
1373
1374        if (this.cachePreparedStatements) {
1375            PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo) cachedPreparedStatementParams
1376                .get(sql);
1377
1378            if (pStmtInfo == null) {
1379                pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
1380                        this.database);
1381
1382                PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo();
1383
1384                if (parseInfo.statementLength < this.preparedStatementCacheMaxSqlSize) {
1385                    if (this.cachedPreparedStatementParams.size() >= 25) {
1386                        Iterator oldestIter = this.cachedPreparedStatementParams.keySet()
1387                                                                                .iterator();
1388                        long lruTime = Long.MAX_VALUE;
1389                        String oldestSql = null;
1390
1391                        while (oldestIter.hasNext()) {
1392                            String sqlKey = (String) oldestIter.next();
1393                            PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams
1394                                .get(sqlKey);
1395
1396                            if (lruInfo.lastUsed < lruTime) {
1397                                lruTime = lruInfo.lastUsed;
1398                                oldestSql = sqlKey;
1399                            }
1400                        }
1401
1402                        if (oldestSql != null) {
1403                            this.cachedPreparedStatementParams.remove(oldestSql);
1404                        }
1405                    }
1406
1407                    cachedPreparedStatementParams.put(sql, pStmt.getParseInfo());
1408                }
1409            } else {
1410                pStmtInfo.lastUsed = System.currentTimeMillis();
1411                pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
1412                        this.database, pStmtInfo);
1413            }
1414        } else {
1415            pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
1416                    this.database);
1417        }
1418
1419        //
1420        // FIXME: Create warnings if can't create results of the given
1421        //        type or concurrency
1422        //
1423        pStmt.setResultSetType(resultSetType);
1424        pStmt.setResultSetConcurrency(resultSetConcurrency);
1425
1426        return pStmt;
1427    }
1428
1429    /**
1430     * @see Connection#prepareStatement(String, int, int, int)
1431     */
1432    public java.sql.PreparedStatement prepareStatement(String sql,
1433        int resultSetType, int resultSetConcurrency, int resultSetHoldability)
1434        throws SQLException {
1435        if (this.pedantic) {
1436            if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
1437                throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
1438                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1439            }
1440        }
1441
1442        return prepareStatement(sql, resultSetType, resultSetConcurrency);
1443    }
1444
1445    /**
1446     * @see Connection#prepareStatement(String, int)
1447     */
1448    public java.sql.PreparedStatement prepareStatement(String sql,
1449        int autoGenKeyIndex) throws SQLException {
1450        java.sql.PreparedStatement pStmt = prepareStatement(sql);
1451
1452        ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys(autoGenKeyIndex == Statement.RETURN_GENERATED_KEYS);
1453
1454        return pStmt;
1455    }
1456
1457    /**
1458     * @see Connection#prepareStatement(String, int[])
1459     */
1460    public java.sql.PreparedStatement prepareStatement(String sql,
1461        int[] autoGenKeyIndexes) throws SQLException {
1462        java.sql.PreparedStatement pStmt = prepareStatement(sql);
1463
1464        ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys((autoGenKeyIndexes != null)
1465            && (autoGenKeyIndexes.length > 0));
1466
1467        return pStmt;
1468    }
1469
1470    /**
1471     * @see Connection#prepareStatement(String, String[])
1472     */
1473    public java.sql.PreparedStatement prepareStatement(String sql,
1474        String[] autoGenKeyColNames) throws SQLException {
1475        java.sql.PreparedStatement pStmt = prepareStatement(sql);
1476
1477        ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys((autoGenKeyColNames != null)
1478            && (autoGenKeyColNames.length > 0));
1479
1480        return pStmt;
1481    }
1482
1483    /**
1484     * @see Connection#releaseSavepoint(Savepoint)
1485     */
1486    public void releaseSavepoint(Savepoint arg0) throws SQLException {
1487        throw new NotImplemented();
1488    }
1489
1490    /**
1491     * Resets the server-side state of this connection. Doesn't work for MySQL
1492     * versions older than 4.0.6 or if isParanoid() is set (it will become  a
1493     * no-op in these cases). Usually only used from connection pooling code.
1494     *
1495     * @throws SQLException if the operation fails while resetting server
1496     *         state.
1497     */
1498    public void resetServerState() throws SQLException {
1499      
1500        if (!this.paranoid
1501                && ((this.io != null) & this.io.versionMeetsMinimum(4, 0, 6))) {
1502            changeUser(this.user, this.password);
1503        }
1504    }
1505
1506    /**
1507     * The method rollback() drops all changes made since the previous
1508     * commit/rollback and releases any database locks currently held by the
1509     * Connection.
1510     *
1511     * @exception java.sql.SQLException if a database access error occurs
1512     * @throws SQLException DOCUMENT ME!
1513     *
1514     * @see commit
1515     */
1516    public void rollback() throws java.sql.SQLException {
1517        if (Driver.TRACE) {
1518            Object[] args = new Object[0];
1519            Debug.methodCall(this, "rollback", args);
1520        }
1521
1522        checkClosed();
1523
1524        try {
1525            // no-op if _relaxAutoCommit == true
1526            if (this.autoCommit && !this.relaxAutoCommit) {
1527                throw new SQLException("Can't call rollback when autocommit=true",
1528                    SQLError.SQL_STATE_GENERAL_ERROR);
1529            } else if (this.transactionsSupported) {
1530                try {
1531                    rollbackNoChecks();
1532                } catch (SQLException sqlEx) {
1533                    // We ignore non-transactional tables if told to do so
1534                    if (this.ignoreNonTxTables
1535                            && (sqlEx.getErrorCode() != MysqlDefs.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
1536                        throw sqlEx;
1537                    }
1538                }
1539            }
1540        } finally {
1541            if (this.reconnectAtTxEnd) {
1542                pingAndReconnect(true);
1543            }
1544        }
1545    }
1546
1547    /**
1548     * @see Connection#rollback(Savepoint)
1549     */
1550    public void rollback(Savepoint arg0) throws SQLException {
1551        throw new NotImplemented();
1552    }
1553
1554    /**
1555     * Used by MiniAdmin to shutdown a MySQL server
1556     *
1557     * @throws SQLException if the command can not be issued.
1558     */
1559    public void shutdownServer() throws SQLException {
1560        try {
1561            this.io.sendCommand(MysqlDefs.SHUTDOWN, null, null);
1562        } catch (Exception ex) {
1563            throw new SQLException("Unhandled exception '" + ex.toString()
1564                + "'", SQLError.SQL_STATE_GENERAL_ERROR);
1565        }
1566    }
1567
1568    /**
1569     * DOCUMENT ME!
1570     *
1571     * @return DOCUMENT ME!
1572     */
1573    public boolean supportsIsolationLevel() {
1574        return this.hasIsolationLevels;
1575    }
1576
1577    /**
1578     * DOCUMENT ME!
1579     *
1580     * @return DOCUMENT ME!
1581     */
1582    public boolean supportsQuotedIdentifiers() {
1583        return this.hasQuotedIdentifiers;
1584    }
1585
1586    /**
1587     * DOCUMENT ME!
1588     *
1589     * @return DOCUMENT ME!
1590     */
1591    public boolean supportsTransactions() {
1592        return this.transactionsSupported;
1593    }
1594
1595    /**
1596     * Should we use compression?
1597     *
1598     * @return should we use compression to communicate with the server?
1599     */
1600    public boolean useCompression() {
1601        return this.useCompression;
1602    }
1603
1604    /**
1605     * Returns the paranoidErrorMessages.
1606     *
1607     * @return boolean if we should be paranoid about error messages.
1608     */
1609    public boolean useParanoidErrorMessages() {
1610        return paranoid;
1611    }
1612
1613    /**
1614     * Should we use SSL?
1615     *
1616     * @return should we use SSL to communicate with the server?
1617     */
1618    public boolean useSSL() {
1619        return this.useSSL;
1620    }
1621
1622    /**
1623     * Should we enable work-arounds for floating point rounding errors in the
1624     * server?
1625     *
1626     * @return should we use floating point work-arounds?
1627     */
1628    public boolean useStrictFloatingPoint() {
1629        return this.strictFloatingPoint;
1630    }
1631
1632    /**
1633     * Returns the strictUpdates value.
1634     *
1635     * @return boolean
1636     */
1637    public boolean useStrictUpdates() {
1638        return strictUpdates;
1639    }
1640
1641    /**
1642     * DOCUMENT ME!
1643     *
1644     * @return DOCUMENT ME!
1645     */
1646    public boolean useTimezone() {
1647        return this.useTimezone;
1648    }
1649
1650    /**
1651     * Should unicode character mapping be used ?
1652     *
1653     * @return should we use Unicode character mapping?
1654     */
1655    public boolean useUnicode() {
1656        return this.doUnicode;
1657    }
1658
1659    /**
1660     * Returns the Java character encoding name for the given MySQL server
1661     * charset index
1662     *
1663     * @param charsetIndex
1664     *
1665     * @return the Java character encoding name for the given MySQL server
1666     *         charset index
1667     *
1668     * @throws SQLException if the character set index isn't known by the
1669     *         driver
1670     */
1671    protected String getCharsetNameForIndex(int charsetIndex)
1672        throws SQLException {
1673        String charsetName = null;
1674
1675        if (charsetIndex != MysqlDefs.NO_CHARSET_INFO) {
1676            try {
1677                charsetName = this.indexToCharsetMapping[charsetIndex];
1678            } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
1679                throw new SQLException(
1680                    "Unknown character set index for field '" + charsetIndex
1681                    + "' received from server.",
1682                    SQLError.SQL_STATE_GENERAL_ERROR);
1683            }
1684
1685            // Punt
1686            if (charsetName == null) {
1687                charsetName = getEncoding();
1688            }
1689        } else {
1690            charsetName = getEncoding();
1691        }
1692
1693        return charsetName;
1694    }
1695
1696    /**
1697     * DOCUMENT ME!
1698     *
1699     * @return Returns the defaultTimeZone.
1700     */
1701    protected TimeZone getDefaultTimeZone() {
1702        return defaultTimeZone;
1703    }
1704
1705    /**
1706     * Returns the IO channel to the server
1707     *
1708     * @return the IO channel to the server
1709     *
1710     * @throws SQLException if the connection is closed.
1711     */
1712    protected MysqlIO getIO() throws SQLException {
1713        if ((this.io == null) || this.isClosed) {
1714            throw new SQLException("Operation not allowed on closed connection",
1715                "08003");
1716        }
1717
1718        return this.io;
1719    }
1720
1721    protected int getNetWriteTimeout() {
1722        String netWriteTimeoutStr = (String) this.serverVariables.get(
1723                "net_write_timeout");
1724
1725        if (netWriteTimeoutStr != null) {
1726            try {
1727                return Integer.parseInt(netWriteTimeoutStr);
1728            } catch (NumberFormatException nfe) {
1729                return Integer.MAX_VALUE;
1730            }
1731        } else {
1732            return Integer.MAX_VALUE;
1733        }
1734    }
1735
1736    /**
1737     * Is this connection using unbuffered input?
1738     *
1739     * @return whether or not to use buffered input streams
1740     */
1741    protected boolean isUsingUnbufferedInput() {
1742        return this.useUnbufferedInput;
1743    }
1744
1745    /**
1746     * Creates an IO channel to the server
1747     *
1748     * @param isForReconnect is this request for a re-connect
1749     *
1750     * @return a new MysqlIO instance connected to a server
1751     *
1752     * @throws SQLException if a database access error occurs
1753     */
1754    protected com.mysql.jdbc.MysqlIO createNewIO(boolean isForReconnect)
1755        throws SQLException {
1756        MysqlIO newIo = null;
1757
1758        if (!highAvailability && !this.failedOver) {
1759            for (int hostIndex = 0; hostIndex < hostListSize; hostIndex++) {
1760                try {
1761                    String newHostPortPair = (String) this.hostList.get(hostIndex);
1762
1763                    int newPort = 3306;
1764                    
1765                    String[] hostPortPair = NonRegisteringDriver.parseHostPortPair(newHostPortPair);
1766                    String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];
1767                  
1768                    if (newHost == null || newHost.trim().length() == 0) {
1769                      newHost = "localhost";
1770                    }
1771                  
1772                  if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) {
1773                    try {
1774                            newPort = Integer.parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]);
1775                        } catch (NumberFormatException nfe) {
1776                            throw new SQLException(
1777                                "Illegal connection port value '"
1778                                + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] + "'",
1779                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
1780                        }
1781                  }
1782
1783                    this.io = new MysqlIO(newHost, newPort,
1784                            this.socketFactoryClassName, this.props, this,
1785                            this.socketTimeout);
1786                    this.io.doHandshake(this.user, this.password, this.database);
1787                    this.isClosed = false;
1788
1789                    if (this.database.length() != 0) {
1790                        this.io.sendCommand(MysqlDefs.INIT_DB, this.database,
1791                            null);
1792                    }
1793
1794                    // save state from old connection
1795                    boolean autoCommit = getAutoCommit();
1796                    int oldIsolationLevel = getTransactionIsolation();
1797                    boolean oldReadOnly = isReadOnly();
1798                    String oldCatalog = getCatalog();
1799
1800                    // Server properties might be different
1801                    // from previous connection, so initialize
1802                    // again...
1803                    initializePropsFromServer(this.props);
1804
1805                    if (isForReconnect) {
1806                        // Restore state from old connection
1807                        setAutoCommit(autoCommit);
1808
1809                        if (this.hasIsolationLevels) {
1810                            setTransactionIsolation(oldIsolationLevel);
1811                        }
1812
1813                        setCatalog(oldCatalog);
1814                    }
1815
1816                    if (hostIndex != 0) {
1817                        setFailedOverState();
1818                    } else {
1819                        this.failedOver = false;
1820
1821                        if (hostListSize > 1) {
1822                            setReadOnly(false);
1823                        } else {
1824                            setReadOnly(oldReadOnly);
1825                        }
1826                    }
1827
1828                    break; // low-level connection succeeded
1829                } catch (SQLException sqlEx) {
1830                    if (this.io != null) {
1831                        this.io.forceClose();
1832                    }
1833
1834                    String sqlState = sqlEx.getSQLState();
1835
1836                    if ((sqlState == null)
1837                            || !sqlState.equals(
1838                                SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
1839                        throw sqlEx;
1840                    }
1841
1842                    if ((hostListSize - 1) == hostIndex) {
1843                        throw sqlEx;
1844                    }
1845                } catch (Exception unknownException) {
1846                    if (this.io != null) {
1847                        this.io.forceClose();
1848                    }
1849
1850                    if ((hostListSize - 1) == hostIndex) {
1851                        throw new SQLException(
1852                            "Unable to connect to any hosts due to exception: "
1853                            + unknownException.toString()
1854                            + (this.paranoid ? ""
1855                                             : Util.stackTraceToString(
1856                                unknownException)),
1857                            SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
1858                    }
1859                }
1860            }
1861        } else {
1862            double timeout = this.initialTimeout;
1863            boolean connectionGood = false;
1864            Exception connectionException = null;
1865
1866            for (int hostIndex = 0;
1867                    (hostIndex < hostListSize) && !connectionGood;
1868                    hostIndex++) {
1869                for (int attemptCount = 0;
1870                        !connectionGood && (attemptCount < this.maxReconnects);
1871                        attemptCount++) {
1872                    try {
1873                        if (this.io != null) {
1874                            this.io.forceClose();
1875                        }
1876
1877                        String newHostPortPair = (String) this.hostList.get(hostIndex);
1878
1879                        int newPort = 3306;
1880                        
1881                        String[] hostPortPair = NonRegisteringDriver.parseHostPortPair(newHostPortPair);
1882                        String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];
1883                      
1884                        if (newHost == null || newHost.trim().length() == 0) {
1885                          newHost = "localhost";
1886                        }
1887                      
1888                      if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) {
1889                        try {
1890                                newPort = Integer.parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]);
1891                            } catch (NumberFormatException nfe) {
1892                                throw new SQLException(
1893                                    "Illegal connection port value '"
1894                                    + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] + "'",
1895                                    SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
1896                            }
1897                      }
1898
1899                        this.io = new MysqlIO(newHost, newPort,
1900                                this.socketFactoryClassName, this.props, this,
1901                                this.socketTimeout);
1902                        this.io.doHandshake(this.user, this.password,
1903                            this.database);
1904
1905                        if (this.database.length() != 0) {
1906                            this.io.sendCommand(MysqlDefs.INIT_DB,
1907                                this.database, null);
1908                        }
1909
1910                        ping();
1911                        this.isClosed = false;
1912
1913                        // save state from old connection
1914                        boolean autoCommit = getAutoCommit();
1915                        int oldIsolationLevel = getTransactionIsolation();
1916                        boolean oldReadOnly = isReadOnly();
1917                        String oldCatalog = getCatalog();
1918
1919                        // Server properties might be different
1920                        // from previous connection, so initialize
1921                        // again...
1922                        initializePropsFromServer(this.props);
1923
1924                        if (isForReconnect) {
1925                            // Restore state from old connection
1926                            setAutoCommit(autoCommit);
1927
1928                            if (this.hasIsolationLevels) {
1929                                setTransactionIsolation(oldIsolationLevel);
1930                            }
1931
1932                            setCatalog(oldCatalog);
1933                        }
1934
1935                        connectionGood = true;
1936
1937                        if (hostIndex != 0) {
1938                            setFailedOverState();
1939                        } else {
1940                            this.failedOver = false;
1941
1942                            if (hostListSize > 1) {
1943                                setReadOnly(false);
1944                            } else {
1945                                setReadOnly(oldReadOnly);
1946                            }
1947                        }
1948
1949                        break;
1950                    } catch (Exception EEE) {
1951                        connectionException = EEE;
1952                        connectionGood = false;
1953                    }
1954
1955                    if (!connectionGood) {
1956                        try {
1957                            Thread.sleep((long) timeout * 1000);
1958                            timeout = timeout * 2;
1959                        } catch (InterruptedException IE) {
1960                            ;
1961                        }
1962                    }
1963                } // end attempt on hosts
1964            } // end iterator through list of hosts
1965            
1966            if (!connectionGood) {
1967                // We've really failed!
1968                throw new SQLException(
1969                    "Server connection failure during transaction. Due to underlying exception: '"
1970                    + connectionException + "'."
1971                    + (this.paranoid ? ""
1972                                     : Util.stackTraceToString(
1973                        connectionException)) + "\nAttempted reconnect "
1974                    + this.maxReconnects + " times. Giving up.",
1975                    SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
1976            }
1977        }
1978
1979        if (paranoid && !highAvailability && (hostListSize <= 1)) {
1980            password = null;
1981            user = null;
1982        }
1983
1984        return newIo;
1985    }
1986
1987    /**
1988     * Closes connection and frees resources.
1989     *
1990     * @param calledExplicitly is this being called from close()
1991     * @param issueRollback should a rollback() be issued?
1992     *
1993     * @throws SQLException if an error occurs
1994     */
1995    protected void realClose(boolean calledExplicitly, boolean issueRollback)
1996        throws SQLException {
1997        if (Driver.TRACE) {
1998            Object[] args = new Object[] {
1999                    new Boolean(calledExplicitly), new Boolean(issueRollback)
2000                };
2001            Debug.methodCall(this, "realClose", args);
2002        }
2003
2004        SQLException sqlEx = null;
2005
2006        if (!isClosed() && !getAutoCommit() && issueRollback) {
2007            try {
2008                rollback();
2009            } catch (SQLException ex) {
2010                sqlEx = ex;
2011            }
2012        }
2013
2014        if (this.io != null) {
2015            try {
2016                this.io.quit();
2017            } catch (Exception e) {
2018                ;
2019            }
2020
2021            this.io = null;
2022        }
2023
2024        if (this.cachedPreparedStatementParams != null) {
2025            this.cachedPreparedStatementParams.clear();
2026            this.cachedPreparedStatementParams = null;
2027        }
2028
2029        this.isClosed = true;
2030
2031        if (sqlEx != null) {
2032            throw sqlEx;
2033        }
2034    }
2035
2036    /**
2037     * Returns the locally mapped instance of a charset converter (to avoid
2038     * overhead of static synchronization).
2039     *
2040     * @param javaEncodingName the encoding name to retrieve
2041     *
2042     * @return a character converter, or null if one couldn't be mapped.
2043     */
2044    synchronized SingleByteCharsetConverter getCharsetConverter(
2045        String javaEncodingName) {
2046        SingleByteCharsetConverter converter = (SingleByteCharsetConverter) this.charsetConverterMap
2047            .get(javaEncodingName);
2048
2049        if (converter == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) {
2050            return null;
2051        }
2052
2053        if (converter == null) {
2054            try {
2055                converter = SingleByteCharsetConverter.getInstance(javaEncodingName);
2056
2057                if (converter == null) {
2058                    this.charsetConverterMap.put(javaEncodingName,
2059                        CHARSET_CONVERTER_NOT_AVAILABLE_MARKER);
2060                }
2061
2062                this.charsetConverterMap.put(javaEncodingName, converter);
2063            } catch (UnsupportedEncodingException unsupEncEx) {
2064                this.charsetConverterMap.put(javaEncodingName,
2065                    CHARSET_CONVERTER_NOT_AVAILABLE_MARKER);
2066
2067                converter = null;
2068            }
2069        }
2070
2071        return converter;
2072    }
2073
2074    /**
2075     * Returns the maximum packet size the MySQL server will accept
2076     *
2077     * @return DOCUMENT ME!
2078     */
2079    int getMaxAllowedPacket() {
2080        return this.maxAllowedPacket;
2081    }
2082
2083    /**
2084     * DOCUMENT ME!
2085     *
2086     * @return the max rows to return for statements (by default)
2087     */
2088    int getMaxRows() {
2089        return this.maxRows;
2090    }
2091
2092    /**
2093     * Returns the Mutex all queries are locked against
2094     *
2095     * @return DOCUMENT ME!
2096     *
2097     * @throws SQLException DOCUMENT ME!
2098     */
2099    Object getMutex() throws SQLException {
2100        if (this.io == null) {
2101            throw new SQLException("Connection.close() has already been called. Invalid operation in this state.",
2102                "08003");
2103        }
2104
2105        return this.mutex;
2106    }
2107
2108    /**
2109     * Returns the packet buffer size the MySQL server reported upon connection
2110     *
2111     * @return DOCUMENT ME!
2112     */
2113    int getNetBufferLength() {
2114        return this.netBufferLength;
2115    }
2116
2117    boolean isPedantic() {
2118        return this.pedantic;
2119    }
2120
2121    void setReadInfoMsgEnabled(boolean flag) {
2122        this.readInfoMsg = flag;
2123    }
2124
2125    boolean isReadInfoMsgEnabled() {
2126        return this.readInfoMsg;
2127    }
2128
2129    int getServerMajorVersion() {
2130        return this.io.getServerMajorVersion();
2131    }
2132
2133    int getServerMinorVersion() {
2134        return this.io.getServerMinorVersion();
2135    }
2136
2137    int getServerSubMinorVersion() {
2138        return this.io.getServerSubMinorVersion();
2139    }
2140
2141    String getServerVersion() {
2142        return this.io.getServerVersion();
2143    }
2144
2145    String getURL() {
2146        return this.myURL;
2147    }
2148
2149    /**
2150     * Set whether or not this connection should use SSL
2151     *
2152     * @param flag DOCUMENT ME!
2153     */
2154    void setUseSSL(boolean flag) {
2155        this.useSSL = flag;
2156    }
2157
2158    String getUser() {
2159        return this.user;
2160    }
2161
2162    boolean alwaysClearStream() {
2163        return this.alwaysClearStream;
2164    }
2165
2166    boolean continueBatchOnError() {
2167        return this.continueBatchOnError;
2168    }
2169
2170    /**
2171     * Send a query to the server.  Returns one of the ResultSet objects. This
2172     * is synchronized, so Statement's queries will be serialized.
2173     *
2174     * @param sql the SQL statement to be executed
2175     * @param maxRowsToRetreive DOCUMENT ME!
2176     * @param catalog DOCUMENT ME!
2177     *
2178     * @return a ResultSet holding the results
2179     *
2180     * @exception java.sql.SQLException if a database error occurs
2181     */
2182    ResultSet execSQL(String sql, int maxRowsToRetreive, String catalog)
2183        throws java.sql.SQLException {
2184        if (Driver.TRACE) {
2185            Object[] args = { sql, new Integer(maxRowsToRetreive) };
2186            Debug.methodCall(this, "execSQL", args);
2187        }
2188
2189        return execSQL(sql, maxRowsToRetreive, null,
2190            java.sql.ResultSet.CONCUR_READ_ONLY, catalog);
2191    }
2192
2193    ResultSet execSQL(String sql, int maxRows, int resultSetType,
2194        boolean streamResults, boolean queryIsSelectOnly, String catalog)
2195        throws SQLException {
2196        return execSQL(sql, maxRows, null, resultSetType, streamResults,
2197            queryIsSelectOnly, catalog);
2198    }
2199
2200    ResultSet execSQL(String sql, int maxRows, Buffer packet, String catalog)
2201        throws java.sql.SQLException {
2202        return execSQL(sql, maxRows, packet,
2203            java.sql.ResultSet.CONCUR_READ_ONLY, catalog);
2204    }
2205
2206    ResultSet execSQL(String sql, int maxRows, Buffer packet,
2207        int resultSetType, String catalog) throws java.sql.SQLException {
2208        return execSQL(sql, maxRows, packet, resultSetType, true, false, catalog);
2209    }
2210
2211    ResultSet execSQL(String sql, int maxRows, Buffer packet,
2212        int resultSetType, boolean streamResults, boolean queryIsSelectOnly,
2213        String catalog) throws java.sql.SQLException {
2214        if (Driver.TRACE) {
2215            Object[] args = { sql, new Integer(maxRows), packet };
2216            Debug.methodCall(this, "execSQL", args);
2217        }
2218
2219        if ((sql == null) || (sql.length() == 0)) {
2220            if (packet == null) {
2221                throw new SQLException("Query can not be null or empty",
2222                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2223            }
2224        }
2225
2226        //
2227        // Fall-back if the master is back online if we've
2228        // issued queriesBeforeRetryMaster queries since
2229        // we failed over
2230        //
2231        synchronized (this.mutex) {
2232            this.lastQueryFinishedTime = 0; // we're busy!
2233
2234            if ((this.highAvailability || this.failedOver) && this.needsPing) {
2235                pingAndReconnect(false);
2236            }
2237
2238            try {
2239                int realMaxRows = (maxRows == -1) ? MysqlDefs.MAX_ROWS : maxRows;
2240
2241                if (packet == null) {
2242                    String encoding = null;
2243
2244                    if (useUnicode()) {
2245                        encoding = getEncoding();
2246                    }
2247
2248                    return this.io.sqlQuery(sql, realMaxRows, encoding, this,
2249                        resultSetType, streamResults, catalog);
2250                } else {
2251                    return this.io.sqlQueryDirect(packet, realMaxRows, this,
2252                        resultSetType, streamResults, catalog);
2253                }
2254            } catch (java.sql.SQLException sqlE) {
2255                // don't clobber SQL exceptions
2256                String sqlState = sqlE.getSQLState();
2257
2258                if (this.highAvailability || this.failedOver) {
2259                    this.needsPing = true;
2260                } else if ((sqlState != null)
2261                        && sqlState.equals(
2262                            SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
2263                    cleanup(sqlE);
2264                }
2265
2266                throw sqlE;
2267            } catch (Exception ex) {
2268                if (this.highAvailability || this.failedOver) {
2269                    this.needsPing = true;
2270                } else if (ex instanceof IOException) {
2271                    cleanup(ex);
2272                }
2273
2274                String exceptionType = ex.getClass().getName();
2275                String exceptionMessage = ex.getMessage();
2276
2277                if (!this.useParanoidErrorMessages()) {
2278                    exceptionMessage += "\n\nNested Stack Trace:\n";
2279                    exceptionMessage += Util.stackTraceToString(ex);
2280                }
2281
2282                throw new java.sql.SQLException(
2283                    "Error during query: Unexpected Exception: "
2284                    + exceptionType + " message given: " + exceptionMessage,
2285                    SQLError.SQL_STATE_GENERAL_ERROR);
2286            } finally {
2287                this.lastQueryFinishedTime = System.currentTimeMillis();
2288            }
2289        }
2290    }
2291
2292    /**
2293     * Has the maxRows value changed?
2294     *
2295     * @param stmt DOCUMENT ME!
2296     */
2297    void maxRowsChanged(Statement stmt) {
2298        synchronized (this.mutex) {
2299            if (this.statementsUsingMaxRows == null) {
2300                this.statementsUsingMaxRows = new HashMap();
2301            }
2302
2303            this.statementsUsingMaxRows.put(stmt, stmt);
2304
2305            this.maxRowsChanged = true;
2306        }
2307    }
2308
2309    /**
2310     * Called by statements on their .close() to let the connection know when
2311     * it is safe to set the connection back to 'default' row limits.
2312     *
2313     * @param stmt the statement releasing it's max-rows requirement
2314     *
2315     * @throws SQLException if a database error occurs issuing the statement
2316     *         that sets the limit default.
2317     */
2318    void unsetMaxRows(Statement stmt) throws SQLException {
2319        synchronized (this.mutex) {
2320            if (this.statementsUsingMaxRows != null) {
2321                Object found = this.statementsUsingMaxRows.remove(stmt);
2322
2323                if ((found != null)
2324                        && (this.statementsUsingMaxRows.size() == 0)) {
2325                    execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1,
2326                        this.database);
2327                    this.maxRowsChanged = false;
2328                }
2329            }
2330        }
2331    }
2332
2333    boolean useAnsiQuotedIdentifiers() {
2334        return this.useAnsiQuotes;
2335    }
2336
2337    boolean useHostsInPrivileges() {
2338        return this.useHostsInPrivileges;
2339    }
2340
2341    /**
2342     * Has maxRows() been set?
2343     *
2344     * @return DOCUMENT ME!
2345     */
2346    boolean useMaxRows() {
2347        synchronized (this.mutex) {
2348            return this.maxRowsChanged;
2349        }
2350    }
2351
2352    boolean useStreamLengthsInPrepStmts() {
2353        return this.useStreamLengthsInPrepStmts;
2354    }
2355
2356    /**
2357     * Sets state for a failed-over connection
2358     *
2359     * @throws SQLException DOCUMENT ME!
2360     */
2361    private void setFailedOverState() throws SQLException {
2362        if (this.failOverReadOnly) {
2363            setReadOnly(true);
2364        }
2365
2366        this.queriesIssuedFailedOver = 0;
2367        this.failedOver = true;
2368        this.masterFailTimeMillis = System.currentTimeMillis();
2369    }
2370
2371    /**
2372     * Builds the map needed for 4.1.0 and newer servers that maps field-level
2373     * charset/collation info to a java character encoding name.
2374     *
2375     * @throws SQLException DOCUMENT ME!
2376     */
2377    private void buildCollationMapping() throws SQLException {
2378        if (this.io.versionMeetsMinimum(4, 1, 0)) {
2379            com.mysql.jdbc.Statement stmt = null;
2380            com.mysql.jdbc.ResultSet results = null;
2381
2382            TreeMap sortedCollationMap = new TreeMap();
2383
2384            try {
2385                stmt = (com.mysql.jdbc.Statement) createStatement();
2386
2387                if (stmt.getMaxRows() != 0) {
2388                    stmt.setMaxRows(0);
2389                }
2390
2391                results = (com.mysql.jdbc.ResultSet) stmt.executeQuery(
2392                        "SHOW COLLATION");
2393
2394                while (results.next()) {
2395                    String charsetName = results.getString(2);
2396                    Integer charsetIndex = new Integer(results.getInt(3));
2397
2398                    sortedCollationMap.put(charsetIndex, charsetName);
2399                }
2400
2401                // Now, merge with what we already know
2402                int highestIndex = ((Integer) sortedCollationMap.lastKey())
2403                    .intValue();
2404
2405                if (CharsetMapping.INDEX_TO_CHARSET.length > highestIndex) {
2406                    highestIndex = CharsetMapping.INDEX_TO_CHARSET.length;
2407                }
2408
2409                this.indexToCharsetMapping = new String[highestIndex + 1];
2410
2411                for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length;
2412                        i++) {
2413                    this.indexToCharsetMapping[i] = CharsetMapping.INDEX_TO_CHARSET[i];
2414                }
2415
2416                for (Iterator indexIter = sortedCollationMap.entrySet()
2417                                                            .iterator();
2418                        indexIter.hasNext();) {
2419                    Map.Entry indexEntry = (Map.Entry) indexIter.next();
2420
2421                    String mysqlCharsetName = (String) indexEntry.getValue();
2422
2423                    this.indexToCharsetMapping[((Integer) indexEntry.getKey())
2424                    .intValue()] = (String) CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP
2425                        .get(mysqlCharsetName);
2426                }
2427            } catch (java.sql.SQLException e) {
2428                throw e;
2429            } finally {
2430                if (results != null) {
2431                    try {
2432                        results.close();
2433                    } catch (java.sql.SQLException sqlE) {
2434                        ;
2435                    }
2436                }
2437
2438                if (stmt != null) {
2439                    try {
2440                        stmt.close();
2441                    } catch (java.sql.SQLException sqlE) {
2442                        ;
2443                    }
2444                }
2445            }
2446        } else {
2447            // Safety, we already do this as an initializer, but this makes 
2448            // the intent more clear
2449            this.indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
2450        }
2451    }
2452
2453    private void checkClosed() throws SQLException {
2454        if (this.isClosed) {
2455            StringBuffer exceptionMessage = new StringBuffer();
2456
2457            exceptionMessage.append(
2458                "No operations allowed after connection closed.");
2459
2460            if (!this.paranoid) {
2461                if (this.forcedCloseReason != null) {
2462                    exceptionMessage.append(
2463                        "\n\nConnection was closed due to the following exception:");
2464                    exceptionMessage.append(Util.stackTraceToString(
2465                            this.forcedCloseReason));
2466                } else if (this.explicitCloseLocation != null) {
2467                    exceptionMessage.append(
2468                        "\n\nConnection was closed explicitly by the application at the following location:");
2469                    exceptionMessage.append(Util.stackTraceToString(
2470                            this.explicitCloseLocation));
2471                }
2472            }
2473
2474            throw new SQLException(exceptionMessage.toString(), "08003");
2475        }
2476    }
2477
2478    /**
2479     * If useUnicode flag is set and explicit client character encoding isn't
2480     * specified then assign encoding from server if any.
2481     *
2482     * @throws SQLException DOCUMENT ME!
2483     */
2484    private void checkServerEncoding() throws SQLException {
2485        if (this.doUnicode && (this.encoding != null)) {
2486            // spec'd by client, don't map, but check
2487            return;
2488        }
2489
2490        this.mysqlEncodingName = (String) this.serverVariables.get(
2491                "character_set");
2492
2493        String javaEncodingName = null;
2494
2495        if (this.mysqlEncodingName != null) {
2496            javaEncodingName = (String) charsetMap.get(this.mysqlEncodingName
2497                    .toUpperCase());
2498        }
2499
2500        //
2501        // First check if we can do the encoding ourselves
2502        //
2503        if (!this.doUnicode && (javaEncodingName != null)) {
2504            SingleByteCharsetConverter converter = getCharsetConverter(javaEncodingName);
2505
2506            if (converter != null) { // we know how to convert this ourselves
2507                this.doUnicode = true; // force the issue
2508                this.encoding = javaEncodingName;
2509
2510                return;
2511            }
2512        }
2513
2514        //
2515        // Now, try and find a Java I/O converter that can do
2516        // the encoding for us
2517        //
2518        if (this.mysqlEncodingName != null) {
2519            if (javaEncodingName == null) {
2520                // We don't have a mapping for it, so try
2521                // and canonicalize the name....
2522                if (Character.isLowerCase(this.mysqlEncodingName.charAt(0))) {
2523                    char[] ach = this.mysqlEncodingName.toCharArray();
2524                    ach[0] = Character.toUpperCase(this.mysqlEncodingName
2525                            .charAt(0));
2526                    this.encoding = new String(ach);
2527                }
2528            }
2529
2530            //
2531            // Attempt to use the encoding, and bail out if it
2532            // can't be used
2533            //
2534            try {
2535                "abc".getBytes(javaEncodingName);
2536                this.encoding = javaEncodingName;
2537                this.doUnicode = true;
2538            } catch (UnsupportedEncodingException UE) {
2539                throw new SQLException(
2540                    "The driver can not map the character encoding '"
2541                    + this.encoding + "' that your server is using "
2542                    + "to a character encoding your JVM understands. You "
2543                    + "can specify this mapping manually by adding \"useUnicode=true\" "
2544                    + "as well as \"characterEncoding=[an_encoding_your_jvm_understands]\" "
2545                    + "to your JDBC URL.",
2546                    SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2547            }
2548        }
2549    }
2550
2551    /**
2552     * Set transaction isolation level to the value received from server if
2553     * any. Is called by connectionInit(...)
2554     *
2555     * @throws SQLException DOCUMENT ME!
2556     */
2557    private void checkTransactionIsolationLevel() throws SQLException {
2558        String txIsolationName = null;
2559
2560        if (this.io.versionMeetsMinimum(4, 0, 3)) {
2561            txIsolationName = "tx_isolation";
2562        } else {
2563            txIsolationName = "transaction_isolation";
2564        }
2565
2566        String s = (String) this.serverVariables.get(txIsolationName);
2567
2568        if (s != null) {
2569            Integer intTI = (Integer) mapTransIsolationName2Value.get(s);
2570
2571            if (intTI != null) {
2572                isolationLevel = intTI.intValue();
2573            }
2574        }
2575    }
2576
2577    /**
2578     * Destroys this connection and any underlying resources
2579     *
2580     * @param cleanupReason DOCUMENT ME!
2581     */
2582    private void cleanup(Throwable cleanupReason) {
2583        try {
2584            if ((this.io != null) && !isClosed()) {
2585                realClose(false, false);
2586            } else if (this.io != null) {
2587                this.io.forceClose();
2588            }
2589        } catch (SQLException sqlEx) {
2590            // ignore, we're going away.
2591        }
2592
2593        this.isClosed = true;
2594        this.forcedCloseReason = cleanupReason;
2595    }
2596
2597    /**
2598     * Sets up client character set for MySQL-4.1 and newer.  This
2599     * must be done before any further communication with the server!
2600     *
2601     * @return true if this routine actually configured the client character
2602     *         set, or false if the driver needs to use 'older' methods to
2603     *         detect the character set, as it is connected to a MySQL server
2604     *         older than 4.1.0
2605     *
2606     * @throws SQLException if an exception happens while sending 'SET NAMES'
2607     *         to the server, or the server sends character set  information
2608     *         that the client doesn't know about.
2609     */
2610    private boolean configureClientCharacterSet() throws SQLException {
2611        String realJavaEncoding = getEncoding();
2612        boolean characterSetAlreadyConfigured = false;
2613
2614        try {
2615            if (this.io.versionMeetsMinimum(4, 1, 0)) {
2616              
2617                characterSetAlreadyConfigured = true;
2618
2619                this.doUnicode = true;
2620                
2621                configureCharsetProperties(this.props);
2622                
2623                realJavaEncoding = getEncoding(); // we need to do this again to grab this for 
2624                                                  // versions > 4.1.0
2625
2626                try {
2627                    this.encoding = CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex];
2628                } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
2629                    if (realJavaEncoding != null) {
2630                        // user knows best, try it
2631                        this.encoding = realJavaEncoding;
2632                    } else {
2633                        throw new SQLException(
2634                            "Unknown initial character set index '"
2635                            + this.io.serverCharsetIndex
2636                            + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.",
2637                            SQLError.SQL_STATE_GENERAL_ERROR);
2638                    }
2639                }
2640
2641                if (this.encoding == null) {
2642                    // punt?
2643                    this.encoding = "ISO8859_1";
2644                }
2645
2646                //
2647                // Has the user has 'forced' the character encoding via
2648                // driver properties?
2649                //
2650                if (useUnicode()) {
2651                  if (realJavaEncoding != null) {
2652                      if ("ISO8859_2".equals(realJavaEncoding)
2653                              && (this.mysqlEncodingName == null)) {
2654                          throw new SQLException(
2655                              "Character encoding 'ISO8859_2' specified in JDBC URL which maps to multiple MySQL character encodings:"
2656                              + "\n\n" + "* 'latin2'\n" + "* 'czech'\n"
2657                              + "* 'hungarian'\n" + "* 'croat'\n"
2658                              + "\nSpecify one of the above encodings using the 'mysqlEncoding' connection property.",
2659                              SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2660                      } else if ("ISO8859_13".equals(realJavaEncoding)
2661                              && (this.mysqlEncodingName == null)) {
2662                          throw new SQLException(
2663                              "Character encoding 'ISO8859_13' specified in JDBC URL which maps to multiple MySQL character encodings:"
2664                              + "\n\n" + "* 'latvian'\n" + "* 'latvian1'\n"
2665                              + "* 'estonia'\n"
2666                              + "\nSpecify one of the above encodings using the 'mysqlEncoding' connection property.",
2667                              SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2668                      }
2669  
2670                      if (this.mysqlEncodingName == null) {
2671                          this.mysqlEncodingName = (String) CharsetMapping.JAVA_UC_TO_MYSQL_CHARSET_MAP
2672                              .get(realJavaEncoding.toUpperCase());
2673                      }
2674  
2675                      //
2676                      // Now, inform the server what character set we
2677                      // will be using from now-on...
2678                      //
2679                      if (realJavaEncoding.equalsIgnoreCase("UTF-8")
2680                              || realJavaEncoding.equalsIgnoreCase("UTF8")) {
2681                          // charset names are case-sensitive
2682                          execSQL("SET NAMES utf8", -1, this.database);
2683  
2684                          // Switch driver's encoding now, since the server
2685                          // knows what we're sending...
2686                          this.encoding = realJavaEncoding;
2687                      } else {
2688                          String namesEncoding = this.mysqlEncodingName;
2689  
2690                          if ("koi8_ru".equals(this.mysqlEncodingName)) {
2691                              // This has a _different_ name in 4.1...
2692                              namesEncoding = "ko18r";
2693                          }
2694                         
2695                          if (namesEncoding != null) {
2696                              execSQL("SET NAMES " + namesEncoding, -1,
2697                                  this.database);
2698                          }
2699  
2700                          // Switch driver's encoding now, since the server
2701                          // knows what we're sending...
2702                          this.encoding = realJavaEncoding;
2703                      }
2704                  } else if (this.encoding != null) {
2705                    // Tell the server we'll use the server default charset to send our
2706                    // queries from now on....
2707                    this.mysqlEncodingName = (String) CharsetMapping.JAVA_UC_TO_MYSQL_CHARSET_MAP
2708                          .get(this.encoding.toUpperCase());
2709                    
2710                    execSQL("SET NAMES " + this.mysqlEncodingName, -1, this.database);
2711                    
2712                    realJavaEncoding = this.encoding;
2713                  }
2714                }
2715                
2716                //
2717                // We know how to deal with any charset coming back from
2718                // the database, so tell the server not to do conversion
2719                // if the user hasn't 'forced' a result-set character set
2720                //
2721                
2722                if (this.io.versionMeetsMinimum(4, 1, 1)) {
2723                  if (this.characterSetResults == null) {
2724                    execSQL("SET character_set_results = NULL", -1, this.database);
2725                  } else {
2726                    StringBuffer setBuf = new StringBuffer("SET character_set_results = ".length() + this.characterSetResults.length());
2727                    setBuf.append("SET character_set_results = ").append(this.characterSetResults);
2728                  
2729                    execSQL(setBuf.toString(), -1, this.database);
2730                  }
2731                }
2732            } else {
2733                // Use what the server has specified
2734                realJavaEncoding = this.encoding; // so we don't get 
2735                                                  // swapped out in the finally
2736                                                  // block....
2737            }
2738
2739           
2740        } finally {
2741            // Failsafe, make sure that the driver's notion of character
2742            // encoding matches what the user has specified.
2743            this.encoding = realJavaEncoding;
2744        }
2745
2746        return characterSetAlreadyConfigured;
2747    }
2748    
2749    /**
2750     * The character set we want results and result metadata
2751     * returned in (null == results in any charset, metadata
2752     * in UTF-8).
2753     */
2754    private String characterSetResults = null;
2755    
2756    /**
2757     * The character set we want results and result metadata
2758     * returned in (null == results in any charset, metadata
2759     * in UTF-8).
2760     */
2761    private String characterSetResultsOnServer = null;
2762    
2763    /**
2764     * For servers > 4.1.0, what character set is the metadata
2765     * returned in?
2766     */
2767    private String characterSetMetadata = null;
2768
2769    /**
2770     * Should rollback() be called when pooled connections are closed?
2771     */
2772  private boolean rollbackOnPooledClose = true;
2773
2774  private boolean tinyint1isBit;
2775
2776    /**
2777     * Configures the client's timezone if required.
2778     *
2779     * @throws SQLException if the timezone the server is configured to use
2780     *         can't be mapped to a Java timezone.
2781     */
2782    private void configureTimezone() throws SQLException {
2783      String configuredTimeZoneOnServer = (String)this.serverVariables.get("timezone");
2784      
2785      if (configuredTimeZoneOnServer == null) {
2786        configuredTimeZoneOnServer = (String)this.serverVariables.get("time_zone");
2787        
2788        if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
2789          configuredTimeZoneOnServer = (String)this.serverVariables.get("system_time_zone");
2790        }
2791      }
2792      
2793        if (this.useTimezone && configuredTimeZoneOnServer != null) {
2794            // user can specify/override as property
2795            String canoncicalTimezone = this.props.getProperty("serverTimezone");
2796
2797            if ((canoncicalTimezone == null)
2798                    || (canoncicalTimezone.length() == 0)) {
2799                String serverTimezoneStr = configuredTimeZoneOnServer;
2800
2801                try {
2802                    canoncicalTimezone = TimeUtil.getCanoncialTimezone(serverTimezoneStr);
2803
2804                    if (canoncicalTimezone == null) {
2805                        throw new SQLException("Can't map timezone '"
2806                            + serverTimezoneStr + "' to "
2807                            + " canonical timezone.",
2808                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2809                    }
2810                } catch (IllegalArgumentException iae) {
2811                    throw new SQLException(iae.getMessage(),
2812                        SQLError.SQL_STATE_GENERAL_ERROR);
2813                }
2814            }
2815
2816            serverTimezone = TimeZone.getTimeZone(canoncicalTimezone);
2817
2818            //
2819            // The Calendar class has the behavior of mapping
2820            // unknown timezones to 'GMT' instead of throwing an 
2821            // exception, so we must check for this...
2822            //
2823            if (!canoncicalTimezone.equalsIgnoreCase("GMT")
2824                    && serverTimezone.getID().equals("GMT")) {
2825                throw new SQLException("No timezone mapping entry for '"
2826                    + canoncicalTimezone + "'",
2827                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2828            }
2829        }
2830    }
2831
2832    private void detectFloatingPointStyle() throws SQLException {
2833        java.sql.Statement stmt = null;
2834        java.sql.ResultSet rs = null;
2835
2836        try {
2837            stmt = createStatement();
2838
2839            if (stmt.getMaxRows() != 0) {
2840                stmt.setMaxRows(0);
2841            }
2842
2843            rs = stmt.executeQuery(
2844                    "select round('inf'), round('-inf'), round('nan')");
2845
2846            if (rs.next()) {
2847                String posInf = rs.getString(1);
2848
2849                if ("inf".equalsIgnoreCase(posInf)) {
2850                    this.positiveInfinityRep = "'inf'";
2851                    this.positiveInfinityRepIsClipped = false;
2852                }
2853
2854                String negInf = rs.getString(2);
2855
2856                if ("-inf".equalsIgnoreCase(negInf)) {
2857                    this.negativeInfinityRep = "'-inf'";
2858                    this.negativeInfinityRepIsClipped = false;
2859                }
2860
2861                String nan = rs.getString(3);
2862
2863                if ("nan".equalsIgnoreCase(nan)) {
2864                    this.notANumberRep = "'nan'";
2865                    this.notANumberRepIsClipped = false;
2866                }
2867            }
2868
2869            rs.close();
2870            rs = null;
2871
2872            stmt.close();
2873            stmt = null;
2874        } catch (SQLException sqlEx) {
2875            ; // ignore here, we default to lowest-common denominator
2876        } finally {
2877            if (rs != null) {
2878                try {
2879                    rs.close();
2880                } catch (SQLException sqlEx) {
2881                    ; // ignore
2882                }
2883
2884                rs = null;
2885            }
2886
2887            if (stmt != null) {
2888                try {
2889                    stmt.close();
2890                } catch (SQLException sqlEx) {
2891                    ; // ignore
2892                }
2893
2894                stmt = null;
2895            }
2896        }
2897    }
2898
2899    /**
2900     * Initializes driver properties that come from URL or properties passed to
2901     * the driver manager.
2902     *
2903     * @param info DOCUMENT ME!
2904     *
2905     * @throws SQLException DOCUMENT ME!
2906     */
2907    private void initializeDriverProperties(Properties info)
2908        throws SQLException {
2909      
2910      if (info.getProperty("tinyInt1isBit") != null) {
2911        this.tinyint1isBit = ("TRUE".equalsIgnoreCase(info.getProperty("tinyInt1isBit")));
2912      } else {
2913        this.tinyint1isBit = true;
2914      }
2915      
2916      this.useOnlyServerErrorMessages = ("TRUE".equalsIgnoreCase(info.getProperty("useOnlyServerErrorMessages")));
2917      
2918      // This property has a 'default', so need to use long-form
2919      if (info.getProperty("rollbackOnPooledClose") != null) {
2920        this.rollbackOnPooledClose = "TRUE".equalsIgnoreCase(info.getProperty("rollbackOnPooledClose"));
2921      }
2922      
2923        this.socketFactoryClassName = info.getProperty("socketFactory",
2924                DEFAULT_SOCKET_FACTORY);
2925
2926        this.failOverReadOnly = "TRUE".equalsIgnoreCase(info.getProperty(
2927                    "failOverReadOnly"));
2928
2929        if (info.getProperty("useUnbufferedInput") != null) {
2930          this.useUnbufferedInput = "TRUE".equalsIgnoreCase(info.getProperty(
2931                    "useUnbufferedInput"));
2932        }
2933
2934        if (info.getProperty("cachePrepStmts") != null) {
2935            this.cachePreparedStatements = info.getProperty("cachePrepStmts")
2936                                               .equalsIgnoreCase("TRUE");
2937
2938            if (this.cachePreparedStatements) {
2939                if (info.getProperty("prepStmtCacheSize") != null) {
2940                    try {
2941                        this.preparedStatementCacheSize = Integer.parseInt(info
2942                                .getProperty("prepStmtCacheSize"));
2943
2944                        if (this.preparedStatementCacheSize < 0) {
2945                            throw new SQLException("Connection property 'prepStmtCacheSize' must be a non-negative integer value.",
2946                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2947                        }
2948                    } catch (NumberFormatException nfe) {
2949                        throw new SQLException("Connection property 'prepStmtCacheSize' must be a non-negative integer value.",
2950                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2951                    }
2952                }
2953
2954                if (info.getProperty("prepStmtCacheSqlLimit") != null) {
2955                    try {
2956                        this.preparedStatementCacheMaxSqlSize = Integer
2957                            .parseInt(info.getProperty("prepStmtCacheSqlLimit"));
2958
2959                        if (this.preparedStatementCacheMaxSqlSize < 0) {
2960                            throw new SQLException("Connection property 'prepStmtCacheSqlLimit' must be a non-negative integer value.",
2961                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2962                        }
2963                    } catch (NumberFormatException nfe) {
2964                        throw new SQLException("Connection property 'prepStmtCacheSqlLimit' must be a non-negative integer value.",
2965                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2966                    }
2967                }
2968
2969                this.cachedPreparedStatementParams = new HashMap(this.preparedStatementCacheSize);
2970            }
2971        }
2972
2973        if (info.getProperty("alwaysClearStream") != null) {
2974            this.alwaysClearStream = info.getProperty("alwaysClearStream")
2975                                         .equalsIgnoreCase("TRUE");
2976        }
2977
2978        if (info.getProperty("reconnectAtTxEnd") != null) {
2979            this.reconnectAtTxEnd = info.getProperty("reconnectAtTxEnd")
2980                                        .equalsIgnoreCase("TRUE");
2981        }
2982
2983        if (info.getProperty("clobberStreamingResults") != null) {
2984            this.clobberStreamingResults = info.getProperty(
2985                    "clobberStreamingResults").equalsIgnoreCase("TRUE");
2986        }
2987
2988        if (info.getProperty("strictUpdates") != null) {
2989            this.strictUpdates = info.getProperty("strictUpdates")
2990                                     .equalsIgnoreCase("TRUE");
2991        }
2992
2993        if (info.getProperty("ignoreNonTxTables") != null) {
2994            this.ignoreNonTxTables = info.getProperty("ignoreNonTxTables")
2995                                         .equalsIgnoreCase("TRUE");
2996        }
2997
2998        if (info.getProperty("secondsBeforeRetryMaster") != null) {
2999            String secondsBeforeRetryStr = info.getProperty(
3000                    "secondsBeforeRetryMaster");
3001
3002            try {
3003                int seconds = Integer.parseInt(secondsBeforeRetryStr);
3004
3005                if (seconds < 1) {
3006                    throw new SQLException("Illegal (< 1)  value '"
3007                        + secondsBeforeRetryStr
3008                        + "' for 'secondsBeforeRetryMaster'",
3009                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3010                }
3011
3012                this.secondsBeforeRetryMaster = seconds;
3013            } catch (NumberFormatException nfe) {
3014                throw new SQLException("Illegal non-numeric value '"
3015                    + secondsBeforeRetryStr
3016                    + "' for 'secondsBeforeRetryMaster'",
3017                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3018            }
3019        }
3020
3021        if (info.getProperty("queriesBeforeRetryMaster") != null) {
3022            String queriesBeforeRetryStr = info.getProperty(
3023                    "queriesBeforeRetryMaster");
3024
3025            try {
3026                this.queriesBeforeRetryMaster = Integer.parseInt(queriesBeforeRetryStr);
3027            } catch (NumberFormatException nfe) {
3028                throw new SQLException("Illegal non-numeric value '"
3029                    + queriesBeforeRetryStr
3030                    + "' for 'queriesBeforeRetryMaster'",
3031                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3032            }
3033        }
3034
3035        if (info.getProperty("allowLoadLocalInfile") != null) {
3036            this.allowLoadLocalInfile = info.getProperty("allowLoadLocalInfile")
3037                                            .equalsIgnoreCase("TRUE");
3038        }
3039
3040        if (info.getProperty("continueBatchOnError") != null) {
3041            this.continueBatchOnError = info.getProperty("continueBatchOnError")
3042                                            .equalsIgnoreCase("TRUE");
3043        }
3044
3045        if (info.getProperty("pedantic") != null) {
3046            this.pedantic = info.getProperty("pedantic").equalsIgnoreCase("TRUE");
3047        }
3048
3049        if (info.getProperty("useStreamLengthsInPrepStmts") != null) {
3050            this.useStreamLengthsInPrepStmts = info.getProperty(
3051                    "useStreamLengthsInPrepStmts").equalsIgnoreCase("TRUE");
3052        }
3053
3054        if (info.getProperty("useTimezone") != null) {
3055            this.useTimezone = info.getProperty("useTimezone").equalsIgnoreCase("TRUE");
3056        }
3057
3058        if (info.getProperty("relaxAutoCommit") != null) {
3059            this.relaxAutoCommit = info.getProperty("relaxAutoCommit")
3060                                       .equalsIgnoreCase("TRUE");
3061        } else if (info.getProperty("relaxAutocommit") != null) {
3062            this.relaxAutoCommit = info.getProperty("relaxAutocommit")
3063                                       .equalsIgnoreCase("TRUE");
3064        }
3065
3066        if (info.getProperty("paranoid") != null) {
3067            this.paranoid = info.getProperty("paranoid").equalsIgnoreCase("TRUE");
3068        }
3069
3070        if (info.getProperty("autoReconnect") != null) {
3071            this.highAvailability = info.getProperty("autoReconnect")
3072                                        .equalsIgnoreCase("TRUE");
3073        }
3074
3075        if (info.getProperty("capitalizeTypeNames") != null) {
3076            this.capitalizeDBMDTypes = info.getProperty("capitalizeTypeNames")
3077                                           .equalsIgnoreCase("TRUE");
3078        }
3079
3080        if (info.getProperty("ultraDevHack") != null) {
3081            this.useUltraDevWorkAround = info.getProperty("ultraDevHack")
3082                                             .equalsIgnoreCase("TRUE");
3083        }
3084
3085        if (info.getProperty("strictFloatingPoint") != null) {
3086            this.strictFloatingPoint = info.getProperty("strictFloatingPoint")
3087                                           .equalsIgnoreCase("TRUE");
3088        }
3089
3090        if (info.getProperty("useSSL") != null) {
3091            this.useSSL = info.getProperty("useSSL").equalsIgnoreCase("TRUE");
3092        }
3093
3094        if (info.getProperty("useCompression") != null) {
3095            this.useCompression = info.getProperty("useCompression")
3096                                      .equalsIgnoreCase("TRUE");
3097        }
3098
3099        if (info.getProperty("socketTimeout") != null) {
3100            try {
3101                int n = Integer.parseInt(info.getProperty("socketTimeout"));
3102
3103                if (n < 0) {
3104                    throw new SQLException("socketTimeout can not " + "be < 0",
3105                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3106                }
3107
3108                this.socketTimeout = n;
3109            } catch (NumberFormatException NFE) {
3110                throw new SQLException("Illegal parameter '"
3111                    + info.getProperty("socketTimeout") + "' for socketTimeout",
3112                    SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3113            }
3114        }
3115
3116        if (this.highAvailability) {
3117            if (info.getProperty("maxReconnects") != null) {
3118                try {
3119                    int n = Integer.parseInt(info.getProperty("maxReconnects"));
3120                    this.maxReconnects = n;
3121                } catch (NumberFormatException NFE) {
3122                    throw new SQLException("Illegal parameter '"
3123                        + info.getProperty("maxReconnects")
3124                        + "' for maxReconnects",
3125                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3126                }
3127            }
3128
3129            if (info.getProperty("initialTimeout") != null) {
3130                try {
3131                    double n = Integer.parseInt(info.getProperty(
3132                                "initialTimeout"));
3133                    this.initialTimeout = n;
3134                } catch (NumberFormatException NFE) {
3135                    throw new SQLException("Illegal parameter '"
3136                        + info.getProperty("initialTimeout")
3137                        + "' for initialTimeout",
3138                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3139                }
3140            }
3141        }
3142
3143        if (info.getProperty("maxRows") != null) {
3144            try {
3145                int n = Integer.parseInt(info.getProperty("maxRows"));
3146
3147                if (n == 0) {
3148                    n = -1;
3149                }
3150
3151                // adjust so that it will become MysqlDefs.MAX_ROWS
3152                // in execSQL()
3153                this.maxRows = n;
3154                this.maxRowsChanged = true;
3155            } catch (NumberFormatException NFE) {
3156                throw new SQLException("Illegal parameter '"
3157                    + info.getProperty("maxRows") + "' for maxRows",
3158                    SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3159            }
3160        }
3161
3162        if (info.getProperty("useHostsInPrivileges") != null) {
3163            this.useHostsInPrivileges = info.getProperty("useHostsInPrivileges")
3164                                            .equalsIgnoreCase("TRUE");
3165        }
3166
3167        if (info.getProperty("interactiveClient") != null) {
3168            this.isInteractiveClient = info.getProperty("interactiveClient")
3169                                           .equalsIgnoreCase("TRUE");
3170        }
3171
3172        if (info.getProperty("useUnicode") != null) {
3173            this.doUnicode = info.getProperty("useUnicode").equalsIgnoreCase("TRUE");
3174        }
3175        
3176       
3177        if (this.doUnicode) {
3178            configureCharsetProperties(info);
3179        }
3180    }
3181
3182    /**
3183     * Configures client-side properties for character set information.
3184     * 
3185   * @param info the properties passed during connection
3186   * 
3187   * @throws SQLException if unable to configure the specified character set.
3188   */
3189  private void configureCharsetProperties(Properties info) throws SQLException {
3190    if (info.getProperty("mysqlEncoding") != null) {
3191        this.mysqlEncodingName = info.getProperty("mysqlEncoding");
3192    }
3193
3194    if (info.getProperty("characterEncoding") != null) {
3195        this.encoding = info.getProperty("characterEncoding");
3196
3197        // Attempt to use the encoding, and bail out if it
3198        // can't be used
3199        try {
3200            String testString = "abc";
3201            testString.getBytes(this.encoding);
3202        } catch (UnsupportedEncodingException UE) {
3203          // Try the MySQL character encoding, then....
3204          String oldEncoding = this.encoding;
3205          
3206          this.encoding = (String)CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(oldEncoding);
3207          
3208          if (this.encoding == null) {
3209            throw new SQLException("Java does not support the MySQL character encoding " +
3210                " "
3211                + "encoding '" + oldEncoding + "'.",
3212                  SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3213          }
3214          
3215          try {
3216              String testString = "abc";
3217              testString.getBytes(this.encoding);
3218          } catch (UnsupportedEncodingException encodingEx) {
3219            throw new SQLException("Unsupported character "
3220                + "encoding '" + this.encoding + "'.",
3221                  SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3222          }
3223        }
3224    }
3225  }
3226
3227  /**
3228     * Sets varying properties that depend on server information. Called once
3229     * we have connected to the server.
3230     *
3231     * @param info DOCUMENT ME!
3232     *
3233     * @throws SQLException DOCUMENT ME!
3234     */
3235    private void initializePropsFromServer(Properties info)
3236        throws SQLException {
3237        // We need to do this before any further data gets
3238        // sent to the server....
3239        boolean clientCharsetIsConfigured = configureClientCharacterSet();
3240
3241        this.useFastPing = this.io.versionMeetsMinimum(3, 22, 1);
3242
3243        this.parserKnowsUnicode = this.io.versionMeetsMinimum(4, 1, 0);
3244
3245        detectFloatingPointStyle();
3246
3247        this.serverVariables.clear();
3248
3249        //
3250        // If version is greater than 3.21.22 get the server
3251        // variables, and do configurations based on them...
3252        //
3253        if (this.io.versionMeetsMinimum(3, 21, 22)) {
3254            loadServerVariables();
3255
3256            buildCollationMapping();
3257
3258            LicenseConfiguration.checkLicenseType(this.serverVariables);
3259
3260            String lowerCaseTables = (String) serverVariables.get(
3261                    "lower_case_table_names");
3262
3263            this.lowerCaseTableNames = "on".equalsIgnoreCase(lowerCaseTables)
3264                || "1".equalsIgnoreCase(lowerCaseTables)
3265                || "2".equalsIgnoreCase(lowerCaseTables);
3266
3267            configureTimezone();
3268
3269            if (this.serverVariables.containsKey("max_allowed_packet")) {
3270                this.maxAllowedPacket = Integer.parseInt((String) this.serverVariables
3271                        .get("max_allowed_packet"));
3272            }
3273
3274            if (this.serverVariables.containsKey("net_buffer_length")) {
3275                this.netBufferLength = Integer.parseInt((String) this.serverVariables
3276                        .get("net_buffer_length"));
3277            }
3278
3279            checkTransactionIsolationLevel();
3280
3281            //
3282            // We only do this for servers older than 4.1.0, because
3283            // 4.1.0 and newer actually send the server charset
3284            // during the handshake, and that's handled at the
3285            // top of this method...
3286            //
3287            if (!clientCharsetIsConfigured) {
3288                checkServerEncoding();
3289            }
3290
3291            this.io.checkForCharsetMismatch();
3292
3293            if (this.serverVariables.containsKey("sql_mode")) {
3294                int sqlMode = 0;
3295
3296                try {
3297                    sqlMode = Integer.parseInt((String) this.serverVariables
3298                            .get("sql_mode"));
3299                } catch (NumberFormatException nfe) {
3300                    sqlMode = 0;
3301                }
3302
3303                if ((sqlMode & 4) > 0) {
3304                    this.useAnsiQuotes = true;
3305                } else {
3306                    this.useAnsiQuotes = false;
3307                }
3308            }
3309        }
3310
3311        if (this.io.versionMeetsMinimum(3, 23, 15)) {
3312            this.transactionsSupported = true;
3313            setAutoCommit(true); // to override anything
3314                                 // the server is set to...reqd
3315                                 // by JDBC spec.
3316        } else {
3317            this.transactionsSupported = false;
3318        }
3319
3320        if (this.io.versionMeetsMinimum(3, 23, 36)) {
3321            this.hasIsolationLevels = true;
3322        } else {
3323            this.hasIsolationLevels = false;
3324        }
3325
3326        // Start logging perf/profile data if the user has requested it.
3327        String profileSql = info.getProperty("profileSql");
3328
3329        if ((profileSql != null) && profileSql.trim().equalsIgnoreCase("true")) {
3330            this.io.setProfileSql(true);
3331        } else {
3332            this.io.setProfileSql(false);
3333        }
3334
3335        this.hasQuotedIdentifiers = this.io.versionMeetsMinimum(3, 23, 6);
3336
3337        // Set to what we've read from the server....
3338        this.io.resetMaxBuf();
3339        
3340        //
3341        // If we're using MySQL 4.1.0 or newer, we need to figure
3342        // out what character set metadata will be returned in,
3343        // and then map that to a Java encoding name.
3344        //
3345        if (this.io.versionMeetsMinimum(4, 1, 0)) {
3346          String characterSetResultsOnServerMysql = (String)this.serverVariables.get("character_set_results");
3347          
3348          if (characterSetResultsOnServerMysql == null || StringUtils.startsWithIgnoreCaseAndWs(characterSetResultsOnServerMysql, "NULL")) {
3349            String defaultMetadataCharsetMysql = (String)this.serverVariables.get("character_set_system");
3350            String defaultMetadataCharset = null;
3351        
3352            if (defaultMetadataCharsetMysql != null) {
3353              defaultMetadataCharset = (String)CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(defaultMetadataCharsetMysql);
3354            } else {
3355              defaultMetadataCharset = "UTF-8";
3356            }
3357            
3358            this.characterSetMetadata = defaultMetadataCharset;
3359          } else {
3360            this.characterSetResultsOnServer = (String)CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(characterSetResultsOnServerMysql);
3361            this.characterSetMetadata = this.characterSetResultsOnServer;
3362          }
3363        }
3364    }
3365
3366    /**
3367     * Loads the mapping between MySQL character sets and Java character sets
3368     */
3369    private static void loadCharacterSetMapping() {
3370        multibyteCharsetsMap = new HashMap();
3371
3372        Iterator multibyteCharsets = CharsetMapping.MULTIBYTE_CHARSETS.keySet()
3373                                                                      .iterator();
3374
3375        while (multibyteCharsets.hasNext()) {
3376            String charset = ((String) multibyteCharsets.next()).toUpperCase();
3377            multibyteCharsetsMap.put(charset, charset);
3378        }
3379
3380        //
3381        // Now change all server encodings to upper-case to "future-proof"
3382        // this mapping
3383        //
3384        Iterator keys = CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.keySet()
3385                                                                .iterator();
3386        charsetMap = new HashMap();
3387
3388        while (keys.hasNext()) {
3389            String mysqlCharsetName = ((String) keys.next()).trim();
3390              String javaCharsetName = CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlCharsetName)
3391                                                                             .toString()
3392                                                                             .trim();
3393              charsetMap.put(mysqlCharsetName.toUpperCase(), javaCharsetName);
3394              charsetMap.put(mysqlCharsetName, javaCharsetName);
3395        }
3396    }
3397
3398    private boolean getUseUltraDevWorkAround() {
3399        return useUltraDevWorkAround;
3400    }
3401
3402    /**
3403     * Loads the result of 'SHOW VARIABLES' into the serverVariables field so
3404     * that the driver can configure itself.
3405     *
3406     * @throws SQLException if the 'SHOW VARIABLES' query fails for any reason.
3407     */
3408    private void loadServerVariables() throws SQLException {
3409        com.mysql.jdbc.Statement stmt = null;
3410        com.mysql.jdbc.ResultSet results = null;
3411
3412        try {
3413            stmt = (com.mysql.jdbc.Statement) createStatement();
3414
3415            if (stmt.getMaxRows() != 0) {
3416                stmt.setMaxRows(0);
3417            }
3418
3419            results = (com.mysql.jdbc.ResultSet) stmt.executeQuery(
3420                    "SHOW VARIABLES");
3421
3422            while (results.next()) {
3423                this.serverVariables.put(results.getString(1),
3424                    results.getString(2));
3425            }
3426        } catch (java.sql.SQLException e) {
3427            throw e;
3428        } finally {
3429            if (results != null) {
3430                try {
3431                    results.close();
3432                } catch (java.sql.SQLException sqlE) {
3433                    ;
3434                }
3435            }
3436
3437            if (stmt != null) {
3438                try {
3439                    stmt.close();
3440                } catch (java.sql.SQLException sqlE) {
3441                    ;
3442                }
3443            }
3444        }
3445    }
3446
3447    // *********************************************************************
3448    //
3449    //                END OF PUBLIC INTERFACE
3450    //
3451    // *********************************************************************
3452
3453    /**
3454     * Detect if the connection is still good
3455     *
3456     * @throws Exception DOCUMENT ME!
3457     */
3458    private void ping() throws Exception {
3459        if (this.useFastPing) {
3460            this.io.sendCommand(MysqlDefs.PING, null, null);
3461        } else {
3462            this.io.sqlQuery(PING_COMMAND, MysqlDefs.MAX_ROWS, this.encoding,
3463                this, java.sql.ResultSet.CONCUR_READ_ONLY, false, this.database);
3464        }
3465    }
3466
3467    private void pingAndReconnect(boolean ignoreAutoCommitSetting)
3468        throws SQLException {
3469        boolean localAutoCommit = this.autoCommit;
3470
3471        // We use this to catch the 'edge' case
3472        // of autoReconnect going from true->false
3473        //
3474        if (ignoreAutoCommitSetting) {
3475            localAutoCommit = true;
3476        }
3477
3478        if (this.failedOver && localAutoCommit) {
3479            this.queriesIssuedFailedOver++;
3480
3481            if (shouldFallBack()) {
3482                createNewIO(true);
3483
3484                String connectedHost = this.io.getHost();
3485
3486                if ((connectedHost != null)
3487                        && this.hostList.get(0).equals(connectedHost)) {
3488                    this.failedOver = false;
3489                    this.queriesIssuedFailedOver = 0;
3490                    setReadOnly(false);
3491                }
3492            }
3493        }
3494
3495        if ((this.highAvailability || this.failedOver) && localAutoCommit) {
3496            try {
3497                ping();
3498            } catch (Exception Ex) {
3499                createNewIO(true);
3500            }
3501        }
3502
3503        this.needsPing = false;
3504    }
3505
3506    private void rollbackNoChecks() throws SQLException {
3507        execSQL("rollback", -1, null);
3508    }
3509
3510    /**
3511     * Should we try to connect back to the master? We try when we've been
3512     * failed over >= this.secondsBeforeRetryMaster _or_ we've issued >
3513     * this.queriesIssuedFailedOver
3514     *
3515     * @return DOCUMENT ME!
3516     */
3517    private boolean shouldFallBack() {
3518        long secondsSinceFailedOver = (System.currentTimeMillis()
3519            - this.masterFailTimeMillis) / 1000;
3520
3521        return ((secondsSinceFailedOver >= this.secondsBeforeRetryMaster)
3522        || ((this.queriesIssuedFailedOver % this.queriesBeforeRetryMaster) == 0));
3523    }
3524
3525    /**
3526     * Wrapper class for UltraDev CallableStatements that are really
3527     * PreparedStatments. Nice going, UltraDev developers.
3528     */
3529    class UltraDevWorkAround implements java.sql.CallableStatement {
3530        private java.sql.PreparedStatement delegate = null;
3531
3532        UltraDevWorkAround(java.sql.PreparedStatement pstmt) {
3533            delegate = pstmt;
3534        }
3535
3536        public void setArray(int p1, final java.sql.Array p2)
3537            throws java.sql.SQLException {
3538            delegate.setArray(p1, p2);
3539        }
3540
3541        public java.sql.Array getArray(int p1) throws java.sql.SQLException {
3542            throw new SQLException("Not supported");
3543        }
3544
3545        /**
3546         * @see CallableStatement#getArray(String)
3547         */
3548        public java.sql.Array getArray(String arg0) throws SQLException {
3549            throw new NotImplemented();
3550        }
3551
3552        public void setAsciiStream(int p1, final java.io.InputStream p2, int p3)
3553            throws java.sql.SQLException {
3554            delegate.setAsciiStream(p1, p2, p3);
3555        }
3556
3557        /**
3558         * @see CallableStatement#setAsciiStream(String, InputStream, int)
3559         */
3560        public void setAsciiStream(String arg0, InputStream arg1, int arg2)
3561            throws SQLException {
3562            throw new NotImplemented();
3563        }
3564
3565        public void setBigDecimal(int p1, final java.math.BigDecimal p2)
3566            throws java.sql.SQLException {
3567            delegate.setBigDecimal(p1, p2);
3568        }
3569
3570        /**
3571         * @see CallableStatement#setBigDecimal(String, BigDecimal)
3572         */
3573        public void setBigDecimal(String arg0, BigDecimal arg1)
3574            throws SQLException {
3575            throw new NotImplemented();
3576        }
3577
3578        public java.math.BigDecimal getBigDecimal(int p1)
3579            throws java.sql.SQLException {
3580            throw new SQLException("Not supported");
3581        }
3582
3583        public java.math.BigDecimal getBigDecimal(int p1, int p2)
3584            throws java.sql.SQLException {
3585            throw new SQLException("Not supported");
3586        }
3587
3588        /**
3589         * @see CallableStatement#getBigDecimal(String)
3590         */
3591        public BigDecimal getBigDecimal(String arg0) throws SQLException {
3592            return null;
3593        }
3594
3595        public void setBinaryStream(int p1, final java.io.InputStream p2, int p3)
3596            throws java.sql.SQLException {
3597            delegate.setBinaryStream(p1, p2, p3);
3598        }
3599
3600        /**
3601         * @see CallableStatement#setBinaryStream(String, InputStream, int)
3602         */
3603        public void setBinaryStream(String arg0, InputStream arg1, int arg2)
3604            throws SQLException {
3605            throw new NotImplemented();
3606        }
3607
3608        public void setBlob(int p1, final java.sql.Blob p2)
3609            throws java.sql.SQLException {
3610            delegate.setBlob(p1, p2);
3611        }
3612
3613        public java.sql.Blob getBlob(int p1) throws java.sql.SQLException {
3614            throw new SQLException("Not supported");
3615        }
3616
3617        /**
3618         * @see CallableStatement#getBlob(String)
3619         */
3620        public java.sql.Blob getBlob(String arg0) throws SQLException {
3621            throw new NotImplemented();
3622        }
3623
3624        public void setBoolean(int p1, boolean p2) throws java.sql.SQLException {
3625            delegate.setBoolean(p1, p2);
3626        }
3627
3628        /**
3629         * @see CallableStatement#setBoolean(String, boolean)
3630         */
3631        public void setBoolean(String arg0, boolean arg1)
3632            throws SQLException {
3633            throw new NotImplemented();
3634        }
3635
3636        public boolean getBoolean(int p1) throws java.sql.SQLException {
3637            throw new SQLException("Not supported");
3638        }
3639
3640        /**
3641         * @see CallableStatement#getBoolean(String)
3642         */
3643        public boolean getBoolean(String arg0) throws SQLException {
3644            throw new NotImplemented();
3645        }
3646
3647        public void setByte(int p1, byte p2) throws java.sql.SQLException {
3648            delegate.setByte(p1, p2);
3649        }
3650
3651        /**
3652         * @see CallableStatement#setByte(String, byte)
3653         */
3654        public void setByte(String arg0, byte arg1) throws SQLException {
3655            throw new NotImplemented();
3656        }
3657
3658        public byte getByte(int p1) throws java.sql.SQLException {
3659            throw new SQLException("Not supported");
3660        }
3661
3662        /**
3663         * @see CallableStatement#getByte(String)
3664         */
3665        public byte getByte(String arg0) throws SQLException {
3666            throw new NotImplemented();
3667        }
3668
3669        public void setBytes(int p1, byte[] p2) throws java.sql.SQLException {
3670            delegate.setBytes(p1, p2);
3671        }
3672
3673        /**
3674         * @see CallableStatement#setBytes(String, byte[])
3675         */
3676        public void setBytes(String arg0, byte[] arg1)
3677            throws SQLException {
3678            throw new NotImplemented();
3679        }
3680
3681        public byte[] getBytes(int p1) throws java.sql.SQLException {
3682            throw new SQLException("Not supported");
3683        }
3684
3685        /**
3686         * @see CallableStatement#getBytes(String)
3687         */
3688        public byte[] getBytes(String arg0) throws SQLException {
3689            throw new NotImplemented();
3690        }
3691
3692        public void setCharacterStream(int p1, final java.io.Reader p2, int p3)
3693            throws java.sql.SQLException {
3694            delegate.setCharacterStream(p1, p2, p3);
3695        }
3696
3697        /**
3698         * @see CallableStatement#setCharacterStream(String, Reader, int)
3699         */
3700        public void setCharacterStream(String arg0, Reader arg1, int arg2)
3701            throws SQLException {
3702            throw new NotImplemented();
3703        }
3704
3705        public void setClob(int p1, final java.sql.Clob p2)
3706            throws java.sql.SQLException {
3707            delegate.setClob(p1, p2);
3708        }
3709
3710        public java.sql.Clob getClob(int p1) throws java.sql.SQLException {
3711            throw new SQLException("Not supported");
3712        }
3713
3714        /**
3715         * @see CallableStatement#getClob(String)
3716         */
3717        public Clob getClob(String arg0) throws SQLException {
3718            throw new NotImplemented();
3719        }
3720
3721        public java.sql.Connection getConnection() throws java.sql.SQLException {
3722            return delegate.getConnection();
3723        }
3724
3725        public void setCursorName(java.lang.String p1)
3726            throws java.sql.SQLException {
3727            throw new SQLException("Not supported");
3728        }
3729
3730        public void setDate(int p1, final java.sql.Date p2)
3731            throws java.sql.SQLException {
3732            delegate.setDate(p1, p2);
3733        }
3734
3735        public void setDate(int p1, final java.sql.Date p2,
3736            final java.util.Calendar p3) throws java.sql.SQLException {
3737            delegate.setDate(p1, p2, p3);
3738        }
3739
3740        /**
3741         * @see CallableStatement#setDate(String, Date, Calendar)
3742         */
3743        public void setDate(String arg0, Date arg1, Calendar arg2)
3744            throws SQLException {
3745            throw new NotImplemented();
3746        }
3747
3748        /**
3749         * @see CallableStatement#setDate(String, Date)
3750         */
3751        public void setDate(String arg0, Date arg1) throws SQLException {
3752            throw new NotImplemented();
3753        }
3754
3755        public java.sql.Date getDate(int p1) throws java.sql.SQLException {
3756            throw new SQLException("Not supported");
3757        }
3758
3759        public java.sql.Date getDate(int p1, final java.util.Calendar p2)
3760            throws java.sql.SQLException {
3761            throw new SQLException("Not supported");
3762        }
3763
3764        /**
3765         * @see CallableStatement#getDate(String, Calendar)
3766         */
3767        public Date getDate(String arg0, Calendar arg1)
3768            throws SQLException {
3769            throw new NotImplemented();
3770        }
3771
3772        /**
3773         * @see CallableStatement#getDate(String)
3774         */
3775        public Date getDate(String arg0) throws SQLException {
3776            throw new NotImplemented();
3777        }
3778
3779        public void setDouble(int p1, double p2) throws java.sql.SQLException {
3780            delegate.setDouble(p1, p2);
3781        }
3782
3783        /**
3784         * @see CallableStatement#setDouble(String, double)
3785         */
3786        public void setDouble(String arg0, double arg1)
3787            throws SQLException {
3788            throw new NotImplemented();
3789        }
3790
3791        public double getDouble(int p1) throws java.sql.SQLException {
3792            throw new SQLException("Not supported");
3793        }
3794
3795        /**
3796         * @see CallableStatement#getDouble(String)
3797         */
3798        public double getDouble(String arg0) throws SQLException {
3799            throw new NotImplemented();
3800        }
3801
3802        public void setEscapeProcessing(boolean p1)
3803            throws java.sql.SQLException {
3804            delegate.setEscapeProcessing(p1);
3805        }
3806
3807        public void setFetchDirection(int p1) throws java.sql.SQLException {
3808            delegate.setFetchDirection(p1);
3809        }
3810
3811        public int getFetchDirection() throws java.sql.SQLException {
3812            return delegate.getFetchDirection();
3813        }
3814
3815        public void setFetchSize(int p1) throws java.sql.SQLException {
3816            delegate.setFetchSize(p1);
3817        }
3818
3819        public int getFetchSize() throws java.sql.SQLException {
3820            return delegate.getFetchSize();
3821        }
3822
3823        public void setFloat(int p1, float p2) throws java.sql.SQLException {
3824            delegate.setFloat(p1, p2);
3825        }
3826
3827        /**
3828         * @see CallableStatement#setFloat(String, float)
3829         */
3830        public void setFloat(String arg0, float arg1) throws SQLException {
3831            throw new NotImplemented();
3832        }
3833
3834        public float getFloat(int p1) throws java.sql.SQLException {
3835            throw new SQLException("Not supported");
3836        }
3837
3838        /**
3839         * @see CallableStatement#getFloat(String)
3840         */
3841        public float getFloat(String arg0) throws SQLException {
3842            throw new NotImplemented();
3843        }
3844
3845        /**
3846         * @see Statement#getGeneratedKeys()
3847         */
3848        public java.sql.ResultSet getGeneratedKeys() throws SQLException {
3849            return delegate.getGeneratedKeys();
3850        }
3851
3852        public void setInt(int p1, int p2) throws java.sql.SQLException {
3853            delegate.setInt(p1, p2);
3854        }
3855
3856        /**
3857         * @see CallableStatement#setInt(String, int)
3858         */
3859        public void setInt(String arg0, int arg1) throws SQLException {
3860            throw new NotImplemented();
3861        }
3862
3863        public int getInt(int p1) throws java.sql.SQLException {
3864            throw new SQLException("Not supported");
3865        }
3866
3867        /**
3868         * @see CallableStatement#getInt(String)
3869         */
3870        public int getInt(String arg0) throws SQLException {
3871            throw new NotImplemented();
3872        }
3873
3874        public void setLong(int p1, long p2) throws java.sql.SQLException {
3875            delegate.setLong(p1, p2);
3876        }
3877
3878        /**
3879         * @see CallableStatement#setLong(String, long)
3880         */
3881        public void setLong(String arg0, long arg1) throws SQLException {
3882            throw new NotImplemented();
3883        }
3884
3885        public long getLong(int p1) throws java.sql.SQLException {
3886            throw new SQLException("Not supported");
3887        }
3888
3889        /**
3890         * @see CallableStatement#getLong(String)
3891         */
3892        public long getLong(String arg0) throws SQLException {
3893            throw new NotImplemented();
3894        }
3895
3896        public void setMaxFieldSize(int p1) throws java.sql.SQLException {
3897            delegate.setMaxFieldSize(p1);
3898        }
3899
3900        public int getMaxFieldSize() throws java.sql.SQLException {
3901            return delegate.getMaxFieldSize();
3902        }
3903
3904        public void setMaxRows(int p1) throws java.sql.SQLException {
3905            delegate.setMaxRows(p1);
3906        }
3907
3908        public int getMaxRows() throws java.sql.SQLException {
3909            return delegate.getMaxRows();
3910        }
3911
3912        public java.sql.ResultSetMetaData getMetaData()
3913            throws java.sql.SQLException {
3914            throw new SQLException("Not supported");
3915        }
3916
3917        public boolean getMoreResults() throws java.sql.SQLException {
3918            return delegate.getMoreResults();
3919        }
3920
3921        /**
3922         * @see Statement#getMoreResults(int)
3923         */
3924        public boolean getMoreResults(int arg0) throws SQLException {
3925            return delegate.getMoreResults();
3926        }
3927
3928        public void setNull(int p1, int p2) throws java.sql.SQLException {
3929            delegate.setNull(p1, p2);
3930        }
3931
3932        public void setNull(int p1, int p2, java.lang.String p3)
3933            throws java.sql.SQLException {
3934            delegate.setNull(p1, p2, p3);
3935        }
3936
3937        /**
3938         * @see CallableStatement#setNull(String, int, String)
3939         */
3940        public void setNull(String arg0, int arg1, String arg2)
3941            throws SQLException {
3942            throw new NotImplemented();
3943        }
3944
3945        /**
3946         * @see CallableStatement#setNull(String, int)
3947         */
3948        public void setNull(String arg0, int arg1) throws SQLException {
3949            throw new NotImplemented();
3950        }
3951
3952        public void setObject(int p1, final java.lang.Object p2)
3953            throws java.sql.SQLException {
3954            delegate.setObject(p1, p2);
3955        }
3956
3957        public void setObject(int p1, final java.lang.Object p2, int p3)
3958            throws java.sql.SQLException {
3959            delegate.setObject(p1, p2, p3);
3960        }
3961
3962        public void setObject(int p1, final java.lang.Object p2, int p3, int p4)
3963            throws java.sql.SQLException {
3964            delegate.setObject(p1, p2, p3, p4);
3965        }
3966
3967        /**
3968         * @see CallableStatement#setObject(String, Object, int, int)
3969         */
3970        public void setObject(String arg0, Object arg1, int arg2, int arg3)
3971            throws SQLException {
3972            throw new NotImplemented();
3973        }
3974
3975        /**
3976         * @see CallableStatement#setObject(String, Object, int)
3977         */
3978        public void setObject(String arg0, Object arg1, int arg2)
3979            throws SQLException {
3980            throw new NotImplemented();
3981        }
3982
3983        /**
3984         * @see CallableStatement#setObject(String, Object)
3985         */
3986        public void setObject(String arg0, Object arg1)
3987            throws SQLException {
3988            throw new NotImplemented();
3989        }
3990
3991        public java.lang.Object getObject(int p1) throws java.sql.SQLException {
3992            throw new SQLException("Not supported");
3993        }
3994
3995        public java.lang.Object getObject(int p1, final java.util.Map p2)
3996            throws java.sql.SQLException {
3997            throw new SQLException("Not supported");
3998        }
3999
4000        /**
4001         * @see CallableStatement#getObject(String, Map)
4002         */
4003        public Object getObject(String arg0, Map arg1)
4004            throws SQLException {
4005            throw new NotImplemented();
4006        }
4007
4008        /**
4009         * @see CallableStatement#getObject(String)
4010         */
4011        public Object getObject(String arg0) throws SQLException {
4012            throw new NotImplemented();
4013        }
4014
4015        /**
4016         * @see PreparedStatement#getParameterMetaData()
4017         */
4018        public ParameterMetaData getParameterMetaData()
4019            throws SQLException {
4020            return delegate.getParameterMetaData();
4021        }
4022
4023        public void setQueryTimeout(int p1) throws java.sql.SQLException {
4024            throw new SQLException("Not supported");
4025        }
4026
4027        public int getQueryTimeout() throws java.sql.SQLException {
4028            return delegate.getQueryTimeout();
4029        }
4030
4031        public void setRef(int p1, final java.sql.Ref p2)
4032            throws java.sql.SQLException {
4033            throw new SQLException("Not supported");
4034        }
4035
4036        public java.sql.Ref getRef(int p1) throws java.sql.SQLException {
4037            throw new SQLException("Not supported");
4038        }
4039
4040        /**
4041         * @see CallableStatement#getRef(String)
4042         */
4043        public Ref getRef(String arg0) throws SQLException {
4044            throw new NotImplemented();
4045        }
4046
4047        public java.sql.ResultSet getResultSet() throws java.sql.SQLException {
4048            return delegate.getResultSet();
4049        }
4050
4051        public int getResultSetConcurrency() throws java.sql.SQLException {
4052            return delegate.getResultSetConcurrency();
4053        }
4054
4055        /**
4056         * @see Statement#getResultSetHoldability()
4057         */
4058        public int getResultSetHoldability() throws SQLException {
4059            return delegate.getResultSetHoldability();
4060        }
4061
4062        public int getResultSetType() throws java.sql.SQLException {
4063            return delegate.getResultSetType();
4064        }
4065
4066        public void setShort(int p1, short p2) throws java.sql.SQLException {
4067            delegate.setShort(p1, p2);
4068        }
4069
4070        /**
4071         * @see CallableStatement#setShort(String, short)
4072         */
4073        public void setShort(String arg0, short arg1) throws SQLException {
4074            throw new NotImplemented();
4075        }
4076
4077        public short getShort(int p1) throws java.sql.SQLException {
4078            throw new SQLException("Not supported");
4079        }
4080
4081        /**
4082         * @see CallableStatement#getShort(String)
4083         */
4084        public short getShort(String arg0) throws SQLException {
4085            throw new NotImplemented();
4086        }
4087
4088        public void setString(int p1, java.lang.String p2)
4089            throws java.sql.SQLException {
4090            delegate.setString(p1, p2);
4091        }
4092
4093        /**
4094         * @see CallableStatement#setString(String, String)
4095         */
4096        public void setString(String arg0, String arg1)
4097            throws SQLException {
4098            throw new NotImplemented();
4099        }
4100
4101        public java.lang.String getString(int p1) throws java.sql.SQLException {
4102            throw new SQLException("Not supported");
4103        }
4104
4105        /**
4106         * @see CallableStatement#getString(String)
4107         */
4108        public String getString(String arg0) throws SQLException {
4109            throw new NotImplemented();
4110        }
4111
4112        public void setTime(int p1, final java.sql.Time p2)
4113            throws java.sql.SQLException {
4114            delegate.setTime(p1, p2);
4115        }
4116
4117        public void setTime(int p1, final java.sql.Time p2,
4118            final java.util.Calendar p3) throws java.sql.SQLException {
4119            delegate.setTime(p1, p2, p3);
4120        }
4121
4122        /**
4123         * @see CallableStatement#setTime(String, Time, Calendar)
4124         */
4125        public void setTime(String arg0, Time arg1, Calendar arg2)
4126            throws SQLException {
4127            throw new NotImplemented();
4128        }
4129
4130        /**
4131         * @see CallableStatement#setTime(String, Time)
4132         */
4133        public void setTime(String arg0, Time arg1) throws SQLException {
4134            throw new NotImplemented();
4135        }
4136
4137        public java.sql.Time getTime(int p1) throws java.sql.SQLException {
4138            throw new SQLException("Not supported");
4139        }
4140
4141        public java.sql.Time getTime(int p1, final java.util.Calendar p2)
4142            throws java.sql.SQLException {
4143            throw new SQLException("Not supported");
4144        }
4145
4146        /**
4147         * @see CallableStatement#getTime(String, Calendar)
4148         */
4149        public Time getTime(String arg0, Calendar arg1)
4150            throws SQLException {
4151            throw new NotImplemented();
4152        }
4153
4154        /**
4155         * @see CallableStatement#getTime(String)
4156         */
4157        public Time getTime(String arg0) throws SQLException {
4158            throw new NotImplemented();
4159        }
4160
4161        public void setTimestamp(int p1, final java.sql.Timestamp p2)
4162            throws java.sql.SQLException {
4163            delegate.setTimestamp(p1, p2);
4164        }
4165
4166        public void setTimestamp(int p1, final java.sql.Timestamp p2,
4167            final java.util.Calendar p3) throws java.sql.SQLException {
4168            delegate.setTimestamp(p1, p2, p3);
4169        }
4170
4171        /**
4172         * @see CallableStatement#setTimestamp(String, Timestamp, Calendar)
4173         */
4174        public void setTimestamp(String arg0, Timestamp arg1, Calendar arg2)
4175            throws SQLException {
4176            throw new NotImplemented();
4177        }
4178
4179        /**
4180         * @see CallableStatement#setTimestamp(String, Timestamp)
4181         */
4182        public void setTimestamp(String arg0, Timestamp arg1)
4183            throws SQLException {
4184            throw new NotImplemented();
4185        }
4186
4187        public java.sql.Timestamp getTimestamp(int p1)
4188            throws java.sql.SQLException {
4189            throw new SQLException("Not supported");
4190        }
4191
4192        public java.sql.Timestamp getTimestamp(int p1,
4193            final java.util.Calendar p2) throws java.sql.SQLException {
4194            throw new SQLException("Not supported");
4195        }
4196
4197        /**
4198         * @see CallableStatement#getTimestamp(String, Calendar)
4199         */
4200        public Timestamp getTimestamp(String arg0, Calendar arg1)
4201            throws SQLException {
4202            throw new NotImplemented();
4203        }
4204
4205        /**
4206         * @see CallableStatement#getTimestamp(String)
4207         */
4208        public Timestamp getTimestamp(String arg0) throws SQLException {
4209            throw new NotImplemented();
4210        }
4211
4212        /**
4213         * @see CallableStatement#setURL(String, URL)
4214         */
4215        public void setURL(String arg0, URL arg1) throws SQLException {
4216            throw new NotImplemented();
4217        }
4218
4219        /**
4220         * @see PreparedStatement#setURL(int, URL)
4221         */
4222        public void setURL(int arg0, URL arg1) throws SQLException {
4223            delegate.setURL(arg0, arg1);
4224        }
4225
4226        /**
4227         * @see CallableStatement#getURL(int)
4228         */
4229        public URL getURL(int arg0) throws SQLException {
4230            throw new NotImplemented();
4231        }
4232
4233        /**
4234         * @see CallableStatement#getURL(String)
4235         */
4236        public URL getURL(String arg0) throws SQLException {
4237            throw new NotImplemented();
4238        }
4239
4240        /**
4241         * @deprecated -- we know, but we need to override...
4242         */
4243        public void setUnicodeStream(int p1, final java.io.InputStream p2,
4244            int p3) throws java.sql.SQLException {
4245            delegate.setUnicodeStream(p1, p2, p3);
4246        }
4247
4248        public int getUpdateCount() throws java.sql.SQLException {
4249            return delegate.getUpdateCount();
4250        }
4251
4252        public java.sql.SQLWarning getWarnings() throws java.sql.SQLException {
4253            return delegate.getWarnings();
4254        }
4255
4256        public void addBatch() throws java.sql.SQLException {
4257            delegate.addBatch();
4258        }
4259
4260        public void addBatch(java.lang.String p1) throws java.sql.SQLException {
4261            delegate.addBatch(p1);
4262        }
4263
4264        public void cancel() throws java.sql.SQLException {
4265            delegate.cancel();
4266        }
4267
4268        public void clearBatch() throws java.sql.SQLException {
4269            delegate.clearBatch();
4270        }
4271
4272        public void clearParameters() throws java.sql.SQLException {
4273            delegate.clearParameters();
4274        }
4275
4276        public void clearWarnings() throws java.sql.SQLException {
4277            delegate.clearWarnings();
4278        }
4279
4280        public void close() throws java.sql.SQLException {
4281            delegate.close();
4282        }
4283
4284        public boolean execute() throws java.sql.SQLException {
4285            return delegate.execute();
4286        }
4287
4288        public boolean execute(java.lang.String p1)
4289            throws java.sql.SQLException {
4290            return delegate.execute(p1);
4291        }
4292
4293        /**
4294         * @see Statement#execute(String, int)
4295         */
4296        public boolean execute(String arg0, int arg1) throws SQLException {
4297            return delegate.execute(arg0, arg1);
4298        }
4299
4300        /**
4301         * @see Statement#execute(String, int[])
4302         */
4303        public boolean execute(String arg0, int[] arg1)
4304            throws SQLException {
4305            return delegate.execute(arg0, arg1);
4306        }
4307
4308        /**
4309         * @see Statement#execute(String, String[])
4310         */
4311        public boolean execute(String arg0, String[] arg1)
4312            throws SQLException {
4313            return delegate.execute(arg0, arg1);
4314        }
4315
4316        public int[] executeBatch() throws java.sql.SQLException {
4317            return delegate.executeBatch();
4318        }
4319
4320        public java.sql.ResultSet executeQuery() throws java.sql.SQLException {
4321            return delegate.executeQuery();
4322        }
4323
4324        public java.sql.ResultSet executeQuery(java.lang.String p1)
4325            throws java.sql.SQLException {
4326            return delegate.executeQuery(p1);
4327        }
4328
4329        public int executeUpdate() throws java.sql.SQLException {
4330            return delegate.executeUpdate();
4331        }
4332
4333        public int executeUpdate(java.lang.String p1)
4334            throws java.sql.SQLException {
4335            return delegate.executeUpdate(p1);
4336        }
4337
4338        /**
4339         * @see Statement#executeUpdate(String, int)
4340         */
4341        public int executeUpdate(String arg0, int arg1)
4342            throws SQLException {
4343            return delegate.executeUpdate(arg0, arg1);
4344        }
4345
4346        /**
4347         * @see Statement#executeUpdate(String, int[])
4348         */
4349        public int executeUpdate(String arg0, int[] arg1)
4350            throws SQLException {
4351            return delegate.executeUpdate(arg0, arg1);
4352        }
4353
4354        /**
4355         * @see Statement#executeUpdate(String, String[])
4356         */
4357        public int executeUpdate(String arg0, String[] arg1)
4358            throws SQLException {
4359            return delegate.executeUpdate(arg0, arg1);
4360        }
4361
4362        public void registerOutParameter(int p1, int p2)
4363            throws java.sql.SQLException {
4364            throw new SQLException("Not supported");
4365        }
4366
4367        public void registerOutParameter(int p1, int p2, int p3)
4368            throws java.sql.SQLException {
4369            throw new SQLException("Not supported");
4370        }
4371
4372        public void registerOutParameter(int p1, int p2, java.lang.String p3)
4373            throws java.sql.SQLException {
4374            throw new SQLException("Not supported");
4375        }
4376
4377        /**
4378         * @see CallableStatement#registerOutParameter(String, int, int)
4379         */
4380        public void registerOutParameter(String arg0, int arg1, int arg2)
4381            throws SQLException {
4382            throw new NotImplemented();
4383        }
4384
4385        /**
4386         * @see CallableStatement#registerOutParameter(String, int, String)
4387         */
4388        public void registerOutParameter(String arg0, int arg1, String arg2)
4389            throws SQLException {
4390            throw new NotImplemented();
4391        }
4392
4393        /**
4394         * @see CallableStatement#registerOutParameter(String, int)
4395         */
4396        public void registerOutParameter(String arg0, int arg1)
4397            throws SQLException {
4398            throw new NotImplemented();
4399        }
4400
4401        public boolean wasNull() throws java.sql.SQLException {
4402            throw new SQLException("Not supported");
4403        }
4404    }
4405    
4406  /**
4407   * @return Returns the characterSetMetadata.
4408   */
4409  protected String getCharacterSetMetadata() {
4410    return characterSetMetadata;
4411  }
4412  
4413  /**
4414   * Returns the server's character set
4415   * 
4416   * @return the server's character set.
4417   */
4418  protected String getServerCharacterEncoding() {
4419    return (String)this.serverVariables.get("character_set");
4420  }
4421  
4422  /**
4423   * @return Returns the rollbackOnPooledClose.
4424   */
4425  public boolean getRollbackOnPooledClose() {
4426    return rollbackOnPooledClose;
4427  }
4428  /**
4429   * @return Returns the useOnlyServerErrorMessages.
4430   */
4431  protected boolean getUseOnlyServerErrorMessages() {
4432    return this.useOnlyServerErrorMessages;
4433  }
4434
4435  /**
4436   * @return
4437   */
4438  public boolean getTinyint1isBit() {
4439    // TODO Auto-generated method stub
4440    return this.tinyint1isBit;
4441  }
4442}