~ubuntu-branches/ubuntu/trusty/mysql-connector-java/trusty

« back to all changes in this revision

Viewing changes to src/com/mysql/jdbc/ConnectionImpl.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Miguel Landaeta
  • Date: 2013-07-02 17:07:51 UTC
  • mfrom: (1.1.8) (3.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20130702170751-f4rszjabxg0391fr
Tags: 5.1.25-1
* New upstream release
* Refreshed the patches
* Added a patch to build with one JDK and removed the build
  dependency on java-gcj-compat-dev
* Updated Standards-Version to 3.9.4 (no changes)
* Use canonical URLs for the Vcs-* fields
* debian/rules: Improved the clean target to allow rebuilds
* Updated the watch file
* Renamed debian/README.Debian-source to README.source

[ Miguel Landaeta ] 
* Fix FTBFS with OpenJDK 7 (Closes: #706668)
* Remove Michael Koch from Uploaders list.
  Thanks for your work on this package. (Closes: #654122).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
  Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 
2
  Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3
3
 
4
4
  The MySQL Connector/J is licensed under the terms of the GPLv2
5
5
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
26
26
import java.io.UnsupportedEncodingException;
27
27
import java.lang.reflect.Array;
28
28
import java.lang.reflect.Constructor;
 
29
import java.lang.reflect.InvocationHandler;
29
30
import java.lang.reflect.Method;
30
 
import java.lang.reflect.Proxy;
31
 
import java.net.InetAddress;
32
 
import java.net.UnknownHostException;
33
31
import java.nio.ByteBuffer;
34
32
import java.nio.CharBuffer;
35
33
import java.nio.charset.Charset;
38
36
import java.sql.DatabaseMetaData;
39
37
import java.sql.ResultSet;
40
38
import java.sql.SQLException;
 
39
import java.sql.SQLPermission;
41
40
import java.sql.SQLWarning;
42
41
import java.sql.Savepoint;
43
42
import java.util.ArrayList;
44
43
import java.util.Calendar;
 
44
import java.util.Collections;
45
45
import java.util.Enumeration;
46
46
import java.util.GregorianCalendar;
47
47
import java.util.HashMap;
55
55
import java.util.TimeZone;
56
56
import java.util.Timer;
57
57
import java.util.TreeMap;
 
58
import java.util.concurrent.Executor;
58
59
 
 
60
import com.mysql.jdbc.PreparedStatement.ParseInfo;
59
61
import com.mysql.jdbc.log.Log;
60
62
import com.mysql.jdbc.log.LogFactory;
 
63
import com.mysql.jdbc.log.LogUtils;
61
64
import com.mysql.jdbc.log.NullLogger;
62
65
import com.mysql.jdbc.profiler.ProfilerEvent;
63
66
import com.mysql.jdbc.profiler.ProfilerEventHandler;
79
82
 */
80
83
public class ConnectionImpl extends ConnectionPropertiesImpl implements
81
84
                MySQLConnection {
 
85
 
 
86
        private static final long serialVersionUID = 2877471301981509474L;
 
87
 
 
88
        private static final SQLPermission SET_NETWORK_TIMEOUT_PERM = new SQLPermission("setNetworkTimeout");
 
89
        
 
90
        private static final SQLPermission ABORT_PERM = new SQLPermission("abort");
 
91
 
82
92
        private static final String JDBC_LOCAL_CHARACTER_SET_RESULTS = "jdbc.local.character_set_results";
83
93
 
84
 
   public String getHost() {
85
 
      return host;
86
 
   }
87
 
 
88
 
   private MySQLConnection proxy = null;
89
 
   
90
 
   public boolean isProxySet(){
91
 
           return this.proxy != null;
92
 
   }
93
 
 
94
 
   public void setProxy(MySQLConnection proxy) {
95
 
      this.proxy = proxy;
96
 
   }
97
 
 
98
 
   // We have to proxy ourselves when we're load balanced so that
99
 
   // statements get routed to the right physical connection
100
 
   // (when load balanced, we're a "logical" connection)
101
 
   private MySQLConnection getProxy() {
102
 
      return (proxy != null) ? proxy : (MySQLConnection) this;
103
 
   }
104
 
   
105
 
   public MySQLConnection getLoadBalanceSafeProxy() {
106
 
           return this.getProxy();
107
 
   }
108
 
   
 
94
        public String getHost() {
 
95
                return host;
 
96
        }
 
97
 
 
98
        private MySQLConnection proxy = null;
 
99
 
 
100
        private InvocationHandler realProxy = null;
 
101
 
 
102
        public boolean isProxySet(){
 
103
                return this.proxy != null;
 
104
        }
 
105
 
 
106
        public void setProxy(MySQLConnection proxy) {
 
107
                this.proxy = proxy;
 
108
        }
 
109
 
 
110
        public void setRealProxy(InvocationHandler proxy) {
 
111
                this.realProxy = proxy;
 
112
        }
 
113
 
 
114
        // We have to proxy ourselves when we're load balanced so that
 
115
        // statements get routed to the right physical connection
 
116
        // (when load balanced, we're a "logical" connection)
 
117
        private MySQLConnection getProxy() {
 
118
                return (proxy != null) ? proxy : (MySQLConnection) this;
 
119
        }
 
120
 
 
121
        public MySQLConnection getLoadBalanceSafeProxy() {
 
122
                return this.getProxy();
 
123
        }
 
124
 
 
125
        public Object getConnectionMutex() {
 
126
                return (this.realProxy != null) ? this.realProxy : this;
 
127
        }
109
128
 
110
129
        class ExceptionInterceptorChain implements ExceptionInterceptor {
111
 
                List interceptors;
 
130
                List<Extension> interceptors;
112
131
                
113
132
                ExceptionInterceptorChain(String interceptorClasses) throws SQLException {
114
133
                        interceptors = Util.loadExtensions(ConnectionImpl.this, props, interceptorClasses, "Connection.BadExceptionInterceptor",  this);
115
134
                }
116
135
                
 
136
                void addRingZero(ExceptionInterceptor interceptor) throws SQLException {        
 
137
                        interceptors.add(0, interceptor);
 
138
                }
 
139
                
117
140
                public SQLException interceptException(SQLException sqlEx, Connection conn) {
118
141
                        if (interceptors != null) {
119
 
                                Iterator iter = interceptors.iterator();
 
142
                                Iterator<Extension> iter = interceptors.iterator();
120
143
                                
121
144
                                while (iter.hasNext()) {
122
145
                                        sqlEx = ((ExceptionInterceptor)iter.next()).interceptException(sqlEx, ConnectionImpl.this);
128
151
 
129
152
                public void destroy() {
130
153
                        if (interceptors != null) {
131
 
                                Iterator iter = interceptors.iterator();
 
154
                                Iterator<Extension> iter = interceptors.iterator();
132
155
                                
133
156
                                while (iter.hasNext()) {
134
157
                                        ((ExceptionInterceptor)iter.next()).destroy();
137
160
                        
138
161
                }
139
162
 
140
 
                public void init(Connection conn, Properties props) throws SQLException {
 
163
                public void init(Connection conn, Properties properties) throws SQLException {
141
164
                        if (interceptors != null) {
142
 
                                Iterator iter = interceptors.iterator();
 
165
                                Iterator<Extension> iter = interceptors.iterator();
143
166
                                
144
167
                                while (iter.hasNext()) {
145
 
                                        ((ExceptionInterceptor)iter.next()).init(conn, props);
 
168
                                        ((ExceptionInterceptor)iter.next()).init(conn, properties);
146
169
                                }
147
170
                        }
148
171
                }
215
238
         * The mapping between MySQL charset names and Java charset names.
216
239
         * Initialized by loadCharacterSetMapping()
217
240
         */
218
 
        public static Map charsetMap;
 
241
        public static Map<?, ?> charsetMap;
219
242
 
220
243
        /** Default logger class name */
221
244
        protected static final String DEFAULT_LOGGER_CLASS = "com.mysql.jdbc.log.StandardLogger";
229
252
         * Map mysql transaction isolation level name to
230
253
         * java.sql.Connection.TRANSACTION_XXX
231
254
         */
232
 
        private static Map mapTransIsolationNameToValue = null;
 
255
        private static Map<String, Integer> mapTransIsolationNameToValue = null;
233
256
 
234
257
        /** Null logger shared by all connections at startup */
235
258
        private static final Log NULL_LOGGER = new NullLogger(LOGGER_INSTANCE_NAME);
236
259
 
237
 
        private static Map roundRobinStatsMap;
238
 
 
239
 
        private static final Map serverCollationByUrl = new HashMap();
240
 
 
241
 
        private static final Map serverConfigByUrl = new HashMap();
 
260
        protected static Map<?, ?> roundRobinStatsMap;
 
261
 
 
262
        private static final Map<String, Map<Long, String>> serverCollationByUrl = new HashMap<String, Map<Long,String>>();
 
263
 
 
264
        /**
 
265
         * Map for Java charsets of user defined charsets. We can't map them statically, because
 
266
         * they can be different for different server URLs.
 
267
         */
 
268
        private static final Map<String, Map<Integer, String>> serverJavaCharsetByUrl = new HashMap<String, Map<Integer,String>>();
 
269
        /**
 
270
         * Map for user defined charsets. We can't map them statically, because
 
271
         * they can be different for different server URLs.
 
272
         */
 
273
        private static final Map<String, Map<Integer, String>> serverCustomCharsetByUrl = new HashMap<String, Map<Integer,String>>();
 
274
        /**
 
275
         * Map for user defined charsets. We can't map them statically, because
 
276
         * they can be different for different server URLs.
 
277
         */
 
278
        private static final Map<String, Map<String, Integer>> serverCustomMblenByUrl = new HashMap<String, Map<String, Integer>>();
 
279
        
 
280
        private CacheAdapter<String, Map<String, String>> serverConfigCache;
242
281
 
243
282
        private long queryTimeCount;
244
283
        private double queryTimeSum;
247
286
        
248
287
        private transient Timer cancelTimer;
249
288
        
250
 
        private List connectionLifecycleInterceptors;
 
289
        private List<Extension> connectionLifecycleInterceptors;
251
290
        
252
 
        private static final Constructor JDBC_4_CONNECTION_CTOR;
 
291
        private static final Constructor<?> JDBC_4_CONNECTION_CTOR;
253
292
        
254
293
        private static final int DEFAULT_RESULT_SET_TYPE = ResultSet.TYPE_FORWARD_ONLY;
255
294
        
256
295
        private static final int DEFAULT_RESULT_SET_CONCURRENCY = ResultSet.CONCUR_READ_ONLY;
257
296
        
258
297
        static {
259
 
                mapTransIsolationNameToValue = new HashMap(8);
260
 
                mapTransIsolationNameToValue.put("READ-UNCOMMITED", Integer.valueOf(
261
 
                                TRANSACTION_READ_UNCOMMITTED));
262
 
                mapTransIsolationNameToValue.put("READ-UNCOMMITTED", Integer.valueOf(
263
 
                                TRANSACTION_READ_UNCOMMITTED));
264
 
                mapTransIsolationNameToValue.put("READ-COMMITTED", Integer.valueOf(
265
 
                                TRANSACTION_READ_COMMITTED));
266
 
                mapTransIsolationNameToValue.put("REPEATABLE-READ", Integer.valueOf(
267
 
                                TRANSACTION_REPEATABLE_READ));
268
 
                mapTransIsolationNameToValue.put("SERIALIZABLE", Integer.valueOf(
269
 
                                TRANSACTION_SERIALIZABLE));
 
298
                mapTransIsolationNameToValue = new HashMap<String, Integer>(8);
 
299
                mapTransIsolationNameToValue.put("READ-UNCOMMITED", TRANSACTION_READ_UNCOMMITTED);
 
300
                mapTransIsolationNameToValue.put("READ-UNCOMMITTED", TRANSACTION_READ_UNCOMMITTED);
 
301
                mapTransIsolationNameToValue.put("READ-COMMITTED", TRANSACTION_READ_COMMITTED);
 
302
                mapTransIsolationNameToValue.put("REPEATABLE-READ", TRANSACTION_REPEATABLE_READ);
 
303
                mapTransIsolationNameToValue.put("SERIALIZABLE", TRANSACTION_SERIALIZABLE);
270
304
 
271
305
                if (Util.isJdbc4()) {
272
306
                        try {
311
345
                        Method setStackTraceMethod = null;
312
346
                        Object theStackTraceAsObject = null;
313
347
 
314
 
                        Class stackTraceElementClass = Class
315
 
                                        .forName("java.lang.StackTraceElement");
316
 
                        Class stackTraceElementArrayClass = Array.newInstance(
 
348
                        Class<?> stackTraceElementClass = Class.forName("java.lang.StackTraceElement");
 
349
                        Class<?> stackTraceElementArrayClass = Array.newInstance(
317
350
                                        stackTraceElementClass, new int[] { 0 }).getClass();
318
351
 
319
352
                        getStackTraceMethod = Throwable.class.getMethod("getStackTrace",
339
372
                return sqlExceptionWithNewMessage;
340
373
        }
341
374
 
342
 
        public synchronized Timer getCancelTimer() {
343
 
                if (cancelTimer == null) {
344
 
                        boolean createdNamedTimer = false;
345
 
                        
346
 
                        // Use reflection magic to try this on JDK's 1.5 and newer, fallback to non-named
347
 
                        // timer on older VMs.
348
 
                        try {
349
 
                                Constructor ctr = Timer.class.getConstructor(new Class[] {String.class, Boolean.TYPE});
350
 
                                
351
 
                                cancelTimer = (Timer)ctr.newInstance(new Object[] { "MySQL Statement Cancellation Timer", Boolean.TRUE});
352
 
                                createdNamedTimer = true;
353
 
                        } catch (Throwable t) {
354
 
                                createdNamedTimer = false;
355
 
                        }
356
 
                        
357
 
                        if (!createdNamedTimer) {
358
 
                                cancelTimer = new Timer(true);
359
 
                        }
 
375
        public Timer getCancelTimer() {
 
376
                synchronized (getConnectionMutex()) {
 
377
                        if (cancelTimer == null) {
 
378
                                boolean createdNamedTimer = false;
 
379
                                
 
380
                                // Use reflection magic to try this on JDK's 1.5 and newer, fallback to non-named
 
381
                                // timer on older VMs.
 
382
                                try {
 
383
                                        Constructor<Timer> ctr = Timer.class.getConstructor(new Class[] {String.class, Boolean.TYPE});
 
384
                                        
 
385
                                        cancelTimer = ctr.newInstance(new Object[] { "MySQL Statement Cancellation Timer", Boolean.TRUE});
 
386
                                        createdNamedTimer = true;
 
387
                                } catch (Throwable t) {
 
388
                                        createdNamedTimer = false;
 
389
                                }
 
390
                                
 
391
                                if (!createdNamedTimer) {
 
392
                                        cancelTimer = new Timer(true);
 
393
                                }
 
394
                        }
 
395
                        
 
396
                        return cancelTimer;
360
397
                }
361
 
                
362
 
                return cancelTimer;
363
398
        }
364
399
 
365
400
        
386
421
 
387
422
        private static final Random random = new Random();
388
423
        
389
 
        private static synchronized int getNextRoundRobinHostIndex(String url,
390
 
                        List hostList) {
 
424
        /**
 
425
         * 
 
426
         * @param url
 
427
         * @param hostList
 
428
         * @return
 
429
         */
 
430
        protected static synchronized int getNextRoundRobinHostIndex(String url,
 
431
                        List<?> hostList) {
391
432
                // we really do "random" here, because you don't get even
392
433
                // distribution when this is coupled with connection pools
393
434
                
413
454
        /** Are we in autoCommit mode? */
414
455
        private boolean autoCommit = true;
415
456
 
416
 
        /** A map of SQL to parsed prepared statement parameters. */
417
 
        private Map cachedPreparedStatementParams;
 
457
        /** A cache of SQL to parsed prepared statement parameters. */
 
458
        private CacheAdapter<String, ParseInfo> cachedPreparedStatementParams;
418
459
 
419
460
        /**
420
461
         * For servers > 4.1.0, what character set is the metadata returned in?
432
473
         * synchronization and at the same time save memory (each charset converter
433
474
         * takes approx 65K of static data).
434
475
         */
435
 
        private Map charsetConverterMap = new HashMap(CharsetMapping
 
476
        private Map<String, Object> charsetConverterMap = new HashMap<String, Object>(CharsetMapping
436
477
                        .getNumberOfCharsetsConfigured());
437
478
 
438
 
        /**
439
 
         * The mapping between MySQL charset names and the max number of chars in
440
 
         * them. Lazily instantiated via getMaxBytesPerChar().
441
 
         */
442
 
        private Map charsetToNumBytesMap;
443
 
 
444
479
        /** The point in time when this connection was created */
445
480
        private long connectionCreationTimeMillis = 0;
446
481
 
474
509
         * We need this 'bootstrapped', because 4.1 and newer will send fields back
475
510
         * with this even before we fill this dynamically from the server.
476
511
         */
477
 
        private String[] indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
 
512
        public Map<Integer, String> indexToJavaCharset = new HashMap<Integer, String>();
 
513
 
 
514
        public Map<Integer, String> indexToCustomMysqlCharset = new HashMap<Integer, String>();
 
515
 
 
516
        private Map<String, Integer> mysqlCharsetToCustomMblen = new HashMap<String, Integer>();
478
517
        
479
518
        /** The I/O abstraction interface (network conn to MySQL server */
480
519
        private transient MysqlIO io = null;
511
550
        private boolean lowerCaseTableNames = false;
512
551
 
513
552
        /** When did the master fail? */
514
 
        private long masterFailTimeMillis = 0L;
 
553
//      private long masterFailTimeMillis = 0L;
515
554
 
516
555
        private long maximumNumberTablesAccessed = 0;
517
556
 
550
589
        private int[] oldHistCounts = null;
551
590
 
552
591
        /** A map of currently open statements */
553
 
        private Map openStatements;
 
592
        private Map<Statement, Statement> openStatements;
554
593
 
555
594
        private LRUCache parsedCallableStatementCache;
556
595
 
564
603
        private int[] perfMetricsHistCounts;
565
604
 
566
605
        /** Point of origin where this Connection was created */
567
 
        private Throwable pointOfOrigin;
 
606
        private String pointOfOrigin;
568
607
 
569
608
        /** The port number we're connected to (defaults to 3306) */
570
609
        private int port = 3306;
585
624
        private TimeZone serverTimezoneTZ = null;
586
625
 
587
626
        /** The map of server variables that we retrieve at connection init. */
588
 
        private Map serverVariables = null;
 
627
        private Map<String, String> serverVariables = null;
589
628
 
590
629
        private long shortestQueryTimeMs = Long.MAX_VALUE;
591
630
 
592
631
        /** A map of statements that have had setMaxRows() called on them */
593
 
        private Map statementsUsingMaxRows;
 
632
        private Map<Statement, Statement> statementsUsingMaxRows;
594
633
 
595
634
        private double totalQueryTimeMs = 0;
596
635
 
601
640
         * The type map for UDTs (not implemented, but used by some third-party
602
641
         * vendors, most notably IBM WebSphere)
603
642
         */
604
 
        private Map typeMap;
 
643
        private Map<String,Class<?>> typeMap;
605
644
 
606
645
        /** Has ANSI_QUOTES been enabled on the server? */
607
646
        private boolean useAnsiQuotes = false;
646
685
 
647
686
        private boolean storesLowerCaseTableName;
648
687
 
649
 
        private List statementInterceptors;
 
688
        private List<StatementInterceptorV2> statementInterceptors;
650
689
        
651
690
        /**
652
691
         * If a CharsetEncoder is required for escaping. Needed for SJIS and related
683
722
        protected ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info,
684
723
                        String databaseToConnectTo, String url)
685
724
                        throws SQLException {
686
 
                this.charsetToNumBytesMap = new HashMap();
687
725
        
688
726
                this.connectionCreationTimeMillis = System.currentTimeMillis();
689
 
                this.pointOfOrigin = new Throwable();
690
 
 
691
 
      if (databaseToConnectTo == null) {
 
727
                
 
728
                if (databaseToConnectTo == null) {
692
729
                        databaseToConnectTo = "";
693
730
                }
694
731
 
734
771
                        this.isClientTzUTC = false;
735
772
                }
736
773
 
737
 
                this.openStatements = new HashMap();
738
 
 
 
774
                this.openStatements = new HashMap<Statement, Statement>();
 
775
                
739
776
                if (NonRegisteringDriver.isHostPropertiesList(hostToConnectTo)) {
740
777
                        Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(hostToConnectTo);
741
778
                        
784
821
                
785
822
                
786
823
                initializeDriverProperties(info);
787
 
                
 
824
 
 
825
                if (getUseUsageAdvisor()) {
 
826
                        this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable());
 
827
                } else {
 
828
                        this.pointOfOrigin = "";
 
829
                }
788
830
                
789
831
                try {
790
832
                        this.dbmd = getMetaData(false, false);
829
871
                        
830
872
                        throw sqlEx;
831
873
                }
 
874
                
 
875
                NonRegisteringDriver.trackConnection(this);
832
876
        }
833
877
 
834
878
    public void unSafeStatementInterceptors() throws SQLException {
835
879
        
836
 
        ArrayList unSafedStatementInterceptors = new ArrayList(this.statementInterceptors.size());
 
880
        ArrayList<StatementInterceptorV2> unSafedStatementInterceptors = new ArrayList<StatementInterceptorV2>(this.statementInterceptors.size());
837
881
 
838
882
        for (int i = 0; i < this.statementInterceptors.size(); i++) {
839
883
                NoSubInterceptorWrapper wrappedInterceptor = (NoSubInterceptorWrapper) this.statementInterceptors.get(i);
851
895
    public void initializeSafeStatementInterceptors() throws SQLException {
852
896
        this.isClosed = false;
853
897
        
854
 
        List unwrappedInterceptors = Util.loadExtensions(this, this.props, 
 
898
        List<Extension> unwrappedInterceptors = Util.loadExtensions(this, this.props, 
855
899
                                getStatementInterceptors(),
856
900
                                "MysqlIo.BadStatementInterceptor", getExceptionInterceptor());
857
901
        
858
 
        this.statementInterceptors = new ArrayList(unwrappedInterceptors.size());
 
902
        this.statementInterceptors = new ArrayList<StatementInterceptorV2>(unwrappedInterceptors.size());
859
903
 
860
904
        for (int i = 0; i < unwrappedInterceptors.size(); i++) {
861
 
                Object interceptor = unwrappedInterceptors.get(i);
 
905
                Extension interceptor = unwrappedInterceptors.get(i);
862
906
                
863
907
                // adapt older versions of statement interceptors, handle the case where something wants v2
864
908
                // functionality but wants to run with an older driver
876
920
        
877
921
    }
878
922
    
879
 
    public List getStatementInterceptorsInstances() {
 
923
    public List<StatementInterceptorV2> getStatementInterceptorsInstances() {
880
924
        return this.statementInterceptors;
881
925
    }
882
926
    
924
968
         *             DOCUMENT ME!
925
969
         */
926
970
        private void buildCollationMapping() throws SQLException {
 
971
 
 
972
                HashMap<Integer, String> javaCharset = null;
 
973
 
927
974
                if (versionMeetsMinimum(4, 1, 0)) {
928
975
 
929
 
                        TreeMap sortedCollationMap = null;
 
976
                        TreeMap<Long, String> sortedCollationMap = null;
 
977
                        HashMap<Integer, String> customCharset = null;
 
978
                        HashMap<String, Integer> customMblen = null;
930
979
 
931
980
                        if (getCacheServerConfiguration()) {
932
 
                                synchronized (serverConfigByUrl) {
933
 
                                        sortedCollationMap = (TreeMap) serverCollationByUrl
934
 
                                                        .get(getURL());
 
981
                                synchronized (serverCollationByUrl) {
 
982
                                        sortedCollationMap = (TreeMap<Long, String>) serverCollationByUrl.get(getURL());
 
983
                                        javaCharset = (HashMap<Integer, String>) serverJavaCharsetByUrl.get(getURL());
 
984
                                        customCharset = (HashMap<Integer, String>) serverCustomCharsetByUrl.get(getURL());
 
985
                                        customMblen = (HashMap<String, Integer>) serverCustomMblenByUrl.get(getURL());
935
986
                                }
936
987
                        }
937
988
 
940
991
 
941
992
                        try {
942
993
                                if (sortedCollationMap == null) {
943
 
                                        sortedCollationMap = new TreeMap();
 
994
                                        sortedCollationMap = new TreeMap<Long, String>();
 
995
                                        javaCharset = new HashMap<Integer, String>();
 
996
                                        customCharset = new HashMap<Integer, String>();
 
997
                                        customMblen = new HashMap<String, Integer>();
944
998
 
945
999
                                        stmt = getMetadataSafeStatement();
946
1000
 
947
 
                                        results = stmt
948
 
                                                        .executeQuery("SHOW COLLATION");
949
 
 
950
 
                                        while (results.next()) {
951
 
                                                String charsetName = results.getString(2);
952
 
                                                Integer charsetIndex = Integer.valueOf(results.getInt(3));
953
 
 
954
 
                                                sortedCollationMap.put(charsetIndex, charsetName);
 
1001
                                        try {
 
1002
                                                results = stmt.executeQuery("SHOW COLLATION");
 
1003
                                                if (versionMeetsMinimum(5, 0, 0)) {
 
1004
                                                        Util.resultSetToMap(sortedCollationMap, results, 3, 2);
 
1005
                                                } else {
 
1006
                                                        while (results.next()) {
 
1007
                                                                sortedCollationMap.put(results.getLong(3), results.getString(2));
 
1008
                                                        }
 
1009
                                                }
 
1010
                                        } catch (SQLException ex) {
 
1011
                                                if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
1012
                                                        throw ex;
 
1013
                                                }
 
1014
                                        }
 
1015
 
 
1016
                                        for (Iterator<Map.Entry<Long, String>> indexIter = sortedCollationMap.entrySet().iterator(); indexIter.hasNext();) {
 
1017
                                                Map.Entry<Long, String> indexEntry = indexIter.next();
 
1018
 
 
1019
                                                int collationIndex = indexEntry.getKey().intValue();
 
1020
                                                String charsetName = indexEntry.getValue();
 
1021
 
 
1022
                                                javaCharset.put(collationIndex, getJavaEncodingForMysqlEncoding(charsetName));
 
1023
 
 
1024
                                                // if no static map for charsetIndex
 
1025
                                                // or server has a different mapping then our static map,
 
1026
                                                // adding it to custom map 
 
1027
                                                if (collationIndex >= CharsetMapping.MAP_SIZE ||
 
1028
                                                        !charsetName.equals(CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(collationIndex))) {
 
1029
                                                        customCharset.put(collationIndex, charsetName);
 
1030
                                                }
 
1031
 
 
1032
                                                // if no static map for charsetName adding to custom map
 
1033
                                                if (!CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP.containsKey(charsetName) &&
 
1034
                                                        !CharsetMapping.STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP.containsKey(charsetName)) {
 
1035
                                                        customMblen.put(charsetName, null);
 
1036
                                                }
 
1037
                                        }
 
1038
                                        
 
1039
                                        // if there is a number of custom charsets we should execute SHOW CHARACTER SET to know theirs mblen
 
1040
                                        if (customMblen.size() > 0) {
 
1041
                                                try {
 
1042
                                                        results = stmt.executeQuery("SHOW CHARACTER SET");
 
1043
                                                        while (results.next()) {
 
1044
                                                                String charsetName = results.getString("Charset");
 
1045
                                                                if (customMblen.containsKey(charsetName)) {
 
1046
                                                                        customMblen.put(charsetName, results.getInt("Maxlen"));
 
1047
                                                                }
 
1048
                                                        }
 
1049
                                                } catch (SQLException ex) {
 
1050
                                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
1051
                                                                throw ex;
 
1052
                                                        }
 
1053
                                                }
955
1054
                                        }
956
1055
 
957
1056
                                        if (getCacheServerConfiguration()) {
958
 
                                                synchronized (serverConfigByUrl) {
959
 
                                                        serverCollationByUrl.put(getURL(),
960
 
                                                                        sortedCollationMap);
 
1057
                                                synchronized (serverCollationByUrl) {
 
1058
                                                        serverCollationByUrl.put(getURL(), sortedCollationMap);
 
1059
                                                        serverJavaCharsetByUrl.put(getURL(), javaCharset);
 
1060
                                                        serverCustomCharsetByUrl.put(getURL(), customCharset);
 
1061
                                                        serverCustomMblenByUrl.put(getURL(), customMblen);
961
1062
                                                }
962
1063
                                        }
963
1064
 
964
1065
                                }
965
1066
 
966
 
                                // Now, merge with what we already know
967
 
                                int highestIndex = ((Integer) sortedCollationMap.lastKey())
968
 
                                                .intValue();
969
 
 
970
 
                                if (CharsetMapping.INDEX_TO_CHARSET.length > highestIndex) {
971
 
                                        highestIndex = CharsetMapping.INDEX_TO_CHARSET.length;
972
 
                                }
973
 
 
974
 
                                this.indexToCharsetMapping = new String[highestIndex + 1];
975
 
 
976
 
                                for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) {
977
 
                                        this.indexToCharsetMapping[i] = CharsetMapping.INDEX_TO_CHARSET[i];
978
 
                                }
979
 
 
980
 
                                for (Iterator indexIter = sortedCollationMap.entrySet()
981
 
                                                .iterator(); indexIter.hasNext();) {
982
 
                                        Map.Entry indexEntry = (Map.Entry) indexIter.next();
983
 
 
984
 
                                        String mysqlCharsetName = (String) indexEntry.getValue();
985
 
 
986
 
                                        this.indexToCharsetMapping[((Integer) indexEntry.getKey())
987
 
                                                        .intValue()] = CharsetMapping
988
 
                                                        .getJavaEncodingForMysqlEncoding(mysqlCharsetName,
989
 
                                                                        this);
990
 
                                }
991
 
                        } catch (java.sql.SQLException e) {
992
 
                                throw e;
 
1067
                                this.indexToJavaCharset = Collections.unmodifiableMap(javaCharset);
 
1068
                                this.indexToCustomMysqlCharset = Collections.unmodifiableMap(customCharset);
 
1069
                                this.mysqlCharsetToCustomMblen = Collections.unmodifiableMap(customMblen);
 
1070
                                
 
1071
                        } catch (SQLException ex) {
 
1072
                                throw ex;
 
1073
                        } catch (RuntimeException ex) {
 
1074
                                SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
1075
                                sqlEx.initCause(ex);
 
1076
                                throw sqlEx;
993
1077
                        } finally {
994
1078
                                if (results != null) {
995
1079
                                        try {
1008
1092
                                }
1009
1093
                        }
1010
1094
                } else {
1011
 
                        // Safety, we already do this as an initializer, but this makes
1012
 
                        // the intent more clear
1013
 
                        this.indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
1014
 
                }
 
1095
                        javaCharset = new HashMap<Integer, String>();
 
1096
                        for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) {
 
1097
                                javaCharset.put(i, CharsetMapping.INDEX_TO_CHARSET[i]);
 
1098
                        }
 
1099
                        this.indexToJavaCharset = Collections.unmodifiableMap(javaCharset);
 
1100
                }
 
1101
        }
 
1102
 
 
1103
        public String getJavaEncodingForMysqlEncoding(String mysqlEncoding) throws SQLException {
 
1104
                
 
1105
                if (versionMeetsMinimum(4, 1, 0) && "latin1".equalsIgnoreCase(mysqlEncoding)) {
 
1106
                        return "Cp1252";
 
1107
                }
 
1108
                
 
1109
                return CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding);
1015
1110
        }
1016
1111
 
1017
1112
        private boolean canHandleAsServerPreparedStatement(String sql) 
1143
1238
         */
1144
1239
        public void changeUser(String userName, String newPassword)
1145
1240
                        throws SQLException {
1146
 
                if ((userName == null) || userName.equals("")) {
1147
 
                        userName = "";
1148
 
                }
1149
 
 
1150
 
                if (newPassword == null) {
1151
 
                        newPassword = "";
1152
 
                }
1153
 
 
1154
 
                this.io.changeUser(userName, newPassword, this.database);
1155
 
                this.user = userName;
1156
 
                this.password = newPassword;
1157
 
 
1158
 
                if (versionMeetsMinimum(4, 1, 0)) {
1159
 
                        configureClientCharacterSet(true);
1160
 
                }
1161
 
                
1162
 
                setSessionVariables();
1163
 
                
1164
 
                setupServerForTruncationChecks();
 
1241
                synchronized (getConnectionMutex()) {
 
1242
                        checkClosed();
 
1243
                        
 
1244
                        if ((userName == null) || userName.equals("")) {
 
1245
                                userName = "";
 
1246
                        }
 
1247
        
 
1248
                        if (newPassword == null) {
 
1249
                                newPassword = "";
 
1250
                        }
 
1251
        
 
1252
                        this.io.changeUser(userName, newPassword, this.database);
 
1253
                        this.user = userName;
 
1254
                        this.password = newPassword;
 
1255
        
 
1256
                        if (versionMeetsMinimum(4, 1, 0)) {
 
1257
                                configureClientCharacterSet(true);
 
1258
                        }
 
1259
                        
 
1260
                        setSessionVariables();
 
1261
                        
 
1262
                        setupServerForTruncationChecks();
 
1263
                }
1165
1264
        }
1166
1265
 
1167
1266
        private boolean characterSetNamesMatches(String mysqlEncodingName) {
1168
1267
                // set names is equivalent to character_set_client ..._results and ..._connection,
1169
1268
                // but we set _results later, so don't check it here.
1170
 
                
1171
1269
                return (mysqlEncodingName != null && 
1172
 
                                mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_client")) &&
1173
 
                                mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_connection")));
 
1270
                                mysqlEncodingName.equalsIgnoreCase(this.serverVariables.get("character_set_client")) &&
 
1271
                                mysqlEncodingName.equalsIgnoreCase(this.serverVariables.get("character_set_connection")));
1174
1272
        }
1175
1273
 
1176
1274
        private void checkAndCreatePerformanceHistogram() {
1226
1324
                        return;
1227
1325
                }
1228
1326
 
1229
 
                String serverEncoding = (String) this.serverVariables
1230
 
                                .get("character_set");
 
1327
                String serverEncoding = this.serverVariables.get("character_set");
1231
1328
 
1232
1329
                if (serverEncoding == null) {
1233
1330
                        // must be 4.1.1 or newer?
1234
 
                        serverEncoding = (String) this.serverVariables
1235
 
                                        .get("character_set_server");
 
1331
                        serverEncoding = this.serverVariables.get("character_set_server");
1236
1332
                }
1237
1333
 
1238
1334
                String mappedServerEncoding = null;
1239
1335
 
1240
1336
                if (serverEncoding != null) {
1241
 
                        mappedServerEncoding = CharsetMapping
1242
 
                                        .getJavaEncodingForMysqlEncoding(serverEncoding
1243
 
                                                        .toUpperCase(Locale.ENGLISH), this);
 
1337
                        try {
 
1338
                                mappedServerEncoding = getJavaEncodingForMysqlEncoding(serverEncoding
 
1339
                                                        .toUpperCase(Locale.ENGLISH));
 
1340
                        } catch (SQLException ex) {
 
1341
                                throw ex;
 
1342
                        } catch (RuntimeException ex) {
 
1343
                                SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
1344
                                sqlEx.initCause(ex);
 
1345
                                throw sqlEx;
 
1346
                        }
1244
1347
                }
1245
1348
 
1246
1349
                //
1285
1388
                        // can't be used
1286
1389
                        //
1287
1390
                        try {
1288
 
                                "abc".getBytes(mappedServerEncoding);
 
1391
                                StringUtils.getBytes("abc",mappedServerEncoding);
1289
1392
                                setEncoding(mappedServerEncoding);
1290
1393
                                setUseUnicode(true);
1291
1394
                        } catch (UnsupportedEncodingException UE) {
1317
1420
                        txIsolationName = "transaction_isolation";
1318
1421
                }
1319
1422
 
1320
 
                String s = (String) this.serverVariables.get(txIsolationName);
 
1423
                String s = this.serverVariables.get(txIsolationName);
1321
1424
 
1322
1425
                if (s != null) {
1323
 
                        Integer intTI = (Integer) mapTransIsolationNameToValue.get(s);
 
1426
                        Integer intTI = mapTransIsolationNameToValue.get(s);
1324
1427
 
1325
1428
                        if (intTI != null) {
1326
1429
                                this.isolationLevel = intTI.intValue();
1444
1547
                PreparedStatement pStmt = null;
1445
1548
 
1446
1549
                if (getCachePreparedStatements()) {
1447
 
                        synchronized (this.cachedPreparedStatementParams) {
1448
 
                                PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams
1449
 
                                                .get(nativeSql);
1450
 
        
1451
 
                                if (pStmtInfo == null) {
1452
 
                                        pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
1453
 
                                                        this.database);
1454
 
        
1455
 
                                        PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo();
1456
 
        
1457
 
                                        if (parseInfo.statementLength < getPreparedStatementCacheSqlLimit()) {
1458
 
                                                if (this.cachedPreparedStatementParams.size() >= getPreparedStatementCacheSize()) {
1459
 
                                                        Iterator oldestIter = this.cachedPreparedStatementParams
1460
 
                                                                        .keySet().iterator();
1461
 
                                                        long lruTime = Long.MAX_VALUE;
1462
 
                                                        String oldestSql = null;
1463
 
        
1464
 
                                                        while (oldestIter.hasNext()) {
1465
 
                                                                String sqlKey = (String) oldestIter.next();
1466
 
                                                                PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams
1467
 
                                                                                .get(sqlKey);
1468
 
        
1469
 
                                                                if (lruInfo.lastUsed < lruTime) {
1470
 
                                                                        lruTime = lruInfo.lastUsed;
1471
 
                                                                        oldestSql = sqlKey;
1472
 
                                                                }
1473
 
                                                        }
1474
 
        
1475
 
                                                        if (oldestSql != null) {
1476
 
                                                                this.cachedPreparedStatementParams
1477
 
                                                                                .remove(oldestSql);
1478
 
                                                        }
1479
 
                                                }
1480
 
        
1481
 
                                                this.cachedPreparedStatementParams.put(nativeSql, pStmt
1482
 
                                                                .getParseInfo());
1483
 
                                        }
1484
 
                                } else {
1485
 
                                        pStmtInfo.lastUsed = System.currentTimeMillis();
1486
 
                                        pStmt = new com.mysql.jdbc.PreparedStatement(getLoadBalanceSafeProxy(), nativeSql,
1487
 
                                                        this.database, pStmtInfo);
1488
 
                                }
 
1550
                        PreparedStatement.ParseInfo pStmtInfo = this.cachedPreparedStatementParams.get(nativeSql);
 
1551
 
 
1552
                        if (pStmtInfo == null) {
 
1553
                                pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
 
1554
                                                this.database);
 
1555
 
 
1556
                                this.cachedPreparedStatementParams.put(nativeSql, pStmt
 
1557
                                                        .getParseInfo());
 
1558
                        } else {
 
1559
                                pStmt = new com.mysql.jdbc.PreparedStatement(getLoadBalanceSafeProxy(), nativeSql,
 
1560
                                                this.database, pStmtInfo);
1489
1561
                        }
1490
1562
                } else {
1491
1563
                        pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
1545
1617
         * @exception SQLException
1546
1618
         *                if a database access error occurs
1547
1619
         */
1548
 
        public synchronized void close() throws SQLException {
1549
 
                if (this.connectionLifecycleInterceptors != null) {
1550
 
                        new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
1551
 
                                void forEach(Object each) throws SQLException {
1552
 
                                        ((ConnectionLifecycleInterceptor)each).close();
1553
 
                                }
1554
 
                        }.doForAll();
 
1620
        public void close() throws SQLException {
 
1621
                synchronized (getConnectionMutex()) {
 
1622
                        if (this.connectionLifecycleInterceptors != null) {
 
1623
                                new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
1624
                                        void forEach(Extension each) throws SQLException {
 
1625
                                                ((ConnectionLifecycleInterceptor)each).close();
 
1626
                                        }
 
1627
                                }.doForAll();
 
1628
                        }
 
1629
                
 
1630
                        realClose(true, true, false, null);
1555
1631
                }
1556
 
        
1557
 
                realClose(true, true, false, null);
1558
1632
        }
1559
1633
 
1560
1634
        /**
1567
1641
                SQLException postponedException = null;
1568
1642
 
1569
1643
                if (this.openStatements != null) {
1570
 
                        List currentlyOpenStatements = new ArrayList(); // we need this to
 
1644
                        List<Statement> currentlyOpenStatements = new ArrayList<Statement>(); // we need this to
1571
1645
                        // avoid
1572
1646
                        // ConcurrentModificationEx
1573
1647
 
1574
 
                        for (Iterator iter = this.openStatements.keySet().iterator(); iter
1575
 
                                        .hasNext();) {
 
1648
                        for (Iterator<Statement> iter = this.openStatements.keySet().iterator(); iter.hasNext();) {
1576
1649
                                currentlyOpenStatements.add(iter.next());
1577
1650
                        }
1578
1651
 
1621
1694
         *                if a database access error occurs
1622
1695
         * @see setAutoCommit
1623
1696
         */
1624
 
        public synchronized void commit() throws SQLException {
1625
 
                checkClosed();
1626
 
 
1627
 
                try {
1628
 
                        if (this.connectionLifecycleInterceptors != null) {
1629
 
                                IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
1630
 
 
1631
 
                                        void forEach(Object each) throws SQLException {
1632
 
                                                if (!((ConnectionLifecycleInterceptor)each).commit()) {
1633
 
                                                        this.stopIterating = true;
1634
 
                                                }
1635
 
                                        }
1636
 
                                };
1637
 
                                
1638
 
                                iter.doForAll();
1639
 
                                
1640
 
                                if (!iter.fullIteration()) {
1641
 
                                        return;
1642
 
                                }
1643
 
                        }
1644
 
                        
1645
 
                        // no-op if _relaxAutoCommit == true
1646
 
                        if (this.autoCommit && !getRelaxAutoCommit()) {
1647
 
                                throw SQLError.createSQLException("Can't call commit when autocommit=true", getExceptionInterceptor());
1648
 
                        } else if (this.transactionsSupported) {
1649
 
                                if (getUseLocalTransactionState() && versionMeetsMinimum(5, 0, 0)) {
1650
 
                                        if (!this.io.inTransactionOnServer()) {
1651
 
                                                return; // effectively a no-op
1652
 
                                        }
1653
 
                                }
1654
 
 
1655
 
                                execSQL(null, "commit", -1, null,
1656
 
                                                DEFAULT_RESULT_SET_TYPE,
1657
 
                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
1658
 
                                                this.database, null,
1659
 
                                                false);
1660
 
                        }
1661
 
                } catch (SQLException sqlException) {
1662
 
                        if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
1663
 
                                        .equals(sqlException.getSQLState())) {
1664
 
                                throw SQLError
1665
 
                                                .createSQLException(
1666
 
                                                                "Communications link failure during commit(). Transaction resolution unknown.",
1667
 
                                                                SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN,
1668
 
                                                                getExceptionInterceptor());
1669
 
                        }
1670
 
 
1671
 
                        throw sqlException;
1672
 
                } finally {
1673
 
                        this.needsPing = this.getReconnectAtTxEnd();
 
1697
        public void commit() throws SQLException {
 
1698
                synchronized (getConnectionMutex()) {
 
1699
                        checkClosed();
 
1700
        
 
1701
                        try {
 
1702
                                if (this.connectionLifecycleInterceptors != null) {
 
1703
                                        IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
1704
        
 
1705
                                                void forEach(Extension each) throws SQLException {
 
1706
                                                        if (!((ConnectionLifecycleInterceptor)each).commit()) {
 
1707
                                                                this.stopIterating = true;
 
1708
                                                        }
 
1709
                                                }
 
1710
                                        };
 
1711
                                        
 
1712
                                        iter.doForAll();
 
1713
                                        
 
1714
                                        if (!iter.fullIteration()) {
 
1715
                                                return;
 
1716
                                        }
 
1717
                                }
 
1718
                                
 
1719
                                // no-op if _relaxAutoCommit == true
 
1720
                                if (this.autoCommit && !getRelaxAutoCommit()) {
 
1721
                                        throw SQLError.createSQLException("Can't call commit when autocommit=true", getExceptionInterceptor());
 
1722
                                } else if (this.transactionsSupported) {
 
1723
                                        if (getUseLocalTransactionState() && versionMeetsMinimum(5, 0, 0)) {
 
1724
                                                if (!this.io.inTransactionOnServer()) {
 
1725
                                                        return; // effectively a no-op
 
1726
                                                }
 
1727
                                        }
 
1728
        
 
1729
                                        execSQL(null, "commit", -1, null,
 
1730
                                                        DEFAULT_RESULT_SET_TYPE,
 
1731
                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
 
1732
                                                        this.database, null,
 
1733
                                                        false);
 
1734
                                }
 
1735
                        } catch (SQLException sqlException) {
 
1736
                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
 
1737
                                                .equals(sqlException.getSQLState())) {
 
1738
                                        throw SQLError
 
1739
                                                        .createSQLException(
 
1740
                                                                        "Communications link failure during commit(). Transaction resolution unknown.",
 
1741
                                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN,
 
1742
                                                                        getExceptionInterceptor());
 
1743
                                }
 
1744
        
 
1745
                                throw sqlException;
 
1746
                        } finally {
 
1747
                                this.needsPing = this.getReconnectAtTxEnd();
 
1748
                        }
1674
1749
                }
1675
 
 
1676
1750
                return;
1677
1751
        }
1678
1752
        
1688
1762
                        // can't be used
1689
1763
                        try {
1690
1764
                                String testString = "abc";
1691
 
                                testString.getBytes(getEncoding());
 
1765
                                StringUtils.getBytes(testString, getEncoding());
1692
1766
                        } catch (UnsupportedEncodingException UE) {
1693
1767
                                // Try the MySQL character encoding, then....
1694
1768
                                String oldEncoding = getEncoding();
1695
1769
 
1696
 
                                setEncoding(CharsetMapping.getJavaEncodingForMysqlEncoding(
1697
 
                                                oldEncoding, this));
 
1770
                                try {
 
1771
                                        setEncoding(getJavaEncodingForMysqlEncoding(oldEncoding));
 
1772
                                } catch (SQLException ex) {
 
1773
                                        throw ex;
 
1774
                                } catch (RuntimeException ex) {
 
1775
                                        SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
1776
                                        sqlEx.initCause(ex);
 
1777
                                        throw sqlEx;
 
1778
                                }
1698
1779
 
1699
1780
                                if (getEncoding() == null) {
1700
1781
                                        throw SQLError.createSQLException(
1705
1786
 
1706
1787
                                try {
1707
1788
                                        String testString = "abc";
1708
 
                                        testString.getBytes(getEncoding());
 
1789
                                        StringUtils.getBytes(testString, getEncoding());
1709
1790
                                } catch (UnsupportedEncodingException encodingEx) {
1710
1791
                                        throw SQLError.createSQLException("Unsupported character "
1711
1792
                                                        + "encoding '" + getEncoding() + "'.",
1774
1855
                                                        "ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) {
1775
1856
                                                serverEncodingToSet = "Cp1252";
1776
1857
                                        }
1777
 
                                        
 
1858
                                        if ("UnicodeBig".equalsIgnoreCase(serverEncodingToSet) ||
 
1859
                                                        "UTF-16".equalsIgnoreCase(serverEncodingToSet) ||
 
1860
                                                        "UTF-16LE".equalsIgnoreCase(serverEncodingToSet) ||
 
1861
                                                        "UTF-32".equalsIgnoreCase(serverEncodingToSet)
 
1862
                                                        ) {
 
1863
                                                serverEncodingToSet = "UTF-8";
 
1864
                                        }
 
1865
 
1778
1866
                                        setEncoding(serverEncodingToSet);
1779
1867
                                
1780
1868
                                } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
1788
1876
                                                                                + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.",
1789
1877
                                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
1790
1878
                                        }
 
1879
                                } catch (SQLException ex) {
 
1880
                                        throw ex;
 
1881
                                } catch (RuntimeException ex) {
 
1882
                                        SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
1883
                                        sqlEx.initCause(ex);
 
1884
                                        throw sqlEx;
1791
1885
                                }
1792
1886
 
1793
1887
                                if (getEncoding() == null) {
1869
1963
                                                // Tell the server we'll use the server default charset
1870
1964
                                                // to send our
1871
1965
                                                // queries from now on....
1872
 
                                                String mysqlEncodingName = CharsetMapping
1873
 
                                                                .getMysqlEncodingForJavaEncoding(getEncoding()
1874
 
                                                                                .toUpperCase(Locale.ENGLISH), this);
 
1966
                                                String mysqlEncodingName = getServerCharacterEncoding();
1875
1967
                                                
1876
1968
                                                if(getUseOldUTF8Behavior()){
1877
1969
                                                        mysqlEncodingName = "latin1";
1878
1970
                                                }
1879
1971
 
1880
 
                                                if (dontCheckServerMatch || !characterSetNamesMatches(mysqlEncodingName)) {
1881
 
                                                        execSQL(null, "SET NAMES " + mysqlEncodingName, -1,
1882
 
                                                                null, DEFAULT_RESULT_SET_TYPE,
1883
 
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
1884
 
                                                                this.database, null, false);
 
1972
                                                boolean ucs2 = false;
 
1973
                                                if (    "ucs2".equalsIgnoreCase(mysqlEncodingName) ||
 
1974
                                                                "utf16".equalsIgnoreCase(mysqlEncodingName) ||
 
1975
                                                                "utf16le".equalsIgnoreCase(mysqlEncodingName) ||
 
1976
                                                                "utf32".equalsIgnoreCase(mysqlEncodingName)) {
 
1977
                                                        mysqlEncodingName = "utf8";
 
1978
                                                        ucs2 = true;
 
1979
                                                        if (getCharacterSetResults() == null) {
 
1980
                                                                setCharacterSetResults("UTF-8");
 
1981
                                                        }
 
1982
                                                }
 
1983
 
 
1984
                                                if (dontCheckServerMatch || !characterSetNamesMatches(mysqlEncodingName) || ucs2) {
 
1985
                                                        try {
 
1986
                                                                execSQL(null, "SET NAMES " + mysqlEncodingName, -1,
 
1987
                                                                                null, DEFAULT_RESULT_SET_TYPE,
 
1988
                                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
 
1989
                                                                                this.database, null, false);
 
1990
                                                        } catch (SQLException ex) {
 
1991
                                                                if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
1992
                                                                        throw ex;
 
1993
                                                                }
 
1994
                                                        }
1885
1995
                                                }
1886
1996
 
1887
1997
                                                realJavaEncoding = getEncoding();
1899
2009
                                boolean isNullOnServer = false;
1900
2010
                                
1901
2011
                                if (this.serverVariables != null) {
1902
 
                                        onServer = (String)this.serverVariables.get("character_set_results");
 
2012
                                        onServer = this.serverVariables.get("character_set_results");
1903
2013
                                        
1904
2014
                                        isNullOnServer = onServer == null || "NULL".equalsIgnoreCase(onServer) || onServer.length() == 0;
1905
2015
                                }
1912
2022
                                        // before we cached them.
1913
2023
                                        //
1914
2024
                                        if (!isNullOnServer) {
1915
 
                                                execSQL(null, "SET character_set_results = NULL", -1, null,
1916
 
                                                                DEFAULT_RESULT_SET_TYPE,
1917
 
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
1918
 
                                                                this.database, null, 
1919
 
                                                                false);
 
2025
                                                try {
 
2026
                                                        execSQL(null, "SET character_set_results = NULL", -1, null,
 
2027
                                                                        DEFAULT_RESULT_SET_TYPE,
 
2028
                                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
 
2029
                                                                        this.database, null, 
 
2030
                                                                        false);
 
2031
                                                } catch (SQLException ex) {
 
2032
                                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
2033
                                                                throw ex;
 
2034
                                                        }
 
2035
                                                }
1920
2036
                                                if (!this.usingCachedConfig) {
1921
2037
                                                        this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, null);
1922
2038
                                                }
1928
2044
                                } else {
1929
2045
 
1930
2046
                                        if(getUseOldUTF8Behavior()){
1931
 
                                                execSQL(null, "SET NAMES " + "latin1", -1,
1932
 
                                                        null, DEFAULT_RESULT_SET_TYPE,
1933
 
                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
1934
 
                                                        this.database, null, false);
 
2047
                                                try {
 
2048
                                                        execSQL(null, "SET NAMES " + "latin1", -1,
 
2049
                                                                null, DEFAULT_RESULT_SET_TYPE,
 
2050
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
 
2051
                                                                this.database, null, false);
 
2052
                                                } catch (SQLException ex) {
 
2053
                                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
2054
                                                                throw ex;
 
2055
                                                        }
 
2056
                                                }
1935
2057
                                        }
1936
2058
                                        String charsetResults = getCharacterSetResults();
1937
2059
                                        String mysqlEncodingName = null;
1939
2061
                                        if ("UTF-8".equalsIgnoreCase(charsetResults)
1940
2062
                                                        || "UTF8".equalsIgnoreCase(charsetResults)) {
1941
2063
                                                mysqlEncodingName = "utf8";
 
2064
                                        } else if ("null".equalsIgnoreCase(charsetResults)) {
 
2065
                                                mysqlEncodingName = "NULL";
1942
2066
                                        } else {
1943
2067
                                                mysqlEncodingName = CharsetMapping
1944
2068
                                                                .getMysqlEncodingForJavaEncoding(charsetResults
1949
2073
                                        // Only change the value if needed
1950
2074
                                        //
1951
2075
                                        
 
2076
                                        if (mysqlEncodingName == null) {
 
2077
                                                throw SQLError.createSQLException(
 
2078
                                                                "Can't map "+charsetResults+" given for characterSetResults to a supported MySQL encoding.",
 
2079
                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
2080
                                        }
 
2081
 
1952
2082
                                        if (!mysqlEncodingName.equalsIgnoreCase(
1953
 
                                                        (String)this.serverVariables.get("character_set_results"))) {
 
2083
                                                        this.serverVariables.get("character_set_results"))) {
1954
2084
                                                StringBuffer setBuf = new StringBuffer(
1955
2085
                                                                "SET character_set_results = ".length()
1956
2086
                                                                                + mysqlEncodingName.length());
1957
2087
                                                setBuf.append("SET character_set_results = ").append(
1958
2088
                                                                mysqlEncodingName);
1959
2089
        
1960
 
                                                execSQL(null, setBuf.toString(), -1, null,
1961
 
                                                                DEFAULT_RESULT_SET_TYPE,
1962
 
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
1963
 
                                                                this.database, null, false);
 
2090
                                                try {
 
2091
                                                        execSQL(null, setBuf.toString(), -1, null,
 
2092
                                                                        DEFAULT_RESULT_SET_TYPE,
 
2093
                                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
 
2094
                                                                        this.database, null, false);
 
2095
                                                } catch (SQLException ex) {
 
2096
                                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
2097
                                                                throw ex;
 
2098
                                                        }
 
2099
                                                }
1964
2100
                                                
1965
2101
                                                if (!this.usingCachedConfig) {
1966
2102
                                                        this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, 
1967
2103
                                                                mysqlEncodingName);
1968
2104
                                                }
 
2105
 
 
2106
                                                // We have to set errorMessageEncoding according to new value
 
2107
                                                // of charsetResults for server version 5.5 and higher
 
2108
                                                if (versionMeetsMinimum(5, 5, 0)) {
 
2109
                                                        this.errorMessageEncoding = charsetResults;
 
2110
                                                }
 
2111
 
1969
2112
                                        } else {
1970
2113
                                                if (!this.usingCachedConfig) {
1971
2114
                                                        this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, onServer);
1980
2123
                                        setBuf.append("SET collation_connection = ").append(
1981
2124
                                                        getConnectionCollation());
1982
2125
 
1983
 
                                        execSQL(null, setBuf.toString(), -1, null,
1984
 
                                                        DEFAULT_RESULT_SET_TYPE,
1985
 
                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
1986
 
                                                        this.database, null, false);
 
2126
                                        try {
 
2127
                                                execSQL(null, setBuf.toString(), -1, null,
 
2128
                                                                DEFAULT_RESULT_SET_TYPE,
 
2129
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
 
2130
                                                                this.database, null, false);
 
2131
                                        } catch (SQLException ex) {
 
2132
                                                if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
2133
                                                        throw ex;
 
2134
                                                }
 
2135
                                        }
1987
2136
                                }
1988
2137
                        } else {
1989
2138
                                // Use what the server has specified
2026
2175
                } catch(java.nio.charset.UnsupportedCharsetException ucex) {
2027
2176
                        // fallback to String API - for Java 1.4
2028
2177
                        try {
2029
 
                                byte bbuf[] = "\u00a5".getBytes(getEncoding());
 
2178
                                byte bbuf[] = StringUtils.getBytes("\u00a5", getEncoding());
2030
2179
                                if (bbuf[0] == '\\') {
2031
2180
                                        requiresEscapingEncoder = true;
2032
2181
                                } else {
2033
 
                                        bbuf = "\u20a9".getBytes(getEncoding());
 
2182
                                        bbuf = StringUtils.getBytes("\u20a9", getEncoding());
2034
2183
                                        if (bbuf[0] == '\\') {
2035
2184
                                                requiresEscapingEncoder = true;
2036
2185
                                        }
2053
2202
         *             mapped to a Java timezone.
2054
2203
         */
2055
2204
        private void configureTimezone() throws SQLException {
2056
 
                String configuredTimeZoneOnServer = (String) this.serverVariables
2057
 
                                .get("timezone");
 
2205
                String configuredTimeZoneOnServer = this.serverVariables.get("timezone");
2058
2206
 
2059
2207
                if (configuredTimeZoneOnServer == null) {
2060
 
                        configuredTimeZoneOnServer = (String) this.serverVariables
2061
 
                                        .get("time_zone");
 
2208
                        configuredTimeZoneOnServer = this.serverVariables.get("time_zone");
2062
2209
 
2063
2210
                        if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
2064
 
                                configuredTimeZoneOnServer = (String) this.serverVariables
2065
 
                                                .get("system_time_zone");
 
2211
                                configuredTimeZoneOnServer = this.serverVariables.get("system_time_zone");
2066
2212
                        }
2067
2213
                }
2068
2214
 
2139
2285
         * @throws CommunicationsException
2140
2286
         *             DOCUMENT ME!
2141
2287
         */
2142
 
        public synchronized void createNewIO(boolean isForReconnect)
 
2288
        public void createNewIO(boolean isForReconnect)
2143
2289
                        throws SQLException {
2144
 
                // Synchronization Not needed for *new* connections, but defintely for
2145
 
                // connections going through fail-over, since we might get the
2146
 
                // new connection up and running *enough* to start sending
2147
 
                // cached or still-open server-side prepared statements over
2148
 
                // to the backend before we get a chance to re-prepare them...
2149
 
                
2150
 
 
2151
 
                Properties mergedProps  = exposeAsProperties(this.props);
2152
 
 
2153
 
                if (!getHighAvailability()) {
2154
 
                        connectOneTryOnly(isForReconnect, mergedProps);
 
2290
                synchronized (getConnectionMutex()) {
 
2291
                        // Synchronization Not needed for *new* connections, but defintely for
 
2292
                        // connections going through fail-over, since we might get the
 
2293
                        // new connection up and running *enough* to start sending
 
2294
                        // cached or still-open server-side prepared statements over
 
2295
                        // to the backend before we get a chance to re-prepare them...
2155
2296
                        
2156
 
                        return;
2157
 
                } 
2158
 
 
2159
 
                connectWithRetries(isForReconnect, mergedProps);
2160
 
                
 
2297
        
 
2298
                        Properties mergedProps  = exposeAsProperties(this.props);
 
2299
        
 
2300
                        if (!getHighAvailability()) {
 
2301
                                connectOneTryOnly(isForReconnect, mergedProps);
 
2302
                                
 
2303
                                return;
 
2304
                        } 
 
2305
        
 
2306
                        connectWithRetries(isForReconnect, mergedProps);
 
2307
                }               
2161
2308
        }
2162
2309
 
2163
2310
        private void connectWithRetries(boolean isForReconnect,
2182
2329
                                boolean oldReadOnly;
2183
2330
                                String oldCatalog;
2184
2331
                                
2185
 
                                synchronized (this) {
 
2332
                                synchronized (getConnectionMutex()) {
2186
2333
                                        this.connectionId = this.io.getThreadId();
2187
2334
                                        this.isClosed = false;
2188
2335
 
2189
2336
                                        // save state from old connection
2190
2337
                                        oldAutoCommit = getAutoCommit();
2191
2338
                                        oldIsolationLevel = this.isolationLevel;
2192
 
                                        oldReadOnly = isReadOnly();
 
2339
                                        oldReadOnly = isReadOnly(false);
2193
2340
                                        oldCatalog = getCatalog();
2194
2341
        
2195
2342
                                        this.io.setStatementInterceptors(this.statementInterceptors);
2253
2400
                        //
2254
2401
                        // Retrieve any 'lost' prepared statements if re-connecting
2255
2402
                        //
2256
 
                        Iterator statementIter = this.openStatements.values()
2257
 
                                        .iterator();
 
2403
                        Iterator<Statement> statementIter = this.openStatements.values().iterator();
2258
2404
 
2259
2405
                        //
2260
2406
                        // We build a list of these outside the map of open statements,
2265
2411
                        // generating
2266
2412
                        // a ConcurrentModificationException
2267
2413
                        //
2268
 
                        Stack serverPreparedStatements = null;
 
2414
                        Stack<Statement> serverPreparedStatements = null;
2269
2415
 
2270
2416
                        while (statementIter.hasNext()) {
2271
 
                                Object statementObj = statementIter.next();
 
2417
                                Statement statementObj = statementIter.next();
2272
2418
 
2273
2419
                                if (statementObj instanceof ServerPreparedStatement) {
2274
2420
                                        if (serverPreparedStatements == null) {
2275
 
                                                serverPreparedStatements = new Stack();
 
2421
                                                serverPreparedStatements = new Stack<Statement>();
2276
2422
                                        }
2277
2423
 
2278
2424
                                        serverPreparedStatements.add(statementObj);
2338
2484
                                this.database);
2339
2485
        }
2340
2486
 
2341
 
        private String normalizeHost(String host) {
2342
 
                if (host == null || StringUtils.isEmptyOrWhitespaceOnly(host)) {
 
2487
        private String normalizeHost(String hostname) {
 
2488
                if (hostname == null || StringUtils.isEmptyOrWhitespaceOnly(hostname)) {
2343
2489
                        return "localhost";
2344
2490
                }
2345
2491
                
2346
 
                return host;
 
2492
                return hostname;
2347
2493
        }
2348
2494
        private int parsePortNumber(String portAsString)
2349
2495
                        throws SQLException {
2374
2520
                        // save state from old connection
2375
2521
                        boolean oldAutoCommit = getAutoCommit();
2376
2522
                        int oldIsolationLevel = this.isolationLevel;
2377
 
                        boolean oldReadOnly = isReadOnly();
 
2523
                        boolean oldReadOnly = isReadOnly(false);
2378
2524
                        String oldCatalog = getCatalog();
2379
2525
 
2380
2526
                        this.io.setStatementInterceptors(this.statementInterceptors);
2399
2545
                        return;
2400
2546
                        
2401
2547
                } catch (Exception EEE) {
 
2548
 
 
2549
                        if (EEE instanceof SQLException
 
2550
                                        && ((SQLException)EEE).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD
 
2551
                                        && !getDisconnectOnExpiredPasswords()) {
 
2552
                                return;
 
2553
                        }
 
2554
 
2402
2555
                        if (this.io != null) {
2403
2556
                                this.io.forceClose();
2404
2557
                        }
2418
2571
                }
2419
2572
        }
2420
2573
 
2421
 
        private synchronized void createPreparedStatementCaches() {
2422
 
                int cacheSize = getPreparedStatementCacheSize();
2423
 
                
2424
 
                this.cachedPreparedStatementParams = new HashMap(cacheSize);
2425
 
                
2426
 
                if (getUseServerPreparedStmts()) {
2427
 
                        this.serverSideStatementCheckCache = new LRUCache(cacheSize);
 
2574
        private void createPreparedStatementCaches() throws SQLException {
 
2575
                synchronized (getConnectionMutex()) {
 
2576
                        int cacheSize = getPreparedStatementCacheSize();
2428
2577
                        
2429
 
                        this.serverSideStatementCache = new LRUCache(cacheSize) {
2430
 
                                protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
2431
 
                                        if (this.maxElements <= 1) {
2432
 
                                                return false;
2433
 
                                        }
2434
 
                                        
2435
 
                                        boolean removeIt = super.removeEldestEntry(eldest);
2436
 
                                        
2437
 
                                        if (removeIt) {
2438
 
                                                ServerPreparedStatement ps = 
2439
 
                                                        (ServerPreparedStatement)eldest.getValue();
2440
 
                                                ps.isCached = false;
2441
 
                                                ps.setClosed(false);
2442
 
                                                
2443
 
                                                try {
2444
 
                                                        ps.close();
2445
 
                                                } catch (SQLException sqlEx) {
2446
 
                                                        // punt
2447
 
                                                }
2448
 
                                        }
2449
 
                                        
2450
 
                                        return removeIt;
2451
 
                                }
2452
 
                        };
 
2578
                        try {
 
2579
                                Class<?> factoryClass;
 
2580
                                
 
2581
                                factoryClass = Class.forName(getParseInfoCacheFactory());
 
2582
                                
 
2583
                                @SuppressWarnings("unchecked")
 
2584
                                CacheAdapterFactory<String, ParseInfo> cacheFactory = ((CacheAdapterFactory<String, ParseInfo>)factoryClass.newInstance());
 
2585
                                
 
2586
                                this.cachedPreparedStatementParams = cacheFactory.getInstance(this, myURL, getPreparedStatementCacheSize(), getPreparedStatementCacheSqlLimit(), props);
 
2587
                                
 
2588
                        } catch (ClassNotFoundException e) {
 
2589
                                SQLException sqlEx = SQLError.createSQLException(
 
2590
                                                Messages.getString("Connection.CantFindCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
2591
                                                getExceptionInterceptor());
 
2592
                                sqlEx.initCause(e);
 
2593
                                
 
2594
                                throw sqlEx;
 
2595
                        } catch (InstantiationException e) {
 
2596
                                SQLException sqlEx = SQLError.createSQLException(
 
2597
                                                Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
2598
                                                getExceptionInterceptor());
 
2599
                                sqlEx.initCause(e);
 
2600
                                
 
2601
                                throw sqlEx;
 
2602
                        } catch (IllegalAccessException e) {
 
2603
                                SQLException sqlEx = SQLError.createSQLException(
 
2604
                                                Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
2605
                                                getExceptionInterceptor());
 
2606
                                sqlEx.initCause(e);
 
2607
                                
 
2608
                                throw sqlEx;
 
2609
                        }
 
2610
        
 
2611
                        if (getUseServerPreparedStmts()) {
 
2612
                                this.serverSideStatementCheckCache = new LRUCache(cacheSize);
 
2613
                                
 
2614
                                this.serverSideStatementCache = new LRUCache(cacheSize) {
 
2615
        
 
2616
                                        private static final long serialVersionUID = 7692318650375988114L;
 
2617
        
 
2618
                                        protected boolean removeEldestEntry(java.util.Map.Entry<Object, Object> eldest) {
 
2619
                                                if (this.maxElements <= 1) {
 
2620
                                                        return false;
 
2621
                                                }
 
2622
                                                
 
2623
                                                boolean removeIt = super.removeEldestEntry(eldest);
 
2624
                                                
 
2625
                                                if (removeIt) {
 
2626
                                                        ServerPreparedStatement ps = 
 
2627
                                                                (ServerPreparedStatement)eldest.getValue();
 
2628
                                                        ps.isCached = false;
 
2629
                                                        ps.setClosed(false);
 
2630
                                                        
 
2631
                                                        try {
 
2632
                                                                ps.close();
 
2633
                                                        } catch (SQLException sqlEx) {
 
2634
                                                                // punt
 
2635
                                                        }
 
2636
                                                }
 
2637
                                                
 
2638
                                                return removeIt;
 
2639
                                        }
 
2640
                                };
 
2641
                        }
2453
2642
                }
2454
2643
        }
2455
2644
 
2571
2760
                                catalog, cachedMetadata, false);
2572
2761
        }
2573
2762
 
2574
 
        public synchronized ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows,
 
2763
        public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows,
2575
2764
                        Buffer packet, int resultSetType, int resultSetConcurrency,
2576
2765
                        boolean streamResults, String catalog,
2577
2766
                        Field[] cachedMetadata,
2578
2767
                        boolean isBatch) throws SQLException {
2579
 
                //
2580
 
                // Fall-back if the master is back online if we've
2581
 
                // issued queriesBeforeRetryMaster queries since
2582
 
                // we failed over
2583
 
                //
2584
 
 
2585
 
                long queryStartTime = 0;
2586
 
 
2587
 
                int endOfQueryPacketPosition = 0;
2588
 
 
2589
 
                if (packet != null) {
2590
 
                        endOfQueryPacketPosition = packet.getPosition();
2591
 
                }
2592
 
 
2593
 
                if (getGatherPerformanceMetrics()) {
2594
 
                        queryStartTime = System.currentTimeMillis();
2595
 
                }
2596
 
 
2597
 
                this.lastQueryFinishedTime = 0; // we're busy!
2598
 
 
2599
 
                if ((getHighAvailability())
2600
 
                                && (this.autoCommit || getAutoReconnectForPools())
2601
 
                                && this.needsPing && !isBatch) {
 
2768
                synchronized (getConnectionMutex()) {
 
2769
                        //
 
2770
                        // Fall-back if the master is back online if we've
 
2771
                        // issued queriesBeforeRetryMaster queries since
 
2772
                        // we failed over
 
2773
                        //
 
2774
        
 
2775
                        long queryStartTime = 0;
 
2776
        
 
2777
                        int endOfQueryPacketPosition = 0;
 
2778
        
 
2779
                        if (packet != null) {
 
2780
                                endOfQueryPacketPosition = packet.getPosition();
 
2781
                        }
 
2782
        
 
2783
                        if (getGatherPerformanceMetrics()) {
 
2784
                                queryStartTime = System.currentTimeMillis();
 
2785
                        }
 
2786
        
 
2787
                        this.lastQueryFinishedTime = 0; // we're busy!
 
2788
        
 
2789
                        if ((getHighAvailability())
 
2790
                                        && (this.autoCommit || getAutoReconnectForPools())
 
2791
                                        && this.needsPing && !isBatch) {
 
2792
                                try {
 
2793
                                        pingInternal(false, 0);
 
2794
        
 
2795
                                        this.needsPing = false;
 
2796
                                } catch (Exception Ex) {
 
2797
                                        createNewIO(true);
 
2798
                                }
 
2799
                        }
 
2800
        
2602
2801
                        try {
2603
 
                                pingInternal(false, 0);
2604
 
 
2605
 
                                this.needsPing = false;
2606
 
                        } catch (Exception Ex) {
2607
 
                                createNewIO(true);
2608
 
                        }
2609
 
                }
2610
 
 
2611
 
                try {
2612
 
                        if (packet == null) {
2613
 
                                String encoding = null;
2614
 
 
2615
 
                                if (getUseUnicode()) {
2616
 
                                        encoding = getEncoding();
 
2802
                                if (packet == null) {
 
2803
                                        String encoding = null;
 
2804
        
 
2805
                                        if (getUseUnicode()) {
 
2806
                                                encoding = getEncoding();
 
2807
                                        }
 
2808
        
 
2809
                                        return this.io.sqlQueryDirect(callingStatement, sql,
 
2810
                                                        encoding, null, maxRows, resultSetType,
 
2811
                                                        resultSetConcurrency, streamResults, catalog,
 
2812
                                                        cachedMetadata);
2617
2813
                                }
2618
 
 
2619
 
                                return this.io.sqlQueryDirect(callingStatement, sql,
2620
 
                                                encoding, null, maxRows, resultSetType,
 
2814
        
 
2815
                                return this.io.sqlQueryDirect(callingStatement, null, null,
 
2816
                                                packet, maxRows, resultSetType,
2621
2817
                                                resultSetConcurrency, streamResults, catalog,
2622
2818
                                                cachedMetadata);
2623
 
                        }
2624
 
 
2625
 
                        return this.io.sqlQueryDirect(callingStatement, null, null,
2626
 
                                        packet, maxRows, resultSetType,
2627
 
                                        resultSetConcurrency, streamResults, catalog,
2628
 
                                        cachedMetadata);
2629
 
                } catch (java.sql.SQLException sqlE) {
2630
 
                        // don't clobber SQL exceptions
2631
 
 
2632
 
                        if (getDumpQueriesOnException()) {
2633
 
                                String extractedSql = extractSqlFromPacket(sql, packet,
2634
 
                                                endOfQueryPacketPosition);
2635
 
                                StringBuffer messageBuf = new StringBuffer(extractedSql
2636
 
                                                .length() + 32);
2637
 
                                messageBuf
2638
 
                                                .append("\n\nQuery being executed when exception was thrown:\n");
2639
 
                                messageBuf.append(extractedSql);
2640
 
                                messageBuf.append("\n\n");
2641
 
 
2642
 
                                sqlE = appendMessageToException(sqlE, messageBuf.toString(), getExceptionInterceptor());
2643
 
                        }
2644
 
 
2645
 
                        if ((getHighAvailability())) {
2646
 
                                this.needsPing = true;
2647
 
                        } else {
2648
 
                                String sqlState = sqlE.getSQLState();
2649
 
 
2650
 
                                if ((sqlState != null)
2651
 
                                                && sqlState
2652
 
                                                                .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
2653
 
                                        cleanup(sqlE);
2654
 
                                }
2655
 
                        }
2656
 
 
2657
 
                        throw sqlE;
2658
 
                } catch (Exception ex) {
2659
 
                        if (getHighAvailability()) {
2660
 
                                this.needsPing = true;
2661
 
                        } else if (ex instanceof IOException) {
2662
 
                                cleanup(ex);
2663
 
                        }
2664
 
 
2665
 
                        SQLException sqlEx = SQLError.createSQLException(
2666
 
                                        Messages.getString("Connection.UnexpectedException"),
2667
 
                                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
2668
 
                        sqlEx.initCause(ex);
2669
 
                        
2670
 
                        throw sqlEx;
2671
 
                } finally {
2672
 
                        if (getMaintainTimeStats()) {
2673
 
                                this.lastQueryFinishedTime = System.currentTimeMillis();
2674
 
                        }
2675
 
 
2676
 
 
2677
 
                        if (getGatherPerformanceMetrics()) {
2678
 
                                long queryTime = System.currentTimeMillis()
2679
 
                                                - queryStartTime;
2680
 
 
2681
 
                                registerQueryExecutionTime(queryTime);
 
2819
                        } catch (java.sql.SQLException sqlE) {
 
2820
                                // don't clobber SQL exceptions
 
2821
        
 
2822
                                if (getDumpQueriesOnException()) {
 
2823
                                        String extractedSql = extractSqlFromPacket(sql, packet,
 
2824
                                                        endOfQueryPacketPosition);
 
2825
                                        StringBuffer messageBuf = new StringBuffer(extractedSql
 
2826
                                                        .length() + 32);
 
2827
                                        messageBuf
 
2828
                                                        .append("\n\nQuery being executed when exception was thrown:\n");
 
2829
                                        messageBuf.append(extractedSql);
 
2830
                                        messageBuf.append("\n\n");
 
2831
        
 
2832
                                        sqlE = appendMessageToException(sqlE, messageBuf.toString(), getExceptionInterceptor());
 
2833
                                }
 
2834
        
 
2835
                                if ((getHighAvailability())) {
 
2836
                                        this.needsPing = true;
 
2837
                                } else {
 
2838
                                        String sqlState = sqlE.getSQLState();
 
2839
        
 
2840
                                        if ((sqlState != null)
 
2841
                                                        && sqlState
 
2842
                                                                        .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
 
2843
                                                cleanup(sqlE);
 
2844
                                        }
 
2845
                                }
 
2846
        
 
2847
                                throw sqlE;
 
2848
                        } catch (Exception ex) {
 
2849
                                if (getHighAvailability()) {
 
2850
                                        this.needsPing = true;
 
2851
                                } else if (ex instanceof IOException) {
 
2852
                                        cleanup(ex);
 
2853
                                }
 
2854
        
 
2855
                                SQLException sqlEx = SQLError.createSQLException(
 
2856
                                                Messages.getString("Connection.UnexpectedException"),
 
2857
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
2858
                                sqlEx.initCause(ex);
 
2859
                                
 
2860
                                throw sqlEx;
 
2861
                        } finally {
 
2862
                                if (getMaintainTimeStats()) {
 
2863
                                        this.lastQueryFinishedTime = System.currentTimeMillis();
 
2864
                                }
 
2865
        
 
2866
        
 
2867
                                if (getGatherPerformanceMetrics()) {
 
2868
                                        long queryTime = System.currentTimeMillis()
 
2869
                                                        - queryStartTime;
 
2870
        
 
2871
                                        registerQueryExecutionTime(queryTime);
 
2872
                                }
2682
2873
                        }
2683
2874
                }
2684
2875
        }
2713
2904
                                truncated = true;
2714
2905
                        }
2715
2906
 
2716
 
                        extractedSql = new String(queryPacket.getByteBuffer(), 5,
 
2907
                        extractedSql = StringUtils.toString(queryPacket.getByteBuffer(), 5,
2717
2908
                                        (extractPosition - 5));
2718
2909
 
2719
2910
                        if (truncated) {
2725
2916
 
2726
2917
        }
2727
2918
 
2728
 
        protected void finalize() throws Throwable {
2729
 
                cleanup(null);
2730
 
                
2731
 
                super.finalize();
2732
 
        }
2733
 
 
2734
2919
        public StringBuffer generateConnectionCommentBlock(StringBuffer buf) {
2735
2920
                buf.append("/* conn id ");
2736
2921
                buf.append(getId());
2761
2946
         *                if an error occurs
2762
2947
         * @see setAutoCommit
2763
2948
         */
2764
 
        public synchronized boolean getAutoCommit() throws SQLException {
2765
 
                return this.autoCommit;
 
2949
        public boolean getAutoCommit() throws SQLException {
 
2950
                synchronized (getConnectionMutex()) {
 
2951
                        return this.autoCommit;
 
2952
                }
2766
2953
        }
2767
2954
 
2768
2955
        /**
2788
2975
         * @exception SQLException
2789
2976
         *                if a database access error occurs
2790
2977
         */
2791
 
        public synchronized String getCatalog() throws SQLException {
2792
 
                return this.database;
 
2978
        public String getCatalog() throws SQLException {
 
2979
                synchronized (getConnectionMutex()) {
 
2980
                        return this.database;
 
2981
                }
2793
2982
        }
2794
2983
 
2795
2984
        /**
2796
2985
         * @return Returns the characterSetMetadata.
2797
2986
         */
2798
 
        public synchronized String getCharacterSetMetadata() {
2799
 
                return this.characterSetMetadata;
 
2987
        public String getCharacterSetMetadata() {
 
2988
                synchronized (getConnectionMutex()) {
 
2989
                        return this.characterSetMetadata;
 
2990
                }
2800
2991
        }
2801
2992
 
2802
2993
        /**
2873
3064
 
2874
3065
                if (charsetIndex != MysqlDefs.NO_CHARSET_INFO) {
2875
3066
                        try {
2876
 
                                charsetName = this.indexToCharsetMapping[charsetIndex];
 
3067
                                charsetName = this.indexToJavaCharset.get(charsetIndex);
 
3068
                                // checking against static maps if no custom charset found
 
3069
                                if (charsetName==null) charsetName = CharsetMapping.INDEX_TO_CHARSET[charsetIndex];
2877
3070
 
2878
 
                                if ("sjis".equalsIgnoreCase(charsetName) || 
2879
 
                                                "MS932".equalsIgnoreCase(charsetName) /* for JDK6 */) {
2880
 
                                        // Use our encoding so that code pages like Cp932 work
2881
 
                                        if (CharsetMapping.isAliasForSjis(getEncoding())) {
 
3071
                                if (this.characterEncodingIsAliasForSjis) {
 
3072
                                        if ("sjis".equalsIgnoreCase(charsetName) || 
 
3073
                                                        "MS932".equalsIgnoreCase(charsetName) /* for JDK6 */) {
 
3074
                                                // Use our encoding so that code pages like Cp932 work
2882
3075
                                                charsetName = getEncoding();
2883
3076
                                        }
2884
3077
                                }
2887
3080
                                                "Unknown character set index for field '"
2888
3081
                                                                + charsetIndex + "' received from server.",
2889
3082
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
3083
                        } catch (RuntimeException ex) {
 
3084
                                SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
3085
                                sqlEx.initCause(ex);
 
3086
                                throw sqlEx;
2890
3087
                        }
2891
3088
 
2892
3089
                        // Punt
2932
3129
         * @return number of ms that this connection has been idle, 0 if the driver
2933
3130
         *         is busy retrieving results.
2934
3131
         */
2935
 
        public synchronized long getIdleFor() {
2936
 
                if (this.lastQueryFinishedTime == 0) {
2937
 
                        return 0;
 
3132
        public long getIdleFor() {
 
3133
                synchronized (getConnectionMutex()) {
 
3134
                        if (this.lastQueryFinishedTime == 0) {
 
3135
                                return 0;
 
3136
                        }
 
3137
        
 
3138
                        long now = System.currentTimeMillis();
 
3139
                        long idleTime = now - this.lastQueryFinishedTime;
 
3140
        
 
3141
                        return idleTime;
2938
3142
                }
2939
 
 
2940
 
                long now = System.currentTimeMillis();
2941
 
                long idleTime = now - this.lastQueryFinishedTime;
2942
 
 
2943
 
                return idleTime;
2944
3143
        }
2945
3144
 
2946
3145
        /**
2972
3171
                return this.log;
2973
3172
        }
2974
3173
 
2975
 
        public int getMaxBytesPerChar(String javaCharsetName)
2976
 
        throws SQLException {
2977
 
                // TODO: Check if we can actually run this query at this point in time
2978
 
                String charset = CharsetMapping.getMysqlEncodingForJavaEncoding(
2979
 
                                javaCharsetName, this);
2980
 
                
2981
 
                if ((this.io.serverCharsetIndex == 33) && (versionMeetsMinimum(5, 5, 3)) && (javaCharsetName.equalsIgnoreCase("UTF-8"))) {
2982
 
                        //Avoid UTF8mb4
2983
 
                        charset = "utf8";
2984
 
                }
2985
 
 
2986
 
                if (versionMeetsMinimum(4, 1, 0)) {
2987
 
                        Map mapToCheck = null;
2988
 
                        
2989
 
                        if (!getUseDynamicCharsetInfo()) {
2990
 
                                mapToCheck = CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP;
2991
 
                        } else {
2992
 
                                mapToCheck = this.charsetToNumBytesMap;
2993
 
                        
2994
 
                                synchronized (this.charsetToNumBytesMap) {
2995
 
                                        if (this.charsetToNumBytesMap.isEmpty()) {
2996
 
                                                
2997
 
                                                java.sql.Statement stmt = null;
2998
 
                                                java.sql.ResultSet rs = null;
2999
 
                
3000
 
                                                try {
3001
 
                                                        stmt = getMetadataSafeStatement();
3002
 
                
3003
 
                                                        rs = stmt.executeQuery("SHOW CHARACTER SET");
3004
 
                
3005
 
                                                        while (rs.next()) {
3006
 
                                                                this.charsetToNumBytesMap.put(rs.getString("Charset"),
3007
 
                                                                                Integer.valueOf(rs.getInt("Maxlen")));
3008
 
                                                        }
3009
 
                
3010
 
                                                        rs.close();
3011
 
                                                        rs = null;
3012
 
                
3013
 
                                                        stmt.close();
3014
 
                
3015
 
                                                        stmt = null;
3016
 
                                                } finally {
3017
 
                                                        if (rs != null) {
3018
 
                                                                rs.close();
3019
 
                                                                rs = null;
3020
 
                                                        }
3021
 
                
3022
 
                                                        if (stmt != null) {
3023
 
                                                                stmt.close();
3024
 
                                                                stmt = null;
3025
 
                                                        }
3026
 
                                                }
3027
 
                                        }
 
3174
        public int getMaxBytesPerChar(String javaCharsetName) throws SQLException {
 
3175
                return getMaxBytesPerChar(null, javaCharsetName);
 
3176
        }
 
3177
        
 
3178
        public int getMaxBytesPerChar(Integer charsetIndex, String javaCharsetName) throws SQLException {
 
3179
                
 
3180
                String charset = null;
 
3181
                
 
3182
                try {
 
3183
                        // if we can get it by charsetIndex just doing it
 
3184
 
 
3185
                        // getting charset name from dynamic maps in connection;
 
3186
                        // we do it before checking against static maps because custom charset on server
 
3187
                        // can be mapped to index from our static map key's diapason 
 
3188
                        charset = this.indexToCustomMysqlCharset.get(charsetIndex);
 
3189
                        // checking against static maps if no custom charset found
 
3190
                        if (charset==null) charset = CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(charsetIndex);
 
3191
 
 
3192
                        // if we didn't find charset name by index
 
3193
                        if (charset == null) {
 
3194
                                charset = CharsetMapping.getMysqlEncodingForJavaEncoding(javaCharsetName, this);
 
3195
                                if ((this.io.serverCharsetIndex == 33) && (versionMeetsMinimum(5, 5, 3)) && (javaCharsetName.equalsIgnoreCase("UTF-8"))) {
 
3196
                                        //Avoid UTF8mb4
 
3197
                                        charset = "utf8";
3028
3198
                                }
3029
3199
                        }
3030
 
                
3031
 
                        //Pin down the case when user with 5.5.3 server actually uses 3 byte UTF8
3032
 
                        //We have already overridden users preference by mapping UTF8 to UTF8mb4
3033
 
                        
3034
 
                        Integer mbPerChar = (Integer) mapToCheck.get(charset);
3035
 
                
3036
 
                        if (mbPerChar != null) {
3037
 
                                return mbPerChar.intValue();
3038
 
                        }
3039
 
                
3040
 
                        return 1; // we don't know
 
3200
        
 
3201
                        // checking against dynamic maps in connection
 
3202
                        Integer mblen = this.mysqlCharsetToCustomMblen.get(charset);
 
3203
 
 
3204
                        // checking against static maps
 
3205
                        if (mblen == null) mblen = CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP.get(charset);
 
3206
                        if (mblen == null) mblen = CharsetMapping.STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP.get(charset);
 
3207
        
 
3208
                        if (mblen != null) return mblen.intValue();
 
3209
                } catch (SQLException ex) {
 
3210
                        throw ex;
 
3211
                } catch (RuntimeException ex) {
 
3212
                        SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
3213
                        sqlEx.initCause(ex);
 
3214
                        throw sqlEx;
3041
3215
                }
3042
 
                
 
3216
 
3043
3217
                return 1; // we don't know
3044
3218
        }
3045
3219
 
3097
3271
         */
3098
3272
        public String getServerCharacterEncoding() {
3099
3273
                if (this.io.versionMeetsMinimum(4, 1, 0)) {
3100
 
                        return (String) this.serverVariables.get("character_set_server");
3101
 
                } else {
3102
 
                        return (String) this.serverVariables.get("character_set");
 
3274
                        String charset = this.indexToCustomMysqlCharset.get(this.io.serverCharsetIndex);
 
3275
                        if (charset == null) charset = CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(this.io.serverCharsetIndex);
 
3276
                        return charset != null ? charset : this.serverVariables.get("character_set_server");
3103
3277
                }
 
3278
                return this.serverVariables.get("character_set");
3104
3279
        }
3105
3280
 
3106
3281
        public int getServerMajorVersion() {
3127
3302
        
3128
3303
        public String getServerVariable(String variableName) {
3129
3304
                if (this.serverVariables != null) {
3130
 
                        return (String) this.serverVariables.get(variableName);
 
3305
                        return this.serverVariables.get(variableName);
3131
3306
                }
3132
3307
 
3133
3308
                return null;
3149
3324
         * @exception SQLException
3150
3325
         *                if a database access error occurs
3151
3326
         */
3152
 
        public synchronized int getTransactionIsolation() throws SQLException {
3153
 
 
3154
 
                if (this.hasIsolationLevels && !getUseLocalSessionState()) {
3155
 
                        java.sql.Statement stmt = null;
3156
 
                        java.sql.ResultSet rs = null;
3157
 
 
3158
 
                        try {
3159
 
                                stmt = getMetadataSafeStatement();
3160
 
 
3161
 
                                String query = null;
3162
 
 
3163
 
                                int offset = 0;
3164
 
                                
3165
 
                                if (versionMeetsMinimum(4, 0, 3)) {
3166
 
                                        query = "SELECT @@session.tx_isolation";
3167
 
                                        offset = 1;
3168
 
                                } else {
3169
 
                                        query = "SHOW VARIABLES LIKE 'transaction_isolation'";
3170
 
                                        offset = 2;
3171
 
                                }
3172
 
 
3173
 
                                rs = stmt.executeQuery(query);
3174
 
 
3175
 
                                if (rs.next()) {
3176
 
                                        String s = rs.getString(offset);
3177
 
 
3178
 
                                        if (s != null) {
3179
 
                                                Integer intTI = (Integer) mapTransIsolationNameToValue
3180
 
                                                                .get(s);
3181
 
 
3182
 
                                                if (intTI != null) {
3183
 
                                                        return intTI.intValue();
 
3327
        public int getTransactionIsolation() throws SQLException {
 
3328
 
 
3329
                synchronized (getConnectionMutex()) {
 
3330
                        if (this.hasIsolationLevels && !getUseLocalSessionState()) {
 
3331
                                java.sql.Statement stmt = null;
 
3332
                                java.sql.ResultSet rs = null;
 
3333
        
 
3334
                                try {
 
3335
                                        stmt = getMetadataSafeStatement();
 
3336
        
 
3337
                                        String query = null;
 
3338
        
 
3339
                                        int offset = 0;
 
3340
                                        
 
3341
                                        if (versionMeetsMinimum(4, 0, 3)) {
 
3342
                                                query = "SELECT @@session.tx_isolation";
 
3343
                                                offset = 1;
 
3344
                                        } else {
 
3345
                                                query = "SHOW VARIABLES LIKE 'transaction_isolation'";
 
3346
                                                offset = 2;
 
3347
                                        }
 
3348
        
 
3349
                                        rs = stmt.executeQuery(query);
 
3350
        
 
3351
                                        if (rs.next()) {
 
3352
                                                String s = rs.getString(offset);
 
3353
        
 
3354
                                                if (s != null) {
 
3355
                                                        Integer intTI = mapTransIsolationNameToValue.get(s);
 
3356
        
 
3357
                                                        if (intTI != null) {
 
3358
                                                                return intTI.intValue();
 
3359
                                                        }
3184
3360
                                                }
 
3361
        
 
3362
                                                throw SQLError.createSQLException(
 
3363
                                                                "Could not map transaction isolation '" + s
 
3364
                                                                                + " to a valid JDBC level.",
 
3365
                                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
3185
3366
                                        }
3186
 
 
 
3367
        
3187
3368
                                        throw SQLError.createSQLException(
3188
 
                                                        "Could not map transaction isolation '" + s
3189
 
                                                                        + " to a valid JDBC level.",
 
3369
                                                        "Could not retrieve transaction isolation level from server",
3190
3370
                                                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
3191
 
                                }
3192
 
 
3193
 
                                throw SQLError.createSQLException(
3194
 
                                                "Could not retrieve transaction isolation level from server",
3195
 
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
3196
 
 
3197
 
                        } finally {
3198
 
                                if (rs != null) {
3199
 
                                        try {
3200
 
                                                rs.close();
3201
 
                                        } catch (Exception ex) {
3202
 
                                                // ignore
3203
 
                                                ;
3204
 
                                        }
3205
 
 
3206
 
                                        rs = null;
3207
 
                                }
3208
 
 
3209
 
                                if (stmt != null) {
3210
 
                                        try {
3211
 
                                                stmt.close();
3212
 
                                        } catch (Exception ex) {
3213
 
                                                // ignore
3214
 
                                                ;
3215
 
                                        }
3216
 
 
3217
 
                                        stmt = null;
 
3371
        
 
3372
                                } finally {
 
3373
                                        if (rs != null) {
 
3374
                                                try {
 
3375
                                                        rs.close();
 
3376
                                                } catch (Exception ex) {
 
3377
                                                        // ignore
 
3378
                                                        ;
 
3379
                                                }
 
3380
        
 
3381
                                                rs = null;
 
3382
                                        }
 
3383
        
 
3384
                                        if (stmt != null) {
 
3385
                                                try {
 
3386
                                                        stmt.close();
 
3387
                                                } catch (Exception ex) {
 
3388
                                                        // ignore
 
3389
                                                        ;
 
3390
                                                }
 
3391
        
 
3392
                                                stmt = null;
 
3393
                                        }
3218
3394
                                }
3219
3395
                        }
 
3396
        
 
3397
                        return this.isolationLevel;
3220
3398
                }
3221
 
 
3222
 
                return this.isolationLevel;
3223
3399
        }
3224
3400
 
3225
3401
        /**
3230
3406
         * @throws SQLException
3231
3407
         *             if a database error occurs
3232
3408
         */
3233
 
        public synchronized java.util.Map getTypeMap() throws SQLException {
3234
 
                if (this.typeMap == null) {
3235
 
                        this.typeMap = new HashMap();
 
3409
        public java.util.Map<String,Class<?>> getTypeMap() throws SQLException {
 
3410
                synchronized (getConnectionMutex()) {
 
3411
                        if (this.typeMap == null) {
 
3412
                                this.typeMap = new HashMap<String,Class<?>>();
 
3413
                        }
 
3414
        
 
3415
                        return this.typeMap;
3236
3416
                }
3237
 
 
3238
 
                return this.typeMap;
3239
3417
        }
3240
3418
 
3241
3419
        public String getURL() {
3332
3510
 
3333
3511
                if (getNoDatetimeStringSync() && getUseTimezone()) {
3334
3512
                        throw SQLError.createSQLException(
3335
 
                                        "Can't enable noDatetimeSync and useTimezone configuration "
 
3513
                                        "Can't enable noDatetimeStringSync and useTimezone configuration "
3336
3514
                                                        + "properties at the same time",
3337
3515
                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor());
3338
3516
                }
3396
3574
                                // don't work on these versions
3397
3575
                        }
3398
3576
                }
3399
 
 
 
3577
                
3400
3578
                //
3401
3579
                // If version is greater than 3.21.22 get the server
3402
3580
                // variables.
3413
3591
 
3414
3592
                        LicenseConfiguration.checkLicenseType(this.serverVariables);
3415
3593
 
3416
 
                        String lowerCaseTables = (String) this.serverVariables
3417
 
                                        .get("lower_case_table_names");
 
3594
                        String lowerCaseTables = this.serverVariables.get("lower_case_table_names");
3418
3595
 
3419
3596
                        this.lowerCaseTableNames = "on".equalsIgnoreCase(lowerCaseTables)
3420
3597
                                        || "1".equalsIgnoreCase(lowerCaseTables)
3459
3636
                        if (this.serverVariables.containsKey("sql_mode")) {
3460
3637
                                int sqlMode = 0;
3461
3638
 
3462
 
                                String sqlModeAsString = (String) this.serverVariables
3463
 
                                                .get("sql_mode");
 
3639
                                String sqlModeAsString = this.serverVariables.get("sql_mode");
3464
3640
                                try {
3465
3641
                                        sqlMode = Integer.parseInt(sqlModeAsString);
3466
3642
                                } catch (NumberFormatException nfe) {
3487
3663
                        }
3488
3664
                }
3489
3665
                
3490
 
                this.errorMessageEncoding = 
3491
 
                        CharsetMapping.getCharacterEncodingForErrorMessages(this);
 
3666
                try {
 
3667
                        this.errorMessageEncoding = 
 
3668
                                CharsetMapping.getCharacterEncodingForErrorMessages(this);
 
3669
                } catch (SQLException ex) {
 
3670
                        throw ex;
 
3671
                } catch (RuntimeException ex) {
 
3672
                        SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
 
3673
                        sqlEx.initCause(ex);
 
3674
                        throw sqlEx;
 
3675
                }
3492
3676
                
3493
3677
                
3494
3678
                boolean overrideDefaultAutocommit = isAutoCommitNonDefaultOnServer();
3499
3683
                        this.transactionsSupported = true;
3500
3684
                        
3501
3685
                        if (!overrideDefaultAutocommit) {
3502
 
                                setAutoCommit(true); // to override anything
3503
 
                                // the server is set to...reqd
3504
 
                                // by JDBC spec.
 
3686
                                try {
 
3687
                                        setAutoCommit(true); // to override anything
 
3688
                                        // the server is set to...reqd
 
3689
                                        // by JDBC spec.
 
3690
                                } catch (SQLException ex) {
 
3691
                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
3692
                                                throw ex;
 
3693
                                        }
 
3694
                                }
3505
3695
                        }
3506
3696
                } else {
3507
3697
                        this.transactionsSupported = false;
3527
3717
                // was originally on the server, which is why we use the
3528
3718
                // "special" key to retrieve it
3529
3719
                if (this.io.versionMeetsMinimum(4, 1, 0)) {
3530
 
                        String characterSetResultsOnServerMysql = (String) this.serverVariables
3531
 
                                        .get(JDBC_LOCAL_CHARACTER_SET_RESULTS);
 
3720
                        String characterSetResultsOnServerMysql = this.serverVariables.get(JDBC_LOCAL_CHARACTER_SET_RESULTS);
3532
3721
 
3533
3722
                        if (characterSetResultsOnServerMysql == null
3534
3723
                                        || StringUtils.startsWithIgnoreCaseAndWs(
3535
3724
                                                        characterSetResultsOnServerMysql, "NULL")
3536
3725
                                        || characterSetResultsOnServerMysql.length() == 0) {
3537
 
                                String defaultMetadataCharsetMysql = (String) this.serverVariables
3538
 
                                                .get("character_set_system");
 
3726
                                String defaultMetadataCharsetMysql = this.serverVariables.get("character_set_system");
3539
3727
                                String defaultMetadataCharset = null;
3540
3728
 
3541
3729
                                if (defaultMetadataCharsetMysql != null) {
3542
 
                                        defaultMetadataCharset = CharsetMapping
3543
 
                                                        .getJavaEncodingForMysqlEncoding(
3544
 
                                                                        defaultMetadataCharsetMysql, this);
 
3730
                                        defaultMetadataCharset = getJavaEncodingForMysqlEncoding(defaultMetadataCharsetMysql);
3545
3731
                                } else {
3546
3732
                                        defaultMetadataCharset = "UTF-8";
3547
3733
                                }
3548
3734
 
3549
3735
                                this.characterSetMetadata = defaultMetadataCharset;
3550
3736
                        } else {
3551
 
                                this.characterSetResultsOnServer = CharsetMapping
3552
 
                                                .getJavaEncodingForMysqlEncoding(
3553
 
                                                                characterSetResultsOnServerMysql, this);
 
3737
                                this.characterSetResultsOnServer = getJavaEncodingForMysqlEncoding(characterSetResultsOnServerMysql);
3554
3738
                                this.characterSetMetadata = this.characterSetResultsOnServer;
3555
3739
                        }
3556
3740
                } else {
3586
3770
        }
3587
3771
 
3588
3772
        private boolean isQueryCacheEnabled() {
3589
 
                return "ON".equalsIgnoreCase((String) this.serverVariables
3590
 
                                .get("query_cache_type"))
3591
 
                                && !"0".equalsIgnoreCase((String) this.serverVariables
3592
 
                                                .get("query_cache_size"));
 
3773
                return "ON".equalsIgnoreCase(this.serverVariables.get("query_cache_type"))
 
3774
                                && !"0".equalsIgnoreCase(this.serverVariables.get("query_cache_size"));
3593
3775
        }
3594
3776
 
3595
3777
        private int getServerVariableAsInt(String variableName, int fallbackValue)
3596
3778
                        throws SQLException {
3597
3779
                try {
3598
 
                        return Integer.parseInt((String) this.serverVariables
3599
 
                                        .get(variableName));
 
3780
                        return Integer.parseInt(this.serverVariables.get(variableName));
3600
3781
                } catch (NumberFormatException nfe) {
3601
3782
                        getLog().logWarn(Messages.getString("Connection.BadValueInServerVariables", new Object[] {variableName, 
3602
3783
                                        this.serverVariables.get(variableName), Integer.valueOf(fallbackValue)}));
3616
3797
        private boolean isAutoCommitNonDefaultOnServer() throws SQLException {
3617
3798
                boolean overrideDefaultAutocommit = false;
3618
3799
                
3619
 
                String initConnectValue = (String) this.serverVariables
3620
 
                .get("init_connect");
 
3800
                String initConnectValue = this.serverVariables.get("init_connect");
3621
3801
 
3622
3802
                if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null
3623
3803
                                && initConnectValue.length() > 0) {
3695
3875
         * @return true if this connection is connected to the first in 
3696
3876
         * the list.
3697
3877
         */
3698
 
        public synchronized boolean isMasterConnection() {
3699
 
                return false; // handled higher up
 
3878
        public boolean isMasterConnection() {
 
3879
                synchronized (getConnectionMutex()) {
 
3880
                        return false; // handled higher up
 
3881
                }
3700
3882
        }
3701
3883
 
3702
3884
        /**
3714
3896
        }
3715
3897
 
3716
3898
        /**
3717
 
         * Tests to see if the connection is in Read Only Mode. Note that we cannot
3718
 
         * really put the database in read only mode, but we pretend we can by
 
3899
         * Tests to see if the connection is in Read Only Mode. Note that prior to 5.6,
 
3900
         * we cannot really put the database in read only mode, but we pretend we can by
3719
3901
         * returning the value of the readOnly flag
3720
3902
         * 
3721
3903
         * @return true if the connection is read only
3722
 
         * @exception SQLException
3723
 
         *                if a database access error occurs
 
3904
         * @exception SQLException if a database access error occurs
3724
3905
         */
3725
3906
        public boolean isReadOnly() throws SQLException {
 
3907
                return isReadOnly(true);
 
3908
        }
 
3909
 
 
3910
        /**
 
3911
         * Tests to see if the connection is in Read Only Mode. Note that prior to 5.6,
 
3912
         * we cannot really put the database in read only mode, but we pretend we can by
 
3913
         * returning the value of the readOnly flag
 
3914
         * 
 
3915
         * @param useSessionStatus in some cases, for example when restoring connection with autoReconnect=true,
 
3916
         * we can rely only on saved readOnly state, so use useSessionStatus=false in that case 
 
3917
         * 
 
3918
         * @return true if the connection is read only
 
3919
         * @exception SQLException if a database access error occurs
 
3920
         */
 
3921
        public boolean isReadOnly(boolean useSessionStatus) throws SQLException {
 
3922
                if (useSessionStatus && !this.isClosed && versionMeetsMinimum(5, 6, 5) && !getUseLocalSessionState()) {
 
3923
                        java.sql.Statement stmt = null;
 
3924
                        java.sql.ResultSet rs = null;
 
3925
 
 
3926
                        try {
 
3927
                                try {
 
3928
                                        stmt = getMetadataSafeStatement();
 
3929
 
 
3930
                                        rs = stmt.executeQuery("select @@session.tx_read_only");
 
3931
                                        if (rs.next()) {
 
3932
                                                return rs.getInt(1) != 0; // mysql has a habit of tri+ state booleans
 
3933
                                        }
 
3934
                                } catch (SQLException ex1) {
 
3935
                                        if (ex1.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
3936
                                                throw SQLError.createSQLException(
 
3937
                                                                "Could not retrieve transation read-only status server",
 
3938
                                                                SQLError.SQL_STATE_GENERAL_ERROR, ex1, getExceptionInterceptor());
 
3939
                                        }
 
3940
                                }
 
3941
 
 
3942
                        } finally {
 
3943
                                if (rs != null) {
 
3944
                                        try {
 
3945
                                                rs.close();
 
3946
                                        } catch (Exception ex) {
 
3947
                                                // ignore
 
3948
                                        }
 
3949
 
 
3950
                                        rs = null;
 
3951
                                }
 
3952
 
 
3953
                                if (stmt != null) {
 
3954
                                        try {
 
3955
                                                stmt.close();
 
3956
                                        } catch (Exception ex) {
 
3957
                                                // ignore
 
3958
                                        }
 
3959
 
 
3960
                                        stmt = null;
 
3961
                                }
 
3962
                        }
 
3963
                }
 
3964
 
3726
3965
                return this.readOnly;
3727
3966
        }
3728
3967
 
3730
3969
                return this.isRunningOnJDK13;
3731
3970
        }
3732
3971
 
3733
 
        public synchronized boolean isSameResource(Connection otherConnection) {
3734
 
                if (otherConnection == null) {
3735
 
                        return false;
3736
 
                }
3737
 
                
3738
 
                boolean directCompare = true;
3739
 
                
3740
 
                String otherHost = ((ConnectionImpl)otherConnection).origHostToConnectTo;
3741
 
                String otherOrigDatabase = ((ConnectionImpl)otherConnection).origDatabaseToConnectTo;
3742
 
                String otherCurrentCatalog = ((ConnectionImpl)otherConnection).database;
3743
 
                
3744
 
                if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) {
3745
 
                        directCompare = false;
3746
 
                } else if (otherHost != null && otherHost.indexOf(',') == -1 && 
3747
 
                                otherHost.indexOf(':') == -1) {
3748
 
                        // need to check port numbers
3749
 
                        directCompare = (((ConnectionImpl)otherConnection).origPortToConnectTo == 
3750
 
                                this.origPortToConnectTo);
3751
 
                }
3752
 
                
3753
 
                if (directCompare) {
3754
 
                        if (!nullSafeCompare(otherOrigDatabase, this.origDatabaseToConnectTo)) {                        directCompare = false;
3755
 
                                directCompare = false;
3756
 
                        } else if (!nullSafeCompare(otherCurrentCatalog, this.database)) {
3757
 
                                directCompare = false;
3758
 
                        }
3759
 
                }
3760
 
 
3761
 
                if (directCompare) {
3762
 
                        return true;
3763
 
                }
3764
 
                
3765
 
                // Has the user explicitly set a resourceId?
3766
 
                String otherResourceId = ((ConnectionImpl)otherConnection).getResourceId();
3767
 
                String myResourceId = getResourceId();
3768
 
                
3769
 
                if (otherResourceId != null || myResourceId != null) {
3770
 
                        directCompare = nullSafeCompare(otherResourceId, myResourceId);
3771
 
                        
 
3972
        public boolean isSameResource(Connection otherConnection) {
 
3973
                synchronized (getConnectionMutex()) {
 
3974
                        if (otherConnection == null) {
 
3975
                                return false;
 
3976
                        }
 
3977
                        
 
3978
                        boolean directCompare = true;
 
3979
                        
 
3980
                        String otherHost = ((ConnectionImpl)otherConnection).origHostToConnectTo;
 
3981
                        String otherOrigDatabase = ((ConnectionImpl)otherConnection).origDatabaseToConnectTo;
 
3982
                        String otherCurrentCatalog = ((ConnectionImpl)otherConnection).database;
 
3983
                        
 
3984
                        if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) {
 
3985
                                directCompare = false;
 
3986
                        } else if (otherHost != null && otherHost.indexOf(',') == -1 && 
 
3987
                                        otherHost.indexOf(':') == -1) {
 
3988
                                // need to check port numbers
 
3989
                                directCompare = (((ConnectionImpl)otherConnection).origPortToConnectTo == 
 
3990
                                        this.origPortToConnectTo);
 
3991
                        }
 
3992
                        
 
3993
                        if (directCompare) {
 
3994
                                if (!nullSafeCompare(otherOrigDatabase, this.origDatabaseToConnectTo)) {                        directCompare = false;
 
3995
                                        directCompare = false;
 
3996
                                } else if (!nullSafeCompare(otherCurrentCatalog, this.database)) {
 
3997
                                        directCompare = false;
 
3998
                                }
 
3999
                        }
 
4000
        
3772
4001
                        if (directCompare) {
3773
4002
                                return true;
3774
4003
                        }
 
4004
                        
 
4005
                        // Has the user explicitly set a resourceId?
 
4006
                        String otherResourceId = ((ConnectionImpl)otherConnection).getResourceId();
 
4007
                        String myResourceId = getResourceId();
 
4008
                        
 
4009
                        if (otherResourceId != null || myResourceId != null) {
 
4010
                                directCompare = nullSafeCompare(otherResourceId, myResourceId);
 
4011
                                
 
4012
                                if (directCompare) {
 
4013
                                        return true;
 
4014
                                }
 
4015
                        }
 
4016
                        
 
4017
                        return false;
3775
4018
                }
3776
 
                
3777
 
                return false;   
3778
4019
        }
3779
4020
 
3780
4021
        public boolean isServerTzUTC() {
3781
4022
                return this.isServerTzUTC;
3782
4023
        }
3783
4024
 
 
4025
        
3784
4026
        private boolean usingCachedConfig = false;
3785
4027
 
 
4028
        private void createConfigCacheIfNeeded() throws SQLException {
 
4029
                synchronized (getConnectionMutex()) {
 
4030
                        if (this.serverConfigCache != null) {
 
4031
                                return;
 
4032
                        }
 
4033
                        
 
4034
                        try {
 
4035
                                Class<?> factoryClass;
 
4036
                                
 
4037
                                factoryClass = Class.forName(getServerConfigCacheFactory());
 
4038
                                
 
4039
                                @SuppressWarnings("unchecked")
 
4040
                                CacheAdapterFactory<String, Map<String, String>> cacheFactory = ((CacheAdapterFactory<String, Map<String, String>>)factoryClass.newInstance());
 
4041
                                
 
4042
                                this.serverConfigCache = cacheFactory.getInstance(this, myURL, Integer.MAX_VALUE, Integer.MAX_VALUE, props);
 
4043
                                
 
4044
                                ExceptionInterceptor evictOnCommsError = new ExceptionInterceptor() {
 
4045
        
 
4046
                                        public void init(Connection conn, Properties config)
 
4047
                                                        throws SQLException {
 
4048
                                        }
 
4049
        
 
4050
                                        public void destroy() {
 
4051
                                        }
 
4052
        
 
4053
                                        @SuppressWarnings("synthetic-access")
 
4054
                                        public SQLException interceptException(SQLException sqlEx,
 
4055
                                                        Connection conn) {
 
4056
                                                if (sqlEx.getSQLState() != null && sqlEx.getSQLState().startsWith("08")) {
 
4057
                                                        serverConfigCache.invalidate(getURL());
 
4058
                                                }
 
4059
                                                return null;
 
4060
                                        }};
 
4061
                                
 
4062
                                if (this.exceptionInterceptor == null) {
 
4063
                                        this.exceptionInterceptor = evictOnCommsError;
 
4064
                                } else {
 
4065
                                        ((ExceptionInterceptorChain)this.exceptionInterceptor).addRingZero(evictOnCommsError);
 
4066
                                }
 
4067
                        } catch (ClassNotFoundException e) {
 
4068
                                SQLException sqlEx = SQLError.createSQLException(
 
4069
                                                Messages.getString("Connection.CantFindCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
4070
                                                getExceptionInterceptor());
 
4071
                                sqlEx.initCause(e);
 
4072
                                
 
4073
                                throw sqlEx;
 
4074
                        } catch (InstantiationException e) {
 
4075
                                SQLException sqlEx = SQLError.createSQLException(
 
4076
                                                Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
4077
                                                getExceptionInterceptor());
 
4078
                                sqlEx.initCause(e);
 
4079
                                
 
4080
                                throw sqlEx;
 
4081
                        } catch (IllegalAccessException e) {
 
4082
                                SQLException sqlEx = SQLError.createSQLException(
 
4083
                                                Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}),
 
4084
                                                getExceptionInterceptor());
 
4085
                                sqlEx.initCause(e);
 
4086
                                
 
4087
                                throw sqlEx;
 
4088
                        }
 
4089
                }
 
4090
        }
 
4091
        
 
4092
        private final static String SERVER_VERSION_STRING_VAR_NAME = "server_version_string";
 
4093
        
3786
4094
        /**
3787
4095
         * Loads the result of 'SHOW VARIABLES' into the serverVariables field so
3788
4096
         * that the driver can configure itself.
3790
4098
         * @throws SQLException
3791
4099
         *             if the 'SHOW VARIABLES' query fails for any reason.
3792
4100
         */
3793
 
        @SuppressWarnings({ "unchecked", "rawtypes" })
3794
4101
        private void loadServerVariables() throws SQLException {
3795
4102
 
3796
4103
                if (getCacheServerConfiguration()) {
3797
 
                        synchronized (serverConfigByUrl) {
3798
 
                                @SuppressWarnings("rawtypes")
3799
 
                                Map cachedVariableMap = (Map) serverConfigByUrl.get(getURL());
 
4104
                        createConfigCacheIfNeeded();
 
4105
                        
 
4106
                        Map<String, String> cachedVariableMap = serverConfigCache.get(getURL());
3800
4107
 
3801
 
                                if (cachedVariableMap != null) {
 
4108
                        if (cachedVariableMap != null) {
 
4109
                                String cachedServerVersion = cachedVariableMap.get(SERVER_VERSION_STRING_VAR_NAME);
 
4110
                                
 
4111
                                if (cachedServerVersion != null && this.io.getServerVersion() != null 
 
4112
                                                && cachedServerVersion.equals(this.io.getServerVersion())) {
3802
4113
                                        this.serverVariables = cachedVariableMap;
3803
4114
                                        this.usingCachedConfig = true;
3804
 
 
 
4115
        
3805
4116
                                        return;
3806
4117
                                }
 
4118
                                
 
4119
                                serverConfigCache.invalidate(getURL());
3807
4120
                        }
3808
4121
                }
3809
4122
 
3860
4173
                                        + " OR Variable_name = 'init_connect'";
3861
4174
                        }
3862
4175
                        
3863
 
                        this.serverVariables = new HashMap();
 
4176
                        this.serverVariables = new HashMap<String, String>();
3864
4177
 
3865
 
                        results = stmt.executeQuery(query);
3866
 
                        
3867
 
                        while (results.next()) {
3868
 
                                this.serverVariables.put(results.getString(1), results
3869
 
                                                .getString(2));
 
4178
                        try {
 
4179
                                results = stmt.executeQuery(query);
 
4180
                                
 
4181
                                while (results.next()) {
 
4182
                                        this.serverVariables.put(results.getString(1), results
 
4183
                                                        .getString(2));
 
4184
                                }
 
4185
        
 
4186
                                results.close();
 
4187
                                results = null;
 
4188
                        } catch (SQLException ex) {
 
4189
                                if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
4190
                                        throw ex;
 
4191
                                }
3870
4192
                        }
3871
 
 
3872
 
                        results.close();
3873
 
                        results = null;
3874
4193
                        
3875
4194
                        if (versionMeetsMinimum(5, 0, 2)) {
3876
 
                                results = stmt.executeQuery(versionComment + "SELECT @@session.auto_increment_increment");
3877
 
                                
3878
 
                                if (results.next()) {
3879
 
                                        this.serverVariables.put("auto_increment_increment", results.getString(1));
 
4195
                                try {
 
4196
                                        results = stmt.executeQuery(versionComment + "SELECT @@session.auto_increment_increment");
 
4197
                                        
 
4198
                                        if (results.next()) {
 
4199
                                                this.serverVariables.put("auto_increment_increment", results.getString(1));
 
4200
                                        }
 
4201
                                } catch (SQLException ex) {
 
4202
                                        if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
 
4203
                                                throw ex;
 
4204
                                        }
3880
4205
                                }
3881
4206
                        }
3882
4207
                        
3883
4208
                        if (getCacheServerConfiguration()) {
3884
 
                                synchronized (serverConfigByUrl) {
3885
 
                                        serverConfigByUrl.put(getURL(), this.serverVariables);
3886
 
                                        
3887
 
                                        this.usingCachedConfig = true;
3888
 
                                }
 
4209
                                this.serverVariables.put(SERVER_VERSION_STRING_VAR_NAME, this.io.getServerVersion());
 
4210
                                
 
4211
                                serverConfigCache.put(getURL(), this.serverVariables);
 
4212
                                
 
4213
                                this.usingCachedConfig = true;
3889
4214
                        }
3890
4215
                } catch (SQLException e) {
3891
4216
                        throw e;
3929
4254
         * @param stmt
3930
4255
         *            DOCUMENT ME!
3931
4256
         */
3932
 
        public synchronized void maxRowsChanged(Statement stmt) {
3933
 
                if (this.statementsUsingMaxRows == null) {
3934
 
                        this.statementsUsingMaxRows = new HashMap();
 
4257
        public void maxRowsChanged(Statement stmt) {
 
4258
                synchronized (getConnectionMutex()) {
 
4259
                        if (this.statementsUsingMaxRows == null) {
 
4260
                                this.statementsUsingMaxRows = new HashMap<Statement, Statement>();
 
4261
                        }
 
4262
        
 
4263
                        this.statementsUsingMaxRows.put(stmt, stmt);
 
4264
        
 
4265
                        this.maxRowsChanged = true;
3935
4266
                }
3936
 
 
3937
 
                this.statementsUsingMaxRows.put(stmt, stmt);
3938
 
 
3939
 
                this.maxRowsChanged = true;
3940
4267
        }
3941
4268
 
3942
4269
        /**
4178
4505
         * @exception SQLException
4179
4506
         *                if a database-access error occurs.
4180
4507
         */
4181
 
        public synchronized java.sql.PreparedStatement prepareStatement(String sql,
 
4508
        public java.sql.PreparedStatement prepareStatement(String sql,
4182
4509
                        int resultSetType, int resultSetConcurrency) throws SQLException {
4183
 
                checkClosed();
4184
 
 
4185
 
                //
4186
 
                // FIXME: Create warnings if can't create results of the given
4187
 
                // type or concurrency
4188
 
                //
4189
 
                PreparedStatement pStmt = null;
4190
 
                
4191
 
                boolean canServerPrepare = true;
4192
 
                
4193
 
                String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql;
4194
 
                
4195
 
                if (this.useServerPreparedStmts && getEmulateUnsupportedPstmts()) {
4196
 
                        canServerPrepare = canHandleAsServerPreparedStatement(nativeSql);
4197
 
                }
4198
 
                
4199
 
                if (this.useServerPreparedStmts && canServerPrepare) {
4200
 
                        if (this.getCachePreparedStatements()) {
4201
 
                                synchronized (this.serverSideStatementCache) {
4202
 
                                        pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql);
4203
 
                                        
4204
 
                                        if (pStmt != null) {
4205
 
                                                ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false);
4206
 
                                                pStmt.clearParameters();
4207
 
                                        }
4208
 
 
4209
 
                                        if (pStmt == null) {
4210
 
                                                try {
4211
 
                                                        pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
4212
 
                                                                        this.database, resultSetType, resultSetConcurrency);
4213
 
                                                        if (sql.length() < getPreparedStatementCacheSqlLimit()) {
4214
 
                                                                ((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true;
4215
 
                                                        }
4216
 
                                                        
4217
 
                                                        pStmt.setResultSetType(resultSetType);
4218
 
                                                        pStmt.setResultSetConcurrency(resultSetConcurrency);
4219
 
                                                } catch (SQLException sqlEx) {
4220
 
                                                        // Punt, if necessary
4221
 
                                                        if (getEmulateUnsupportedPstmts()) {
4222
 
                                                                pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
4223
 
                                                                
 
4510
                synchronized (getConnectionMutex()) {
 
4511
                        checkClosed();
 
4512
        
 
4513
                        //
 
4514
                        // FIXME: Create warnings if can't create results of the given
 
4515
                        // type or concurrency
 
4516
                        //
 
4517
                        PreparedStatement pStmt = null;
 
4518
                        
 
4519
                        boolean canServerPrepare = true;
 
4520
                        
 
4521
                        String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql;
 
4522
                        
 
4523
                        if (this.useServerPreparedStmts && getEmulateUnsupportedPstmts()) {
 
4524
                                canServerPrepare = canHandleAsServerPreparedStatement(nativeSql);
 
4525
                        }
 
4526
                        
 
4527
                        if (this.useServerPreparedStmts && canServerPrepare) {
 
4528
                                if (this.getCachePreparedStatements()) {
 
4529
                                        synchronized (this.serverSideStatementCache) {
 
4530
                                                pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql);
 
4531
                                                
 
4532
                                                if (pStmt != null) {
 
4533
                                                        ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false);
 
4534
                                                        pStmt.clearParameters();
 
4535
                                                }
 
4536
        
 
4537
                                                if (pStmt == null) {
 
4538
                                                        try {
 
4539
                                                                pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
 
4540
                                                                                this.database, resultSetType, resultSetConcurrency);
4224
4541
                                                                if (sql.length() < getPreparedStatementCacheSqlLimit()) {
4225
 
                                                                        this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
4226
 
                                                                }
4227
 
                                                        } else {
4228
 
                                                                throw sqlEx;
 
4542
                                                                        ((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true;
 
4543
                                                                }
 
4544
                                                                
 
4545
                                                                pStmt.setResultSetType(resultSetType);
 
4546
                                                                pStmt.setResultSetConcurrency(resultSetConcurrency);
 
4547
                                                        } catch (SQLException sqlEx) {
 
4548
                                                                // Punt, if necessary
 
4549
                                                                if (getEmulateUnsupportedPstmts()) {
 
4550
                                                                        pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
 
4551
                                                                        
 
4552
                                                                        if (sql.length() < getPreparedStatementCacheSqlLimit()) {
 
4553
                                                                                this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
 
4554
                                                                        }
 
4555
                                                                } else {
 
4556
                                                                        throw sqlEx;
 
4557
                                                                }
4229
4558
                                                        }
4230
4559
                                                }
4231
4560
                                        }
 
4561
                                } else {
 
4562
                                        try {
 
4563
                                                pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
 
4564
                                                                this.database, resultSetType, resultSetConcurrency);
 
4565
                                                
 
4566
                                                pStmt.setResultSetType(resultSetType);
 
4567
                                                pStmt.setResultSetConcurrency(resultSetConcurrency);
 
4568
                                        } catch (SQLException sqlEx) {
 
4569
                                                // Punt, if necessary
 
4570
                                                if (getEmulateUnsupportedPstmts()) {
 
4571
                                                        pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
 
4572
                                                } else {
 
4573
                                                        throw sqlEx;
 
4574
                                                }
 
4575
                                        }
4232
4576
                                }
4233
4577
                        } else {
4234
 
                                try {
4235
 
                                        pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
4236
 
                                                        this.database, resultSetType, resultSetConcurrency);
4237
 
                                        
4238
 
                                        pStmt.setResultSetType(resultSetType);
4239
 
                                        pStmt.setResultSetConcurrency(resultSetConcurrency);
4240
 
                                } catch (SQLException sqlEx) {
4241
 
                                        // Punt, if necessary
4242
 
                                        if (getEmulateUnsupportedPstmts()) {
4243
 
                                                pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
4244
 
                                        } else {
4245
 
                                                throw sqlEx;
4246
 
                                        }
4247
 
                                }
 
4578
                                pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
4248
4579
                        }
4249
 
                } else {
4250
 
                        pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
 
4580
                        
 
4581
                        return pStmt;
4251
4582
                }
4252
 
                
4253
 
                return pStmt;
4254
4583
        }
4255
4584
 
4256
4585
        /**
4377
4706
                        
4378
4707
                if (this.statementInterceptors != null) {
4379
4708
                        for (int i = 0; i < this.statementInterceptors.size(); i++) {
4380
 
                                ((StatementInterceptorV2)this.statementInterceptors.get(i)).destroy();
 
4709
                                this.statementInterceptors.get(i).destroy();
4381
4710
                        }
4382
4711
                }
4383
4712
                
4391
4720
                        this.exceptionInterceptor = null;
4392
4721
                        ProfilerEventHandlerFactory.removeInstance(this);
4393
4722
                        
4394
 
                        synchronized (this) {
 
4723
                        synchronized (getConnectionMutex()) {
4395
4724
                                if (this.cancelTimer != null) {
4396
4725
                                        this.cancelTimer.cancel();
4397
4726
                                }
4406
4735
 
4407
4736
        }
4408
4737
 
4409
 
        public synchronized void recachePreparedStatement(ServerPreparedStatement pstmt) throws SQLException {
4410
 
                if (pstmt.isPoolable()) {
4411
 
                        synchronized (this.serverSideStatementCache) {
4412
 
                                this.serverSideStatementCache.put(pstmt.originalSql, pstmt);
 
4738
        public void recachePreparedStatement(ServerPreparedStatement pstmt) throws SQLException {
 
4739
                synchronized (getConnectionMutex()) {
 
4740
                        if (pstmt.isPoolable()) {
 
4741
                                synchronized (this.serverSideStatementCache) {
 
4742
                                        this.serverSideStatementCache.put(pstmt.originalSql, pstmt);
 
4743
                                }
4413
4744
                        }
4414
4745
                }
4415
4746
        }
4640
4971
         * Reports currently collected metrics if this feature is enabled and the
4641
4972
         * timeout has passed.
4642
4973
         */
4643
 
        private void reportMetricsIfNeeded() {
 
4974
        protected void reportMetricsIfNeeded() {
4644
4975
                if (getGatherPerformanceMetrics()) {
4645
4976
                        if ((System.currentTimeMillis() - this.metricsLastReportedMs) > getReportMetricsIntervalMillis()) {
4646
4977
                                reportMetrics();
4686
5017
         *                if a database access error occurs
4687
5018
         * @see commit
4688
5019
         */
4689
 
        public synchronized void rollback() throws SQLException {
4690
 
                checkClosed();
4691
 
 
4692
 
                try {
4693
 
                        if (this.connectionLifecycleInterceptors != null) {
4694
 
                                IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
4695
 
 
4696
 
                                        void forEach(Object each) throws SQLException {
4697
 
                                                if (!((ConnectionLifecycleInterceptor)each).rollback()) {
4698
 
                                                        this.stopIterating = true;
 
5020
        public void rollback() throws SQLException {
 
5021
                synchronized (getConnectionMutex()) {
 
5022
                        checkClosed();
 
5023
        
 
5024
                        try {
 
5025
                                if (this.connectionLifecycleInterceptors != null) {
 
5026
                                        IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5027
        
 
5028
                                                void forEach(Extension each) throws SQLException {
 
5029
                                                        if (!((ConnectionLifecycleInterceptor)each).rollback()) {
 
5030
                                                                this.stopIterating = true;
 
5031
                                                        }
4699
5032
                                                }
4700
 
                                        }
4701
 
                                };
4702
 
                                
4703
 
                                iter.doForAll();
4704
 
                                
4705
 
                                if (!iter.fullIteration()) {
4706
 
                                        return;
4707
 
                                }
4708
 
                        }
4709
 
                        // no-op if _relaxAutoCommit == true
4710
 
                        if (this.autoCommit && !getRelaxAutoCommit()) {
4711
 
                                throw SQLError.createSQLException(
4712
 
                                                "Can't call rollback when autocommit=true",
4713
 
                                                SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor());
4714
 
                        } else if (this.transactionsSupported) {
4715
 
                                try {
4716
 
                                        rollbackNoChecks();
4717
 
                                } catch (SQLException sqlEx) {
4718
 
                                        // We ignore non-transactional tables if told to do so
4719
 
                                        if (getIgnoreNonTxTables()
4720
 
                                                        && (sqlEx.getErrorCode() == SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
 
5033
                                        };
 
5034
                                        
 
5035
                                        iter.doForAll();
 
5036
                                        
 
5037
                                        if (!iter.fullIteration()) {
4721
5038
                                                return;
4722
5039
                                        }
4723
 
                                        throw sqlEx;
4724
 
 
4725
 
                                }
4726
 
                        }
4727
 
                } catch (SQLException sqlException) {
4728
 
                        if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
4729
 
                                        .equals(sqlException.getSQLState())) {
4730
 
                                throw SQLError.createSQLException(
4731
 
                                                "Communications link failure during rollback(). Transaction resolution unknown.",
4732
 
                                                SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor());
4733
 
                        }
4734
 
 
4735
 
                        throw sqlException;
4736
 
                } finally {
4737
 
                        this.needsPing = this.getReconnectAtTxEnd();
 
5040
                                }
 
5041
                                // no-op if _relaxAutoCommit == true
 
5042
                                if (this.autoCommit && !getRelaxAutoCommit()) {
 
5043
                                        throw SQLError.createSQLException(
 
5044
                                                        "Can't call rollback when autocommit=true",
 
5045
                                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor());
 
5046
                                } else if (this.transactionsSupported) {
 
5047
                                        try {
 
5048
                                                rollbackNoChecks();
 
5049
                                        } catch (SQLException sqlEx) {
 
5050
                                                // We ignore non-transactional tables if told to do so
 
5051
                                                if (getIgnoreNonTxTables()
 
5052
                                                                && (sqlEx.getErrorCode() == SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
 
5053
                                                        return;
 
5054
                                                }
 
5055
                                                throw sqlEx;
 
5056
        
 
5057
                                        }
 
5058
                                }
 
5059
                        } catch (SQLException sqlException) {
 
5060
                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
 
5061
                                                .equals(sqlException.getSQLState())) {
 
5062
                                        throw SQLError.createSQLException(
 
5063
                                                        "Communications link failure during rollback(). Transaction resolution unknown.",
 
5064
                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor());
 
5065
                                }
 
5066
        
 
5067
                                throw sqlException;
 
5068
                        } finally {
 
5069
                                this.needsPing = this.getReconnectAtTxEnd();
 
5070
                        }
4738
5071
                }
4739
5072
        }
4740
5073
 
4741
5074
        /**
4742
5075
         * @see Connection#rollback(Savepoint)
4743
5076
         */
4744
 
        public synchronized void rollback(final Savepoint savepoint) throws SQLException {
4745
 
 
4746
 
                if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
4747
 
                        checkClosed();
4748
 
        
4749
 
                        try {
4750
 
                                if (this.connectionLifecycleInterceptors != null) {
4751
 
                                        IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
4752
 
 
4753
 
                                                void forEach(Object each) throws SQLException {
4754
 
                                                        if (!((ConnectionLifecycleInterceptor)each).rollback(savepoint)) {
4755
 
                                                                this.stopIterating = true;
4756
 
                                                        }
4757
 
                                                }
4758
 
                                        };
4759
 
                                        
4760
 
                                        iter.doForAll();
4761
 
                                        
4762
 
                                        if (!iter.fullIteration()) {
4763
 
                                                return;
4764
 
                                        }
4765
 
                                }
4766
 
                                
4767
 
                                StringBuffer rollbackQuery = new StringBuffer(
4768
 
                                                "ROLLBACK TO SAVEPOINT ");
4769
 
                                rollbackQuery.append('`');
4770
 
                                rollbackQuery.append(savepoint.getSavepointName());
4771
 
                                rollbackQuery.append('`');
4772
 
 
4773
 
                                java.sql.Statement stmt = null;
4774
 
 
 
5077
        public void rollback(final Savepoint savepoint) throws SQLException {
 
5078
 
 
5079
                synchronized (getConnectionMutex()) {
 
5080
                        if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
 
5081
                                checkClosed();
 
5082
                
4775
5083
                                try {
4776
 
                                        stmt = getMetadataSafeStatement();
4777
 
 
4778
 
                                        stmt.executeUpdate(rollbackQuery.toString());
4779
 
                                } catch (SQLException sqlEx) {
4780
 
                                        int errno = sqlEx.getErrorCode();
4781
 
 
4782
 
                                        if (errno == 1181) {
4783
 
                                                String msg = sqlEx.getMessage();
4784
 
 
4785
 
                                                if (msg != null) {
4786
 
                                                        int indexOfError153 = msg.indexOf("153");
4787
 
 
4788
 
                                                        if (indexOfError153 != -1) {
4789
 
                                                                throw SQLError.createSQLException("Savepoint '"
4790
 
                                                                                + savepoint.getSavepointName()
4791
 
                                                                                + "' does not exist",
4792
 
                                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
4793
 
                                                                                errno, getExceptionInterceptor());
 
5084
                                        if (this.connectionLifecycleInterceptors != null) {
 
5085
                                                IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5086
        
 
5087
                                                        void forEach(Extension each) throws SQLException {
 
5088
                                                                if (!((ConnectionLifecycleInterceptor)each).rollback(savepoint)) {
 
5089
                                                                        this.stopIterating = true;
 
5090
                                                                }
4794
5091
                                                        }
 
5092
                                                };
 
5093
                                                
 
5094
                                                iter.doForAll();
 
5095
                                                
 
5096
                                                if (!iter.fullIteration()) {
 
5097
                                                        return;
4795
5098
                                                }
4796
5099
                                        }
4797
 
 
4798
 
                                        // We ignore non-transactional tables if told to do so
4799
 
                                        if (getIgnoreNonTxTables()
4800
 
                                                        && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
 
5100
                                        
 
5101
                                        StringBuffer rollbackQuery = new StringBuffer(
 
5102
                                                        "ROLLBACK TO SAVEPOINT ");
 
5103
                                        rollbackQuery.append('`');
 
5104
                                        rollbackQuery.append(savepoint.getSavepointName());
 
5105
                                        rollbackQuery.append('`');
 
5106
        
 
5107
                                        java.sql.Statement stmt = null;
 
5108
        
 
5109
                                        try {
 
5110
                                                stmt = getMetadataSafeStatement();
 
5111
        
 
5112
                                                stmt.executeUpdate(rollbackQuery.toString());
 
5113
                                        } catch (SQLException sqlEx) {
 
5114
                                                int errno = sqlEx.getErrorCode();
 
5115
        
 
5116
                                                if (errno == 1181) {
 
5117
                                                        String msg = sqlEx.getMessage();
 
5118
        
 
5119
                                                        if (msg != null) {
 
5120
                                                                int indexOfError153 = msg.indexOf("153");
 
5121
        
 
5122
                                                                if (indexOfError153 != -1) {
 
5123
                                                                        throw SQLError.createSQLException("Savepoint '"
 
5124
                                                                                        + savepoint.getSavepointName()
 
5125
                                                                                        + "' does not exist",
 
5126
                                                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
 
5127
                                                                                        errno, getExceptionInterceptor());
 
5128
                                                                }
 
5129
                                                        }
 
5130
                                                }
 
5131
        
 
5132
                                                // We ignore non-transactional tables if told to do so
 
5133
                                                if (getIgnoreNonTxTables()
 
5134
                                                                && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
 
5135
                                                        throw sqlEx;
 
5136
                                                }
 
5137
        
 
5138
                                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
 
5139
                                                                .equals(sqlEx.getSQLState())) {
 
5140
                                                        throw SQLError.createSQLException(
 
5141
                                                                        "Communications link failure during rollback(). Transaction resolution unknown.",
 
5142
                                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor());
 
5143
                                                }
 
5144
        
4801
5145
                                                throw sqlEx;
4802
 
                                        }
4803
 
 
4804
 
                                        if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
4805
 
                                                        .equals(sqlEx.getSQLState())) {
4806
 
                                                throw SQLError.createSQLException(
4807
 
                                                                "Communications link failure during rollback(). Transaction resolution unknown.",
4808
 
                                                                SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor());
4809
 
                                        }
4810
 
 
4811
 
                                        throw sqlEx;
 
5146
                                        } finally {
 
5147
                                                closeStatement(stmt);
 
5148
                                        }
4812
5149
                                } finally {
4813
 
                                        closeStatement(stmt);
 
5150
                                        this.needsPing = this.getReconnectAtTxEnd();
4814
5151
                                }
4815
 
                        } finally {
4816
 
                                this.needsPing = this.getReconnectAtTxEnd();
 
5152
                        } else {
 
5153
                                throw SQLError.notImplemented();
4817
5154
                        }
4818
 
                } else {
4819
 
                        throw SQLError.notImplemented();
4820
5155
                }
4821
5156
        }
4822
5157
 
4947
5282
         * @exception SQLException
4948
5283
         *                if a database access error occurs
4949
5284
         */
4950
 
        public synchronized void setAutoCommit(final boolean autoCommitFlag) throws SQLException {
4951
 
                checkClosed();
4952
 
                
4953
 
                if (this.connectionLifecycleInterceptors != null) {
4954
 
                        IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
4955
 
 
4956
 
                                void forEach(Object each) throws SQLException {
4957
 
                                        if (!((ConnectionLifecycleInterceptor)each).setAutoCommit(autoCommitFlag)) {
4958
 
                                                this.stopIterating = true;
4959
 
                                        }
4960
 
                                }
4961
 
                        };
4962
 
                        
4963
 
                        iter.doForAll();
4964
 
                        
4965
 
                        if (!iter.fullIteration()) {
4966
 
                                return;
4967
 
                        }
4968
 
                }
4969
 
 
4970
 
                if (getAutoReconnectForPools()) {
4971
 
                        setHighAvailability(true);
4972
 
                }
4973
 
 
4974
 
                try {
4975
 
                        if (this.transactionsSupported) {
4976
 
 
4977
 
                                boolean needsSetOnServer = true;
4978
 
 
4979
 
                                if (this.getUseLocalSessionState()
4980
 
                                                && this.autoCommit == autoCommitFlag) {
4981
 
                                        needsSetOnServer = false;
4982
 
                                } else if (!this.getHighAvailability()) {
4983
 
                                        needsSetOnServer = this.getIO()
4984
 
                                                        .isSetNeededForAutoCommitMode(autoCommitFlag);
4985
 
                                }
4986
 
 
4987
 
                                // this internal value must be set first as failover depends on
4988
 
                                // it
4989
 
                                // being set to true to fail over (which is done by most
4990
 
                                // app servers and connection pools at the end of
4991
 
                                // a transaction), and the driver issues an implicit set
4992
 
                                // based on this value when it (re)-connects to a server
4993
 
                                // so the value holds across connections
4994
 
                                this.autoCommit = autoCommitFlag;
4995
 
 
4996
 
                                if (needsSetOnServer) {
4997
 
                                        execSQL(null, autoCommitFlag ? "SET autocommit=1"
4998
 
                                                        : "SET autocommit=0", -1, null,
4999
 
                                                        DEFAULT_RESULT_SET_TYPE,
5000
 
                                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
5001
 
                                                        this.database, null, false);
5002
 
                                }
5003
 
 
5004
 
                        } else {
5005
 
                                if ((autoCommitFlag == false) && !getRelaxAutoCommit()) {
5006
 
                                        throw SQLError.createSQLException("MySQL Versions Older than 3.23.15 "
5007
 
                                                        + "do not support transactions",
5008
 
                                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor());
5009
 
                                }
5010
 
 
5011
 
                                this.autoCommit = autoCommitFlag;
5012
 
                        }
5013
 
                } finally {
5014
 
                        if (this.getAutoReconnectForPools()) {
5015
 
                                setHighAvailability(false);
5016
 
                        }
5017
 
                }
5018
 
                
5019
 
                return;
 
5285
        public void setAutoCommit(final boolean autoCommitFlag) throws SQLException {
 
5286
                synchronized (getConnectionMutex()) {
 
5287
                        checkClosed();
 
5288
                        
 
5289
                        if (this.connectionLifecycleInterceptors != null) {
 
5290
                                IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5291
        
 
5292
                                        void forEach(Extension each) throws SQLException {
 
5293
                                                if (!((ConnectionLifecycleInterceptor)each).setAutoCommit(autoCommitFlag)) {
 
5294
                                                        this.stopIterating = true;
 
5295
                                                }
 
5296
                                        }
 
5297
                                };
 
5298
                                
 
5299
                                iter.doForAll();
 
5300
                                
 
5301
                                if (!iter.fullIteration()) {
 
5302
                                        return;
 
5303
                                }
 
5304
                        }
 
5305
        
 
5306
                        if (getAutoReconnectForPools()) {
 
5307
                                setHighAvailability(true);
 
5308
                        }
 
5309
        
 
5310
                        try {
 
5311
                                if (this.transactionsSupported) {
 
5312
        
 
5313
                                        boolean needsSetOnServer = true;
 
5314
        
 
5315
                                        if (this.getUseLocalSessionState()
 
5316
                                                        && this.autoCommit == autoCommitFlag) {
 
5317
                                                needsSetOnServer = false;
 
5318
                                        } else if (!this.getHighAvailability()) {
 
5319
                                                needsSetOnServer = this.getIO()
 
5320
                                                                .isSetNeededForAutoCommitMode(autoCommitFlag);
 
5321
                                        }
 
5322
        
 
5323
                                        // this internal value must be set first as failover depends on
 
5324
                                        // it
 
5325
                                        // being set to true to fail over (which is done by most
 
5326
                                        // app servers and connection pools at the end of
 
5327
                                        // a transaction), and the driver issues an implicit set
 
5328
                                        // based on this value when it (re)-connects to a server
 
5329
                                        // so the value holds across connections
 
5330
                                        this.autoCommit = autoCommitFlag;
 
5331
        
 
5332
                                        if (needsSetOnServer) {
 
5333
                                                execSQL(null, autoCommitFlag ? "SET autocommit=1"
 
5334
                                                                : "SET autocommit=0", -1, null,
 
5335
                                                                DEFAULT_RESULT_SET_TYPE,
 
5336
                                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
 
5337
                                                                this.database, null, false);
 
5338
                                        }
 
5339
        
 
5340
                                } else {
 
5341
                                        if ((autoCommitFlag == false) && !getRelaxAutoCommit()) {
 
5342
                                                throw SQLError.createSQLException("MySQL Versions Older than 3.23.15 "
 
5343
                                                                + "do not support transactions",
 
5344
                                                                SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor());
 
5345
                                        }
 
5346
        
 
5347
                                        this.autoCommit = autoCommitFlag;
 
5348
                                }
 
5349
                        } finally {
 
5350
                                if (this.getAutoReconnectForPools()) {
 
5351
                                        setHighAvailability(false);
 
5352
                                }
 
5353
                        }
 
5354
                        
 
5355
                        return;
 
5356
                }
5020
5357
        }
5021
5358
 
5022
5359
        /**
5032
5369
         * @throws SQLException
5033
5370
         *             if a database access error occurs
5034
5371
         */
5035
 
        public synchronized void setCatalog(final String catalog) throws SQLException {
5036
 
                checkClosed();
5037
 
 
5038
 
                if (catalog == null) {
5039
 
                        throw SQLError.createSQLException("Catalog can not be null",
5040
 
                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
5041
 
                }
5042
 
                
5043
 
                if (this.connectionLifecycleInterceptors != null) {
5044
 
                        IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
5045
 
 
5046
 
                                void forEach(Object each) throws SQLException {
5047
 
                                        if (!((ConnectionLifecycleInterceptor)each).setCatalog(catalog)) {
5048
 
                                                this.stopIterating = true;
5049
 
                                        }
5050
 
                                }
5051
 
                        };
5052
 
                        
5053
 
                        iter.doForAll();
5054
 
                        
5055
 
                        if (!iter.fullIteration()) {
5056
 
                                return;
5057
 
                        }
5058
 
                }
5059
 
                
5060
 
                if (getUseLocalSessionState()) {
5061
 
                        if (this.lowerCaseTableNames) {
5062
 
                                if (this.database.equalsIgnoreCase(catalog)) {
5063
 
                                        return;
5064
 
                                }
5065
 
                        } else {
5066
 
                                if (this.database.equals(catalog)) {
5067
 
                                        return;
5068
 
                                }
5069
 
                        }
5070
 
                }
5071
 
                
5072
 
                String quotedId = this.dbmd.getIdentifierQuoteString();
5073
 
 
5074
 
                if ((quotedId == null) || quotedId.equals(" ")) {
5075
 
                        quotedId = "";
5076
 
                }
5077
 
 
5078
 
                StringBuffer query = new StringBuffer("USE ");
5079
 
                query.append(quotedId);
5080
 
                query.append(catalog);
5081
 
                query.append(quotedId);
5082
 
 
5083
 
                execSQL(null, query.toString(), -1, null,
5084
 
                                DEFAULT_RESULT_SET_TYPE,
5085
 
                                DEFAULT_RESULT_SET_CONCURRENCY, false,
5086
 
                                this.database, null, false);
5087
 
                
5088
 
                this.database = catalog;
 
5372
        public void setCatalog(final String catalog) throws SQLException {
 
5373
                synchronized (getConnectionMutex()) {
 
5374
                        checkClosed();
 
5375
        
 
5376
                        if (catalog == null) {
 
5377
                                throw SQLError.createSQLException("Catalog can not be null",
 
5378
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
5379
                        }
 
5380
                        
 
5381
                        if (this.connectionLifecycleInterceptors != null) {
 
5382
                                IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5383
        
 
5384
                                        void forEach(Extension each) throws SQLException {
 
5385
                                                if (!((ConnectionLifecycleInterceptor)each).setCatalog(catalog)) {
 
5386
                                                        this.stopIterating = true;
 
5387
                                                }
 
5388
                                        }
 
5389
                                };
 
5390
                                
 
5391
                                iter.doForAll();
 
5392
                                
 
5393
                                if (!iter.fullIteration()) {
 
5394
                                        return;
 
5395
                                }
 
5396
                        }
 
5397
                        
 
5398
                        if (getUseLocalSessionState()) {
 
5399
                                if (this.lowerCaseTableNames) {
 
5400
                                        if (this.database.equalsIgnoreCase(catalog)) {
 
5401
                                                return;
 
5402
                                        }
 
5403
                                } else {
 
5404
                                        if (this.database.equals(catalog)) {
 
5405
                                                return;
 
5406
                                        }
 
5407
                                }
 
5408
                        }
 
5409
                        
 
5410
                        String quotedId = this.dbmd.getIdentifierQuoteString();
 
5411
        
 
5412
                        if ((quotedId == null) || quotedId.equals(" ")) {
 
5413
                                quotedId = "";
 
5414
                        }
 
5415
        
 
5416
                        StringBuffer query = new StringBuffer("USE ");
 
5417
                        query.append(quotedId);
 
5418
                        query.append(catalog);
 
5419
                        query.append(quotedId);
 
5420
        
 
5421
                        execSQL(null, query.toString(), -1, null,
 
5422
                                        DEFAULT_RESULT_SET_TYPE,
 
5423
                                        DEFAULT_RESULT_SET_CONCURRENCY, false,
 
5424
                                        this.database, null, false);
 
5425
                        
 
5426
                        this.database = catalog;
 
5427
                }
5089
5428
        }
5090
5429
 
5091
5430
        /**
5092
5431
         * @param failedOver
5093
5432
         *            The failedOver to set.
5094
5433
         */
5095
 
        public synchronized void setFailedOver(boolean flag) {
5096
 
                // handled higher up
 
5434
        public void setFailedOver(boolean flag) {
 
5435
                synchronized (getConnectionMutex()) {
 
5436
                        // handled higher up
 
5437
                }
5097
5438
        }
5098
5439
 
5099
5440
        /**
5137
5478
        }
5138
5479
        
5139
5480
        public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException {
 
5481
                // note this this is safe even inside a transaction
 
5482
                if (versionMeetsMinimum(5, 6, 5)) {
 
5483
                        if (!getUseLocalSessionState() || (readOnlyFlag != this.readOnly)) {
 
5484
                                execSQL(null, "set session transaction " + (readOnlyFlag ? "read only" : "read write"), -1, null,
 
5485
                                                DEFAULT_RESULT_SET_TYPE,
 
5486
                                                DEFAULT_RESULT_SET_CONCURRENCY, false,
 
5487
                                                this.database, null,
 
5488
                                                false);
 
5489
                        }
 
5490
                }
 
5491
                
5140
5492
                this.readOnly = readOnlyFlag;
5141
5493
        }
5142
5494
        
5151
5503
                return savepoint;
5152
5504
        }
5153
5505
 
5154
 
        private synchronized void setSavepoint(MysqlSavepoint savepoint) throws SQLException {
5155
 
 
5156
 
                if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
5157
 
                        checkClosed();
5158
 
 
5159
 
                        StringBuffer savePointQuery = new StringBuffer("SAVEPOINT ");
5160
 
                        savePointQuery.append('`');
5161
 
                        savePointQuery.append(savepoint.getSavepointName());
5162
 
                        savePointQuery.append('`');
5163
 
 
5164
 
                        java.sql.Statement stmt = null;
5165
 
 
5166
 
                        try {
5167
 
                                stmt = getMetadataSafeStatement();
5168
 
 
5169
 
                                stmt.executeUpdate(savePointQuery.toString());
5170
 
                        } finally {
5171
 
                                closeStatement(stmt);
 
5506
        private void setSavepoint(MysqlSavepoint savepoint) throws SQLException {
 
5507
 
 
5508
                synchronized (getConnectionMutex()) {
 
5509
                        if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
 
5510
                                checkClosed();
 
5511
        
 
5512
                                StringBuffer savePointQuery = new StringBuffer("SAVEPOINT ");
 
5513
                                savePointQuery.append('`');
 
5514
                                savePointQuery.append(savepoint.getSavepointName());
 
5515
                                savePointQuery.append('`');
 
5516
        
 
5517
                                java.sql.Statement stmt = null;
 
5518
        
 
5519
                                try {
 
5520
                                        stmt = getMetadataSafeStatement();
 
5521
        
 
5522
                                        stmt.executeUpdate(savePointQuery.toString());
 
5523
                                } finally {
 
5524
                                        closeStatement(stmt);
 
5525
                                }
 
5526
                        } else {
 
5527
                                throw SQLError.notImplemented();
5172
5528
                        }
5173
 
                } else {
5174
 
                        throw SQLError.notImplemented();
5175
5529
                }
5176
5530
        }
5177
5531
        
5178
5532
        /**
5179
5533
         * @see Connection#setSavepoint(String)
5180
5534
         */
5181
 
        public synchronized java.sql.Savepoint setSavepoint(String name) throws SQLException {
5182
 
                MysqlSavepoint savepoint = new MysqlSavepoint(name, getExceptionInterceptor());
5183
 
 
5184
 
                setSavepoint(savepoint);
5185
 
 
5186
 
                return savepoint;
 
5535
        public java.sql.Savepoint setSavepoint(String name) throws SQLException {
 
5536
                synchronized (getConnectionMutex()) {
 
5537
                        MysqlSavepoint savepoint = new MysqlSavepoint(name, getExceptionInterceptor());
 
5538
        
 
5539
                        setSavepoint(savepoint);
 
5540
        
 
5541
                        return savepoint;
 
5542
                }
5187
5543
        }
5188
5544
        
5189
5545
        /**
5191
5547
         */
5192
5548
        private void setSessionVariables() throws SQLException {
5193
5549
                if (this.versionMeetsMinimum(4, 0, 0) && getSessionVariables() != null) {
5194
 
                        List variablesToSet = StringUtils.split(getSessionVariables(), ",", "\"'", "\"'",
 
5550
                        List<String> variablesToSet = StringUtils.split(getSessionVariables(), ",", "\"'", "\"'",
5195
5551
                                        false);
5196
5552
 
5197
5553
                        int numVariablesToSet = variablesToSet.size();
5202
5558
                                stmt = getMetadataSafeStatement();
5203
5559
 
5204
5560
                                for (int i = 0; i < numVariablesToSet; i++) {
5205
 
                                        String variableValuePair = (String) variablesToSet.get(i);
 
5561
                                        String variableValuePair = variablesToSet.get(i);
5206
5562
 
5207
5563
                                        if (variableValuePair.startsWith("@")) {
5208
5564
                                                stmt.executeUpdate("SET " + variableValuePair);
5227
5583
         * @throws SQLException
5228
5584
         *             DOCUMENT ME!
5229
5585
         */
5230
 
        public synchronized void setTransactionIsolation(int level) throws SQLException {
5231
 
                checkClosed();
5232
 
 
5233
 
                if (this.hasIsolationLevels) {
5234
 
                        String sql = null;
5235
 
 
5236
 
                        boolean shouldSendSet = false;
5237
 
 
5238
 
                        if (getAlwaysSendSetIsolation()) {
5239
 
                                shouldSendSet = true;
5240
 
                        } else {
5241
 
                                if (level != this.isolationLevel) {
 
5586
        public void setTransactionIsolation(int level) throws SQLException {
 
5587
                synchronized (getConnectionMutex()) {
 
5588
                        checkClosed();
 
5589
        
 
5590
                        if (this.hasIsolationLevels) {
 
5591
                                String sql = null;
 
5592
        
 
5593
                                boolean shouldSendSet = false;
 
5594
        
 
5595
                                if (getAlwaysSendSetIsolation()) {
5242
5596
                                        shouldSendSet = true;
5243
 
                                }
5244
 
                        }
5245
 
 
5246
 
                        if (getUseLocalSessionState()) {
5247
 
                                shouldSendSet = this.isolationLevel != level;
5248
 
                        }
5249
 
 
5250
 
                        if (shouldSendSet) {
5251
 
                                switch (level) {
5252
 
                                case java.sql.Connection.TRANSACTION_NONE:
5253
 
                                        throw SQLError.createSQLException("Transaction isolation level "
5254
 
                                                        + "NONE not supported by MySQL", getExceptionInterceptor());
5255
 
 
5256
 
                                case java.sql.Connection.TRANSACTION_READ_COMMITTED:
5257
 
                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED";
5258
 
 
5259
 
                                        break;
5260
 
 
5261
 
                                case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
5262
 
                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
5263
 
 
5264
 
                                        break;
5265
 
 
5266
 
                                case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
5267
 
                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ";
5268
 
 
5269
 
                                        break;
5270
 
 
5271
 
                                case java.sql.Connection.TRANSACTION_SERIALIZABLE:
5272
 
                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE";
5273
 
 
5274
 
                                        break;
5275
 
 
5276
 
                                default:
5277
 
                                        throw SQLError.createSQLException("Unsupported transaction "
5278
 
                                                        + "isolation level '" + level + "'",
5279
 
                                                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
5280
 
                                }
5281
 
 
5282
 
                                execSQL(null, sql, -1, null,
5283
 
                                                DEFAULT_RESULT_SET_TYPE,
5284
 
                                                DEFAULT_RESULT_SET_CONCURRENCY,false,
5285
 
                                                this.database, null, false);
5286
 
 
5287
 
                                this.isolationLevel = level;
5288
 
                        }
5289
 
                } else {
5290
 
                        throw SQLError.createSQLException("Transaction Isolation Levels are "
5291
 
                                        + "not supported on MySQL versions older than 3.23.36.",
5292
 
                                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
 
5597
                                } else {
 
5598
                                        if (level != this.isolationLevel) {
 
5599
                                                shouldSendSet = true;
 
5600
                                        }
 
5601
                                }
 
5602
        
 
5603
                                if (getUseLocalSessionState()) {
 
5604
                                        shouldSendSet = this.isolationLevel != level;
 
5605
                                }
 
5606
        
 
5607
                                if (shouldSendSet) {
 
5608
                                        switch (level) {
 
5609
                                        case java.sql.Connection.TRANSACTION_NONE:
 
5610
                                                throw SQLError.createSQLException("Transaction isolation level "
 
5611
                                                                + "NONE not supported by MySQL", getExceptionInterceptor());
 
5612
        
 
5613
                                        case java.sql.Connection.TRANSACTION_READ_COMMITTED:
 
5614
                                                sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED";
 
5615
        
 
5616
                                                break;
 
5617
        
 
5618
                                        case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
 
5619
                                                sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
 
5620
        
 
5621
                                                break;
 
5622
        
 
5623
                                        case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
 
5624
                                                sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ";
 
5625
        
 
5626
                                                break;
 
5627
        
 
5628
                                        case java.sql.Connection.TRANSACTION_SERIALIZABLE:
 
5629
                                                sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE";
 
5630
        
 
5631
                                                break;
 
5632
        
 
5633
                                        default:
 
5634
                                                throw SQLError.createSQLException("Unsupported transaction "
 
5635
                                                                + "isolation level '" + level + "'",
 
5636
                                                                SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
 
5637
                                        }
 
5638
        
 
5639
                                        execSQL(null, sql, -1, null,
 
5640
                                                        DEFAULT_RESULT_SET_TYPE,
 
5641
                                                        DEFAULT_RESULT_SET_CONCURRENCY,false,
 
5642
                                                        this.database, null, false);
 
5643
        
 
5644
                                        this.isolationLevel = level;
 
5645
                                }
 
5646
                        } else {
 
5647
                                throw SQLError.createSQLException("Transaction Isolation Levels are "
 
5648
                                                + "not supported on MySQL versions older than 3.23.36.",
 
5649
                                                SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
 
5650
                        }
5293
5651
                }
5294
5652
        }
5295
5653
        
5302
5660
         * @throws SQLException
5303
5661
         *             if a database error occurs.
5304
5662
         */
5305
 
        public synchronized void setTypeMap(java.util.Map map) throws SQLException {
5306
 
                this.typeMap = map;
 
5663
        public void setTypeMap(java.util.Map<String,Class<?>> map) throws SQLException {
 
5664
                synchronized (getConnectionMutex()) {
 
5665
                        this.typeMap = map;
 
5666
                }
5307
5667
        }
5308
5668
        
5309
5669
        private void setupServerForTruncationChecks() throws SQLException {
5310
5670
                if (getJdbcCompliantTruncation()) {
5311
5671
                        if (versionMeetsMinimum(5, 0, 2)) {
5312
5672
                                String currentSqlMode = 
5313
 
                                        (String)this.serverVariables.get("sql_mode");
 
5673
                                        this.serverVariables.get("sql_mode");
5314
5674
                                
5315
5675
                                boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1;
5316
5676
                                
5412
5772
         *             if a database error occurs issuing the statement that sets
5413
5773
         *             the limit default.
5414
5774
         */
5415
 
        public synchronized void unsetMaxRows(Statement stmt) throws SQLException {
5416
 
                if (this.statementsUsingMaxRows != null) {
5417
 
                        Object found = this.statementsUsingMaxRows.remove(stmt);
5418
 
 
5419
 
                        if ((found != null)
5420
 
                                        && (this.statementsUsingMaxRows.size() == 0)) {
5421
 
                                execSQL(null, "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1,
5422
 
                                                null, DEFAULT_RESULT_SET_TYPE,
5423
 
                                                DEFAULT_RESULT_SET_CONCURRENCY, false, 
5424
 
                                                this.database, null, false);
5425
 
 
5426
 
                                this.maxRowsChanged = false;
 
5775
        public void unsetMaxRows(Statement stmt) throws SQLException {
 
5776
                synchronized (getConnectionMutex()) {
 
5777
                        if (this.statementsUsingMaxRows != null) {
 
5778
                                Object found = this.statementsUsingMaxRows.remove(stmt);
 
5779
        
 
5780
                                if ((found != null)
 
5781
                                                && (this.statementsUsingMaxRows.size() == 0)) {
 
5782
                                        execSQL(null, "SET SQL_SELECT_LIMIT=DEFAULT", -1,
 
5783
                                                        null, DEFAULT_RESULT_SET_TYPE,
 
5784
                                                        DEFAULT_RESULT_SET_CONCURRENCY, false, 
 
5785
                                                        this.database, null, false);
 
5786
        
 
5787
                                        this.maxRowsChanged = false;
 
5788
                                }
5427
5789
                        }
5428
5790
                }
5429
5791
        }
5430
5792
        
5431
 
        public synchronized boolean useAnsiQuotedIdentifiers() {
5432
 
                return this.useAnsiQuotes;
 
5793
        public boolean useAnsiQuotedIdentifiers() {
 
5794
                synchronized (getConnectionMutex()) {
 
5795
                        return this.useAnsiQuotes;
 
5796
                }
5433
5797
        }
5434
5798
        
5435
5799
        /**
5437
5801
         * 
5438
5802
         * @return DOCUMENT ME!
5439
5803
         */
5440
 
        public synchronized boolean useMaxRows() {
5441
 
                return this.maxRowsChanged;
 
5804
        public boolean useMaxRows() {
 
5805
                synchronized (getConnectionMutex()) {
 
5806
                        return this.maxRowsChanged;
 
5807
                }
5442
5808
        }
5443
5809
        
5444
5810
        public boolean versionMeetsMinimum(int major, int minor, int subminor)
5541
5907
                this.statementComment = comment;
5542
5908
        }
5543
5909
        
5544
 
        public synchronized void reportQueryTime(long millisOrNanos) {
5545
 
                this.queryTimeCount++;
5546
 
                this.queryTimeSum += millisOrNanos;
5547
 
                this.queryTimeSumSquares += (millisOrNanos * millisOrNanos);
5548
 
                this.queryTimeMean = ((this.queryTimeMean * (this.queryTimeCount - 1)) + millisOrNanos)
5549
 
                                / this.queryTimeCount;
 
5910
        public void reportQueryTime(long millisOrNanos) {
 
5911
                synchronized (getConnectionMutex()) {
 
5912
                        this.queryTimeCount++;
 
5913
                        this.queryTimeSum += millisOrNanos;
 
5914
                        this.queryTimeSumSquares += (millisOrNanos * millisOrNanos);
 
5915
                        this.queryTimeMean = ((this.queryTimeMean * (this.queryTimeCount - 1)) + millisOrNanos)
 
5916
                                        / this.queryTimeCount;
 
5917
                }
5550
5918
        }
5551
5919
        
5552
 
        public synchronized boolean isAbonormallyLongQuery(long millisOrNanos) {
5553
 
                if (this.queryTimeCount < 15) {
5554
 
                        return false; // need a minimum amount for this to make sense
 
5920
        public boolean isAbonormallyLongQuery(long millisOrNanos) {
 
5921
                synchronized (getConnectionMutex()) {
 
5922
                        if (this.queryTimeCount < 15) {
 
5923
                                return false; // need a minimum amount for this to make sense
 
5924
                        }
 
5925
                        
 
5926
                        double stddev = Math.sqrt((this.queryTimeSumSquares - ((this.queryTimeSum*this.queryTimeSum) / this.queryTimeCount)) / (this.queryTimeCount - 1));
 
5927
                        
 
5928
                        return millisOrNanos > (this.queryTimeMean + 5 * stddev);
5555
5929
                }
5556
 
                
5557
 
                double stddev = Math.sqrt((this.queryTimeSumSquares - ((this.queryTimeSum*this.queryTimeSum) / this.queryTimeCount)) / (this.queryTimeCount - 1));
5558
 
                
5559
 
                return millisOrNanos > (this.queryTimeMean + 5 * stddev);
5560
5930
        }
5561
5931
 
5562
5932
        public void initializeExtension(Extension ex) throws SQLException {
5563
5933
                ex.init(this, this.props);
5564
5934
        }
5565
5935
        
5566
 
        public synchronized void transactionBegun() throws SQLException {
5567
 
                if (this.connectionLifecycleInterceptors != null) {
5568
 
                        IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
5569
 
 
5570
 
                                void forEach(Object each) throws SQLException {
5571
 
                                        ((ConnectionLifecycleInterceptor)each).transactionBegun();
5572
 
                                }
5573
 
                        };
5574
 
                        
5575
 
                        iter.doForAll();
 
5936
        public void transactionBegun() throws SQLException {
 
5937
                synchronized (getConnectionMutex()) {
 
5938
                        if (this.connectionLifecycleInterceptors != null) {
 
5939
                                IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5940
        
 
5941
                                        void forEach(Extension each) throws SQLException {
 
5942
                                                ((ConnectionLifecycleInterceptor)each).transactionBegun();
 
5943
                                        }
 
5944
                                };
 
5945
                                
 
5946
                                iter.doForAll();
 
5947
                        }
5576
5948
                }
5577
5949
        }
5578
5950
        
5579
 
        public synchronized void transactionCompleted() throws SQLException {
5580
 
                if (this.connectionLifecycleInterceptors != null) {
5581
 
                        IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
5582
 
 
5583
 
                                void forEach(Object each) throws SQLException {
5584
 
                                        ((ConnectionLifecycleInterceptor)each).transactionCompleted();
5585
 
                                }
5586
 
                        };
5587
 
                        
5588
 
                        iter.doForAll();
 
5951
        public void transactionCompleted() throws SQLException {
 
5952
                synchronized (getConnectionMutex()) {
 
5953
                        if (this.connectionLifecycleInterceptors != null) {
 
5954
                                IterateBlock<Extension> iter = new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
 
5955
        
 
5956
                                        void forEach(Extension each) throws SQLException {
 
5957
                                                ((ConnectionLifecycleInterceptor)each).transactionCompleted();
 
5958
                                        }
 
5959
                                };
 
5960
                                
 
5961
                                iter.doForAll();
 
5962
                        }
5589
5963
                }
5590
5964
        }
5591
5965
        
5603
5977
                return requiresEscapingEncoder;
5604
5978
        }
5605
5979
        
5606
 
        public synchronized boolean isServerLocal() throws SQLException {
5607
 
                SocketFactory factory = getIO().socketFactory;
5608
 
                
5609
 
                if (factory instanceof SocketMetadata) {
5610
 
                        return ((SocketMetadata)factory).isLocallyConnected(this);
5611
 
                } else {
 
5980
        public boolean isServerLocal() throws SQLException {
 
5981
                synchronized (getConnectionMutex()) {
 
5982
                        SocketFactory factory = getIO().socketFactory;
 
5983
                        
 
5984
                        if (factory instanceof SocketMetadata) {
 
5985
                                return ((SocketMetadata)factory).isLocallyConnected(this);
 
5986
                        } 
5612
5987
                        getLog().logWarn(Messages.getString("Connection.NoMetadataOnSocketFactory"));
5613
 
                        
5614
5988
                        return false;
5615
5989
                }
5616
5990
        }
 
5991
        
 
5992
        // JDBC-4.1
 
5993
        // until we flip catalog/schema, this is a no-op
 
5994
        public void setSchema(String schema) throws SQLException {
 
5995
                synchronized (getConnectionMutex()) {
 
5996
                        checkClosed();
 
5997
                }
 
5998
        }
 
5999
        
 
6000
        // JDBC-4.1
 
6001
        public String getSchema() throws SQLException {
 
6002
                synchronized (getConnectionMutex()) {
 
6003
                        checkClosed();
 
6004
                        
 
6005
                        return null;
 
6006
                }
 
6007
        }
 
6008
        
 
6009
        /**
 
6010
     * Terminates an open connection.  Calling <code>abort</code> results in:
 
6011
     * <ul>
 
6012
     * <li>The connection marked as closed
 
6013
     * <li>Closes any physical connection to the database
 
6014
     * <li>Releases resources used by the connection
 
6015
     * <li>Insures that any thread that is currently accessing the connection
 
6016
     * will either progress to completion or throw an <code>SQLException</code>.
 
6017
     * </ul>
 
6018
     * <p>
 
6019
     * Calling <code>abort</code> marks the connection closed and releases any
 
6020
     * resources. Calling <code>abort</code> on a closed connection is a
 
6021
     * no-op.
 
6022
     * <p>
 
6023
     * It is possible that the aborting and releasing of the resources that are
 
6024
     * held by the connection can take an extended period of time.  When the
 
6025
     * <code>abort</code> method returns, the connection will have been marked as
 
6026
     * closed and the <code>Executor</code> that was passed as a parameter to abort
 
6027
     * may still be executing tasks to release resources.
 
6028
     * <p>
 
6029
     * This method checks to see that there is an <code>SQLPermission</code>
 
6030
     * object before allowing the method to proceed.  If a
 
6031
     * <code>SecurityManager</code> exists and its
 
6032
     * <code>checkPermission</code> method denies calling <code>abort</code>,
 
6033
     * this method throws a
 
6034
     * <code>java.lang.SecurityException</code>.
 
6035
     * @param executor  The <code>Executor</code>  implementation which will
 
6036
     * be used by <code>abort</code>.
 
6037
     * @throws java.sql.SQLException if a database access error occurs or
 
6038
     * the {@code executor} is {@code null},
 
6039
     * @throws java.lang.SecurityException if a security manager exists and its
 
6040
     *    <code>checkPermission</code> method denies calling <code>abort</code>
 
6041
     * @see SecurityManager#checkPermission
 
6042
     * @see Executor
 
6043
     * @since 1.7
 
6044
     */
 
6045
        public void abort(Executor executor) throws SQLException {
 
6046
                SecurityManager sec = System.getSecurityManager();
 
6047
                
 
6048
                if (sec != null) {
 
6049
                    sec.checkPermission(ABORT_PERM);
 
6050
                }
 
6051
                
 
6052
                if (executor == null) {
 
6053
                        throw SQLError.createSQLException("Executor can not be null", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
6054
                }
 
6055
                
 
6056
                executor.execute(new Runnable() {
 
6057
 
 
6058
                        public void run() {
 
6059
                                try {
 
6060
                                        abortInternal();
 
6061
                                } catch (SQLException e) {
 
6062
                                        throw new RuntimeException(e);
 
6063
                                }
 
6064
                        }
 
6065
                });
 
6066
        }
 
6067
        
 
6068
        // JDBC-4.1
 
6069
        public void setNetworkTimeout(Executor executor, final int milliseconds) throws SQLException {
 
6070
                synchronized (getConnectionMutex()) {
 
6071
                        SecurityManager sec = System.getSecurityManager();
 
6072
                        
 
6073
                        if (sec != null) {
 
6074
                            sec.checkPermission(SET_NETWORK_TIMEOUT_PERM);
 
6075
                        }
 
6076
                        
 
6077
                        if (executor == null) {
 
6078
                                throw SQLError.createSQLException("Executor can not be null", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
6079
                        }
 
6080
                        
 
6081
                        checkClosed();
 
6082
                        final MysqlIO mysqlIo = this.io;
 
6083
                        
 
6084
                        executor.execute(new Runnable() {
 
6085
        
 
6086
                                public void run() {
 
6087
                                        setSocketTimeout(milliseconds); // for re-connects
 
6088
                                        try {
 
6089
                                                mysqlIo.setSocketTimeout(milliseconds);
 
6090
                                        } catch (SQLException e) {
 
6091
                                                throw new RuntimeException(e);
 
6092
                                        }
 
6093
                                }});
 
6094
                }
 
6095
        }
 
6096
        
 
6097
        // JDBC-4.1
 
6098
        public int getNetworkTimeout() throws SQLException {
 
6099
                synchronized (getConnectionMutex()) {
 
6100
                        checkClosed();
 
6101
                        return getSocketTimeout();
 
6102
                }
 
6103
        }
 
6104
 
 
6105
    public java.sql.Clob createClob() throws SQLException {
 
6106
        throw new UnsupportedOperationException();
 
6107
    }
 
6108
 
 
6109
    public java.sql.Blob createBlob() throws SQLException {
 
6110
        throw new UnsupportedOperationException();
 
6111
    }
 
6112
 
 
6113
    public java.sql.NClob createNClob() throws SQLException {
 
6114
        throw new UnsupportedOperationException();
 
6115
    }
 
6116
 
 
6117
    public java.sql.SQLXML createSQLXML() throws SQLException {
 
6118
        throw new UnsupportedOperationException();
 
6119
    }
 
6120
 
 
6121
    public boolean isValid(int timeout) throws SQLException {
 
6122
        throw new UnsupportedOperationException();
 
6123
    }
 
6124
 
 
6125
    public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException {
 
6126
        throw new UnsupportedOperationException();
 
6127
    }
 
6128
 
 
6129
    public void setClientInfo(Properties properties) throws java.sql.SQLClientInfoException {
 
6130
        throw new UnsupportedOperationException();
 
6131
    }
 
6132
 
 
6133
    public String getClientInfo(String name) throws SQLException {
 
6134
        throw new UnsupportedOperationException();
 
6135
    }
 
6136
 
 
6137
    public Properties getClientInfo() throws SQLException {
 
6138
        throw new UnsupportedOperationException();
 
6139
    }
 
6140
 
 
6141
    public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException {
 
6142
        throw new UnsupportedOperationException();
 
6143
    }
 
6144
 
 
6145
    public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException {
 
6146
        throw new UnsupportedOperationException();
 
6147
    }
 
6148
 
 
6149
    public <T> T unwrap(Class<T> iface) throws SQLException {
 
6150
        throw new UnsupportedOperationException();
 
6151
    }
 
6152
 
 
6153
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
 
6154
        throw new UnsupportedOperationException();
 
6155
    }
5617
6156
}