~pbms-core/pbms/async_read

« back to all changes in this revision

Viewing changes to mybs/java/src/testsuite/regression/ConnectionRegressionTest.java

  • Committer: paul-mccullagh
  • Date: 2008-03-26 11:35:17 UTC
  • Revision ID: paul-mccullagh-afb1610c21464a577ae428d72fc725eb986c05a5
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (C) 2002-2007 MySQL AB
 
3
 
 
4
 This program is free software; you can redistribute it and/or modify
 
5
 it under the terms of version 2 of the GNU General Public License as 
 
6
 published by the Free Software Foundation.
 
7
 
 
8
 There are special exceptions to the terms and conditions of the GPL 
 
9
 as it is applied to this software. View the full text of the 
 
10
 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
 
11
 software distribution.
 
12
 
 
13
 This program is distributed in the hope that it will be useful,
 
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 GNU General Public License for more details.
 
17
 
 
18
 You should have received a copy of the GNU General Public License
 
19
 along with this program; if not, write to the Free Software
 
20
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
 
 
22
 
 
23
 
 
24
 */
 
25
package testsuite.regression;
 
26
 
 
27
import java.io.ByteArrayOutputStream;
 
28
import java.io.PrintStream;
 
29
import java.lang.reflect.Field;
 
30
import java.lang.reflect.InvocationTargetException;
 
31
import java.lang.reflect.Method;
 
32
import java.sql.Connection;
 
33
import java.sql.DriverManager;
 
34
import java.sql.DriverPropertyInfo;
 
35
import java.sql.ResultSet;
 
36
import java.sql.SQLException;
 
37
import java.sql.Statement;
 
38
import java.util.HashMap;
 
39
import java.util.Iterator;
 
40
import java.util.Locale;
 
41
import java.util.Map;
 
42
import java.util.Properties;
 
43
import java.util.StringTokenizer;
 
44
 
 
45
import testsuite.BaseTestCase;
 
46
 
 
47
import com.mysql.jdbc.Driver;
 
48
import com.mysql.jdbc.NonRegisteringDriver;
 
49
import com.mysql.jdbc.ReplicationConnection;
 
50
import com.mysql.jdbc.ReplicationDriver;
 
51
import com.mysql.jdbc.log.StandardLogger;
 
52
 
 
53
/**
 
54
 * Regression tests for Connections
 
55
 * 
 
56
 * @author Mark Matthews
 
57
 * @version $Id: ConnectionRegressionTest.java,v 1.1.2.1 2005/05/13 18:58:38
 
58
 *          mmatthews Exp $
 
59
 */
 
60
public class ConnectionRegressionTest extends BaseTestCase {
 
61
        /**
 
62
         * DOCUMENT ME!
 
63
         * 
 
64
         * @param name
 
65
         *            the name of the testcase
 
66
         */
 
67
        public ConnectionRegressionTest(String name) {
 
68
                super(name);
 
69
        }
 
70
 
 
71
        /**
 
72
         * Runs all test cases in this test suite
 
73
         * 
 
74
         * @param args
 
75
         */
 
76
        public static void main(String[] args) {
 
77
                junit.textui.TestRunner.run(ConnectionRegressionTest.class);
 
78
        }
 
79
 
 
80
        /**
 
81
         * DOCUMENT ME!
 
82
         * 
 
83
         * @throws Exception
 
84
         *             ...
 
85
         */
 
86
        public void testBug1914() throws Exception {
 
87
                System.out.println(this.conn
 
88
                                .nativeSQL("{fn convert(foo(a,b,c), BIGINT)}"));
 
89
                System.out.println(this.conn
 
90
                                .nativeSQL("{fn convert(foo(a,b,c), BINARY)}"));
 
91
                System.out
 
92
                                .println(this.conn.nativeSQL("{fn convert(foo(a,b,c), BIT)}"));
 
93
                System.out.println(this.conn
 
94
                                .nativeSQL("{fn convert(foo(a,b,c), CHAR)}"));
 
95
                System.out.println(this.conn
 
96
                                .nativeSQL("{fn convert(foo(a,b,c), DATE)}"));
 
97
                System.out.println(this.conn
 
98
                                .nativeSQL("{fn convert(foo(a,b,c), DECIMAL)}"));
 
99
                System.out.println(this.conn
 
100
                                .nativeSQL("{fn convert(foo(a,b,c), DOUBLE)}"));
 
101
                System.out.println(this.conn
 
102
                                .nativeSQL("{fn convert(foo(a,b,c), FLOAT)}"));
 
103
                System.out.println(this.conn
 
104
                                .nativeSQL("{fn convert(foo(a,b,c), INTEGER)}"));
 
105
                System.out.println(this.conn
 
106
                                .nativeSQL("{fn convert(foo(a,b,c), LONGVARBINARY)}"));
 
107
                System.out.println(this.conn
 
108
                                .nativeSQL("{fn convert(foo(a,b,c), LONGVARCHAR)}"));
 
109
                System.out.println(this.conn
 
110
                                .nativeSQL("{fn convert(foo(a,b,c), TIME)}"));
 
111
                System.out.println(this.conn
 
112
                                .nativeSQL("{fn convert(foo(a,b,c), TIMESTAMP)}"));
 
113
                System.out.println(this.conn
 
114
                                .nativeSQL("{fn convert(foo(a,b,c), TINYINT)}"));
 
115
                System.out.println(this.conn
 
116
                                .nativeSQL("{fn convert(foo(a,b,c), VARBINARY)}"));
 
117
                System.out.println(this.conn
 
118
                                .nativeSQL("{fn convert(foo(a,b,c), VARCHAR)}"));
 
119
        }
 
120
 
 
121
        /**
 
122
         * Tests fix for BUG#3554 - Not specifying database in URL causes
 
123
         * MalformedURL exception.
 
124
         * 
 
125
         * @throws Exception
 
126
         *             if an error ocurrs.
 
127
         */
 
128
        public void testBug3554() throws Exception {
 
129
                try {
 
130
                        new NonRegisteringDriver().connect(
 
131
                                        "jdbc:mysql://localhost:3306/?user=root&password=root",
 
132
                                        new Properties());
 
133
                } catch (SQLException sqlEx) {
 
134
                        assertTrue(sqlEx.getMessage().indexOf("Malformed") == -1);
 
135
                }
 
136
        }
 
137
 
 
138
        /**
 
139
         * DOCUMENT ME!
 
140
         * 
 
141
         * @throws Exception
 
142
         *             ...
 
143
         */
 
144
        public void testBug3790() throws Exception {
 
145
                String field2OldValue = "foo";
 
146
                String field2NewValue = "bar";
 
147
                int field1OldValue = 1;
 
148
 
 
149
                Connection conn1 = null;
 
150
                Connection conn2 = null;
 
151
                Statement stmt1 = null;
 
152
                Statement stmt2 = null;
 
153
                ResultSet rs2 = null;
 
154
 
 
155
                Properties props = new Properties();
 
156
 
 
157
                try {
 
158
                        this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3790");
 
159
                        this.stmt
 
160
                                        .executeUpdate("CREATE TABLE testBug3790 (field1 INT NOT NULL PRIMARY KEY, field2 VARCHAR(32)) TYPE=InnoDB");
 
161
                        this.stmt.executeUpdate("INSERT INTO testBug3790 VALUES ("
 
162
                                        + field1OldValue + ", '" + field2OldValue + "')");
 
163
 
 
164
                        conn1 = getConnectionWithProps(props); // creates a new connection
 
165
                        conn2 = getConnectionWithProps(props); // creates another new
 
166
                        // connection
 
167
                        conn1.setAutoCommit(false);
 
168
                        conn2.setAutoCommit(false);
 
169
 
 
170
                        stmt1 = conn1.createStatement();
 
171
                        stmt1.executeUpdate("UPDATE testBug3790 SET field2 = '"
 
172
                                        + field2NewValue + "' WHERE field1=" + field1OldValue);
 
173
                        conn1.commit();
 
174
 
 
175
                        stmt2 = conn2.createStatement();
 
176
 
 
177
                        rs2 = stmt2.executeQuery("SELECT field1, field2 FROM testBug3790");
 
178
 
 
179
                        assertTrue(rs2.next());
 
180
                        assertTrue(rs2.getInt(1) == field1OldValue);
 
181
                        assertTrue(rs2.getString(2).equals(field2NewValue));
 
182
                } finally {
 
183
                        this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3790");
 
184
 
 
185
                        if (rs2 != null) {
 
186
                                rs2.close();
 
187
                        }
 
188
 
 
189
                        if (stmt2 != null) {
 
190
                                stmt2.close();
 
191
                        }
 
192
 
 
193
                        if (stmt1 != null) {
 
194
                                stmt1.close();
 
195
                        }
 
196
 
 
197
                        if (conn1 != null) {
 
198
                                conn1.close();
 
199
                        }
 
200
 
 
201
                        if (conn2 != null) {
 
202
                                conn2.close();
 
203
                        }
 
204
                }
 
205
        }
 
206
 
 
207
        /**
 
208
         * Tests if the driver configures character sets correctly for 4.1.x
 
209
         * servers. Requires that the 'admin connection' is configured, as this test
 
210
         * needs to create/drop databases.
 
211
         * 
 
212
         * @throws Exception
 
213
         *             if an error occurs
 
214
         */
 
215
        public void testCollation41() throws Exception {
 
216
                if (versionMeetsMinimum(4, 1) && isAdminConnectionConfigured()) {
 
217
                        Map charsetsAndCollations = getCharacterSetsAndCollations();
 
218
                        charsetsAndCollations.remove("latin7"); // Maps to multiple Java
 
219
                        // charsets
 
220
                        charsetsAndCollations.remove("ucs2"); // can't be used as a
 
221
                        // connection charset
 
222
 
 
223
                        Iterator charsets = charsetsAndCollations.keySet().iterator();
 
224
 
 
225
                        while (charsets.hasNext()) {
 
226
                                Connection charsetConn = null;
 
227
                                Statement charsetStmt = null;
 
228
 
 
229
                                try {
 
230
                                        String charsetName = charsets.next().toString();
 
231
                                        String collationName = charsetsAndCollations.get(
 
232
                                                        charsetName).toString();
 
233
                                        Properties props = new Properties();
 
234
                                        props.put("characterEncoding", charsetName);
 
235
 
 
236
                                        System.out.println("Testing character set " + charsetName);
 
237
 
 
238
                                        charsetConn = getAdminConnectionWithProps(props);
 
239
 
 
240
                                        charsetStmt = charsetConn.createStatement();
 
241
 
 
242
                                        charsetStmt
 
243
                                                        .executeUpdate("DROP DATABASE IF EXISTS testCollation41");
 
244
                                        charsetStmt
 
245
                                                        .executeUpdate("DROP TABLE IF EXISTS testCollation41");
 
246
 
 
247
                                        charsetStmt
 
248
                                                        .executeUpdate("CREATE DATABASE testCollation41 DEFAULT CHARACTER SET "
 
249
                                                                        + charsetName);
 
250
                                        charsetConn.setCatalog("testCollation41");
 
251
 
 
252
                                        // We've switched catalogs, so we need to recreate the
 
253
                                        // statement to pick this up...
 
254
                                        charsetStmt = charsetConn.createStatement();
 
255
 
 
256
                                        StringBuffer createTableCommand = new StringBuffer(
 
257
                                                        "CREATE TABLE testCollation41"
 
258
                                                                        + "(field1 VARCHAR(255), field2 INT)");
 
259
 
 
260
                                        charsetStmt.executeUpdate(createTableCommand.toString());
 
261
 
 
262
                                        charsetStmt
 
263
                                                        .executeUpdate("INSERT INTO testCollation41 VALUES ('abc', 0)");
 
264
 
 
265
                                        int updateCount = charsetStmt
 
266
                                                        .executeUpdate("UPDATE testCollation41 SET field2=1 WHERE field1='abc'");
 
267
                                        assertTrue(updateCount == 1);
 
268
                                } finally {
 
269
                                        if (charsetStmt != null) {
 
270
                                                charsetStmt
 
271
                                                                .executeUpdate("DROP TABLE IF EXISTS testCollation41");
 
272
                                                charsetStmt
 
273
                                                                .executeUpdate("DROP DATABASE IF EXISTS testCollation41");
 
274
                                                charsetStmt.close();
 
275
                                        }
 
276
 
 
277
                                        if (charsetConn != null) {
 
278
                                                charsetConn.close();
 
279
                                        }
 
280
                                }
 
281
                        }
 
282
                }
 
283
        }
 
284
 
 
285
        /**
 
286
         * Tests setReadOnly() being reset during failover
 
287
         * 
 
288
         * @throws Exception
 
289
         *             if an error occurs.
 
290
         */
 
291
        public void testSetReadOnly() throws Exception {
 
292
                Properties props = new Properties();
 
293
                props.put("autoReconnect", "true");
 
294
 
 
295
                String sepChar = "?";
 
296
 
 
297
                if (BaseTestCase.dbUrl.indexOf("?") != -1) {
 
298
                        sepChar = "&";
 
299
                }
 
300
 
 
301
                Connection reconnectableConn = DriverManager.getConnection(
 
302
                                BaseTestCase.dbUrl + sepChar + "autoReconnect=true", props);
 
303
 
 
304
                this.rs = reconnectableConn.createStatement().executeQuery(
 
305
                                "SELECT CONNECTION_ID()");
 
306
                this.rs.next();
 
307
 
 
308
                String connectionId = this.rs.getString(1);
 
309
 
 
310
                reconnectableConn.setReadOnly(true);
 
311
 
 
312
                boolean isReadOnly = reconnectableConn.isReadOnly();
 
313
 
 
314
                Connection killConn = getConnectionWithProps(null);
 
315
 
 
316
                killConn.createStatement().executeUpdate("KILL " + connectionId);
 
317
                Thread.sleep(2000);
 
318
 
 
319
                SQLException caughtException = null;
 
320
 
 
321
                int numLoops = 8;
 
322
 
 
323
                while (caughtException == null && numLoops > 0) {
 
324
                        numLoops--;
 
325
 
 
326
                        try {
 
327
                                reconnectableConn.createStatement().executeQuery("SELECT 1");
 
328
                        } catch (SQLException sqlEx) {
 
329
                                caughtException = sqlEx;
 
330
                        }
 
331
                }
 
332
 
 
333
                System.out
 
334
                                .println("Executing statement on reconnectable connection...");
 
335
 
 
336
                this.rs = reconnectableConn.createStatement().executeQuery(
 
337
                                "SELECT CONNECTION_ID()");
 
338
                this.rs.next();
 
339
                assertTrue("Connection is not a reconnected-connection", !connectionId
 
340
                                .equals(this.rs.getString(1)));
 
341
 
 
342
                try {
 
343
                        reconnectableConn.createStatement().executeQuery("SELECT 1");
 
344
                } catch (SQLException sqlEx) {
 
345
                        ; // ignore
 
346
                }
 
347
 
 
348
                reconnectableConn.createStatement().executeQuery("SELECT 1");
 
349
 
 
350
                assertTrue(reconnectableConn.isReadOnly() == isReadOnly);
 
351
        }
 
352
 
 
353
        private Map getCharacterSetsAndCollations() throws Exception {
 
354
                Map charsetsToLoad = new HashMap();
 
355
 
 
356
                try {
 
357
                        this.rs = this.stmt.executeQuery("SHOW character set");
 
358
 
 
359
                        while (this.rs.next()) {
 
360
                                charsetsToLoad.put(this.rs.getString("Charset"), this.rs
 
361
                                                .getString("Default collation"));
 
362
                        }
 
363
 
 
364
                        //
 
365
                        // These don't have mappings in Java...
 
366
                        //
 
367
                        charsetsToLoad.remove("swe7");
 
368
                        charsetsToLoad.remove("hp8");
 
369
                        charsetsToLoad.remove("dec8");
 
370
                        charsetsToLoad.remove("koi8u");
 
371
                        charsetsToLoad.remove("keybcs2");
 
372
                        charsetsToLoad.remove("geostd8");
 
373
                        charsetsToLoad.remove("armscii8");
 
374
                } finally {
 
375
                        if (this.rs != null) {
 
376
                                this.rs.close();
 
377
                        }
 
378
                }
 
379
 
 
380
                return charsetsToLoad;
 
381
        }
 
382
 
 
383
        /**
 
384
         * Tests fix for BUG#4334, port #'s not being picked up for
 
385
         * failover/autoreconnect.
 
386
         * 
 
387
         * @throws Exception
 
388
         *             if an error occurs.
 
389
         */
 
390
        public void testBug4334() throws Exception {
 
391
                if (isAdminConnectionConfigured()) {
 
392
                        Connection adminConnection = null;
 
393
 
 
394
                        try {
 
395
                                adminConnection = getAdminConnection();
 
396
 
 
397
                                int bogusPortNumber = 65534;
 
398
 
 
399
                                NonRegisteringDriver driver = new NonRegisteringDriver();
 
400
 
 
401
                                Properties oldProps = driver.parseURL(BaseTestCase.dbUrl, null);
 
402
 
 
403
                                String host = driver.host(oldProps);
 
404
                                int port = driver.port(oldProps);
 
405
                                String database = oldProps
 
406
                                                .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);
 
407
                                String user = oldProps
 
408
                                                .getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
 
409
                                String password = oldProps
 
410
                                                .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);
 
411
 
 
412
                                StringBuffer newUrlToTestPortNum = new StringBuffer(
 
413
                                                "jdbc:mysql://");
 
414
 
 
415
                                if (host != null) {
 
416
                                        newUrlToTestPortNum.append(host);
 
417
                                }
 
418
 
 
419
                                newUrlToTestPortNum.append(":").append(port);
 
420
                                newUrlToTestPortNum.append(",");
 
421
 
 
422
                                if (host != null) {
 
423
                                        newUrlToTestPortNum.append(host);
 
424
                                }
 
425
 
 
426
                                newUrlToTestPortNum.append(":").append(bogusPortNumber);
 
427
                                newUrlToTestPortNum.append("/");
 
428
 
 
429
                                if (database != null) {
 
430
                                        newUrlToTestPortNum.append(database);
 
431
                                }
 
432
 
 
433
                                if ((user != null) || (password != null)) {
 
434
                                        newUrlToTestPortNum.append("?");
 
435
 
 
436
                                        if (user != null) {
 
437
                                                newUrlToTestPortNum.append("user=").append(user);
 
438
 
 
439
                                                if (password != null) {
 
440
                                                        newUrlToTestPortNum.append("&");
 
441
                                                }
 
442
                                        }
 
443
 
 
444
                                        if (password != null) {
 
445
                                                newUrlToTestPortNum.append("password=")
 
446
                                                                .append(password);
 
447
                                        }
 
448
                                }
 
449
 
 
450
                                Properties autoReconnectProps = new Properties();
 
451
                                autoReconnectProps.put("autoReconnect", "true");
 
452
 
 
453
                                System.out.println(newUrlToTestPortNum);
 
454
 
 
455
                                //
 
456
                                // First test that port #'s are being correctly picked up
 
457
                                //
 
458
                                // We do this by looking at the error message that is returned
 
459
                                //
 
460
                                Connection portNumConn = DriverManager.getConnection(
 
461
                                                newUrlToTestPortNum.toString(), autoReconnectProps);
 
462
                                Statement portNumStmt = portNumConn.createStatement();
 
463
                                this.rs = portNumStmt.executeQuery("SELECT connection_id()");
 
464
                                this.rs.next();
 
465
 
 
466
                                killConnection(adminConnection, this.rs.getString(1));
 
467
 
 
468
                                try {
 
469
                                        portNumStmt.executeQuery("SELECT connection_id()");
 
470
                                } catch (SQLException sqlEx) {
 
471
                                        // we expect this one
 
472
                                }
 
473
 
 
474
                                try {
 
475
                                        portNumStmt.executeQuery("SELECT connection_id()");
 
476
                                } catch (SQLException sqlEx) {
 
477
                                        assertTrue(sqlEx.getMessage().toLowerCase().indexOf(
 
478
                                                        "connection refused") != -1);
 
479
                                }
 
480
 
 
481
                                //
 
482
                                // Now make sure failover works
 
483
                                //
 
484
                                StringBuffer newUrlToTestFailover = new StringBuffer(
 
485
                                                "jdbc:mysql://");
 
486
 
 
487
                                if (host != null) {
 
488
                                        newUrlToTestFailover.append(host);
 
489
                                }
 
490
 
 
491
                                newUrlToTestFailover.append(":").append(port);
 
492
                                newUrlToTestFailover.append(",");
 
493
 
 
494
                                if (host != null) {
 
495
                                        newUrlToTestFailover.append(host);
 
496
                                }
 
497
 
 
498
                                newUrlToTestFailover.append(":").append(bogusPortNumber);
 
499
                                newUrlToTestFailover.append("/");
 
500
 
 
501
                                if (database != null) {
 
502
                                        newUrlToTestFailover.append(database);
 
503
                                }
 
504
 
 
505
                                if ((user != null) || (password != null)) {
 
506
                                        newUrlToTestFailover.append("?");
 
507
 
 
508
                                        if (user != null) {
 
509
                                                newUrlToTestFailover.append("user=").append(user);
 
510
 
 
511
                                                if (password != null) {
 
512
                                                        newUrlToTestFailover.append("&");
 
513
                                                }
 
514
                                        }
 
515
 
 
516
                                        if (password != null) {
 
517
                                                newUrlToTestFailover.append("password=").append(
 
518
                                                                password);
 
519
                                        }
 
520
                                }
 
521
 
 
522
                                Connection failoverConn = DriverManager.getConnection(
 
523
                                                newUrlToTestFailover.toString(), autoReconnectProps);
 
524
                                Statement failoverStmt = portNumConn.createStatement();
 
525
                                this.rs = failoverStmt.executeQuery("SELECT connection_id()");
 
526
                                this.rs.next();
 
527
 
 
528
                                killConnection(adminConnection, this.rs.getString(1));
 
529
 
 
530
                                try {
 
531
                                        failoverStmt.executeQuery("SELECT connection_id()");
 
532
                                } catch (SQLException sqlEx) {
 
533
                                        // we expect this one
 
534
                                }
 
535
 
 
536
                                failoverStmt.executeQuery("SELECT connection_id()");
 
537
                        } finally {
 
538
                                if (adminConnection != null) {
 
539
                                        adminConnection.close();
 
540
                                }
 
541
                        }
 
542
                }
 
543
        }
 
544
 
 
545
        private static void killConnection(Connection adminConn, String threadId)
 
546
                        throws SQLException {
 
547
                adminConn.createStatement().execute("KILL " + threadId);
 
548
        }
 
549
 
 
550
        /**
 
551
         * Tests fix for BUG#6966, connections starting up failed-over (due to down
 
552
         * master) never retry master.
 
553
         * 
 
554
         * @throws Exception
 
555
         *             if the test fails...Note, test is timing-dependent, but
 
556
         *             should work in most cases.
 
557
         */
 
558
        public void testBug6966() throws Exception {
 
559
                Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
 
560
                props.setProperty("autoReconnect", "true");
 
561
 
 
562
                // Re-build the connection information
 
563
                int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
 
564
                int lastIndexOfHost = BaseTestCase.dbUrl.indexOf("/", firstIndexOfHost);
 
565
 
 
566
                String hostPortPair = BaseTestCase.dbUrl.substring(firstIndexOfHost,
 
567
                                lastIndexOfHost);
 
568
 
 
569
                StringTokenizer st = new StringTokenizer(hostPortPair, ":");
 
570
 
 
571
                String host = null;
 
572
                String port = null;
 
573
 
 
574
                if (st.hasMoreTokens()) {
 
575
                        String possibleHostOrPort = st.nextToken();
 
576
 
 
577
                        if (Character.isDigit(possibleHostOrPort.charAt(0)) && 
 
578
                                        (possibleHostOrPort.indexOf(".") == -1 /* IPV4 */)  &&
 
579
                                        (possibleHostOrPort.indexOf("::") == -1 /* IPV6 */)) {
 
580
                                port = possibleHostOrPort;
 
581
                                host = "localhost";
 
582
                        } else {
 
583
                                host = possibleHostOrPort;
 
584
                        }
 
585
                }
 
586
 
 
587
                if (st.hasMoreTokens()) {
 
588
                        port = st.nextToken();
 
589
                }
 
590
 
 
591
                if (host == null) {
 
592
                        host = "";
 
593
                }
 
594
 
 
595
                if (port == null) {
 
596
                        port = "3306";
 
597
                }
 
598
 
 
599
                StringBuffer newHostBuf = new StringBuffer();
 
600
                newHostBuf.append(host);
 
601
                newHostBuf.append(":65532"); // make sure the master fails
 
602
                newHostBuf.append(",");
 
603
                newHostBuf.append(host);
 
604
                if (port != null) {
 
605
                        newHostBuf.append(":");
 
606
                        newHostBuf.append(port);
 
607
                }
 
608
 
 
609
                props.remove("PORT");
 
610
 
 
611
                props.setProperty("HOST", newHostBuf.toString());
 
612
                props.setProperty("queriesBeforeRetryMaster", "50");
 
613
                props.setProperty("maxReconnects", "1");
 
614
 
 
615
                Connection failoverConnection = null;
 
616
 
 
617
                try {
 
618
                        failoverConnection = getConnectionWithProps("jdbc:mysql://"
 
619
                                        + newHostBuf.toString() + "/", props);
 
620
                        failoverConnection.setAutoCommit(false);
 
621
 
 
622
                        String originalConnectionId = getSingleIndexedValueWithQuery(
 
623
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
624
                        
 
625
                        for (int i = 0; i < 49; i++) {
 
626
                                failoverConnection.createStatement().executeQuery("SELECT 1");
 
627
                        }
 
628
 
 
629
                        ((com.mysql.jdbc.Connection)failoverConnection).clearHasTriedMaster();
 
630
                        
 
631
                        failoverConnection.setAutoCommit(true);
 
632
 
 
633
                        String newConnectionId = getSingleIndexedValueWithQuery(
 
634
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
635
                        
 
636
                        assertTrue(((com.mysql.jdbc.Connection)failoverConnection).hasTriedMaster());
 
637
                        
 
638
                        assertTrue(!newConnectionId.equals(originalConnectionId));
 
639
 
 
640
                        failoverConnection.createStatement().executeQuery("SELECT 1");
 
641
                } finally {
 
642
                        if (failoverConnection != null) {
 
643
                                failoverConnection.close();
 
644
                        }
 
645
                }
 
646
        }
 
647
 
 
648
        /**
 
649
         * Test fix for BUG#7952 -- Infinite recursion when 'falling back' to master
 
650
         * in failover configuration.
 
651
         * 
 
652
         * @throws Exception
 
653
         *             if the tests fails.
 
654
         */
 
655
        public void testBug7952() throws Exception {
 
656
                Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
 
657
                props.setProperty("autoReconnect", "true");
 
658
 
 
659
                // Re-build the connection information
 
660
                int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
 
661
                int lastIndexOfHost = BaseTestCase.dbUrl.indexOf("/", firstIndexOfHost);
 
662
 
 
663
                String hostPortPair = BaseTestCase.dbUrl.substring(firstIndexOfHost,
 
664
                                lastIndexOfHost);
 
665
 
 
666
                StringTokenizer st = new StringTokenizer(hostPortPair, ":");
 
667
 
 
668
                String host = null;
 
669
                String port = null;
 
670
 
 
671
                if (st.hasMoreTokens()) {
 
672
                        String possibleHostOrPort = st.nextToken();
 
673
 
 
674
                        if (possibleHostOrPort.indexOf(".") == -1
 
675
                                        && Character.isDigit(possibleHostOrPort.charAt(0))) {
 
676
                                port = possibleHostOrPort;
 
677
                                host = "localhost";
 
678
                        } else {
 
679
                                host = possibleHostOrPort;
 
680
                        }
 
681
                }
 
682
 
 
683
                if (st.hasMoreTokens()) {
 
684
                        port = st.nextToken();
 
685
                }
 
686
 
 
687
                if (host == null) {
 
688
                        host = "";
 
689
                }
 
690
 
 
691
                if (port == null) {
 
692
                        port = "3306";
 
693
                }
 
694
 
 
695
                StringBuffer newHostBuf = new StringBuffer();
 
696
                newHostBuf.append(host);
 
697
                newHostBuf.append(":");
 
698
                newHostBuf.append(port);
 
699
                newHostBuf.append(",");
 
700
                newHostBuf.append(host);
 
701
                if (port != null) {
 
702
                        newHostBuf.append(":");
 
703
                        newHostBuf.append(port);
 
704
                }
 
705
 
 
706
                props.remove("PORT");
 
707
 
 
708
                props.setProperty("HOST", newHostBuf.toString());
 
709
                props.setProperty("queriesBeforeRetryMaster", "10");
 
710
                props.setProperty("maxReconnects", "1");
 
711
 
 
712
                Connection failoverConnection = null;
 
713
                Connection killerConnection = getConnectionWithProps(null);
 
714
 
 
715
                try {
 
716
                        failoverConnection = getConnectionWithProps("jdbc:mysql://"
 
717
                                        + newHostBuf + "/", props);
 
718
                        ((com.mysql.jdbc.Connection) failoverConnection)
 
719
                                        .setPreferSlaveDuringFailover(true);
 
720
                        failoverConnection.setAutoCommit(false);
 
721
 
 
722
                        String failoverConnectionId = getSingleIndexedValueWithQuery(
 
723
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
724
 
 
725
                        System.out.println("Connection id: " + failoverConnectionId);
 
726
 
 
727
                        killConnection(killerConnection, failoverConnectionId);
 
728
 
 
729
                        Thread.sleep(3000); // This can take some time....
 
730
 
 
731
                        try {
 
732
                                failoverConnection.createStatement().executeQuery("SELECT 1");
 
733
                        } catch (SQLException sqlEx) {
 
734
                                assertTrue("08S01".equals(sqlEx.getSQLState()));
 
735
                        }
 
736
 
 
737
                        ((com.mysql.jdbc.Connection) failoverConnection)
 
738
                                        .setPreferSlaveDuringFailover(false);
 
739
                        ((com.mysql.jdbc.Connection) failoverConnection)
 
740
                                        .setFailedOver(true);
 
741
 
 
742
                        failoverConnection.setAutoCommit(true);
 
743
 
 
744
                        String failedConnectionId = getSingleIndexedValueWithQuery(
 
745
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
746
                        System.out.println("Failed over connection id: "
 
747
                                        + failedConnectionId);
 
748
 
 
749
                        ((com.mysql.jdbc.Connection) failoverConnection)
 
750
                                        .setPreferSlaveDuringFailover(false);
 
751
                        ((com.mysql.jdbc.Connection) failoverConnection)
 
752
                                        .setFailedOver(true);
 
753
 
 
754
                        for (int i = 0; i < 30; i++) {
 
755
                                failoverConnection.setAutoCommit(true);
 
756
                                System.out.println(getSingleIndexedValueWithQuery(
 
757
                                                failoverConnection, 1, "SELECT CONNECTION_ID()"));
 
758
                                // failoverConnection.createStatement().executeQuery("SELECT
 
759
                                // 1");
 
760
                                failoverConnection.setAutoCommit(true);
 
761
                        }
 
762
 
 
763
                        String fallbackConnectionId = getSingleIndexedValueWithQuery(
 
764
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
765
                        System.out.println("fallback connection id: "
 
766
                                        + fallbackConnectionId);
 
767
 
 
768
                        /*
 
769
                         * long begin = System.currentTimeMillis();
 
770
                         * 
 
771
                         * failoverConnection.setAutoCommit(true);
 
772
                         * 
 
773
                         * long end = System.currentTimeMillis();
 
774
                         * 
 
775
                         * assertTrue("Probably didn't try failing back to the
 
776
                         * master....check test", (end - begin) > 500);
 
777
                         * 
 
778
                         * failoverConnection.createStatement().executeQuery("SELECT 1");
 
779
                         */
 
780
                } finally {
 
781
                        if (failoverConnection != null) {
 
782
                                failoverConnection.close();
 
783
                        }
 
784
                }
 
785
        }
 
786
 
 
787
        /**
 
788
         * Tests fix for BUG#7607 - MS932, SHIFT_JIS and Windows_31J not recog. as
 
789
         * aliases for sjis.
 
790
         * 
 
791
         * @throws Exception
 
792
         *             if the test fails.
 
793
         */
 
794
        public void testBug7607() throws Exception {
 
795
                if (versionMeetsMinimum(4, 1)) {
 
796
                        Connection ms932Conn = null, cp943Conn = null, shiftJisConn = null, windows31JConn = null;
 
797
 
 
798
                        try {
 
799
                                Properties props = new Properties();
 
800
                                props.setProperty("characterEncoding", "MS932");
 
801
 
 
802
                                ms932Conn = getConnectionWithProps(props);
 
803
 
 
804
                                this.rs = ms932Conn.createStatement().executeQuery(
 
805
                                                "SHOW VARIABLES LIKE 'character_set_client'");
 
806
                                assertTrue(this.rs.next());
 
807
                                String encoding = this.rs.getString(2);
 
808
                                if (!versionMeetsMinimum(5, 0, 3)
 
809
                                                && !versionMeetsMinimum(4, 1, 11)) {
 
810
                                        assertEquals("sjis", encoding.toLowerCase(Locale.ENGLISH));
 
811
                                } else {
 
812
                                        assertEquals("cp932", encoding.toLowerCase(Locale.ENGLISH));
 
813
                                }
 
814
 
 
815
                                this.rs = ms932Conn.createStatement().executeQuery(
 
816
                                                "SELECT 'abc'");
 
817
                                assertTrue(this.rs.next());
 
818
 
 
819
                                String charsetToCheck = "ms932";
 
820
 
 
821
                                if (versionMeetsMinimum(5, 0, 3)
 
822
                                                || versionMeetsMinimum(4, 1, 11)) {
 
823
                                        charsetToCheck = "windows-31j";
 
824
                                }
 
825
 
 
826
                                assertEquals(charsetToCheck,
 
827
                                                ((com.mysql.jdbc.ResultSetMetaData) this.rs
 
828
                                                                .getMetaData()).getColumnCharacterSet(1)
 
829
                                                                .toLowerCase(Locale.ENGLISH));
 
830
 
 
831
                                try {
 
832
                                        ms932Conn.createStatement().executeUpdate(
 
833
                                                        "drop table if exists testBug7607");
 
834
                                        ms932Conn
 
835
                                                        .createStatement()
 
836
                                                        .executeUpdate(
 
837
                                                                        "create table testBug7607 (sortCol int, col1 varchar(100) ) character set sjis");
 
838
                                        ms932Conn.createStatement().executeUpdate(
 
839
                                                        "insert into testBug7607 values(1, 0x835C)"); // standard
 
840
                                        // sjis
 
841
                                        ms932Conn.createStatement().executeUpdate(
 
842
                                                        "insert into testBug7607 values(2, 0x878A)"); // NEC
 
843
                                        // kanji
 
844
 
 
845
                                        this.rs = ms932Conn
 
846
                                                        .createStatement()
 
847
                                                        .executeQuery(
 
848
                                                                        "SELECT col1 FROM testBug7607 ORDER BY sortCol ASC");
 
849
                                        assertTrue(this.rs.next());
 
850
                                        String asString = this.rs.getString(1);
 
851
                                        assertTrue("\u30bd".equals(asString));
 
852
 
 
853
                                        // Can't be fixed unless server is fixed,
 
854
                                        // this is fixed in 4.1.7.
 
855
 
 
856
                                        assertTrue(this.rs.next());
 
857
                                        asString = this.rs.getString(1);
 
858
                                        assertEquals("\u3231", asString);
 
859
                                } finally {
 
860
                                        ms932Conn.createStatement().executeUpdate(
 
861
                                                        "drop table if exists testBug7607");
 
862
                                }
 
863
 
 
864
                                props = new Properties();
 
865
                                props.setProperty("characterEncoding", "SHIFT_JIS");
 
866
 
 
867
                                shiftJisConn = getConnectionWithProps(props);
 
868
 
 
869
                                this.rs = shiftJisConn.createStatement().executeQuery(
 
870
                                                "SHOW VARIABLES LIKE 'character_set_client'");
 
871
                                assertTrue(this.rs.next());
 
872
                                encoding = this.rs.getString(2);
 
873
                                assertTrue("sjis".equalsIgnoreCase(encoding));
 
874
 
 
875
                                this.rs = shiftJisConn.createStatement().executeQuery(
 
876
                                                "SELECT 'abc'");
 
877
                                assertTrue(this.rs.next());
 
878
 
 
879
                                String charSetUC = ((com.mysql.jdbc.ResultSetMetaData) this.rs
 
880
                                                .getMetaData()).getColumnCharacterSet(1).toUpperCase(
 
881
                                                Locale.US);
 
882
 
 
883
                                if (isRunningOnJdk131()) {
 
884
                                        assertEquals("WINDOWS-31J", charSetUC);
 
885
                                } else {
 
886
//                                      assertEquals("SHIFT_JIS", charSetUC);
 
887
                                }
 
888
 
 
889
                                props = new Properties();
 
890
                                props.setProperty("characterEncoding", "WINDOWS-31J");
 
891
 
 
892
                                windows31JConn = getConnectionWithProps(props);
 
893
 
 
894
                                this.rs = windows31JConn.createStatement().executeQuery(
 
895
                                                "SHOW VARIABLES LIKE 'character_set_client'");
 
896
                                assertTrue(this.rs.next());
 
897
                                encoding = this.rs.getString(2);
 
898
 
 
899
                                if (!versionMeetsMinimum(5, 0, 3)
 
900
                                                && !versionMeetsMinimum(4, 1, 11)) {
 
901
                                        assertEquals("sjis", encoding.toLowerCase(Locale.ENGLISH));
 
902
                                } else {
 
903
                                        assertEquals("cp932", encoding.toLowerCase(Locale.ENGLISH));
 
904
                                }
 
905
 
 
906
                                this.rs = windows31JConn.createStatement().executeQuery(
 
907
                                                "SELECT 'abc'");
 
908
                                assertTrue(this.rs.next());
 
909
 
 
910
                                if (!versionMeetsMinimum(4, 1, 11)) {
 
911
                                        assertEquals("sjis".toLowerCase(Locale.ENGLISH),
 
912
                                                        ((com.mysql.jdbc.ResultSetMetaData) this.rs
 
913
                                                                        .getMetaData()).getColumnCharacterSet(1)
 
914
                                                                        .toLowerCase(Locale.ENGLISH));
 
915
                                } else {
 
916
                                        assertEquals("windows-31j".toLowerCase(Locale.ENGLISH),
 
917
                                                        ((com.mysql.jdbc.ResultSetMetaData) this.rs
 
918
                                                                        .getMetaData()).getColumnCharacterSet(1)
 
919
                                                                        .toLowerCase(Locale.ENGLISH));
 
920
                                }
 
921
 
 
922
                                props = new Properties();
 
923
                                props.setProperty("characterEncoding", "CP943");
 
924
 
 
925
                                cp943Conn = getConnectionWithProps(props);
 
926
 
 
927
                                this.rs = cp943Conn.createStatement().executeQuery(
 
928
                                                "SHOW VARIABLES LIKE 'character_set_client'");
 
929
                                assertTrue(this.rs.next());
 
930
                                encoding = this.rs.getString(2);
 
931
                                assertTrue("sjis".equalsIgnoreCase(encoding));
 
932
 
 
933
                                this.rs = cp943Conn.createStatement().executeQuery(
 
934
                                                "SELECT 'abc'");
 
935
                                assertTrue(this.rs.next());
 
936
 
 
937
                                charSetUC = ((com.mysql.jdbc.ResultSetMetaData) this.rs
 
938
                                                .getMetaData()).getColumnCharacterSet(1).toUpperCase(
 
939
                                                Locale.US);
 
940
 
 
941
                                if (isRunningOnJdk131()) {
 
942
                                        assertEquals("WINDOWS-31J", charSetUC);
 
943
                                } else {
 
944
                                        assertEquals("CP943", charSetUC);
 
945
                                }
 
946
 
 
947
                        } finally {
 
948
                                if (ms932Conn != null) {
 
949
                                        ms932Conn.close();
 
950
                                }
 
951
 
 
952
                                if (shiftJisConn != null) {
 
953
                                        shiftJisConn.close();
 
954
                                }
 
955
 
 
956
                                if (windows31JConn != null) {
 
957
                                        windows31JConn.close();
 
958
                                }
 
959
 
 
960
                                if (cp943Conn != null) {
 
961
                                        cp943Conn.close();
 
962
                                }
 
963
                        }
 
964
                }
 
965
        }
 
966
 
 
967
        /**
 
968
         * In some case Connector/J's round-robin function doesn't work.
 
969
         * 
 
970
         * I had 2 mysqld, node1 "localhost:3306" and node2 "localhost:3307".
 
971
         * 
 
972
         * 1. node1 is up, node2 is up
 
973
         * 
 
974
         * 2. java-program connect to node1 by using properties
 
975
         * "autoRecconect=true","roundRobinLoadBalance=true","failOverReadOnly=false".
 
976
         * 
 
977
         * 3. node1 is down, node2 is up
 
978
         * 
 
979
         * 4. java-program execute a query and fail, but Connector/J's round-robin
 
980
         * fashion failover work and if java-program retry a query it can succeed
 
981
         * (connection is change to node2 by Connector/j)
 
982
         * 
 
983
         * 5. node1 is up, node2 is up
 
984
         * 
 
985
         * 6. node1 is up, node2 is down
 
986
         * 
 
987
         * 7. java-program execute a query, but this time Connector/J doesn't work
 
988
         * althought node1 is up and usable.
 
989
         * 
 
990
         * 
 
991
         * @throws Exception
 
992
         */
 
993
        public void testBug8643() throws Exception {
 
994
                if (runMultiHostTests()) {
 
995
                        Properties defaultProps = getMasterSlaveProps();
 
996
 
 
997
                        defaultProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY);
 
998
                        defaultProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY);
 
999
 
 
1000
                        defaultProps.put("autoReconnect", "true");
 
1001
                        defaultProps.put("roundRobinLoadBalance", "true");
 
1002
                        defaultProps.put("failOverReadOnly", "false");
 
1003
 
 
1004
                        Connection con = null;
 
1005
                        try {
 
1006
                                con = DriverManager.getConnection(getMasterSlaveUrl(),
 
1007
                                                defaultProps);
 
1008
                                Statement stmt1 = con.createStatement();
 
1009
 
 
1010
                                ResultSet rs1 = stmt1
 
1011
                                                .executeQuery("show variables like 'port'");
 
1012
                                rs1.next();
 
1013
 
 
1014
                                rs1 = stmt1.executeQuery("select connection_id()");
 
1015
                                rs1.next();
 
1016
                                String originalConnectionId = rs1.getString(1);
 
1017
                                this.stmt.executeUpdate("kill " + originalConnectionId);
 
1018
 
 
1019
                                int numLoops = 8;
 
1020
 
 
1021
                                SQLException caughtException = null;
 
1022
 
 
1023
                                while (caughtException == null && numLoops > 0) {
 
1024
                                        numLoops--;
 
1025
 
 
1026
                                        try {
 
1027
                                                rs1 = stmt1.executeQuery("show variables like 'port'");
 
1028
                                        } catch (SQLException sqlEx) {
 
1029
                                                caughtException = sqlEx;
 
1030
                                        }
 
1031
                                }
 
1032
 
 
1033
                                assertNotNull(caughtException);
 
1034
 
 
1035
                                // failover and retry
 
1036
                                rs1 = stmt1.executeQuery("show variables like 'port'");
 
1037
 
 
1038
                                rs1.next();
 
1039
                                assertTrue(!((com.mysql.jdbc.Connection) con)
 
1040
                                                .isMasterConnection());
 
1041
 
 
1042
                                rs1 = stmt1.executeQuery("select connection_id()");
 
1043
                                rs1.next();
 
1044
                                String nextConnectionId = rs1.getString(1);
 
1045
                                assertTrue(!nextConnectionId.equals(originalConnectionId));
 
1046
 
 
1047
                                this.stmt.executeUpdate("kill " + nextConnectionId);
 
1048
 
 
1049
                                numLoops = 8;
 
1050
 
 
1051
                                caughtException = null;
 
1052
 
 
1053
                                while (caughtException == null && numLoops > 0) {
 
1054
                                        numLoops--;
 
1055
 
 
1056
                                        try {
 
1057
                                                rs1 = stmt1.executeQuery("show variables like 'port'");
 
1058
                                        } catch (SQLException sqlEx) {
 
1059
                                                caughtException = sqlEx;
 
1060
                                        }
 
1061
                                }
 
1062
 
 
1063
                                assertNotNull(caughtException);
 
1064
 
 
1065
                                // failover and retry
 
1066
                                rs1 = stmt1.executeQuery("show variables like 'port'");
 
1067
 
 
1068
                                rs1.next();
 
1069
                                assertTrue(((com.mysql.jdbc.Connection) con)
 
1070
                                                .isMasterConnection());
 
1071
 
 
1072
                        } finally {
 
1073
                                if (con != null) {
 
1074
                                        try {
 
1075
                                                con.close();
 
1076
                                        } catch (Exception e) {
 
1077
                                                e.printStackTrace();
 
1078
                                        }
 
1079
                                }
 
1080
                        }
 
1081
                }
 
1082
        }
 
1083
 
 
1084
        /**
 
1085
         * Tests fix for BUG#9206, can not use 'UTF-8' for characterSetResults
 
1086
         * configuration property.
 
1087
         */
 
1088
        public void testBug9206() throws Exception {
 
1089
                Properties props = new Properties();
 
1090
                props.setProperty("characterSetResults", "UTF-8");
 
1091
                getConnectionWithProps(props).close();
 
1092
        }
 
1093
 
 
1094
        /**
 
1095
         * These two charsets have different names depending on version of MySQL
 
1096
         * server.
 
1097
         * 
 
1098
         * @throws Exception
 
1099
         *             if the test fails.
 
1100
         */
 
1101
        public void testNewCharsetsConfiguration() throws Exception {
 
1102
                Properties props = new Properties();
 
1103
                props.setProperty("useUnicode", "true");
 
1104
                props.setProperty("characterEncoding", "EUC_KR");
 
1105
                getConnectionWithProps(props).close();
 
1106
 
 
1107
                props = new Properties();
 
1108
                props.setProperty("useUnicode", "true");
 
1109
                props.setProperty("characterEncoding", "KOI8_R");
 
1110
                getConnectionWithProps(props).close();
 
1111
        }
 
1112
 
 
1113
        /**
 
1114
         * Tests fix for BUG#10144 - Memory leak in ServerPreparedStatement if
 
1115
         * serverPrepare() fails.
 
1116
         */
 
1117
 
 
1118
        public void testBug10144() throws Exception {
 
1119
                if (versionMeetsMinimum(4, 1)) {
 
1120
                        Properties props = new Properties();
 
1121
                        props.setProperty("emulateUnsupportedPstmts", "false");
 
1122
                        props.setProperty("useServerPrepStmts", "true");
 
1123
 
 
1124
                        Connection bareConn = getConnectionWithProps(props);
 
1125
 
 
1126
                        int currentOpenStatements = ((com.mysql.jdbc.Connection) bareConn)
 
1127
                                        .getActiveStatementCount();
 
1128
 
 
1129
                        try {
 
1130
                                bareConn.prepareStatement("Boo!");
 
1131
                                fail("Should not've been able to prepare that one!");
 
1132
                        } catch (SQLException sqlEx) {
 
1133
                                assertEquals(currentOpenStatements,
 
1134
                                                ((com.mysql.jdbc.Connection) bareConn)
 
1135
                                                                .getActiveStatementCount());
 
1136
                        } finally {
 
1137
                                if (bareConn != null) {
 
1138
                                        bareConn.close();
 
1139
                                }
 
1140
                        }
 
1141
                }
 
1142
        }
 
1143
 
 
1144
        /**
 
1145
         * Tests fix for BUG#10496 - SQLException is thrown when using property
 
1146
         * "characterSetResults"
 
1147
         */
 
1148
        public void testBug10496() throws Exception {
 
1149
                if (versionMeetsMinimum(5, 0, 3)) {
 
1150
                        Properties props = new Properties();
 
1151
                        props.setProperty("useUnicode", "true");
 
1152
                        props.setProperty("characterEncoding", "WINDOWS-31J");
 
1153
                        props.setProperty("characterSetResults", "WINDOWS-31J");
 
1154
                        getConnectionWithProps(props).close();
 
1155
 
 
1156
                        props = new Properties();
 
1157
                        props.setProperty("useUnicode", "true");
 
1158
                        props.setProperty("characterEncoding", "EUC_JP");
 
1159
                        props.setProperty("characterSetResults", "EUC_JP");
 
1160
                        getConnectionWithProps(props).close();
 
1161
                }
 
1162
        }
 
1163
 
 
1164
        /**
 
1165
         * Tests fix for BUG#11259, autoReconnect ping causes exception on
 
1166
         * connection startup.
 
1167
         * 
 
1168
         * @throws Exception
 
1169
         *             if the test fails.
 
1170
         */
 
1171
        public void testBug11259() throws Exception {
 
1172
                Connection dsConn = null;
 
1173
                try {
 
1174
                        Properties props = new Properties();
 
1175
                        props.setProperty("autoReconnect", "true");
 
1176
                        dsConn = getConnectionWithProps(props);
 
1177
                } finally {
 
1178
                        if (dsConn != null) {
 
1179
                                dsConn.close();
 
1180
                        }
 
1181
                }
 
1182
        }
 
1183
 
 
1184
        /**
 
1185
         * Tests fix for BUG#11879 -- ReplicationConnection won't switch to slave,
 
1186
         * throws "Catalog can't be null" exception.
 
1187
         * 
 
1188
         * @throws Exception
 
1189
         *             if the test fails
 
1190
         */
 
1191
        public void testBug11879() throws Exception {
 
1192
                if (runMultiHostTests()) {
 
1193
                        Connection replConn = null;
 
1194
 
 
1195
                        try {
 
1196
                                replConn = getMasterSlaveReplicationConnection();
 
1197
                                replConn.setReadOnly(true);
 
1198
                                replConn.setReadOnly(false);
 
1199
                        } finally {
 
1200
                                if (replConn != null) {
 
1201
                                        replConn.close();
 
1202
                                }
 
1203
                        }
 
1204
                }
 
1205
        }
 
1206
 
 
1207
        /**
 
1208
         * Tests fix for BUG#11976 - maxPerformance.properties mis-spells
 
1209
         * "elideSetAutoCommits".
 
1210
         * 
 
1211
         * @throws Exception
 
1212
         *             if the test fails.
 
1213
         */
 
1214
        public void testBug11976() throws Exception {
 
1215
                if (isRunningOnJdk131()) {
 
1216
                        return; // test not valid on JDK-1.3.1
 
1217
                }
 
1218
 
 
1219
                Properties props = new Properties();
 
1220
                props.setProperty("useConfigs", "maxPerformance");
 
1221
 
 
1222
                Connection maxPerfConn = getConnectionWithProps(props);
 
1223
                assertEquals(true, ((com.mysql.jdbc.Connection) maxPerfConn)
 
1224
                                .getElideSetAutoCommits());
 
1225
        }
 
1226
 
 
1227
        /**
 
1228
         * Tests fix for BUG#12218, properties shared between master and slave with
 
1229
         * replication connection.
 
1230
         * 
 
1231
         * @throws Exception
 
1232
         *             if the test fails.
 
1233
         */
 
1234
        public void testBug12218() throws Exception {
 
1235
                if (runMultiHostTests()) {
 
1236
                        Connection replConn = null;
 
1237
 
 
1238
                        try {
 
1239
                                replConn = getMasterSlaveReplicationConnection();
 
1240
                                assertTrue(!((ReplicationConnection) replConn)
 
1241
                                                .getMasterConnection().hasSameProperties(
 
1242
                                                                ((ReplicationConnection) replConn)
 
1243
                                                                                .getSlavesConnection()));
 
1244
                        } finally {
 
1245
                                if (replConn != null) {
 
1246
                                        replConn.close();
 
1247
                                }
 
1248
                        }
 
1249
                }
 
1250
        }
 
1251
 
 
1252
        /**
 
1253
         * Tests fix for BUG#12229 - explainSlowQueries hangs with server-side
 
1254
         * prepared statements.
 
1255
         * 
 
1256
         * @throws Exception
 
1257
         *             if the test fails.
 
1258
         */
 
1259
        public void testBug12229() throws Exception {
 
1260
                createTable("testBug12229", "(`int_field` integer )");
 
1261
                this.stmt.executeUpdate("insert into testBug12229 values (123456),(1)");
 
1262
 
 
1263
                Properties props = new Properties();
 
1264
                props.put("profileSQL", "true");
 
1265
                props.put("slowQueryThresholdMillis", "0");
 
1266
                props.put("logSlowQueries", "true");
 
1267
                props.put("explainSlowQueries", "true");
 
1268
                props.put("useServerPrepStmts", "true");
 
1269
 
 
1270
                Connection explainConn = getConnectionWithProps(props);
 
1271
 
 
1272
                this.pstmt = explainConn
 
1273
                                .prepareStatement("SELECT `int_field` FROM `testBug12229` WHERE `int_field` = ?");
 
1274
                this.pstmt.setInt(1, 1);
 
1275
 
 
1276
                this.rs = this.pstmt.executeQuery();
 
1277
                assertTrue(this.rs.next());
 
1278
 
 
1279
                this.rs = this.pstmt.executeQuery();
 
1280
                assertTrue(this.rs.next());
 
1281
 
 
1282
                this.rs = this.pstmt.executeQuery();
 
1283
                assertTrue(this.rs.next());
 
1284
        }
 
1285
 
 
1286
        /**
 
1287
         * Tests fix for BUG#12752 - Cp1251 incorrectly mapped to win1251 for
 
1288
         * servers newer than 4.0.x.
 
1289
         * 
 
1290
         * @throws Exception
 
1291
         *             if the test fails.
 
1292
         */
 
1293
        public void testBug12752() throws Exception {
 
1294
                Properties props = new Properties();
 
1295
                props.setProperty("characterEncoding", "Cp1251");
 
1296
                getConnectionWithProps(props).close();
 
1297
        }
 
1298
 
 
1299
        /**
 
1300
         * Tests fix for BUG#12753, sessionVariables=....=...., doesn't work as it's
 
1301
         * tokenized incorrectly.
 
1302
         * 
 
1303
         * @throws Exception
 
1304
         *             if the test fails.
 
1305
         */
 
1306
        public void testBug12753() throws Exception {
 
1307
                if (versionMeetsMinimum(4, 1)) {
 
1308
                        Properties props = new Properties();
 
1309
                        props.setProperty("sessionVariables", "sql_mode=ansi");
 
1310
 
 
1311
                        Connection sessionConn = null;
 
1312
 
 
1313
                        try {
 
1314
                                sessionConn = getConnectionWithProps(props);
 
1315
 
 
1316
                                String sqlMode = getMysqlVariable(sessionConn, "sql_mode");
 
1317
                                assertTrue(sqlMode.indexOf("ANSI") != -1);
 
1318
                        } finally {
 
1319
                                if (sessionConn != null) {
 
1320
                                        sessionConn.close();
 
1321
                                        sessionConn = null;
 
1322
                                }
 
1323
                        }
 
1324
                }
 
1325
        }
 
1326
 
 
1327
        /**
 
1328
         * Tests fix for BUG#13048 - maxQuerySizeToLog is not respected.
 
1329
         * 
 
1330
         * @throws Exception
 
1331
         *             if the test fails
 
1332
         */
 
1333
        public void testBug13048() throws Exception {
 
1334
 
 
1335
                Connection profileConn = null;
 
1336
                PrintStream oldErr = System.err;
 
1337
 
 
1338
                try {
 
1339
                        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
 
1340
                        System.setErr(new PrintStream(bOut));
 
1341
 
 
1342
                        Properties props = new Properties();
 
1343
                        props.setProperty("profileSQL", "true");
 
1344
                        props.setProperty("maxQuerySizeToLog", "2");
 
1345
                        props.setProperty("logger", "com.mysql.jdbc.log.StandardLogger");
 
1346
 
 
1347
                        profileConn = getConnectionWithProps(props);
 
1348
 
 
1349
                        StringBuffer queryBuf = new StringBuffer("SELECT '");
 
1350
 
 
1351
                        for (int i = 0; i < 500; i++) {
 
1352
                                queryBuf.append("a");
 
1353
                        }
 
1354
 
 
1355
                        queryBuf.append("'");
 
1356
 
 
1357
                        this.rs = profileConn.createStatement().executeQuery(
 
1358
                                        queryBuf.toString());
 
1359
                        this.rs.close();
 
1360
 
 
1361
                        String logString = new String(bOut.toString("ISO8859-1"));
 
1362
                        assertTrue(logString.indexOf("... (truncated)") != -1);
 
1363
 
 
1364
                        bOut = new ByteArrayOutputStream();
 
1365
                        System.setErr(new PrintStream(bOut));
 
1366
 
 
1367
                        this.rs = profileConn.prepareStatement(queryBuf.toString())
 
1368
                                        .executeQuery();
 
1369
                        logString = new String(bOut.toString("ISO8859-1"));
 
1370
 
 
1371
                        assertTrue(logString.indexOf("... (truncated)") != -1);
 
1372
                } finally {
 
1373
                        System.setErr(oldErr);
 
1374
 
 
1375
                        if (profileConn != null) {
 
1376
                                profileConn.close();
 
1377
                        }
 
1378
 
 
1379
                        if (this.rs != null) {
 
1380
                                ResultSet toClose = this.rs;
 
1381
                                this.rs = null;
 
1382
                                toClose.close();
 
1383
                        }
 
1384
                }
 
1385
        }
 
1386
 
 
1387
        /**
 
1388
         * Tests fix for BUG#13453 - can't use & or = in URL configuration values
 
1389
         * (we now allow you to use www-form-encoding).
 
1390
         * 
 
1391
         * @throws Exception
 
1392
         *             if the test fails
 
1393
         */
 
1394
        public void testBug13453() throws Exception {
 
1395
                StringBuffer urlBuf = new StringBuffer(dbUrl);
 
1396
 
 
1397
                if (dbUrl.indexOf('?') == -1) {
 
1398
                        urlBuf.append('?');
 
1399
                } else {
 
1400
                        urlBuf.append('&');
 
1401
                }
 
1402
 
 
1403
                urlBuf.append("sessionVariables=@testBug13453='%25%26+%3D'");
 
1404
 
 
1405
                Connection encodedConn = null;
 
1406
 
 
1407
                try {
 
1408
                        encodedConn = DriverManager.getConnection(urlBuf.toString(), null);
 
1409
 
 
1410
                        this.rs = encodedConn.createStatement().executeQuery(
 
1411
                                        "SELECT @testBug13453");
 
1412
                        assertTrue(this.rs.next());
 
1413
                        assertEquals("%& =", this.rs.getString(1));
 
1414
                } finally {
 
1415
                        if (this.rs != null) {
 
1416
                                this.rs.close();
 
1417
                                this.rs = null;
 
1418
                        }
 
1419
 
 
1420
                        if (encodedConn != null) {
 
1421
                                encodedConn.close();
 
1422
                        }
 
1423
                }
 
1424
        }
 
1425
 
 
1426
        /**
 
1427
         * Tests fix for BUG#15065 - Usage advisor complains about unreferenced
 
1428
         * columns, even though they've been referenced.
 
1429
         * 
 
1430
         * @throws Exception
 
1431
         *             if the test fails.
 
1432
         */
 
1433
        public void testBug15065() throws Exception {
 
1434
                if (isRunningOnJdk131()) {
 
1435
                        return; // test not valid on JDK-1.3.1
 
1436
                }
 
1437
 
 
1438
                createTable("testBug15065", "(field1 int)");
 
1439
 
 
1440
                this.stmt.executeUpdate("INSERT INTO testBug15065 VALUES (1)");
 
1441
 
 
1442
                Connection advisorConn = null;
 
1443
                Statement advisorStmt = null;
 
1444
 
 
1445
                try {
 
1446
                        Properties props = new Properties();
 
1447
                        props.setProperty("useUsageAdvisor", "true");
 
1448
                        props.setProperty("logger", "com.mysql.jdbc.log.StandardLogger");
 
1449
 
 
1450
                        advisorConn = getConnectionWithProps(props);
 
1451
                        advisorStmt = advisorConn.createStatement();
 
1452
 
 
1453
                        Method[] getMethods = ResultSet.class.getMethods();
 
1454
 
 
1455
                        PrintStream oldErr = System.err;
 
1456
 
 
1457
                        try {
 
1458
                                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
 
1459
                                System.setErr(new PrintStream(bOut));
 
1460
                                
 
1461
                                HashMap methodsToSkipMap = new HashMap();
 
1462
                                
 
1463
                                // Needs an actual URL
 
1464
                                methodsToSkipMap.put("getURL", null);
 
1465
                                
 
1466
                                // Java6 JDBC4.0 methods we don't implement
 
1467
                                methodsToSkipMap.put("getNCharacterStream", null);
 
1468
                                methodsToSkipMap.put("getNClob", null);
 
1469
                                methodsToSkipMap.put("getNString", null);
 
1470
                                methodsToSkipMap.put("getRowId", null);
 
1471
                                methodsToSkipMap.put("getSQLXML", null);
 
1472
                                
 
1473
                                for (int j = 0; j < 2; j++) {
 
1474
                                        for (int i = 0; i < getMethods.length; i++) {
 
1475
                                                String methodName = getMethods[i].getName();
 
1476
 
 
1477
                                                if (methodName.startsWith("get")
 
1478
                                                                && !methodsToSkipMap.containsKey(methodName)) {
 
1479
                                                        Class[] parameterTypes = getMethods[i]
 
1480
                                                                        .getParameterTypes();
 
1481
 
 
1482
                                                        if (parameterTypes.length == 1
 
1483
                                                                        && parameterTypes[0] == Integer.TYPE) {
 
1484
                                                                if (j == 0) {
 
1485
                                                                        this.rs = advisorStmt
 
1486
                                                                                        .executeQuery("SELECT COUNT(*) FROM testBug15065");
 
1487
                                                                } else {
 
1488
                                                                        this.rs = advisorConn
 
1489
                                                                                        .prepareStatement(
 
1490
                                                                                                        "SELECT COUNT(*) FROM testBug15065")
 
1491
                                                                                        .executeQuery();
 
1492
                                                                }
 
1493
 
 
1494
                                                                this.rs.next();
 
1495
 
 
1496
                                                                try {
 
1497
 
 
1498
                                                                        getMethods[i].invoke(this.rs,
 
1499
                                                                                        new Object[] { new Integer(1) });
 
1500
                                                                } catch (InvocationTargetException invokeEx) {
 
1501
                                                                        // we don't care about bad values, just that
 
1502
                                                                        // the
 
1503
                                                                        // column gets "touched"
 
1504
                                                                        if (!invokeEx
 
1505
                                                                                        .getCause()
 
1506
                                                                                        .getClass()
 
1507
                                                                                        .isAssignableFrom(
 
1508
                                                                                                        java.sql.SQLException.class)
 
1509
                                                                                        && !invokeEx
 
1510
                                                                                                        .getCause()
 
1511
                                                                                                        .getClass()
 
1512
                                                                                                        .getName()
 
1513
                                                                                                        .equals(
 
1514
                                                                                                                        "com.mysql.jdbc.NotImplemented")) {
 
1515
                                                                                throw invokeEx;
 
1516
                                                                        }
 
1517
                                                                }
 
1518
 
 
1519
                                                                this.rs.close();
 
1520
                                                                this.rs = null;
 
1521
                                                        }
 
1522
                                                }
 
1523
                                        }
 
1524
                                }
 
1525
 
 
1526
                                String logOut = bOut.toString("ISO8859-1");
 
1527
 
 
1528
                                if (logOut.indexOf(".Level") != -1) {
 
1529
                                        return; // we ignore for warnings
 
1530
                                }
 
1531
 
 
1532
                                assertTrue("Usage advisor complained about columns:\n\n"
 
1533
                                                + logOut, logOut.indexOf("columns") == -1);
 
1534
                        } finally {
 
1535
                                System.setErr(oldErr);
 
1536
                        }
 
1537
                } finally {
 
1538
                        if (advisorConn != null) {
 
1539
                                advisorConn.close();
 
1540
                        }
 
1541
                }
 
1542
        }
 
1543
        
 
1544
 
 
1545
        /**
 
1546
         * Tests fix for BUG#15544, no "dos" character set in MySQL > 4.1.0
 
1547
         * 
 
1548
         * @throws Exception
 
1549
         *             if the test fails
 
1550
         */
 
1551
        public void testBug15544() throws Exception {
 
1552
                Properties props = new Properties();
 
1553
                props.setProperty("characterEncoding", "Cp437");
 
1554
                Connection dosConn = null;
 
1555
 
 
1556
                try {
 
1557
                        dosConn = getConnectionWithProps(props);
 
1558
                } finally {
 
1559
                        if (dosConn != null) {
 
1560
                                dosConn.close();
 
1561
                        }
 
1562
                }
 
1563
        }
 
1564
 
 
1565
        public void testCSC5765() throws Exception {
 
1566
                if (isRunningOnJdk131()) {
 
1567
                        return; // test not valid on JDK-1.3.1
 
1568
                }
 
1569
 
 
1570
                Properties props = new Properties();
 
1571
                props.setProperty("useUnicode", "true");
 
1572
                props.setProperty("characterEncoding", "utf8");
 
1573
                props.setProperty("characterSetResults", "utf8");
 
1574
                props.setProperty("connectionCollation", "utf8_bin");
 
1575
 
 
1576
                Connection utf8Conn = null;
 
1577
 
 
1578
                try {
 
1579
                        utf8Conn = getConnectionWithProps(props);
 
1580
                        this.rs = utf8Conn.createStatement().executeQuery(
 
1581
                                        "SHOW VARIABLES LIKE 'character_%'");
 
1582
                        while (this.rs.next()) {
 
1583
                                System.out.println(this.rs.getString(1) + " = "
 
1584
                                                + this.rs.getString(2));
 
1585
                        }
 
1586
 
 
1587
                        this.rs = utf8Conn.createStatement().executeQuery(
 
1588
                                        "SHOW VARIABLES LIKE 'collation_%'");
 
1589
                        while (this.rs.next()) {
 
1590
                                System.out.println(this.rs.getString(1) + " = "
 
1591
                                                + this.rs.getString(2));
 
1592
                        }
 
1593
                } finally {
 
1594
                        if (utf8Conn != null) {
 
1595
                                utf8Conn.close();
 
1596
                        }
 
1597
                }
 
1598
        }
 
1599
 
 
1600
        private Connection getMasterSlaveReplicationConnection()
 
1601
                        throws SQLException {
 
1602
 
 
1603
                Connection replConn = new ReplicationDriver().connect(
 
1604
                                getMasterSlaveUrl(), getMasterSlaveProps());
 
1605
 
 
1606
                return replConn;
 
1607
        }
 
1608
 
 
1609
        protected String getMasterSlaveUrl() throws SQLException {
 
1610
                StringBuffer urlBuf = new StringBuffer("jdbc:mysql://");
 
1611
                Properties defaultProps = getPropertiesFromTestsuiteUrl();
 
1612
                String hostname = defaultProps
 
1613
                                .getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY);
 
1614
 
 
1615
                int colonIndex = hostname.indexOf(":");
 
1616
 
 
1617
                String portNumber = "3306";
 
1618
 
 
1619
                if (colonIndex != -1 && !hostname.startsWith(":")) {
 
1620
                        portNumber = hostname.substring(colonIndex + 1);
 
1621
                        hostname = hostname.substring(0, colonIndex);
 
1622
                } else if (hostname.startsWith(":")) {
 
1623
                        portNumber = hostname.substring(1);
 
1624
                        hostname = "localhost";
 
1625
                } else {
 
1626
                        portNumber = defaultProps
 
1627
                                        .getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY);
 
1628
                }
 
1629
 
 
1630
                for (int i = 0; i < 2; i++) {
 
1631
                        urlBuf.append(hostname);
 
1632
                        urlBuf.append(":");
 
1633
                        urlBuf.append(portNumber);
 
1634
 
 
1635
                        if (i == 0) {
 
1636
                                urlBuf.append(",");
 
1637
                        }
 
1638
                }
 
1639
                urlBuf.append("/");
 
1640
 
 
1641
                return urlBuf.toString();
 
1642
        }
 
1643
 
 
1644
        protected Properties getMasterSlaveProps() throws SQLException {
 
1645
                Properties props = getPropertiesFromTestsuiteUrl();
 
1646
 
 
1647
                props.remove(NonRegisteringDriver.HOST_PROPERTY_KEY);
 
1648
                props.remove(NonRegisteringDriver.PORT_PROPERTY_KEY);
 
1649
 
 
1650
                return props;
 
1651
        }
 
1652
 
 
1653
        /**
 
1654
         * Tests fix for BUG#15570 - ReplicationConnection incorrectly copies state,
 
1655
         * doesn't transfer connection context correctly when transitioning between
 
1656
         * the same read-only states.
 
1657
         * 
 
1658
         * (note, this test will fail if the test user doesn't have permission to
 
1659
         * "USE 'mysql'".
 
1660
         * 
 
1661
         * @throws Exception
 
1662
         *             if the test fails.
 
1663
         */
 
1664
        public void testBug15570() throws Exception {
 
1665
                Connection replConn = null;
 
1666
 
 
1667
                try {
 
1668
                        replConn = getMasterSlaveReplicationConnection();
 
1669
 
 
1670
                        int masterConnectionId = Integer
 
1671
                                        .parseInt(getSingleIndexedValueWithQuery(replConn, 1,
 
1672
                                                        "SELECT CONNECTION_ID()").toString());
 
1673
 
 
1674
                        replConn.setReadOnly(false);
 
1675
 
 
1676
                        assertEquals(masterConnectionId, Integer
 
1677
                                        .parseInt(getSingleIndexedValueWithQuery(replConn, 1,
 
1678
                                                        "SELECT CONNECTION_ID()").toString()));
 
1679
 
 
1680
                        String currentCatalog = replConn.getCatalog();
 
1681
 
 
1682
                        replConn.setCatalog(currentCatalog);
 
1683
                        assertEquals(currentCatalog, replConn.getCatalog());
 
1684
 
 
1685
                        replConn.setReadOnly(true);
 
1686
 
 
1687
                        int slaveConnectionId = Integer
 
1688
                                        .parseInt(getSingleIndexedValueWithQuery(replConn, 1,
 
1689
                                                        "SELECT CONNECTION_ID()").toString());
 
1690
 
 
1691
                        // The following test is okay for now, as the chance
 
1692
                        // of MySQL wrapping the connection id counter during our
 
1693
                        // testsuite is very small.
 
1694
 
 
1695
                        assertTrue("Slave id " + slaveConnectionId
 
1696
                                        + " is not newer than master id " + masterConnectionId,
 
1697
                                        slaveConnectionId > masterConnectionId);
 
1698
 
 
1699
                        assertEquals(currentCatalog, replConn.getCatalog());
 
1700
 
 
1701
                        String newCatalog = "mysql";
 
1702
 
 
1703
                        replConn.setCatalog(newCatalog);
 
1704
                        assertEquals(newCatalog, replConn.getCatalog());
 
1705
 
 
1706
                        replConn.setReadOnly(true);
 
1707
                        assertEquals(newCatalog, replConn.getCatalog());
 
1708
 
 
1709
                        replConn.setReadOnly(false);
 
1710
                        assertEquals(masterConnectionId, Integer
 
1711
                                        .parseInt(getSingleIndexedValueWithQuery(replConn, 1,
 
1712
                                                        "SELECT CONNECTION_ID()").toString()));
 
1713
                } finally {
 
1714
                        if (replConn != null) {
 
1715
                                replConn.close();
 
1716
                        }
 
1717
                }
 
1718
        }
 
1719
 
 
1720
        /**
 
1721
         * Tests bug where downed slave caused round robin load balance not to
 
1722
         * cycle back to first host in the list.
 
1723
         * 
 
1724
         * @throws Exception
 
1725
         *             if the test fails...Note, test is timing-dependent, but
 
1726
         *             should work in most cases.
 
1727
         */
 
1728
        public void testBug23281() throws Exception {
 
1729
                Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
 
1730
                props.setProperty("autoReconnect", "false");
 
1731
                props.setProperty("roundRobinLoadBalance", "true");
 
1732
                props.setProperty("failoverReadOnly", "false");
 
1733
                
 
1734
                if (!isRunningOnJdk131()) {
 
1735
                        props.setProperty("connectTimeout", "5000");
 
1736
                }
 
1737
                
 
1738
                // Re-build the connection information
 
1739
                int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
 
1740
                int lastIndexOfHost = BaseTestCase.dbUrl.indexOf("/", firstIndexOfHost);
 
1741
        
 
1742
                String hostPortPair = BaseTestCase.dbUrl.substring(firstIndexOfHost,
 
1743
                                lastIndexOfHost);
 
1744
        
 
1745
                StringTokenizer st = new StringTokenizer(hostPortPair, ":");
 
1746
        
 
1747
                String host = null;
 
1748
                String port = null;
 
1749
        
 
1750
                if (st.hasMoreTokens()) {
 
1751
                        String possibleHostOrPort = st.nextToken();
 
1752
        
 
1753
                        if (Character.isDigit(possibleHostOrPort.charAt(0)) && 
 
1754
                                        (possibleHostOrPort.indexOf(".") == -1 /* IPV4 */)  &&
 
1755
                                        (possibleHostOrPort.indexOf("::") == -1 /* IPV6 */)) {
 
1756
                                port = possibleHostOrPort;
 
1757
                                host = "localhost";
 
1758
                        } else {
 
1759
                                host = possibleHostOrPort;
 
1760
                        }
 
1761
                }
 
1762
        
 
1763
                if (st.hasMoreTokens()) {
 
1764
                        port = st.nextToken();
 
1765
                }
 
1766
        
 
1767
                if (host == null) {
 
1768
                        host = "";
 
1769
                }
 
1770
        
 
1771
                if (port == null) {
 
1772
                        port = "3306";
 
1773
                }
 
1774
        
 
1775
                StringBuffer newHostBuf = new StringBuffer();
 
1776
                
 
1777
                newHostBuf.append(host);
 
1778
                if (port != null) {
 
1779
                        newHostBuf.append(":");
 
1780
                        newHostBuf.append(port);
 
1781
                }
 
1782
        
 
1783
                newHostBuf.append(",");
 
1784
                //newHostBuf.append(host);
 
1785
                newHostBuf.append("192.0.2.1"); // non-exsitent machine from RFC3330 test network
 
1786
                newHostBuf.append(":65532"); // make sure the slave fails
 
1787
                
 
1788
                props.remove("PORT");
 
1789
                props.remove("HOST");
 
1790
        
 
1791
                Connection failoverConnection = null;
 
1792
        
 
1793
                try {
 
1794
                        failoverConnection = getConnectionWithProps("jdbc:mysql://"
 
1795
                                        + newHostBuf.toString() + "/", props);
 
1796
                
 
1797
                        String originalConnectionId = getSingleIndexedValueWithQuery(
 
1798
                                        failoverConnection, 1, "SELECT CONNECTION_ID()").toString();
 
1799
                        
 
1800
                        System.out.println(originalConnectionId);
 
1801
                        
 
1802
                        Connection nextConnection = getConnectionWithProps("jdbc:mysql://"
 
1803
                                        + newHostBuf.toString() + "/", props);
 
1804
                        
 
1805
                        String nextId = getSingleIndexedValueWithQuery(
 
1806
                                        nextConnection, 1, "SELECT CONNECTION_ID()").toString();
 
1807
                        
 
1808
                        System.out.println(nextId);
 
1809
                        
 
1810
                } finally {
 
1811
                        if (failoverConnection != null) {
 
1812
                                failoverConnection.close();
 
1813
                        }
 
1814
                }
 
1815
        }
 
1816
        
 
1817
        /**
 
1818
         * Tests to insure proper behavior for BUG#24706.
 
1819
         * 
 
1820
         * @throws Exception if the test fails.
 
1821
         */
 
1822
        public void testBug24706() throws Exception {
 
1823
                if (!versionMeetsMinimum(5, 0)) {
 
1824
                        return; // server status isn't there to support this feature
 
1825
                }
 
1826
                
 
1827
                Properties props = new Properties();
 
1828
                props.setProperty("elideSetAutoCommits", "true");
 
1829
                props.setProperty("logger", "StandardLogger");
 
1830
                props.setProperty("profileSQL", "true");
 
1831
                Connection c = null;
 
1832
                
 
1833
                StringBuffer logBuf = new StringBuffer();
 
1834
                
 
1835
                StandardLogger.bufferedLog = logBuf;
 
1836
                
 
1837
                try {
 
1838
                        c = getConnectionWithProps(props);
 
1839
                        c.setAutoCommit(true);
 
1840
                        c.createStatement().execute("SELECT 1");
 
1841
                        c.setAutoCommit(true);
 
1842
                        c.setAutoCommit(false);
 
1843
                        c.createStatement().execute("SELECT 1");
 
1844
                        c.setAutoCommit(false);
 
1845
                        
 
1846
                        // We should only see _one_ "set autocommit=" sent to the server
 
1847
                        
 
1848
                        String log = logBuf.toString();
 
1849
                        int searchFrom = 0;
 
1850
                        int count = 0;
 
1851
                        int found = 0;
 
1852
                        
 
1853
                        while ((found = log.indexOf("SET autocommit=", searchFrom)) != -1) {
 
1854
                                searchFrom =  found + 1;
 
1855
                                count++;
 
1856
                        }
 
1857
                        
 
1858
                        // The SELECT doesn't actually start a transaction, so being pedantic the
 
1859
                        // driver issues SET autocommit=0 again in this case.
 
1860
                        assertEquals(2, count);
 
1861
                } finally {
 
1862
                        StandardLogger.bufferedLog = null;
 
1863
                        
 
1864
                        if (c != null) {
 
1865
                                c.close();
 
1866
                        }
 
1867
                        
 
1868
                }
 
1869
        }
 
1870
        
 
1871
        /**
 
1872
         * Tests fix for BUG#25514 - Timer instance used for Statement.setQueryTimeout()
 
1873
         * created per-connection, rather than per-VM, causing memory leak.
 
1874
         * 
 
1875
         * @throws Exception if the test fails.
 
1876
         */
 
1877
        public void testBug25514() throws Exception {
 
1878
 
 
1879
                for (int i = 0; i < 10; i++) {
 
1880
                        getConnectionWithProps(null).close();
 
1881
                }
 
1882
                
 
1883
                ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
 
1884
 
 
1885
                while (root.getParent() != null) {
 
1886
                root = root.getParent();
 
1887
            }
 
1888
 
 
1889
                int numThreadsNamedTimer = findNamedThreadCount(root, "Timer");
 
1890
 
 
1891
                if (numThreadsNamedTimer == 0) {
 
1892
                        numThreadsNamedTimer = findNamedThreadCount(root, "MySQL Statement Cancellation Timer");
 
1893
                }
 
1894
                
 
1895
                // Notice that this seems impossible to test on JDKs prior to 1.5, as there is no
 
1896
                // reliable way to find the TimerThread, so we have to rely on new JDKs for this 
 
1897
                // test.
 
1898
                assertTrue("More than one timer for cancel was created", numThreadsNamedTimer <= 1);
 
1899
        }
 
1900
        
 
1901
        private int findNamedThreadCount(ThreadGroup group, String nameStart) {
 
1902
                
 
1903
                int count = 0;
 
1904
                
 
1905
        int numThreads = group.activeCount();
 
1906
        Thread[] threads = new Thread[numThreads*2];
 
1907
        numThreads = group.enumerate(threads, false);
 
1908
    
 
1909
        for (int i=0; i<numThreads; i++) {
 
1910
            if (threads[i].getName().startsWith(nameStart)) {
 
1911
                count++;
 
1912
            }
 
1913
        }
 
1914
 
 
1915
        int numGroups = group.activeGroupCount();
 
1916
        ThreadGroup[] groups = new ThreadGroup[numGroups*2];
 
1917
        numGroups = group.enumerate(groups, false);
 
1918
    
 
1919
        for (int i=0; i<numGroups; i++) {
 
1920
                count += findNamedThreadCount(groups[i], nameStart);
 
1921
        }
 
1922
 
 
1923
        return count;
 
1924
        }
 
1925
        
 
1926
        /**
 
1927
         * Ensures that we don't miss getters/setters for driver properties in
 
1928
         * ConnectionProperties so that names given in documentation work with 
 
1929
         * DataSources which will use JavaBean-style names and reflection to 
 
1930
         * set the values (and often fail silently! when the method isn't available).
 
1931
         * 
 
1932
         * @throws Exception
 
1933
         */
 
1934
        public void testBug23626() throws Exception {
 
1935
                Class clazz = this.conn.getClass();
 
1936
                
 
1937
                DriverPropertyInfo[] dpi = new NonRegisteringDriver().getPropertyInfo(dbUrl, null);
 
1938
                StringBuffer missingSettersBuf = new StringBuffer();
 
1939
                StringBuffer missingGettersBuf = new StringBuffer();
 
1940
                
 
1941
                Class[][] argTypes = {new Class[] { String.class }, new Class[] {Integer.TYPE}, new Class[] {Long.TYPE}, new Class[] {Boolean.TYPE}};
 
1942
                
 
1943
                for (int i = 0; i < dpi.length; i++) {
 
1944
                        
 
1945
                        String propertyName = dpi[i].name;
 
1946
                
 
1947
                        if (propertyName.equals("HOST") || propertyName.equals("PORT") 
 
1948
                                        || propertyName.equals("DBNAME") || propertyName.equals("user") ||
 
1949
                                        propertyName.equals("password")) {
 
1950
                                continue;
 
1951
                        }
 
1952
                                        
 
1953
                        StringBuffer mutatorName = new StringBuffer("set");
 
1954
                        mutatorName.append(Character.toUpperCase(propertyName.charAt(0)));
 
1955
                        mutatorName.append(propertyName.substring(1));
 
1956
                                
 
1957
                        StringBuffer accessorName = new StringBuffer("get");
 
1958
                        accessorName.append(Character.toUpperCase(propertyName.charAt(0)));
 
1959
                        accessorName.append(propertyName.substring(1));
 
1960
                        
 
1961
                        try {
 
1962
                                clazz.getMethod(accessorName.toString(), null);
 
1963
                        } catch (NoSuchMethodException nsme) {
 
1964
                                missingGettersBuf.append(accessorName.toString());
 
1965
                                missingGettersBuf.append("\n");
 
1966
                        }
 
1967
                        
 
1968
                        boolean foundMethod = false;
 
1969
                        
 
1970
                        for (int j = 0; j < argTypes.length; j++) {
 
1971
                                try {
 
1972
                                        clazz.getMethod(mutatorName.toString(), argTypes[j]);
 
1973
                                        foundMethod = true;
 
1974
                                        break;
 
1975
                                } catch (NoSuchMethodException nsme) {
 
1976
                                        
 
1977
                                }
 
1978
                        }
 
1979
                        
 
1980
                        if (!foundMethod) {
 
1981
                                missingSettersBuf.append(mutatorName);
 
1982
                                missingSettersBuf.append("\n");
 
1983
                        }
 
1984
                }
 
1985
                
 
1986
                assertEquals("Missing setters for listed configuration properties.", "", missingSettersBuf.toString());
 
1987
                assertEquals("Missing getters for listed configuration properties.", "", missingSettersBuf.toString());
 
1988
        }
 
1989
        
 
1990
        /**
 
1991
         * Tests fix for BUG#25545 - Client flags not sent correctly during handshake
 
1992
         * when using SSL.
 
1993
         * 
 
1994
         * Requires test certificates from testsuite/ssl-test-certs to be installed
 
1995
         * on the server being tested.
 
1996
         * 
 
1997
         * @throws Exception if the test fails.
 
1998
         */
 
1999
        public void testBug25545() throws Exception {
 
2000
                if (!versionMeetsMinimum(5, 0)) {
 
2001
                        return;
 
2002
                }
 
2003
                
 
2004
                if (isRunningOnJdk131()) {
 
2005
                        return;
 
2006
                }
 
2007
        
 
2008
                createProcedure("testBug25545", "() BEGIN SELECT 1; END");
 
2009
                
 
2010
                String trustStorePath = "src/testsuite/ssl-test-certs/test-cert-store";
 
2011
                
 
2012
                System.setProperty("javax.net.ssl.keyStore", trustStorePath);
 
2013
                System.setProperty("javax.net.ssl.keyStorePassword","password");
 
2014
                System.setProperty("javax.net.ssl.trustStore", trustStorePath);
 
2015
                System.setProperty("javax.net.ssl.trustStorePassword","password");
 
2016
                
 
2017
                
 
2018
                Connection sslConn = null;
 
2019
                
 
2020
                try {
 
2021
                        Properties props = new Properties();
 
2022
                        props.setProperty("useSSL", "true");
 
2023
                        props.setProperty("requireSSL", "true");
 
2024
                        
 
2025
                        sslConn = getConnectionWithProps(props);
 
2026
                        sslConn.prepareCall("{ call testBug25545()}").execute();
 
2027
                } finally {
 
2028
                        if (sslConn != null) {
 
2029
                                sslConn.close();
 
2030
                        }
 
2031
                }
 
2032
        }
 
2033
        
 
2034
        /**
 
2035
         * Tests fix for BUG#27655 - getTransactionIsolation() uses
 
2036
         * "SHOW VARIABLES LIKE" which is very inefficient on MySQL-5.0+
 
2037
         * 
 
2038
         * @throws Exception
 
2039
         */
 
2040
        public void testBug27655() throws Exception {
 
2041
                StringBuffer logBuf = new StringBuffer();
 
2042
                Properties props = new Properties();
 
2043
                props.setProperty("profileSQL", "true");
 
2044
                props.setProperty("logger", "StandardLogger");
 
2045
                StandardLogger.bufferedLog = logBuf;
 
2046
                
 
2047
                Connection loggedConn = null;
 
2048
                
 
2049
                try {
 
2050
                        loggedConn = getConnectionWithProps(props);
 
2051
                        loggedConn.getTransactionIsolation();
 
2052
                        
 
2053
                        if (versionMeetsMinimum(4, 0, 3)) {
 
2054
                                assertEquals(-1, logBuf.toString().indexOf("SHOW VARIABLES LIKE 'tx_isolation'"));
 
2055
                        }
 
2056
                } finally {
 
2057
                        if (loggedConn != null) {
 
2058
                                loggedConn.close();
 
2059
                        }
 
2060
                }
 
2061
        }
 
2062
        
 
2063
        /**
 
2064
         * Tests fix for issue where a failed-over connection would let
 
2065
         * an application call setReadOnly(false), when that call 
 
2066
         * should be ignored until the connection is reconnected to a 
 
2067
         * writable master.
 
2068
         * 
 
2069
         * @throws Exception if the test fails.
 
2070
         */
 
2071
        public void testFailoverReadOnly() throws Exception {
 
2072
                Properties props = getMasterSlaveProps();
 
2073
                props.setProperty("autoReconnect", "true");
 
2074
                
 
2075
                
 
2076
                Connection failoverConn = null;
 
2077
                
 
2078
                
 
2079
                Statement failoverStmt = 
 
2080
                        null;
 
2081
                
 
2082
                try {
 
2083
                        failoverConn = getConnectionWithProps(getMasterSlaveUrl(), props);
 
2084
 
 
2085
                        ((com.mysql.jdbc.Connection)failoverConn).setPreferSlaveDuringFailover(true);
 
2086
                        
 
2087
                        failoverStmt = failoverConn.createStatement();
 
2088
                        
 
2089
                        String masterConnectionId = getSingleIndexedValueWithQuery(failoverConn, 1, "SELECT connection_id()").toString();
 
2090
                        
 
2091
                        
 
2092
                        this.stmt.execute("KILL " + masterConnectionId);
 
2093
                        
 
2094
                        // die trying, so we get the next host
 
2095
                        for (int i = 0; i < 100; i++) {
 
2096
                                try {
 
2097
                                        failoverStmt.executeQuery("SELECT 1");
 
2098
                                } catch (SQLException sqlEx) {
 
2099
                                        break;
 
2100
                                }
 
2101
                        }
 
2102
                        
 
2103
                        String slaveConnectionId = getSingleIndexedValueWithQuery(failoverConn, 1, "SELECT connection_id()").toString();
 
2104
                        
 
2105
                        assertTrue("Didn't get a new physical connection",
 
2106
                                        !masterConnectionId.equals(slaveConnectionId));
 
2107
                        
 
2108
                        failoverConn.setReadOnly(false); // this should be ignored
 
2109
                        
 
2110
                        assertTrue(failoverConn.isReadOnly());
 
2111
                        
 
2112
                        ((com.mysql.jdbc.Connection)failoverConn).setPreferSlaveDuringFailover(false);
 
2113
                        
 
2114
                        this.stmt.execute("KILL " + slaveConnectionId); // we can't issue this on our own connection :p
 
2115
                        
 
2116
                        // die trying, so we get the next host
 
2117
                        for (int i = 0; i < 100; i++) {
 
2118
                                try {
 
2119
                                        failoverStmt.executeQuery("SELECT 1");
 
2120
                                } catch (SQLException sqlEx) {
 
2121
                                        break;
 
2122
                                }
 
2123
                        }
 
2124
                        
 
2125
                        String newMasterId = getSingleIndexedValueWithQuery(failoverConn, 1, "SELECT connection_id()").toString();
 
2126
                        
 
2127
                        assertTrue("Didn't get a new physical connection",
 
2128
                                        !slaveConnectionId.equals(newMasterId));
 
2129
                        
 
2130
                        failoverConn.setReadOnly(false);
 
2131
                        
 
2132
                        assertTrue(!failoverConn.isReadOnly());
 
2133
                } finally {
 
2134
                        if (failoverStmt != null) {
 
2135
                                failoverStmt.close();
 
2136
                        }
 
2137
                        
 
2138
                        if (failoverConn != null) {
 
2139
                                failoverConn.close();
 
2140
                        }
 
2141
                }
 
2142
        }
 
2143
}
 
 
b'\\ No newline at end of file'