KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > tests > lang > SpillHash


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.tests.lang.bug4356
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.tests.lang;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.DriverManager JavaDoc;
26 import java.sql.DatabaseMetaData JavaDoc;
27 import java.sql.ResultSet JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.Statement JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.sql.Types JavaDoc;
32 import java.util.BitSet JavaDoc;
33
34 import org.apache.derby.tools.ij;
35 import org.apache.derby.tools.JDBCDisplayUtil;
36
37 /**
38  * Test BackingStoreHashtable spilling to disk.
39  * BackingStoreHashtable is used to implement hash joins, distinct, scroll insensitive cursors,
40  * outer joins, and the HAVING clause.
41  */

42 public class SpillHash
43 {
44     private static PreparedStatement JavaDoc joinStmt;
45     private static PreparedStatement JavaDoc distinctStmt;
46     private static final int LOTS_OF_ROWS = 10000;
47     private static int errorCount = 0;
48     
49     public static void main (String JavaDoc args[])
50     {
51         try {
52             /* Load the JDBC Driver class */
53             // use the ij utility to read the property file and
54
// make the initial connection.
55
ij.getPropertyArg(args);
56             Connection JavaDoc conn = ij.startJBMS();
57             Statement JavaDoc stmt = conn.createStatement();
58
59             for( int i = 0; i < prep.length; i++)
60                 stmt.executeUpdate( prep[i]);
61             PreparedStatement JavaDoc insA = conn.prepareStatement( "insert into ta(ca1,ca2) values(?,?)");
62             PreparedStatement JavaDoc insB = conn.prepareStatement( "insert into tb(cb1,cb2) values(?,?)");
63             insertDups( insA, insB, initDupVals);
64
65             joinStmt =
66               conn.prepareStatement( "select ta.ca1, ta.ca2, tb.cb2 from ta, tb where ca1 = cb1");
67             distinctStmt =
68               conn.prepareStatement( "select distinct ca1 from ta");
69
70             runStatements( conn, 0, new String JavaDoc[][][] {initDupVals});
71
72             System.out.println( "Growing database.");
73             
74             // Add a lot of rows so that the hash tables have to spill to disk
75
conn.setAutoCommit(false);
76             for( int i = 1; i <= LOTS_OF_ROWS; i++)
77             {
78                 insA.setInt(1, i);
79                 insA.setString(2, ca2Val(i));
80                 insA.executeUpdate();
81                 insB.setInt(1, i);
82                 insB.setString(2, cb2Val(i));
83                 insB.executeUpdate();
84
85                 if( (i & 0xff) == 0)
86                     conn.commit();
87             }
88             conn.commit();
89             insertDups( insA, insB, spillDupVals);
90             conn.commit();
91
92             conn.setAutoCommit(true);
93             runStatements( conn, LOTS_OF_ROWS, new String JavaDoc[][][] {initDupVals, spillDupVals});
94             
95             conn.close();
96         } catch (Exception JavaDoc e) {
97             System.out.println("FAIL -- unexpected exception "+e);
98             JDBCDisplayUtil.ShowException(System.out, e);
99             e.printStackTrace();
100             errorCount++;
101         }
102         if( errorCount == 0)
103         {
104             System.out.println( "PASSED.");
105             System.exit(0);
106         }
107         else
108         {
109             System.out.println( "FAILED: " + errorCount + ((errorCount == 1) ? " error" : " errors"));
110             System.exit(1);
111         }
112     } // end of main
113

114     private static final String JavaDoc[] prep =
115     {
116         "create table ta (ca1 integer, ca2 char(200))",
117         "create table tb (cb1 integer, cb2 char(200))",
118         "insert into ta(ca1,ca2) values(null, 'Anull')",
119         "insert into tb(cb1,cb2) values(null, 'Bnull')"
120     };
121
122     private static final String JavaDoc[][] initDupVals =
123     {
124         { "0a", "0b"},
125         { "1a", "1b"},
126         { "2a"}
127     };
128     private static final String JavaDoc[][] spillDupVals =
129     {
130         {},
131         { "1c"},
132         { "2b"},
133         { "3a", "3b", "3c"}
134     };
135
136     private static int expectedMincc2( int cc1)
137     {
138         return 4*cc1;
139     }
140
141     private static int expectedMaxcc2( int cc1)
142     {
143         return expectedMincc2( cc1) + (cc1 & 0x3);
144     }
145     
146     private static void insertDups( PreparedStatement JavaDoc insA, PreparedStatement JavaDoc insB, String JavaDoc[][] dupVals)
147         throws SQLException JavaDoc
148     {
149         for( int i = 0; i < dupVals.length; i++)
150         {
151             insA.setInt(1, -i);
152             insB.setInt(1, -i);
153             String JavaDoc[] vals = dupVals[i];
154             for( int j = 0; j < vals.length; j++)
155             {
156                 insA.setString( 2, "A" + vals[j]);
157                 insA.executeUpdate();
158                 insB.setString( 2, "B" + vals[j]);
159                 insB.executeUpdate();
160             }
161         }
162     } // end of insertDups
163

164     private static String JavaDoc ca2Val( int col1Val)
165     {
166         return "A" + col1Val;
167     }
168     
169     private static String JavaDoc cb2Val( int col1Val)
170     {
171         return "B" + col1Val;
172     }
173     
174     private static void runStatements( Connection JavaDoc conn, int maxColValue, String JavaDoc[][][] dupVals)
175         throws SQLException JavaDoc
176     {
177         runJoin( conn, maxColValue, dupVals);
178         runDistinct( conn, maxColValue, dupVals);
179         runCursor( conn, maxColValue, dupVals);
180     }
181
182     private static void runJoin( Connection JavaDoc conn, int maxColValue, String JavaDoc[][][] dupVals)
183         throws SQLException JavaDoc
184     {
185         System.out.println( "Running join");
186         int expectedRowCount = maxColValue; // plus expected duplicates, to be counted below
187
ResultSet JavaDoc rs = joinStmt.executeQuery();
188         BitSet JavaDoc joinRowFound = new BitSet JavaDoc( maxColValue);
189         int dupKeyCount = 0;
190         for( int i = 0; i < dupVals.length; i++)
191         {
192             if( dupVals[i].length > dupKeyCount)
193                 dupKeyCount = dupVals[i].length;
194         }
195         BitSet JavaDoc[] dupsFound = new BitSet JavaDoc[dupKeyCount];
196         int[] dupCount = new int[ dupKeyCount];
197         for( int i = 0; i < dupKeyCount; i++)
198         {
199             // count the number of rows with column(1) == -i
200
dupCount[i] = 0;
201             for( int j = 0; j < dupVals.length; j++)
202             {
203                 if( i < dupVals[j].length)
204                     dupCount[i] += dupVals[j][i].length;
205             }
206             dupsFound[i] = new BitSet JavaDoc(dupCount[i]*dupCount[i]);
207             expectedRowCount += dupCount[i]*dupCount[i];
208         }
209         
210         int count;
211         for( count = 0; rs.next(); count++)
212         {
213             int col1Val = rs.getInt(1);
214             if( rs.wasNull())
215             {
216                 System.out.println( "Null in join column.");
217                 errorCount++;
218                 continue;
219             }
220             if( col1Val > maxColValue)
221             {
222                 System.out.println( "Invalid value in first join column.");
223                 errorCount++;
224                 continue;
225             }
226             if( col1Val > 0)
227             {
228                 if( joinRowFound.get( col1Val - 1))
229                 {
230                     System.out.println( "Multiple rows for value " + col1Val);
231                     errorCount++;
232                 }
233                 joinRowFound.set( col1Val - 1);
234                 String JavaDoc col2Val = trim( rs.getString(2));
235                 String JavaDoc col3Val = trim( rs.getString(3));
236                 if( !( ca2Val( col1Val).equals( col2Val) && cb2Val( col1Val).equals( col3Val)))
237                 {
238                     System.out.println( "Incorrect value in column 2 or 3 of join.");
239                     errorCount++;
240                 }
241             }
242             else // col1Val <= 0, there are duplicates in the source tables
243
{
244                 int dupKeyIdx = -col1Val;
245                 int col2Idx = findDupVal( rs, 2, 'A', dupKeyIdx, dupVals);
246                 int col3Idx = findDupVal( rs, 3, 'B', dupKeyIdx, dupVals);
247                 if( col2Idx < 0 || col3Idx < 0)
248                     continue;
249
250                 int idx = col2Idx + dupCount[dupKeyIdx]*col3Idx;
251                 if( dupsFound[dupKeyIdx].get( idx))
252                 {
253                     System.out.println( "Repeat of row with key value 0");
254                     errorCount++;
255                 }
256                 dupsFound[dupKeyIdx].set( idx);
257             }
258         };
259         if( count != expectedRowCount)
260         {
261             System.out.println( "Incorrect number of rows in join.");
262             errorCount++;
263         }
264         rs.close();
265     } // end of runJoin
266

267     private static int findDupVal( ResultSet JavaDoc rs, int col, char prefix, int keyIdx, String JavaDoc[][][] dupVals)
268         throws SQLException JavaDoc
269     {
270         String JavaDoc colVal = rs.getString(col);
271         if( colVal != null && colVal.length() > 1 || colVal.charAt(0) == prefix)
272         {
273             colVal = trim( colVal.substring( 1));
274             int dupIdx = 0;
275             for( int i = 0; i < dupVals.length; i++)
276             {
277                 if( keyIdx < dupVals[i].length)
278                 {
279                     for( int j = 0; j < dupVals[i][keyIdx].length; j++, dupIdx++)
280                     {
281                         if( colVal.equals( dupVals[i][keyIdx][j]))
282                             return dupIdx;
283                     }
284                 }
285             }
286         }
287         System.out.println( "Incorrect value in column " + col + " of join with duplicate keys.");
288         errorCount++;
289         return -1;
290     } // end of findDupVal
291

292     private static String JavaDoc trim( String JavaDoc str)
293     {
294         if( str == null)
295             return str;
296         return str.trim();
297     }
298     
299     private static void runDistinct( Connection JavaDoc conn, int maxColValue, String JavaDoc[][][] dupVals)
300         throws SQLException JavaDoc
301     {
302         System.out.println( "Running distinct");
303         ResultSet JavaDoc rs = distinctStmt.executeQuery();
304         checkAllCa1( rs, false, false, maxColValue, dupVals, "DISTINCT");
305     }
306
307     private static void checkAllCa1( ResultSet JavaDoc rs,
308                                      boolean expectDups,
309                                      boolean holdOverCommit,
310                                      int maxColValue,
311                                      String JavaDoc[][][] dupVals,
312                                      String JavaDoc label)
313         throws SQLException JavaDoc
314     {
315         int dupKeyCount = 0;
316         for( int i = 0; i < dupVals.length; i++)
317         {
318             if( dupVals[i].length > dupKeyCount)
319                 dupKeyCount = dupVals[i].length;
320         }
321         int[] expectedDupCount = new int[dupKeyCount];
322         int[] dupFoundCount = new int[dupKeyCount];
323         for( int i = 0; i < dupKeyCount; i++)
324         {
325             
326             dupFoundCount[i] = 0;
327             if( !expectDups)
328                 expectedDupCount[i] = 1;
329             else
330             {
331                 expectedDupCount[i] = 0;
332                 for( int j = 0; j < dupVals.length; j++)
333                 {
334                     if( i < dupVals[j].length)
335                         expectedDupCount[i] += dupVals[j][i].length;
336                 }
337             }
338         }
339         BitSet JavaDoc found = new BitSet JavaDoc( maxColValue);
340         int count = 0;
341         boolean nullFound = false;
342         try
343         {
344             for( count = 0; rs.next();)
345             {
346                 int col1Val = rs.getInt(1);
347                 if( rs.wasNull())
348                 {
349                     if( nullFound)
350                     {
351                         System.out.println( "Too many nulls returned by " + label);
352                         errorCount++;
353                         continue;
354                     }
355                     nullFound = true;
356                     continue;
357                 }
358                 if( col1Val <= -dupKeyCount || col1Val > maxColValue)
359                 {
360                     System.out.println( "Invalid value returned by " + label);
361                     errorCount++;
362                     continue;
363                 }
364                 if( col1Val <= 0)
365                 {
366                     dupFoundCount[ -col1Val]++;
367                     if( !expectDups)
368                     {
369                         if( dupFoundCount[ -col1Val] > 1)
370                         {
371                             System.out.println( label + " returned a duplicate.");
372                             errorCount++;
373                             continue;
374                         }
375                     }
376                     else if( dupFoundCount[ -col1Val] > expectedDupCount[ -col1Val])
377                     {
378                         System.out.println( label + " returned too many duplicates.");
379                         errorCount++;
380                         continue;
381                     }
382                 }
383                 else
384                 {
385                     if( found.get( col1Val))
386                     {
387                         System.out.println( label + " returned a duplicate.");
388                         errorCount++;
389                         continue;
390                     }
391                     found.set( col1Val);
392                     count++;
393                 }
394                 if( holdOverCommit)
395                 {
396                     rs.getStatement().getConnection().commit();
397                     holdOverCommit = false;
398                 }
399             }
400             if( count != maxColValue)
401             {
402                 System.out.println( "Incorrect number of rows in " + label);
403                 errorCount++;
404             }
405             for( int i = 0; i < dupFoundCount.length; i++)
406             {
407                 if( dupFoundCount[i] != expectedDupCount[i])
408                 {
409                     System.out.println( "A duplicate key row is missing in " + label);
410                     errorCount++;
411                     break;
412                 }
413             }
414         }
415         finally
416         {
417             rs.close();
418         }
419     } // End of checkAllCa1
420

421     private static void runCursor( Connection JavaDoc conn, int maxColValue, String JavaDoc[][][] dupVals)
422         throws SQLException JavaDoc
423     {
424         System.out.println( "Running scroll insensitive cursor");
425         DatabaseMetaData JavaDoc dmd = conn.getMetaData();
426         boolean holdOverCommit = dmd.supportsOpenCursorsAcrossCommit();
427         Statement JavaDoc stmt;
428         if( holdOverCommit)
429             stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
430                                         ResultSet.CONCUR_READ_ONLY,
431                                         ResultSet.HOLD_CURSORS_OVER_COMMIT);
432         else
433             stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
434                                         ResultSet.CONCUR_READ_ONLY);
435         ResultSet JavaDoc rs = stmt.executeQuery( "SELECT ca1 FROM ta");
436         checkAllCa1( rs, true, holdOverCommit, maxColValue, dupVals, "scroll insensitive cursor");
437     }
438 }
439
Popular Tags