001: /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the Hypersonic SQL Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: *
030: * This software consists of voluntary contributions made by many individuals
031: * on behalf of the Hypersonic SQL Group.
032: *
033: *
034: * For work added by the HSQL Development Group:
035: *
036: * Copyright (c) 2001-2005, The HSQL Development Group
037: * All rights reserved.
038: *
039: * Redistribution and use in source and binary forms, with or without
040: * modification, are permitted provided that the following conditions are met:
041: *
042: * Redistributions of source code must retain the above copyright notice, this
043: * list of conditions and the following disclaimer.
044: *
045: * Redistributions in binary form must reproduce the above copyright notice,
046: * this list of conditions and the following disclaimer in the documentation
047: * and/or other materials provided with the distribution.
048: *
049: * Neither the name of the HSQL Development Group nor the names of its
050: * contributors may be used to endorse or promote products derived from this
051: * software without specific prior written permission.
052: *
053: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
054: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
055: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
056: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
057: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
058: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
059: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
060: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
061: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
062: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
063: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
064: */
065:
066: package org.hsqldb.test;
067:
068: import java.io.File;
069: import java.sql.Connection;
070: import java.sql.DatabaseMetaData;
071: import java.sql.Date;
072: import java.sql.DriverManager;
073: import java.sql.PreparedStatement;
074: import java.sql.ResultSet;
075: import java.sql.Statement;
076: import java.sql.Types;
077:
078: import org.hsqldb.lib.Sort;
079:
080: /**
081: * Main test class, containing several JDBC and script based tests to
082: * verify correct operation of the engine.<p>
083: *
084: * The tests consist of the following:
085: * <ul>
086: * <li>
087: * Built-in tests for operations, especially those relating to JDBC.
088: *</li>
089: * <li>
090: * Speed tests using insert / delete / update on a simple table.<p>
091: *</li>
092: * <li>
093: * Script based SQL tests consisting of:<p>
094: * <code>TestSelf.txt</code> : the main test script.<p>
095: * <code>TestSelfXXXX.txt</code> : specialised test scripts that
096: * will be run in alphabetical filename order.<p>
097: *</li>
098: * </ul>
099: *
100: * Tests can be added by writing new scripts in the standard format described
101: * in <code>TestSelf.txt</code> and naming the script in the correct format,
102: * <code>TestSelfXXXX.txt</code>, where XXXX is the description of the new
103: * test.<p>
104: * The database can be shutdown at the end of each script (using the
105: * SHUTDOWN command). This allows a test to be divided into two or more
106: * scripts in order to test the persistence mechanism for both objects
107: * created via DDL or data stored in the database. An example of this
108: * is the set of supplied scripts, <code>TestSelfCreate.txt</code>,
109: * <code>TestSelfModify.txt</code> and <code>TestSelfVerify.txt</code>.
110: * (fredt@users)
111: *
112: * @author Thomas Mueller (Hypersonic SQL Group)
113: * @version 1.7.2
114: * @since Hypersonic SQL
115: */
116: class TestSelf extends TestUtil {
117:
118: /**
119: * This test in invoked from the command line using:
120: * <pre>
121: * TestSelf [records [-m]]
122: *
123: * </pre>
124: *
125: * -m means run the tests in-memory only
126: *
127: * @param argv
128: */
129: public static void main(String[] argv) {
130:
131: print("Usage: TestSelf [records [-m]] (-m means in-memory only)");
132:
133: int max = 500;
134:
135: if (argv.length >= 1) {
136: max = Integer.parseInt(argv[0]);
137: }
138:
139: boolean persistent = true;
140: boolean update = false;
141:
142: if (argv.length >= 2) {
143: String a1 = argv[1];
144:
145: if (a1.equals("-m")) {
146: persistent = false;
147: }
148: }
149:
150: test(max, persistent);
151: }
152:
153: /**
154: * Method declaration
155: *
156: * @param max
157: * @param persistent
158: */
159: static void test(int max, boolean persistent) {
160:
161: // DriverManager.setLogStream(System.out);
162: try {
163: DriverManager.registerDriver(new org.hsqldb.jdbcDriver());
164:
165: if (persistent) {
166: testPersistence();
167: deleteDatabase("test2");
168: test("jdbc:hsqldb:test2", "sa", "", true);
169: testPerformance("jdbc:hsqldb:test2", "sa", "", max,
170: true);
171: }
172:
173: test("jdbc:hsqldb:.", "sa", "", false);
174: testPerformance("jdbc:hsqldb:.", "sa", "", max, false);
175: } catch (Exception e) {
176: print("TestSelf error: " + e.getMessage());
177: e.printStackTrace();
178: }
179: }
180:
181: static void delete(String file) {
182:
183: try {
184: new File(file).delete();
185: } catch (Exception e) {
186: }
187: }
188:
189: static void deleteDatabase(String path) {
190:
191: delete(path + ".backup");
192: delete(path + ".properties");
193: delete(path + ".script");
194: delete(path + ".data");
195: delete(path + ".log");
196: }
197:
198: static void test(String url, String user, String password,
199: boolean persistent) throws Exception {
200:
201: String name = persistent ? "Persistent" : "Memory";
202:
203: print(name);
204:
205: Connection cConnection = null;
206:
207: try {
208: cConnection = DriverManager.getConnection(url, user,
209: password);
210: } catch (Exception e) {
211: e.printStackTrace();
212: print("TestSelf init error: " + e.getMessage());
213: }
214:
215: testMainScript(cConnection, persistent);
216: testTabProfile(cConnection, persistent);
217: testMarotest(cConnection, persistent);
218: cConnection.createStatement().execute("SHUTDOWN");
219: cConnection.close();
220: }
221:
222: static void testPersistence() {
223:
224: deleteDatabase("test1");
225:
226: try {
227: String url = "jdbc:hsqldb:test1;sql.enforce_strict_size=true";
228: String user = "sa";
229: String password = "";
230: Connection cConnection = null;
231: String[] filelist;
232: String absolute = new File("TestSelf.txt")
233: .getAbsolutePath();
234:
235: filelist = new File(new File(absolute).getParent()).list();
236:
237: Sort.sort((Object[]) filelist, new Sort.StringComparator(),
238: 0, filelist.length - 1);
239:
240: for (int i = 0; i < filelist.length; i++) {
241: String fname = filelist[i];
242:
243: if (fname.startsWith("TestSelf")
244: && fname.endsWith(".txt")
245: && !fname.equals("TestSelf.txt")) {
246: print("Openning DB");
247:
248: cConnection = DriverManager.getConnection(url,
249: user, password);
250:
251: testScript(cConnection, fname);
252: cConnection.close();
253: }
254: }
255: } catch (Exception e) {
256: e.printStackTrace();
257: print("TestSelf init error: " + e.getMessage());
258: }
259: }
260:
261: static void testMainScript(Connection cConnection,
262: boolean persistent) {
263:
264: String name = persistent ? "Persistent" : "Memory";
265:
266: print(name + " TestScript");
267:
268: // location of TestSelf.txt relative to the development environment
269: String path = "TestSelf.txt";
270:
271: testScript(cConnection, path);
272: }
273:
274: static byte[] b1 = { 0, 1, -128, 44, 12 };
275: static byte[] b2 = { 10, 127 };
276:
277: static void testTabProfile(Connection cConnection,
278: boolean persistent) {
279:
280: Statement sStatement = null;
281: ResultSet r;
282: String s = "";
283: long start;
284: boolean bDropError = false;
285: String name = persistent ? "Persistent" : "Memory";
286:
287: print(name + " TabProfile");
288:
289: try {
290: sStatement = cConnection.createStatement();
291: } catch (Exception e) {
292: e.printStackTrace();
293: print("TabProfile init error: " + e.getMessage());
294:
295: return;
296: }
297:
298: try {
299:
300: // prepared statements
301: s = "create table TabProfile(id int primary key,"
302: + "car char,won bit,licence varbinary,"
303: + "name char,sex char,chance double,birthday date,temp char)";
304:
305: sStatement.execute(s);
306:
307: s = "insert into TabProfile values ( ?, ?, ?, ?,"
308: + "'\"John\" the bird''s best friend', 'M',?,?,'')";
309:
310: PreparedStatement p = cConnection.prepareStatement(s);
311:
312: p.clearParameters();
313: p.setInt(1, 10);
314: p.setString(2, "Matchcartoon");
315: p.setBoolean(3, true);
316: p.setBytes(4, b1);
317: p.setDouble(5, 50.5);
318: p.setNull(6, Types.DATE);
319: p.executeUpdate();
320: p.clearParameters();
321: p.setInt(1, -2);
322: p.setString(2, "\"Birdie\"'s car ?");
323: p.setBoolean(3, false);
324:
325: byte[] b2 = { 10, 127 };
326:
327: p.setBytes(4, b2);
328: p.setDouble(5, -3.1415e-20);
329:
330: java.util.Calendar cal = java.util.Calendar.getInstance();
331:
332: cal.set(2000, 2, 29);
333:
334: // fredt@users - who designed the java.util.Calendar API?
335: p.setDate(6, new Date(cal.getTime().getTime()));
336: p.executeUpdate();
337: readTabProfileTest(sStatement);
338:
339: byte[] b2n;
340: byte[] b1n;
341: boolean mismatch;
342:
343: s = "select \"org.hsqldb.lib.ArrayUtil.containsAt\"(licence,0, ?) "
344: + "from TabProfile";
345: p = cConnection.prepareStatement(s);
346:
347: p.setBytes(1, b2);
348:
349: r = p.executeQuery();
350:
351: r.next();
352:
353: boolean boo1 = r.getBoolean(1);
354:
355: r.next();
356:
357: boolean boo2 = r.getBoolean(1);
358:
359: // test boo1 != boo2
360:
361: /** @todo fredt - nested procedure call doesn't parse */
362: /*
363: s = "select \"org.hsqldb.lib.StringConverter.hexToByte\""
364: + "(\"org.hsqldb.lib.StringConverter.byteToHex\"(car)) "
365: + "from TabProfile";
366: r = sStatement.executeQuery(s);
367:
368: r.next();
369:
370: b1n = r.getBytes(1);
371:
372: r.next();
373:
374: b1n = r.getBytes(1);
375: */
376:
377: /** @todo fredt - alias does not resolve */
378: /*
379: s = "select \"org.hsqldb.lib.StringConverter.byteToHex\"(car) temp, " +
380: "\"org.hsqldb.lib.StringConverter.hexToByte\"(temp) "
381: + "from TabProfile";
382: r = sStatement.executeQuery(s);
383:
384: r.next();
385:
386: b1n = r.getBytes(2);
387:
388: r.next();
389:
390: b1n = r.getBytes(2);
391: */
392: s = "update tabprofile set temp = \"org.hsqldb.lib.StringConverter.byteToHex\"(licence)";
393:
394: sStatement.executeUpdate(s);
395:
396: s = "select \"org.hsqldb.lib.StringConverter.hexToByte\"(temp) "
397: + "from TabProfile order by id desc";
398: r = sStatement.executeQuery(s);
399:
400: r.next();
401:
402: b1n = r.getBytes(1);
403:
404: for (int i = 0; i < b1n.length; i++) {
405: if (b1[i] != b1n[i]) {
406: mismatch = true;
407: }
408: }
409:
410: r.next();
411:
412: b2n = r.getBytes(1);
413:
414: for (int i = 0; i < b2n.length; i++) {
415: if (b2[i] != b2n[i]) {
416: mismatch = true;
417: }
418: }
419:
420: // s = "drop table TabProfile";
421: // sStatement.execute(s);
422: s = "create table obj(id int,o object)";
423:
424: sStatement.execute(s);
425:
426: s = "insert into obj values(?,?)";
427: p = cConnection.prepareStatement(s);
428:
429: p.setInt(1, 1);
430:
431: int[] ia1 = { 1, 2, 3 };
432:
433: p.setObject(2, ia1);
434: p.executeUpdate();
435: p.clearParameters();
436: p.setInt(1, 2);
437:
438: java.awt.Rectangle r1 = new java.awt.Rectangle(10, 11, 12,
439: 13);
440:
441: p.setObject(2, r1);
442: p.executeUpdate();
443:
444: r = sStatement
445: .executeQuery("SELECT o FROM obj ORDER BY id DESC");
446:
447: r.next();
448:
449: java.awt.Rectangle r2 = (java.awt.Rectangle) r.getObject(1);
450:
451: if (r2.x != 10 || r2.y != 11 || r2.width != 12
452: || r2.height != 13) {
453: throw new Exception("Object data error: Rectangle");
454: }
455:
456: r.next();
457:
458: int[] ia2 = (int[]) (r.getObject(1));
459:
460: if (ia2[0] != 1 || ia2[1] != 2 || ia2[2] != 3
461: || ia2.length != 3) {
462: throw new Exception("Object data error: int[]");
463: }
464:
465: // s = "drop table obj";
466: // sStatement.execute(s);
467: sStatement.close();
468: } catch (Exception e) {
469: print("");
470: print("TabProfile error: " + e);
471: print("with SQL command: " + s);
472: e.printStackTrace();
473: }
474: }
475:
476: static void readTabProfileTest(Statement sStatement)
477: throws Exception {
478:
479: String s = "select * from TabProfile where id=-2";
480: ResultSet r = sStatement.executeQuery(s);
481:
482: r.next();
483:
484: if (!r.getString(2).equals("\"Birdie\"'s car ?")) {
485: throw new Exception("Unicode error.");
486: }
487:
488: boolean mismatch = false;
489: byte[] b2n = r.getBytes(4);
490:
491: for (int i = 0; i < b2n.length; i++) {
492: if (b2[i] != b2n[i]) {
493: mismatch = true;
494: }
495: }
496:
497: r.close();
498:
499: s = "select * from TabProfile where id=10";
500: r = sStatement.executeQuery(s);
501:
502: r.next();
503:
504: byte[] b1n = r.getBytes(4);
505:
506: for (int i = 0; i < b1n.length; i++) {
507: if (b1[i] != b1n[i]) {
508: mismatch = true;
509: }
510: }
511:
512: r.close();
513: }
514:
515: static void testMarotest(Connection cConnection, boolean persistent) {
516:
517: Statement sStatement = null;
518: ResultSet r;
519: String s = "";
520: long start;
521: boolean bDropError = false;
522: String name = persistent ? "Persistent" : "Memory";
523:
524: print(name + " Marotest");
525:
526: try {
527: sStatement = cConnection.createStatement();
528: } catch (Exception e) {
529: e.printStackTrace();
530: print("Marotest init error: " + e.getMessage());
531: }
532:
533: try {
534:
535: // test duplicate keys & small transaction rollback
536: s = "CREATE TABLE marotest (id int PRIMARY KEY, dat int);"
537: + "INSERT INTO marotest VALUES (1,0);"
538: + "INSERT INTO marotest VALUES (2,0);"
539: + "INSERT INTO marotest VALUES (2,0);";
540:
541: try {
542: sStatement.execute(s);
543:
544: s = "";
545: } catch (Exception e) {
546: }
547:
548: if (s.equals("")) {
549: throw new Exception(
550: "Duplicate key gave no error on insert");
551: }
552:
553: try {
554: s = "UPDATE marotest SET id=1, dat=-1 WHERE dat=0";
555:
556: sStatement.execute(s);
557:
558: s = "";
559: } catch (Exception e) {
560: }
561:
562: if (s.equals("")) {
563: throw new Exception(
564: "Duplicate key gave no error on update");
565: }
566:
567: int count = 0;
568:
569: s = "SELECT *, id as marotest_id FROM marotest";
570: r = sStatement.executeQuery(s);
571:
572: while (r.next()) {
573: r.getFloat(1);
574: r.getString("ID");
575: r.getInt("DAT");
576: r.getInt("MAROTEST_ID");
577:
578: if (r.getShort("DAT") != 0) {
579: throw new Exception("Bad update worked");
580: }
581:
582: r.getLong("DAT");
583: r.getString(2);
584: r.getObject("ID");
585: r.clearWarnings();
586:
587: try {
588:
589: // this must throw an error
590: r.getTimestamp("Timestamp?");
591:
592: count = 99;
593: } catch (Exception e) {
594: }
595:
596: count++;
597: }
598:
599: r.close();
600:
601: if (count != 2) {
602: throw new Exception("Should have 2 but has " + count
603: + " rows");
604: }
605:
606: // test database meta data
607: DatabaseMetaData dbMeta = cConnection.getMetaData();
608:
609: r = dbMeta.getColumns(null, "DBO", "MAROTEST", "%");
610:
611: while (r.next()) {
612: s = r.getString(4).trim(); // COLUMN_NAME
613:
614: int i = r.getInt(5); // DATA_TYPE
615:
616: s += i + r.getString("TYPE_NAME");
617: i = r.getInt(7); // COLUMN_SIZE
618: i = r.getInt(9); // "Decimal_Digits"
619: i = r.getInt(11); // NULLABLE
620: s = s.toUpperCase();
621:
622: if (!s.equals("ID4INTEGER") && !s.equals("DAT4INTEGER")) {
623: throw new Exception("Wrong database meta data");
624: }
625: }
626:
627: s = "DROP TABLE marotest";
628:
629: sStatement.execute(s);
630: sStatement.close();
631: } catch (Exception e) {
632: print("");
633: print("Marotest error: " + e);
634: print("with SQL command: " + s);
635: e.printStackTrace();
636: }
637: }
638:
639: static void testPerformance(String url, String user,
640: String password, int max, boolean persistent)
641: throws Exception {
642:
643: if (persistent) {
644: deleteDatabase("test2");
645: }
646:
647: Statement sStatement = null;
648: Connection cConnection = null;
649: ResultSet r;
650: String s = "";
651: long start;
652: boolean bDropError = false;
653: String name = persistent ? "Persistent" : "Memory";
654:
655: print(name + " Performance");
656:
657: try {
658: cConnection = DriverManager.getConnection(url, user,
659: password);
660: sStatement = cConnection.createStatement();
661: } catch (Exception e) {
662: e.printStackTrace();
663: print("TestSelf init error: " + e.getMessage());
664: }
665:
666: try {
667:
668: // cache, index and performance tests
669: s = "CREATE CACHED TABLE Addr(ID INT PRIMARY KEY,First CHAR,"
670: + "Name CHAR,ZIP INT)";
671:
672: sStatement.execute(s);
673:
674: s = "CREATE INDEX iName ON Addr(Name)";
675:
676: sStatement.execute(s);
677:
678: s = "SET WRITE_DELAY TRUE";
679:
680: sStatement.execute(s);
681:
682: start = System.currentTimeMillis();
683:
684: for (int i = 0; i < max; i++) {
685: s = "INSERT INTO Addr VALUES(" + i + ",'Marcel" + i
686: + "'," + "'Renggli" + (max - i - (i % 31))
687: + "'," + (3000 + i % 100) + ")";
688:
689: if (sStatement.executeUpdate(s) != 1) {
690: throw new Exception("Insert failed");
691: }
692:
693: if (i % 100 == 0) {
694: printStatus("insert ", i, max, start);
695: }
696: }
697:
698: printStatus("insert ", max, max, start);
699: print("");
700:
701: s = "SELECT COUNT(*) FROM Addr";
702: r = sStatement.executeQuery(s);
703:
704: r.next();
705:
706: int c = r.getInt(1);
707:
708: if (c != max) {
709: throw new Exception("Count should be " + (max)
710: + " but is " + c);
711: }
712:
713: if (persistent) {
714:
715: // close & reopen to test backup
716: cConnection.close();
717:
718: cConnection = DriverManager.getConnection(url, user,
719: password);
720: sStatement = cConnection.createStatement();
721: }
722:
723: start = System.currentTimeMillis();
724:
725: for (int i = 0; i < max; i++) {
726: s = "UPDATE Addr SET Name='Robert" + (i + (i % 31))
727: + "' WHERE ID=" + i;
728:
729: if (sStatement.executeUpdate(s) != 1) {
730: throw new Exception("Update failed");
731: }
732:
733: if (i % 100 == 0) {
734: printStatus("updated ", i, max, start);
735:
736: // s="SELECT COUNT(*) FROM Addr";
737: // r=sStatement.executeQuery(s);
738: // r.next();
739: // int c=r.getInt(1);
740: // if(c!=max) {
741: // throw new Exception("Count should be "+max+" but is "+c);
742: // }
743: }
744: }
745:
746: printStatus("update ", max, max, start);
747: print("");
748:
749: if (persistent) {
750: s = "SHUTDOWN IMMEDIATELY";
751:
752: sStatement.execute(s);
753:
754: // open the database; it must be restored after shutdown
755: cConnection.close();
756:
757: cConnection = DriverManager.getConnection(url, user,
758: password);
759: sStatement = cConnection.createStatement();
760: }
761:
762: start = System.currentTimeMillis();
763:
764: for (int i = 0; i < max; i++) {
765: s = "DELETE FROM Addr WHERE ID=" + (max - 1 - i);
766:
767: if (sStatement.executeUpdate(s) != 1) {
768: throw new Exception("Delete failed");
769: }
770:
771: if (i % 100 == 0) {
772: printStatus("deleting ", i, max, start);
773:
774: // s="SELECT COUNT(*) FROM Addr";
775: // r=sStatement.executeQuery(s);
776: // r.next();
777: // int c=r.getInt(1);
778: // if(c!=max-i-1) {
779: // throw new Exception("Count should be "+(max-i-1)+" but is "+c);
780: // }
781: }
782: }
783:
784: printStatus("delete ", max, max, start);
785: print("");
786: sStatement.execute("DROP TABLE Addr");
787: } catch (Exception e) {
788: print("");
789: print("TestSelf error: " + e);
790: print("with SQL command: " + s);
791: e.printStackTrace();
792: }
793:
794: cConnection.close();
795: print("Test finished");
796: }
797:
798: /**
799: * Method declaration
800: *
801: * @param s
802: * @param i
803: * @param max
804: * @param start
805: */
806: static void printStatus(String s, int i, int max, long start) {
807:
808: System.out.print(s + ": " + i + "/" + max + " "
809: + (100 * i / max) + "% ");
810:
811: long now = System.currentTimeMillis();
812:
813: if (now > start) {
814: System.out.print((i * 1000 / (now - start)));
815: }
816:
817: System.out.print(" rows/s \r");
818: }
819: }
|