KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > testsuite > regression > StatementRegressionTest


1 /*
2  Copyright (C) 2002-2004 MySQL AB
3
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of version 2 of the GNU General Public License as
6  published by the Free Software Foundation.
7
8  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.ByteArrayInputStream JavaDoc;
28 import java.io.CharArrayReader JavaDoc;
29 import java.io.File JavaDoc;
30 import java.io.FileOutputStream JavaDoc;
31 import java.io.FileWriter JavaDoc;
32 import java.io.Writer JavaDoc;
33 import java.math.BigDecimal JavaDoc;
34 import java.sql.BatchUpdateException JavaDoc;
35 import java.sql.Blob JavaDoc;
36 import java.sql.Clob JavaDoc;
37 import java.sql.Connection JavaDoc;
38 import java.sql.DataTruncation JavaDoc;
39 import java.sql.Date JavaDoc;
40 import java.sql.PreparedStatement JavaDoc;
41 import java.sql.ResultSet JavaDoc;
42 import java.sql.SQLException JavaDoc;
43 import java.sql.SQLWarning JavaDoc;
44 import java.sql.Statement JavaDoc;
45 import java.sql.Time JavaDoc;
46 import java.sql.Timestamp JavaDoc;
47 import java.sql.Types JavaDoc;
48 import java.text.SimpleDateFormat JavaDoc;
49 import java.util.Calendar JavaDoc;
50 import java.util.Properties JavaDoc;
51 import java.util.TimeZone JavaDoc;
52
53 import testsuite.BaseTestCase;
54
55 import com.mysql.jdbc.SQLError;
56 import com.mysql.jdbc.ServerPreparedStatement;
57
58 /**
59  * Regression tests for the Statement class
60  *
61  * @author Mark Matthews
62  */

63 public class StatementRegressionTest extends BaseTestCase {
64     class PrepareThread extends Thread JavaDoc {
65         Connection JavaDoc c;
66
67         PrepareThread(Connection JavaDoc cn) {
68             c = cn;
69         }
70
71         public void run() {
72             for (int i = 0; i < 20; i++) // force this to end eventually
73
{
74                 try {
75                     c.prepareStatement("SELECT 1");
76                     testServerPrepStmtDeadlockCounter++;
77                     Thread.sleep(400);
78                 } catch (SQLException JavaDoc sqlEx) {
79                     throw new RuntimeException JavaDoc(sqlEx);
80                 } catch (InterruptedException JavaDoc e) {
81                     e.printStackTrace();
82                 }
83             }
84         }
85     }
86
87     /*
88      * Each row in this table is to be converted into a single REPLACE
89      * statement. If the value is zero, a new record is to be created using then
90      * autoincrement feature. If the value is non-zero, the existing row of that
91      * value is to be replace with, obviously, the same key. I expect one
92      * Generated Key for each zero value - but I would accept one key for each
93      * value, with non-zero values coming back as themselves.
94      */

95     static final int[][] tests = { { 0 }, // generate 1
96
{ 1, 0, 0 }, // update 1, generate 2, 3
97
{ 2, 0, 0, }, // update 2, generate 3, 4
98
};
99
100     static int nextID = 1; // The next ID we expected to generate
101

102     static int count = 0;
103
104     private int testServerPrepStmtDeadlockCounter = 0;
105
106     /**
107      * Constructor for StatementRegressionTest.
108      *
109      * @param name
110      * the name of the test to run
111      */

112     public StatementRegressionTest(String JavaDoc name) {
113         super(name);
114     }
115
116     /**
117      * Runs all test cases in this test suite
118      *
119      * @param args
120      */

121     public static void main(String JavaDoc[] args) {
122         junit.textui.TestRunner.run(StatementRegressionTest.class);
123     }
124
125     /**
126      * Tests fix for BUG#1774 -- Truncated words after double quote
127      *
128      * @throws Exception
129      * if the test fails.
130      */

131     public void testBug1774() throws Exception JavaDoc {
132         try {
133             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1774");
134             this.stmt
135                     .executeUpdate("CREATE TABLE testBug1774 (field1 VARCHAR(255))");
136
137             PreparedStatement JavaDoc pStmt = this.conn
138                     .prepareStatement("INSERT INTO testBug1774 VALUES (?)");
139
140             String JavaDoc testString = "The word contains \" character";
141
142             pStmt.setString(1, testString);
143             pStmt.executeUpdate();
144
145             this.rs = this.stmt.executeQuery("SELECT * FROM testBug1774");
146             this.rs.next();
147             assertTrue(this.rs.getString(1).equals(testString));
148         } finally {
149             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1774");
150         }
151     }
152
153     /**
154      * Tests fix for BUG#1901 -- PreparedStatement.setObject(int, Object, int,
155      * int) doesn't support CLOB or BLOB types.
156      *
157      * @throws Exception
158      * if this test fails for any reason
159      */

160     public void testBug1901() throws Exception JavaDoc {
161         try {
162             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1901");
163             this.stmt
164                     .executeUpdate("CREATE TABLE testBug1901 (field1 VARCHAR(255))");
165             this.stmt.executeUpdate("INSERT INTO testBug1901 VALUES ('aaa')");
166
167             this.rs = this.stmt.executeQuery("SELECT field1 FROM testBug1901");
168             this.rs.next();
169
170             Clob JavaDoc valueAsClob = this.rs.getClob(1);
171             Blob JavaDoc valueAsBlob = this.rs.getBlob(1);
172
173             PreparedStatement JavaDoc pStmt = this.conn
174                     .prepareStatement("INSERT INTO testBug1901 VALUES (?)");
175             pStmt.setObject(1, valueAsClob, java.sql.Types.CLOB, 0);
176             pStmt.executeUpdate();
177             pStmt.setObject(1, valueAsBlob, java.sql.Types.BLOB, 0);
178             pStmt.executeUpdate();
179         } finally {
180             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1901");
181         }
182     }
183
184     /**
185      * Test fix for BUG#1933 -- Driver property 'maxRows' has no effect.
186      *
187      * @throws Exception
188      * if the test fails.
189      */

190     public void testBug1933() throws Exception JavaDoc {
191         if (versionMeetsMinimum(4, 0)) {
192             Connection JavaDoc maxRowsConn = null;
193             PreparedStatement JavaDoc maxRowsPrepStmt = null;
194             Statement JavaDoc maxRowsStmt = null;
195
196             try {
197                 Properties JavaDoc props = new Properties JavaDoc();
198
199                 props.setProperty("maxRows", "1");
200
201                 maxRowsConn = getConnectionWithProps(props);
202
203                 maxRowsStmt = maxRowsConn.createStatement();
204
205                 assertTrue(maxRowsStmt.getMaxRows() == 1);
206
207                 this.rs = maxRowsStmt.executeQuery("SELECT 1 UNION SELECT 2");
208
209                 this.rs.next();
210
211                 maxRowsPrepStmt = maxRowsConn
212                         .prepareStatement("SELECT 1 UNION SELECT 2");
213
214                 assertTrue(maxRowsPrepStmt.getMaxRows() == 1);
215
216                 this.rs = maxRowsPrepStmt.executeQuery();
217
218                 this.rs.next();
219
220                 assertTrue(!this.rs.next());
221
222                 props.setProperty("useServerPrepStmts", "false");
223
224                 maxRowsConn = getConnectionWithProps(props);
225
226                 maxRowsPrepStmt = maxRowsConn
227                         .prepareStatement("SELECT 1 UNION SELECT 2");
228
229                 assertTrue(maxRowsPrepStmt.getMaxRows() == 1);
230
231                 this.rs = maxRowsPrepStmt.executeQuery();
232
233                 this.rs.next();
234
235                 assertTrue(!this.rs.next());
236             } finally {
237                 maxRowsConn.close();
238             }
239         }
240     }
241
242     /**
243      * Tests the fix for BUG#1934 -- prepareStatement dies silently when
244      * encountering Statement.RETURN_GENERATED_KEY
245      *
246      * @throws Exception
247      * if the test fails
248      */

249     public void testBug1934() throws Exception JavaDoc {
250         try {
251             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1934");
252             this.stmt.executeUpdate("CREATE TABLE testBug1934 (field1 INT)");
253
254             System.out.println("Before prepareStatement()");
255
256             this.pstmt = this.conn.prepareStatement(
257                     "INSERT INTO testBug1934 VALUES (?)",
258                     java.sql.Statement.RETURN_GENERATED_KEYS);
259
260             assertTrue(this.pstmt != null);
261
262             System.out.println("After prepareStatement() - " + this.pstmt);
263         } finally {
264             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1934");
265         }
266     }
267
268     /**
269      * Tests fix for BUG#1958 - Improper bounds checking on
270      * PreparedStatement.setFoo().
271      *
272      * @throws Exception
273      * if the test fails.
274      */

275     public void testBug1958() throws Exception JavaDoc {
276         PreparedStatement JavaDoc pStmt = null;
277
278         try {
279             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1958");
280             this.stmt.executeUpdate("CREATE TABLE testBug1958 (field1 int)");
281
282             pStmt = this.conn
283                     .prepareStatement("SELECT * FROM testBug1958 WHERE field1 IN (?, ?, ?)");
284
285             try {
286                 pStmt.setInt(4, 1);
287             } catch (SQLException JavaDoc sqlEx) {
288                 assertTrue(SQLError.SQL_STATE_ILLEGAL_ARGUMENT.equals(sqlEx
289                         .getSQLState()));
290             }
291         } finally {
292             if (pStmt != null) {
293                 pStmt.close();
294             }
295
296             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug1958");
297         }
298     }
299
300     /**
301      * Tests the fix for BUG#2606, server-side prepared statements not returning
302      * datatype YEAR correctly.
303      *
304      * @throws Exception
305      * if the test fails.
306      */

307     public void testBug2606() throws Exception JavaDoc {
308         try {
309             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug2606");
310             this.stmt
311                     .executeUpdate("CREATE TABLE testBug2606(year_field YEAR)");
312             this.stmt.executeUpdate("INSERT INTO testBug2606 VALUES (2004)");
313
314             PreparedStatement JavaDoc yrPstmt = this.conn
315                     .prepareStatement("SELECT year_field FROM testBug2606");
316
317             this.rs = yrPstmt.executeQuery();
318
319             assertTrue(this.rs.next());
320
321             assertEquals(2004, this.rs.getInt(1));
322         } finally {
323             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug2606");
324         }
325     }
326
327     /**
328      * Tests the fix for BUG#2671, nulls encoded incorrectly in server-side
329      * prepared statements.
330      *
331      * @throws Exception
332      * if an error occurs.
333      */

334     public void testBug2671() throws Exception JavaDoc {
335         if (versionMeetsMinimum(4, 1)) {
336             try {
337                 this.stmt.executeUpdate("DROP TABLE IF EXISTS test3");
338                 this.stmt
339                         .executeUpdate("CREATE TABLE test3 ("
340                                 + " `field1` int(8) NOT NULL auto_increment,"
341                                 + " `field2` int(8) unsigned zerofill default NULL,"
342                                 + " `field3` varchar(30) binary NOT NULL default '',"
343                                 + " `field4` varchar(100) default NULL,"
344                                 + " `field5` datetime NOT NULL default '0000-00-00 00:00:00',"
345                                 + " PRIMARY KEY (`field1`),"
346                                 + " UNIQUE KEY `unq_id` (`field2`),"
347                                 + " UNIQUE KEY (`field3`),"
348                                 + " UNIQUE KEY (`field2`)"
349                                 + " ) TYPE=InnoDB CHARACTER SET utf8");
350
351                 this.stmt
352                         .executeUpdate("insert into test3 (field1, field3, field4) values (1,'blewis','Bob Lewis')");
353
354                 String JavaDoc query = " " + "UPDATE "
355                         + " test3 "
356                         + "SET "
357                         + " field2=? " + " ,field3=? "
358                         + " ,field4=? " + " ,field5=? "
359                         + "WHERE "
360                         + " field1 = ? ";
361
362                 java.sql.Date JavaDoc mydate = null;
363
364                 this.pstmt = this.conn.prepareStatement(query);
365
366                 this.pstmt.setInt(1, 13);
367                 this.pstmt.setString(2, "abc");
368                 this.pstmt.setString(3, "def");
369                 this.pstmt.setDate(4, mydate);
370                 this.pstmt.setInt(5, 1);
371
372                 int retval = this.pstmt.executeUpdate();
373                 assertTrue(retval == 1);
374             } finally {
375                 this.stmt.executeUpdate("DROP TABLE IF EXISTS test3");
376             }
377         }
378     }
379
380     /**
381      * Tests fix for BUG#3103 -- java.util.Date not accepted as parameter to
382      * PreparedStatement.setObject().
383      *
384      * @throws Exception
385      * if the test fails
386      *
387      * @deprecated uses deprecated methods of Date class
388      */

389     public void testBug3103() throws Exception JavaDoc {
390         try {
391             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3103");
392             this.stmt
393                     .executeUpdate("CREATE TABLE testBug3103 (field1 DATETIME)");
394
395             PreparedStatement JavaDoc pStmt = this.conn
396                     .prepareStatement("INSERT INTO testBug3103 VALUES (?)");
397
398             java.util.Date JavaDoc utilDate = new java.util.Date JavaDoc();
399
400             pStmt.setObject(1, utilDate);
401             pStmt.executeUpdate();
402
403             this.rs = this.stmt.executeQuery("SELECT field1 FROM testBug3103");
404             this.rs.next();
405
406             java.util.Date JavaDoc retrUtilDate = new java.util.Date JavaDoc(this.rs
407                     .getTimestamp(1).getTime());
408
409             // We can only compare on the day/month/year hour/minute/second
410
// interval, because the timestamp has added milliseconds to the
411
// internal date...
412
assertTrue("Dates not equal", (utilDate.getMonth() == retrUtilDate
413                     .getMonth())
414                     && (utilDate.getDate() == retrUtilDate.getDate())
415                     && (utilDate.getYear() == retrUtilDate.getYear())
416                     && (utilDate.getHours() == retrUtilDate.getHours())
417                     && (utilDate.getMinutes() == retrUtilDate.getMinutes())
418                     && (utilDate.getSeconds() == retrUtilDate.getSeconds()));
419         } finally {
420             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3103");
421         }
422     }
423
424     /**
425      * Tests fix for BUG#3520
426      *
427      * @throws Exception
428      * ...
429      */

430     public void testBug3520() throws Exception JavaDoc {
431         try {
432             this.stmt.executeUpdate("DROP TABLE IF EXISTS t");
433             this.stmt.executeUpdate("CREATE TABLE t (s1 int,primary key (s1))");
434             this.stmt.executeUpdate("INSERT INTO t VALUES (1)");
435             this.stmt.executeUpdate("INSERT INTO t VALUES (1)");
436         } catch (SQLException JavaDoc sqlEx) {
437             System.out.println(sqlEx.getSQLState());
438         } finally {
439             this.stmt.executeUpdate("DROP TABLE IF EXISTS t");
440         }
441     }
442
443     /**
444      * Test fix for BUG#3557 -- UpdatableResultSet not picking up default values
445      *
446      * @throws Exception
447      * if test fails.
448      */

449     public void testBug3557() throws Exception JavaDoc {
450         try {
451             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3557");
452
453             this.stmt.executeUpdate("CREATE TABLE testBug3557 ( "
454                     + "`a` varchar(255) NOT NULL default 'XYZ', "
455                     + "`b` varchar(255) default '123', "
456                     + "PRIMARY KEY (`a`))");
457
458             Statement JavaDoc updStmt = this.conn
459                     .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
460                             ResultSet.CONCUR_UPDATABLE);
461             this.rs = updStmt.executeQuery("SELECT * FROM testBug3557");
462
463             assertTrue(this.rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
464
465             this.rs.moveToInsertRow();
466
467             assertEquals("XYZ", this.rs.getObject(1));
468             assertEquals("123", this.rs.getObject(2));
469         } finally {
470             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3557");
471         }
472     }
473
474     /**
475      * Tests fix for BUG#3620 -- Timezone not respected correctly.
476      *
477      * @throws SQLException
478      * if the test fails.
479      */

480     public void testBug3620() throws SQLException JavaDoc {
481         long epsillon = 3000; // 3 seconds time difference
482

483         try {
484             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3620");
485             this.stmt
486                     .executeUpdate("CREATE TABLE testBug3620 (field1 TIMESTAMP)");
487
488             PreparedStatement JavaDoc tsPstmt = this.conn
489                     .prepareStatement("INSERT INTO testBug3620 VALUES (?)");
490
491             Calendar JavaDoc pointInTime = Calendar.getInstance();
492             pointInTime.set(2004, 02, 29, 10, 0, 0);
493
494             long pointInTimeOffset = pointInTime.getTimeZone().getRawOffset();
495
496             java.sql.Timestamp JavaDoc ts = new java.sql.Timestamp JavaDoc(pointInTime
497                     .getTime().getTime());
498
499             tsPstmt.setTimestamp(1, ts);
500             tsPstmt.executeUpdate();
501
502             String JavaDoc tsValueAsString = getSingleValue("testBug3620", "field1",
503                     null).toString();
504
505             System.out.println("Timestamp as string with no calendar: "
506                     + tsValueAsString.toString());
507
508             Calendar JavaDoc cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
509
510             this.stmt.executeUpdate("DELETE FROM testBug3620");
511
512             Properties JavaDoc props = new Properties JavaDoc();
513             props.put("useTimezone", "true");
514             // props.put("serverTimezone", "UTC");
515

516             Connection JavaDoc tzConn = getConnectionWithProps(props);
517
518             Statement JavaDoc tsStmt = tzConn.createStatement();
519
520             tsPstmt = tzConn
521                     .prepareStatement("INSERT INTO testBug3620 VALUES (?)");
522
523             tsPstmt.setTimestamp(1, ts, cal);
524             tsPstmt.executeUpdate();
525
526             tsValueAsString = getSingleValue("testBug3620", "field1", null)
527                     .toString();
528
529             Timestamp JavaDoc tsValueAsTimestamp = (Timestamp JavaDoc) getSingleValue(
530                     "testBug3620", "field1", null);
531
532             System.out.println("Timestamp as string with UTC calendar: "
533                     + tsValueAsString.toString());
534             System.out.println("Timestamp as Timestamp with UTC calendar: "
535                     + tsValueAsTimestamp);
536
537             this.rs = tsStmt.executeQuery("SELECT field1 FROM testBug3620");
538             this.rs.next();
539
540             Timestamp JavaDoc tsValueUTC = this.rs.getTimestamp(1, cal);
541
542             //
543
// We use this testcase with other vendors, JDBC spec
544
// requires result set fields can only be read once,
545
// although MySQL doesn't require this ;)
546
//
547
this.rs = tsStmt.executeQuery("SELECT field1 FROM testBug3620");
548             this.rs.next();
549
550             Timestamp JavaDoc tsValueStmtNoCal = this.rs.getTimestamp(1);
551
552             System.out
553                     .println("Timestamp specifying UTC calendar from normal statement: "
554                             + tsValueUTC.toString());
555
556             PreparedStatement JavaDoc tsPstmtRetr = tzConn
557                     .prepareStatement("SELECT field1 FROM testBug3620");
558
559             this.rs = tsPstmtRetr.executeQuery();
560             this.rs.next();
561
562             Timestamp JavaDoc tsValuePstmtUTC = this.rs.getTimestamp(1, cal);
563
564             System.out
565                     .println("Timestamp specifying UTC calendar from prepared statement: "
566                             + tsValuePstmtUTC.toString());
567
568             //
569
// We use this testcase with other vendors, JDBC spec
570
// requires result set fields can only be read once,
571
// although MySQL doesn't require this ;)
572
//
573
this.rs = tsPstmtRetr.executeQuery();
574             this.rs.next();
575
576             Timestamp JavaDoc tsValuePstmtNoCal = this.rs.getTimestamp(1);
577
578             System.out
579                     .println("Timestamp specifying no calendar from prepared statement: "
580                             + tsValuePstmtNoCal.toString());
581
582             long stmtDeltaTWithCal = (ts.getTime() - tsValueStmtNoCal.getTime());
583
584             long deltaOrig = Math.abs(stmtDeltaTWithCal - pointInTimeOffset);
585
586             assertTrue(
587                     "Difference between original timestamp and timestamp retrieved using java.sql.Statement "
588                             + "set in database using UTC calendar is not ~= "
589                             + epsillon + ", it is actually " + deltaOrig,
590                     (deltaOrig < epsillon));
591
592             long pStmtDeltaTWithCal = (ts.getTime() - tsValuePstmtNoCal
593                     .getTime());
594
595             System.out
596                     .println(Math.abs(pStmtDeltaTWithCal - pointInTimeOffset)
597                             + " < "
598                             + epsillon
599                             + (Math.abs(pStmtDeltaTWithCal - pointInTimeOffset) < epsillon));
600             assertTrue(
601                     "Difference between original timestamp and timestamp retrieved using java.sql.PreparedStatement "
602                             + "set in database using UTC calendar is not ~= "
603                             + epsillon
604                             + ", it is actually "
605                             + pStmtDeltaTWithCal, (Math.abs(pStmtDeltaTWithCal
606                             - pointInTimeOffset) < epsillon));
607
608             System.out
609                     .println("Difference between original ts and ts with no calendar: "
610                             + (ts.getTime() - tsValuePstmtNoCal.getTime())
611                             + ", offset should be " + pointInTimeOffset);
612         } finally {
613             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3620");
614         }
615     }
616
617     /**
618      * Tests that DataTruncation is thrown when data is truncated.
619      *
620      * @throws Exception
621      * if the test fails.
622      */

623     public void testBug3697() throws Exception JavaDoc {
624         try {
625             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3697");
626             this.stmt
627                     .executeUpdate("CREATE TABLE testBug3697 (field1 VARCHAR(255))");
628
629             StringBuffer JavaDoc updateBuf = new StringBuffer JavaDoc(
630                     "INSERT INTO testBug3697 VALUES ('");
631
632             for (int i = 0; i < 512; i++) {
633                 updateBuf.append("A");
634             }
635
636             updateBuf.append("')");
637
638             try {
639                 this.stmt.executeUpdate(updateBuf.toString());
640             } catch (DataTruncation JavaDoc dtEx) {
641                 // This is an expected exception....
642
}
643
644             SQLWarning JavaDoc warningChain = this.stmt.getWarnings();
645
646             System.out.println(warningChain);
647         } finally {
648             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3697");
649         }
650     }
651
652     /**
653      * Tests fix for BUG#3804, data truncation on server should throw
654      * DataTruncation exception.
655      *
656      * @throws Exception
657      * if the test fails
658      */

659     public void testBug3804() throws Exception JavaDoc {
660         if (versionMeetsMinimum(4, 1)) {
661             try {
662                 this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3804");
663                 this.stmt
664                         .executeUpdate("CREATE TABLE testBug3804 (field1 VARCHAR(5))");
665
666                 boolean caughtTruncation = false;
667
668                 try {
669                     this.stmt
670                             .executeUpdate("INSERT INTO testBug3804 VALUES ('1234567')");
671                 } catch (DataTruncation JavaDoc truncationEx) {
672                     caughtTruncation = true;
673                     System.out.println(truncationEx);
674                 }
675
676                 assertTrue("Data truncation exception should've been thrown",
677                         caughtTruncation);
678             } finally {
679                 this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3804");
680             }
681         }
682     }
683
684     /**
685      * Tests BUG#3873 - PreparedStatement.executeBatch() not returning all
686      * generated keys (even though that's not JDBC compliant).
687      *
688      * @throws Exception
689      * if the test fails
690      */

691     public void testBug3873() throws Exception JavaDoc {
692         PreparedStatement JavaDoc batchStmt = null;
693
694         try {
695             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3873");
696             this.stmt
697                     .executeUpdate("CREATE TABLE testBug3873 (keyField INT NOT NULL PRIMARY KEY AUTO_INCREMENT, dataField VARCHAR(32))");
698             batchStmt = this.conn.prepareStatement(
699                     "INSERT INTO testBug3873 (dataField) VALUES (?)",
700                     Statement.RETURN_GENERATED_KEYS);
701             batchStmt.setString(1, "abc");
702             batchStmt.addBatch();
703             batchStmt.setString(1, "def");
704             batchStmt.addBatch();
705             batchStmt.setString(1, "ghi");
706             batchStmt.addBatch();
707
708             int[] updateCounts = batchStmt.executeBatch();
709
710             this.rs = batchStmt.getGeneratedKeys();
711
712             while (this.rs.next()) {
713                 System.out.println(this.rs.getInt(1));
714             }
715
716             this.rs = batchStmt.getGeneratedKeys();
717             assertTrue(this.rs.next());
718             assertTrue(1 == this.rs.getInt(1));
719             assertTrue(this.rs.next());
720             assertTrue(2 == this.rs.getInt(1));
721             assertTrue(this.rs.next());
722             assertTrue(3 == this.rs.getInt(1));
723             assertTrue(!this.rs.next());
724         } finally {
725             if (batchStmt != null) {
726                 batchStmt.close();
727             }
728
729             this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug3873");
730         }
731     }
732
733     /**
734      * Tests that you can close a statement twice without an NPE.
735      *
736      * @throws Exception
737      * if an error occurs.
738      */

739     public void testCloseTwice() throws Exception JavaDoc {
740         Statement JavaDoc closeMe = this.conn.createStatement();
741         closeMe.close();
742         closeMe.close();
743     }
744
745     /**
746      * Tests all forms of statements influencing getGeneratedKeys().
747      *
748      * @throws Exception
749      * if the test fails.
750      */

751     public void testGetGeneratedKeysAllCases() throws Exception JavaDoc {
752         System.out.println("Using Statement.executeUpdate()\n");
753
754         try {
755             createGGKTables();
756
757             // Do the tests
758
for (int i = 0; i < tests.length; i++) {
759                 doGGKTestStatement(tests[i], true);
760             }
761         } finally {
762             dropGGKTables();
763         }
764
765         nextID = 1;
766         count = 0;
767
768         System.out.println("Using Statement.execute()\n");
769
770         try {
771             createGGKTables();
772
773             // Do the tests
774
for (int i = 0; i < tests.length; i++) {
775                 doGGKTestStatement(tests[i], false);
776             }
777         } finally {
778             dropGGKTables();
779         }
780
781         nextID = 1;
782         count = 0;
783
784         System.out.println("Using PreparedStatement.executeUpdate()\n");
785
786         try {
787             createGGKTables();
788
789             // Do the tests
790
for (int i = 0; i < tests.length; i++) {
791                 doGGKTestPreparedStatement(tests[i], true);
792             }
793         } finally {
794             dropGGKTables();
795