KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > unitTests > store > T_AccessFactory


1 /*
2
3    Derby - Class org.apache.derbyTesting.unitTests.store.T_AccessFactory
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.unitTests.store;
23
24 import org.apache.derbyTesting.unitTests.harness.T_Generic;
25 import org.apache.derbyTesting.unitTests.harness.T_Fail;
26
27 import org.apache.derby.iapi.store.access.*;
28
29 import org.apache.derby.iapi.types.SQLLongint;
30
31 import org.apache.derby.iapi.services.context.ContextManager;
32 import org.apache.derby.iapi.services.context.ContextService;
33
34 import org.apache.derby.iapi.services.io.Storable;
35
36 import org.apache.derby.iapi.services.monitor.Monitor;
37 import org.apache.derby.iapi.services.sanity.SanityManager;
38 import org.apache.derby.iapi.services.io.FormatIdUtil;
39
40 import org.apache.derby.iapi.error.StandardException;
41
42 import org.apache.derby.iapi.types.DataValueDescriptor;
43
44 import org.apache.derby.iapi.types.RowLocation;
45
46 import org.apache.derby.iapi.store.raw.RawStoreFactory;
47 import org.apache.derby.iapi.store.raw.Transaction;
48 import org.apache.derby.iapi.reference.Property;
49 import org.apache.derby.iapi.reference.SQLState;
50 import org.apache.derby.iapi.services.io.FormatableBitSet;
51 import org.apache.derby.iapi.services.i18n.MessageService;
52 import java.io.File JavaDoc;
53 import java.io.Serializable JavaDoc;
54 import java.util.Hashtable JavaDoc;
55 import java.util.Properties JavaDoc;
56 import org.apache.derby.iapi.types.SQLInteger;
57
58 import org.apache.derby.iapi.types.SQLChar;
59
60 public class T_AccessFactory extends T_Generic
61 {
62     private static final String JavaDoc testService = "accessTest";
63
64     AccessFactory store = null;
65
66     public T_AccessFactory()
67     {
68         super();
69     }
70
71     /*
72     ** Methods of UnitTest.
73     */

74
75     /*
76     ** Methods required by T_Generic
77     */

78
79     public String JavaDoc getModuleToTestProtocolName()
80     {
81         return AccessFactory.MODULE;
82     }
83
84     /**
85         @exception T_Fail Unexpected behaviour from the API
86      */

87
88     protected void runTests() throws T_Fail
89     {
90         TransactionController tc = null;
91         boolean pass = false;
92
93         // Create a AccessFactory to test.
94

95         // don't automatic boot this service if it gets left around
96
if (startParams == null)
97         {
98             startParams = new Properties JavaDoc();
99         }
100         startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
101         // remove the service directory to ensure a clean run
102
startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
103
104         // see if we are testing encryption
105
startParams = T_Util.setEncryptionParam(startParams);
106
107         try {
108             store = (AccessFactory) Monitor.createPersistentService(
109                 getModuleToTestProtocolName(), testService, startParams);
110         } catch (StandardException mse) {
111             throw T_Fail.exceptionFail(mse);
112         }
113
114
115         if (store == null)
116         {
117             throw T_Fail.testFailMsg(
118                 getModuleToTestProtocolName() + " service not started.");
119         }
120
121         REPORT("(unitTestMain) Testing " + testService);
122
123         try {
124
125             ContextManager cm =
126                     ContextService.getFactory().getCurrentContextManager();
127
128             tc = store.getAndNameTransaction(
129                     cm, AccessFactoryGlobals.USER_TRANS_NAME);
130
131
132             if (
133                 dropTest(tc)
134                 && holdCursor(tc)
135                 && readUncommitted(tc)
136                 && updatelocks(tc)
137                 && nestedUserTransaction(tc)
138                 && positionAtRowLocation(tc)
139                 && sortCost(tc)
140                 && storeCost(tc)
141                 && partialScan(tc)
142                 && scanInfo(tc)
143                 && insertAndUpdateExample(tc)
144                 && insertAndFetchExample(tc)
145                 && scanExample(tc)
146                 && alterTable(tc)
147                 && tempTest(tc)
148                 && getTableProperties(tc)
149                 && insert_bench(tc)
150                 && transactionalProperties(tc)
151                 && commitTest(tc))
152             {
153                 pass = true;
154             }
155
156             // Make sure commitNoSync gets executed sometimes.
157
tc.commitNoSync(TransactionController.RELEASE_LOCKS);
158
159             tc.destroy();
160
161             if (!pass)
162                 throw T_Fail.testFailMsg("test failed");
163
164         }
165         catch (StandardException e)
166         {
167             String JavaDoc msg = e.getMessage();
168             if (msg == null)
169                 msg = e.getClass().getName();
170             REPORT(msg);
171             e.printStackTrace();
172             throw T_Fail.exceptionFail(e);
173         }
174         catch (Throwable JavaDoc t)
175         {
176             t.printStackTrace();
177         }
178
179     }
180
181     /*
182     ** Methods of T_AccessFactory.
183     */

184
185     private void flush_cache()
186         throws StandardException
187     {
188         // flush and empty cache to make sure rereading stuff works.
189
RawStoreFactory rawstore =
190             (RawStoreFactory) Monitor.findServiceModule(
191                 this.store, RawStoreFactory.MODULE);
192
193         rawstore.checkpoint();
194     }
195
196     protected boolean insertAndFetchExample(TransactionController tc)
197         throws StandardException, T_Fail
198     {
199         REPORT("(insertAndFetchExample)");
200
201         // First a negative test - make sure heap requires a template:
202

203         try
204         {
205             // Create a heap conglomerate.
206
long conglomid =
207                 tc.createConglomerate(
208                     "heap", // create a heap conglomerate
209
null, // ERROR - Heap requires a template!!!
210
null, // column sort order not required for heap
211
null, // default properties
212
TransactionController.IS_DEFAULT); // not temporary
213

214             throw T_Fail.testFailMsg("Allowed heap create without template.");
215         }
216         catch (Throwable JavaDoc t)
217         {
218             // expected error, just continue.
219
}
220
221         // Create a heap conglomerate.
222
T_AccessRow template_row = new T_AccessRow(1);
223         long conglomid =
224             tc.createConglomerate(
225                 "heap", // create a heap conglomerate
226
template_row.getRowArray(), // 1 column template.
227
null, // column sort order not required for heap
228
null, // default properties
229
TransactionController.IS_DEFAULT); // not temporary
230

231
232         // Insert and fetch some values.
233
if (insertAndFetch(tc, conglomid, 33)
234             && insertAndFetch(tc, conglomid, -1)
235             && insertAndFetch(tc, conglomid, -1000000000))
236         {
237             return true;
238         }
239         else
240         {
241             return false;
242         }
243     }
244
245     // Insert a single row with a single column containing
246
// the argument integer, and fetch it back, making sure that
247
// we read the correct value.
248
//
249
protected boolean insertAndFetch(
250     TransactionController tc,
251     long conglomid,
252     int value)
253         throws StandardException, T_Fail
254     {
255         StaticCompiledOpenConglomInfo static_info =
256             tc.getStaticCompiledConglomInfo(conglomid);
257
258         DynamicCompiledOpenConglomInfo dynamic_info =
259             tc.getDynamicCompiledConglomInfo(conglomid);
260
261         String JavaDoc curr_xact_name = tc.getTransactionIdString();
262
263         REPORT("(insertAndFetch) xact id = " + curr_xact_name);
264
265         // Open the conglomerate.
266
ConglomerateController cc =
267             tc.openCompiledConglomerate(
268                 false,
269                 TransactionController.OPENMODE_FORUPDATE,
270                 TransactionController.MODE_RECORD,
271                 TransactionController.ISOLATION_SERIALIZABLE,
272                 static_info,
273                 dynamic_info);
274
275         // Create a row.
276
T_AccessRow r1 = new T_AccessRow(1);
277         SQLInteger c1 = new SQLInteger(value);
278         r1.setCol(0, c1);
279
280         // Get a location template
281
RowLocation rowloc = cc.newRowLocationTemplate();
282
283
284
285         // Insert the row and remember its location.
286
cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
287
288         // quick test to make sure we can hash insert and find row location.
289
Hashtable JavaDoc test_rowloc_hash = new Hashtable JavaDoc();
290         test_rowloc_hash.put(rowloc, rowloc);
291
292         RowLocation hash_find = (RowLocation) test_rowloc_hash.get(rowloc);
293
294         if (!hash_find.equals(rowloc))
295             throw T_Fail.testFailMsg("(insertAndFetch) bad hash lookup 1");
296
297         hash_find = (RowLocation) test_rowloc_hash.remove(rowloc);
298
299         if (!hash_find.equals(rowloc))
300             throw T_Fail.testFailMsg("(insertAndFetch) bad hash lookup 2");
301
302         hash_find = (RowLocation) test_rowloc_hash.remove(rowloc);
303
304         if (hash_find != null)
305             throw T_Fail.testFailMsg("(insertAndFetch) bad hash lookup 3");
306
307
308         // Create a new row of the same type (since the interface expects
309
// the callers to be keeping the row types straight), but with
310
// a different column value.
311
T_AccessRow r2 = new T_AccessRow(1);
312         SQLInteger c2 = new SQLInteger(0);
313         r2.setCol(0, c2);
314
315         // Fetch the stored value.
316
if (!cc.fetch(rowloc, r2.getRowArray(), (FormatableBitSet) null))
317         {
318             throw T_Fail.testFailMsg("(insertAndFetch) fetch found no row.");
319         }
320
321         // Fetch using the fetch partial column interface
322
SQLInteger c3 = new SQLInteger(0);
323         FormatableBitSet singleColumn = new FormatableBitSet(1);
324         singleColumn.set(0);
325         DataValueDescriptor[] c3row = new DataValueDescriptor[1];
326         c3row[0] = c3;
327
328         if (!cc.fetch(rowloc, c3row, singleColumn))
329         {
330             throw T_Fail.testFailMsg("(insertAndFetch) fetch found no row.");
331         }
332
333         // Close the conglomerate.
334
cc.close();
335
336         // Make sure we read back the value we wrote.
337
if (c2.getInt() != value)
338             throw T_Fail.testFailMsg("(insertAndFetch) Fetched value != inserted value.");
339
340         if (c3.getInt() != value)
341             throw T_Fail.testFailMsg("(insertAndFetch) Fetched value != inserted value.");
342         
343         return true;
344     }
345
346     protected boolean insertAndUpdateExample(TransactionController tc)
347         throws StandardException, T_Fail
348     {
349         // Create a heap conglomerate.
350
long conglomid =
351             tc.createConglomerate(
352                 "heap", // create a heap conglomerate
353
new T_AccessRow(1).getRowArray(), // 1 column template.
354
null, // column sort order not required for heap
355
null, // default properties
356
TransactionController.IS_DEFAULT); // not temporary
357

358         REPORT("(insertAndUpdateExample)");
359
360         // Insert and update some values
361
if (insertAndUpdate(tc, conglomid, -1, -1003152)
362             && insertAndUpdate(tc, conglomid, 0, 2000000000)
363             && deletetest(tc, conglomid, 1, 2))
364         {
365             return true;
366         }
367
368         return false;
369     }
370
371     // Insert a single row with a single column containing
372
// the first argument integer, delete it, make sure subsequent
373
// delete, replace, and replace a single column return false.
374
//
375
protected boolean deletetest(
376     TransactionController tc,
377     long conglomid,
378     int value1,
379     int value2)
380         throws StandardException, T_Fail
381     {
382         boolean ret_val;
383
384         // Open the conglomerate.
385
ConglomerateController cc =
386             tc.openConglomerate(
387                 conglomid,
388                 false,
389                 TransactionController.OPENMODE_FORUPDATE,
390                 TransactionController.MODE_RECORD,
391                 TransactionController.ISOLATION_SERIALIZABLE);
392
393         // Create a row.
394
T_AccessRow r1 = new T_AccessRow(1);
395         r1.setCol(0, new SQLInteger(value1));
396
397         // Get a location template
398
RowLocation rowloc = cc.newRowLocationTemplate();
399
400         // Insert the row and remember its location.
401
cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
402
403         // delete it.
404
if (!cc.delete(rowloc))
405         {
406             throw T_Fail.testFailMsg("(deleteTest) delete of row failed");
407         }
408
409         // subsequent replace, update a single column, and delete
410
// should return false
411

412         // update single column
413
DataValueDescriptor[] update_row = new DataValueDescriptor[1];
414         FormatableBitSet update_desc = new FormatableBitSet(1);
415         update_desc.set(0);
416         if (cc.replace(rowloc, update_row, update_desc))
417         {
418             throw T_Fail.testFailMsg(
419             "(deleteTest) partial column row replace returned true on del row");
420         }
421
422         // update whole row.
423
if (cc.replace(rowloc, r1.getRowArray(), (FormatableBitSet) null))
424         {
425             throw T_Fail.testFailMsg("(deleteTest) update returned true on del row");
426         }
427         if (cc.delete(rowloc))
428         {
429             throw T_Fail.testFailMsg("(deleteTest) delete returned true on del row");
430         }
431
432         // Close the conglomerate.
433
cc.close();
434
435         return true;
436     }
437
438     // Insert a single row with a single column containing
439
// the first argument integer, update it to the second
440
// value, and make sure the update happened.
441
//
442
protected boolean insertAndUpdate(TransactionController tc, long conglomid,
443         int value1, int value2)
444         throws StandardException, T_Fail
445     {
446         // Open the conglomerate.
447
ConglomerateController cc =
448             tc.openConglomerate(
449                 conglomid,
450                 false,
451                 TransactionController.OPENMODE_FORUPDATE,
452                 TransactionController.MODE_RECORD,
453                 TransactionController.ISOLATION_SERIALIZABLE);
454
455         // Create a row.
456
T_AccessRow r1 = new T_AccessRow(1);
457         r1.setCol(0, new SQLInteger(value1));
458
459         // Get a location template
460
RowLocation rowloc = cc.newRowLocationTemplate();
461
462         // Insert the row and remember its location.
463
cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
464
465         // Update it to the second value
466
DataValueDescriptor[] update_row = new DataValueDescriptor[1];
467         update_row[0] = new SQLInteger(value2);
468
469         FormatableBitSet update_desc = new FormatableBitSet(1);
470         update_desc.set(0);
471
472         cc.replace(rowloc, update_row, update_desc);
473
474         // Create a new row (of the same type, since the interface expects
475
// the callers to be keeping the row types straight.
476
T_AccessRow r2 = new T_AccessRow(1);
477         SQLInteger c2 = new SQLInteger(0);
478         r2.setCol(0, c2);
479
480         // Fetch the stored value.
481
if (!cc.fetch(rowloc, r2.getRowArray(), (FormatableBitSet) null))
482         {
483             throw T_Fail.testFailMsg("(insertAndUpdate) Fetch val not there.");
484         }
485
486         // Close the conglomerate.
487
cc.close();
488
489         // Make sure we read back the value we wrote.
490
if (c2.getInt() != value2)
491             throw T_Fail.testFailMsg("(insertAndUpdate) Fetch value != updated value.");
492         else
493             return true;
494     }
495
496     protected boolean scanExample(TransactionController tc)
497         throws StandardException, T_Fail
498     {
499         tc.commit();
500
501         if (!tc.isPristine() || !tc.isIdle() || tc.isGlobal())
502             throw T_Fail.testFailMsg(
503                 "(scanExample) bad xact state after commit.");
504
505         if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0) ||
506             (tc.countOpens(TransactionController.OPEN_CONGLOMERATE) > 0) ||
507             (tc.countOpens(TransactionController.OPEN_SCAN) > 0) ||
508             (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) > 0) ||
509             (tc.countOpens(TransactionController.OPEN_SORT) > 0))
510         {
511             System.out.println("OPENED 0:\n" + tc.debugOpened());
512             return(FAIL("unexpected open count."));
513         }
514
515         // Create a heap conglomerate.
516
long conglomid =
517             tc.createConglomerate(
518                 "heap", // create a heap conglomerate
519
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
520
null, // column sort order not required for heap
521
null, // default properties
522
TransactionController.IS_DEFAULT); // not temporary
523

524         REPORT("(scanExample) starting");
525
526
527         // Open it.
528
ConglomerateController cc =
529             tc.openConglomerate(
530                 conglomid,
531                 false,
532                 TransactionController.OPENMODE_FORUPDATE,
533                 TransactionController.MODE_RECORD,
534                 TransactionController.ISOLATION_SERIALIZABLE);
535
536
537         // Insert some values.
538
int values[] = { 11, 22, 33, 44, 55, 66 };
539         T_AccessRow row = new T_AccessRow(1);
540         for (int i = 0; i < values.length; i++)
541         {
542             row.setCol(0, new SQLInteger(values[i]));
543             if (cc.insert(row.getRowArray()) != 0)
544                 throw T_Fail.testFailMsg("(scanExample after insert) insert failed ");
545         }
546
547         // For test coverage call the debugging output routine - can't diff it.
548
REPORT("(scanExample) debug output testing: " + tc.debugOpened());
549
550         // Close the conglomerate.
551
cc.close();
552
553         if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0) ||
554             (tc.countOpens(TransactionController.OPEN_CONGLOMERATE) > 0) ||
555             (tc.countOpens(TransactionController.OPEN_SCAN) > 0) ||
556             (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) > 0) ||
557             (tc.countOpens(TransactionController.OPEN_SORT) > 0))
558         {
559             System.out.println("OPENED 1:\n" + tc.debugOpened());
560             return(FAIL("unexpected open count."));
561         }
562
563         REPORT("(scanExample) rows inserted");
564
565         // Correlates our position in the upcoming scan to the values array.
566
int scanindex = 0;
567
568         // Put a specific column in the row so we can look at it.
569
SQLInteger col = new SQLInteger(0);
570         row.setCol(0, col);
571
572         flush_cache();
573
574         StaticCompiledOpenConglomInfo static_info =
575             tc.getStaticCompiledConglomInfo(conglomid);
576
577         // Open a scan on the conglomerate.
578
ScanController scan1 = tc.openCompiledScan(
579             false, // don't hold
580
0, // not for update
581
TransactionController.MODE_RECORD,
582             TransactionController.ISOLATION_SERIALIZABLE,
583             (FormatableBitSet) null, // all columns, all as objects
584
null, // start position - first row in conglomerate
585
0, // unused if start position is null.
586
null, // qualifier - accept all rows
587
null, // stop position - last row in conglomerate
588
0, // unused if stop position is null.
589
static_info,
590             tc.getDynamicCompiledConglomInfo(conglomid));
591
592         // check out the RowCountable interface's.
593

594         if (scan1.getEstimatedRowCount() != 6)
595         {
596             throw T_Fail.testFailMsg(
597                 "(scanExample) estimated row count not 6:" +
598                 scan1.getEstimatedRowCount());
599         }
600
601         // Test 2 - ASSERT(should be able to set arbitrary row count)
602

603         scan1.setEstimatedRowCount(5);
604
605         if (scan1.getEstimatedRowCount() != 5)
606         {
607             throw T_Fail.testFailMsg("(scanExample) estimated row count not 5");
608         }
609
610
611         // Iterate through and check that the rows are still there.
612
while (scan1.next())
613         {
614             scan1.fetch(row.getRowArray());
615
616             // Check we got the value we put in.
617
if (col.getInt() != values[scanindex])
618                 throw T_Fail.testFailMsg("(scanExample after insert) Row "
619                     + scanindex
620                     + " should have been "
621                     + values[scanindex]
622                     + ", was "
623                     + col.getInt());
624
625             scanindex++;
626         }
627
628         // make sure another next() call continues to return false.
629
if (scan1.next())
630             throw T_Fail.testFailMsg("(scanExample after insert) should continue to return false after reaching end of scan");
631
632         // see if reopen scan interfaces work
633
scan1.reopenScan(
634             null, // start position - first row in conglomerate
635
0, // unused if start position is null.
636
null, // qualifier - accept all rows
637
null, // stop position - last row in conglomerate
638
0); // unused if stop position is null.
639

640         scan1.next();
641         scan1.next();
642         scan1.next();
643         RowLocation third_row_rowloc = scan1.newRowLocationTemplate();
644         scan1.fetchLocation(third_row_rowloc);
645
646         // see if reopen scan interfaces work
647
scan1.reopenScanByRowLocation(
648             third_row_rowloc,
649             null);
650
651         scanindex = 2;
652         while (scan1.next())
653         {
654             scan1.fetch(row.getRowArray());
655
656             // Check we got the value we put in.
657
if (col.getInt() != values[scanindex])
658                 throw T_Fail.testFailMsg("(scanExample after insert) Row "
659                     + scanindex
660                     + " should have been "
661                     + values[scanindex]
662                     + ", was "
663                     + col.getInt());
664
665             scanindex++;
666         }
667
668         scan1.close();
669
670         // Check we saw the right number of rows.
671
if (scanindex != values.length)
672             throw T_Fail.testFailMsg("(scanExample after insert) Expected "
673                 + values.length
674                 + "rows, got "
675                 + scanindex);
676
677         REPORT("(scanExample) rows present and accounted for");
678
679         // Open another scan on the conglomerate.
680
ScanController scan2 = tc.openScan(
681             conglomid,
682             false, // don't hold
683
TransactionController.OPENMODE_FORUPDATE, // for update
684
TransactionController.MODE_RECORD,
685             TransactionController.ISOLATION_SERIALIZABLE,
686             (FormatableBitSet) null, // all columns, all as objects
687
null, // start position - first row in conglomerate
688
0, // unused if start position is null.
689
null, // qualifier - accept all rows
690
null, // stop position - last row in conglomerate
691
0); // unused if stop position is null.
692

693         // Iterate with the second scan and fiddle with the values so they
694
// look like the new value array.
695
int newvalues[] = { 22, 33, 444, 55, 6666 };
696         while (scan2.next())
697         {
698             scan2.fetch(row.getRowArray());
699
700             switch(((SQLInteger) row.getCol(0)).getInt())
701             {
702             case 11:
703                 if (!scan2.delete())
704                     throw T_Fail.testFailMsg("(scanExample) delete failed.");
705                 break;
706             case 22:
707             case 33:
708             case 55:
709                 // leave these alone
710
break;
711             case 44:
712                 DataValueDescriptor[] update_row = new DataValueDescriptor[1];
713                 update_row[0] = new SQLInteger(444);
714
715                 FormatableBitSet update_desc = new FormatableBitSet(1);
716                 update_desc.set(0);
717
718                 if (!scan2.replace(update_row, update_desc))
719                 {
720                     throw T_Fail.testFailMsg(
721                         "(scanExample) partial column row replace failed.");
722                 }
723                 break;
724             case 66:
725                 row.setCol(0, new SQLInteger(6666));
726                 if (!scan2.replace(row.getRowArray(), (FormatableBitSet) null))
727                     throw T_Fail.testFailMsg("(scanExample) replace failed.");
728                 break;
729             default:
730                 throw T_Fail.testFailMsg("(scanExample) Read unexpected value.");
731             }
732         }
733         scan2.close();
734
735         REPORT("(scanExample) rows fiddled with");
736
737         // Open a third scan on the conglomerate.
738
ScanController scan3 = tc.openScan(
739             conglomid,
740             false, // don't hold
741
0, // not for update
742
TransactionController.MODE_RECORD,
743             TransactionController.ISOLATION_SERIALIZABLE,
744             (FormatableBitSet) null, // all columns, all as objects
745
null, // start position - first row in conglomerate
746
0, // unused if start position is null.
747
null, // qualifier - accept all rows
748
null, // stop position - last row in conglomerate
749
0); // unused if stop position is null.
750

751         // Iterate through and inspect the changes.
752
scanindex = 0;
753         row.setCol(0, col);
754         while (scan3.next())
755         {
756             scan3.fetch(row.getRowArray());
757
758             REPORT("(scanExample) scan3 fetched " + col.getInt());
759
760             // Check we got the value we put in.
761
if (col.getInt() != newvalues[scanindex])
762                 throw T_Fail.testFailMsg("(scanExample after changes) Row "
763                     + scanindex
764                     + " should have been "
765                     + newvalues[scanindex]
766                     + ", was "
767                     + col.getInt());
768
769             scanindex++;
770         }
771         scan3.close();
772
773         // Open a third scan on the conglomerate.
774
scan3 = tc.openScan(
775             conglomid,
776             false, // don't hold
777
0, // not for update
778
TransactionController.MODE_RECORD,
779             TransactionController.ISOLATION_READ_UNCOMMITTED,
780             (FormatableBitSet) null, // all columns, all as objects
781
null, // start position - first row in conglomerate
782
0, // unused if start position is null.
783
null, // qualifier - accept all rows
784
null, // stop position - last row in conglomerate
785
0); // unused if stop position is null.
786

787         // Iterate through and inspect the changes.
788
scanindex = 0;
789         row.setCol(0, col);
790         while (scan3.next())
791         {
792             scan3.fetch(row.getRowArray());
793
794             REPORT("(scanExample) scan3 fetched " + col.getInt());
795
796             // Check we got the value we put in.
797
if (col.getInt() != newvalues[scanindex])
798                 throw T_Fail.testFailMsg("(scanExample after changes) Row "
799                     + scanindex
800                     + " should have been "
801                     + newvalues[scanindex]
802                     + ", was "
803                     + col.getInt());
804
805             scanindex++;
806         }
807         scan3.close();
808
809         // Check we saw the right number of rows.
810
if (scanindex != newvalues.length)
811             throw T_Fail.testFailMsg("(scanExample after changes) Expected "
812                 + newvalues.length
813                 + "rows, got "
814                 + scanindex);
815
816         REPORT("(scanExample) fiddled rows present and accounted for");
817
818         REPORT("(scanExample) testing expected delete errors");
819
820         // Open 4th scan on conglomerate and test "expected" error returns
821
// from replace, partial column replace, delete.
822
ScanController scan4 = tc.openScan(
823             conglomid,
824             false, // don't hold
825
TransactionController.OPENMODE_FORUPDATE, // for update
826
TransactionController.MODE_RECORD,
827             TransactionController.ISOLATION_SERIALIZABLE,
828             (FormatableBitSet) null, // all columns, all as objects
829
null, // start position - first row in conglomerate
830
0, // unused if start position is null.
831
null, // qualifier - accept all rows
832
null, // stop position - last row in conglomerate
833
0); // unused if stop position is null.
834

835         // Iterate with the second scan find the "22" row, delete it and
836
// then test that operations on that deleted entry FAIL as expected.
837
while (scan4.next())
838         {
839             scan4.fetch(row.getRowArray());
840
841             if (!scan4.doesCurrentPositionQualify())
842             {
843                 throw T_Fail.testFailMsg("(scanExample doesCurrentPositionQualify() errors) Expected requalify of current row to succeed");
844             }
845
846             if (((SQLInteger) row.getCol(0)).getInt() == 22)
847             {
848                 if (!scan4.delete())
849                 {
850                     throw T_Fail.testFailMsg("(scanExample delete errors) Delete failed.");
851                 }
852                 break;
853             }
854         }
855
856         if (scan4.doesCurrentPositionQualify())
857         {
858             throw T_Fail.testFailMsg("(scanExample doesCurrentPositionQualify() errors) Expected qualify of deleted row to FAIL");
859         }
860
861         DataValueDescriptor[] update_row = new DataValueDescriptor[1];
862
863         FormatableBitSet update_desc = new FormatableBitSet(1);
864         update_desc.set(0);
865
866         if (scan4.replace(update_row, update_desc))
867         {
868             throw T_Fail.testFailMsg("(scanExample delete errors) Expected partial column replace to FAIL");
869         }
870         if (scan4.replace(row.getRowArray(), (FormatableBitSet) null))
871         {
872             throw T_Fail.testFailMsg("(scanExample after changes) Expected replace to FAIL");
873         }
874         if (scan4.delete())
875         {
876             throw T_Fail.testFailMsg("(scanExample after changes) Expected delete to FAIL");
877         }
878
879         scan4.close();
880
881         if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0) ||
882             (tc.countOpens(TransactionController.OPEN_CONGLOMERATE) > 0) ||
883             (tc.countOpens(TransactionController.OPEN_SCAN) > 0) ||
884             (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) > 0) ||
885             (tc.countOpens(TransactionController.OPEN_SORT) > 0))
886         {
887             System.out.println("OPENED:\n" + tc.debugOpened());
888             return(FAIL("unexpected open count."));
889         }
890
891
892         REPORT("(scanExample) completed");
893         return true;
894     }
895
896     protected boolean dropTest(TransactionController tc)
897         throws StandardException, T_Fail
898     {
899         ConglomerateController cc;
900
901         REPORT("(dropTest) starting");
902
903         // Test of drop conglomerate with abort by doing the following:
904
// create table
905
// commit
906
// drop table
907
// make sure table is not still there.
908
// abort
909
// make sure table is still there.
910

911         // Create a heap conglomerate.
912
long orig_conglomid =
913             tc.createConglomerate(
914                 "heap", // create a heap conglomerate
915
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
916
null, // column sort order not required for heap
917
null, // default properties
918
TransactionController.IS_DEFAULT); // not temporary
919

920         tc.commit();
921
922         tc.dropConglomerate(orig_conglomid);
923
924
925         // Try and Open it - it should fail.
926
try
927         {
928             cc = tc.openConglomerate(
929                     orig_conglomid,
930                     false,
931                     TransactionController.OPENMODE_FORUPDATE,
932                     TransactionController.MODE_RECORD,
933                     TransactionController.ISOLATION_SERIALIZABLE);
934
935             throw T_Fail.testFailMsg("Open conglom on deleted conglom worked.");
936         }
937         catch (StandardException e)
938         {
939             if (!e.getMessageId().equals(
940                     SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST))
941             {
942                 throw e;
943             }
944
945             // normal path through the test - conglomerate does not exist,
946
// ignore the expected error
947
}
948
949         // Try and Open a random non-existant conglomerate - it should fail.
950
try
951         {
952             cc = tc.openConglomerate(
953                     42424242,
954                     false,
955                     TransactionController.OPENMODE_FORUPDATE,
956                     TransactionController.MODE_RECORD,
957                     TransactionController.ISOLATION_SERIALIZABLE);
958
959             throw T_Fail.testFailMsg("Open conglom on deleted conglom worked.");
960         }
961         catch (StandardException e)
962         {
963             if (!e.getMessageId().equals(
964                     SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST))
965             {
966                 throw e;
967             }
968
969             // normal path through the test - conglomerate does not exist,
970
// ignore the expected error
971
}
972
973         // Try and delete it again - it should fail.
974
try
975         {
976             tc.dropConglomerate(orig_conglomid);
977
978             throw T_Fail.testFailMsg("Delete conglom on deleted conglom worked.");
979         }
980         catch (StandardException e)
981         {
982             // normal path through the test, ignore the expected error
983
}
984
985
986         // cursory test to make sure conglom directory is not screwed up.
987

988         // Create a heap conglomerate.
989
long conglomid =
990             tc.createConglomerate(
991                 "heap", // create a heap conglomerate
992
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
993
null, // column sort order not required for heap
994
null, // default properties
995
TransactionController.IS_DEFAULT); // not temporary
996

997         cc = tc.openConglomerate(
998                 conglomid,
999                 false,
1000                TransactionController.OPENMODE_FORUPDATE,
1001                TransactionController.MODE_RECORD,
1002                TransactionController.ISOLATION_SERIALIZABLE);
1003
1004        tc.abort();
1005
1006        // the original conglomerate should be still around after the abort.
1007
cc = tc.openConglomerate(
1008                orig_conglomid,
1009                false,
1010                TransactionController.OPENMODE_FORUPDATE,
1011                TransactionController.MODE_RECORD,
1012                TransactionController.ISOLATION_SERIALIZABLE);
1013
1014        cc.close();
1015
1016        return true;
1017    }
1018
1019    /**
1020     * Test the access level getTableProperties() call.
1021     * <p>
1022     *
1023     * @return true if the test succeeded.
1024     *
1025     * @param tc The transaction controller to use in the test.
1026     *
1027     * @exception StandardException Standard exception policy.
1028     * @exception T_Fail Unexpected behaviour from the API
1029     **/

1030    protected boolean getTableProperties(
1031    TransactionController tc)
1032        throws StandardException, T_Fail
1033    {
1034        int key_value;
1035
1036        Properties JavaDoc prop = new Properties JavaDoc();
1037
1038        prop.put(Property.PAGE_SIZE_PARAMETER, "8192");
1039        prop.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, "99");
1040        prop.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, "42");
1041        prop.put(RawStoreFactory.CONTAINER_INITIAL_PAGES, "22");
1042
1043        // Create a heap conglomerate.
1044
T_AccessRow template_row = new T_AccessRow(1);
1045        long conglomid =
1046            tc.createConglomerate(
1047                "heap", // create a heap conglomerate
1048
template_row.getRowArray(), // 1 column template.
1049
null, // column sort order not required for heap
1050
prop, // default properties
1051
TransactionController.IS_DEFAULT); // not temporary
1052
// Open the conglomerate.
1053
ConglomerateController cc =
1054            tc.openConglomerate(
1055                conglomid,
1056                false,
1057                TransactionController.OPENMODE_FORUPDATE,
1058                TransactionController.MODE_RECORD,
1059                TransactionController.ISOLATION_SERIALIZABLE);
1060
1061        // verify that input properties were used.
1062
Properties JavaDoc ret_prop = tc.getUserCreateConglomPropList();
1063
1064        cc.getTableProperties(ret_prop);
1065
1066        if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER).
1067                compareTo("8192") != 0 ||
1068            ret_prop.getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER).
1069                compareTo("99") != 0 ||
1070            ret_prop.getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER).
1071                compareTo("42") != 0 ||
1072            ret_prop.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES).
1073                compareTo("22") != 0)
1074        {
1075            throw T_Fail.testFailMsg(
1076                "(getTableProperties) Did not get expected table propertes(1)." +
1077                "\nGot pageSize = " +
1078                    ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER) +
1079                "\nGot reserved = " +
1080                    ret_prop.getProperty(
1081                        RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER) +
1082                "\nGot minimum record size = " +
1083                    ret_prop.getProperty(
1084                        RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER) +
1085                "\nGot initial pages = " +
1086                    ret_prop.getProperty(
1087                        RawStoreFactory.CONTAINER_INITIAL_PAGES));
1088        }
1089
1090        ret_prop = cc.getInternalTablePropertySet(null);
1091
1092        if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER).
1093                compareTo("8192") != 0 ||
1094            ret_prop.getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER).
1095                compareTo("99") != 0 ||
1096            ret_prop.getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER).
1097                compareTo("42") != 0 ||
1098            ret_prop.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES).
1099                compareTo("22") != 0)
1100        {
1101            throw T_Fail.testFailMsg(
1102                "(getTableProperties) Did not get expected table propertes(2)." +
1103                "\nGot pageSize = " +
1104                    ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER) +
1105                "\nGot reserved = " +
1106                    ret_prop.getProperty(
1107                        RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER) +
1108                "\nGot minimum record size = " +
1109                    ret_prop.getProperty(
1110                        RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER) +
1111                "\nGot initial pages = " +
1112                    ret_prop.getProperty(
1113                        RawStoreFactory.CONTAINER_INITIAL_PAGES));
1114        }
1115
1116        ret_prop = new Properties JavaDoc();
1117        
1118        ret_prop = cc.getInternalTablePropertySet(ret_prop);
1119
1120        if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER).
1121                compareTo("8192") != 0 ||
1122            ret_prop.getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER).
1123                compareTo("99") != 0 ||
1124            ret_prop.getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER).
1125                compareTo("42") != 0 ||
1126            ret_prop.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES).
1127                compareTo("22") != 0)
1128        {
1129            throw T_Fail.testFailMsg(
1130                "(getTableProperties) Did not get expected table propertes(3)." +
1131                "\nGot pageSize = " +
1132                    ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER) +
1133                "\nGot reserved = " +
1134                    ret_prop.getProperty(
1135                        RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER) +
1136                "\nGot minimum record size = " +
1137                    ret_prop.getProperty(
1138                        RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER) +
1139                "\nGot initial pages = " +
1140                    ret_prop.getProperty(
1141                        RawStoreFactory.CONTAINER_INITIAL_PAGES));
1142        }
1143
1144        return(true);
1145    }
1146
1147    /**
1148     * Test the access level alter table interface for adding columns.
1149     * <p>
1150     *
1151     * @return true if the test succeeded.
1152     *
1153     * @param tc The transaction controller to use in the test.
1154     *
1155     * @exception StandardException Standard exception policy.
1156     * @exception T_Fail Unexpected behaviour from the API
1157     **/

1158    protected boolean alterTable(
1159    TransactionController tc)
1160        throws StandardException, T_Fail
1161    {
1162        int key_value;
1163
1164        REPORT("(alterTable) starting");
1165
1166        // Create a heap conglomerate.
1167
T_AccessRow template_row = new T_AccessRow(1);
1168        long conglomid =
1169            tc.createConglomerate(
1170                "heap", // create a heap conglomerate
1171
template_row.getRowArray(), // 1 column template.
1172
null, // column sort order not required for heap
1173
null, // default properties
1174
TransactionController.IS_DEFAULT); // not temporary
1175
// Open the conglomerate.
1176
ConglomerateController cc =
1177            tc.openConglomerate(
1178                conglomid,
1179                false,
1180                TransactionController.OPENMODE_FORUPDATE,
1181                TransactionController.MODE_RECORD,
1182                TransactionController.ISOLATION_SERIALIZABLE);
1183
1184        // Create a 1 column row. int column = 1.
1185
T_AccessRow r1 = new T_AccessRow(1);
1186        SQLInteger c1 = new SQLInteger(1);
1187        r1.setCol(0, c1);
1188
1189        // Get a location template
1190
RowLocation rowloc1 = cc.newRowLocationTemplate();
1191
1192        // Insert the row and remember its location.
1193
cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1194
1195        // create another 1 column row. int column = 2.
1196
// Get a location template
1197
r1.setCol(0, new SQLInteger(2));
1198        RowLocation rowloc2 = cc.newRowLocationTemplate();
1199
1200        // Insert the row and remember its location.
1201
cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1202
1203        // At this point the table looks like:
1204
// col1
1205
// ----
1206
// 1
1207
// 2
1208

1209        // RESOLVE - currently the store can't catch the following error:
1210
/*
1211        // Test that we can't alter while it is open.
1212        try
1213        {
1214            tc.addColumnToConglomerate(conglomid, 1, c1);
1215            throw T_Fail.testFailMsg(
1216                "(alterTable) Allowed alter table while table was open.");
1217        }
1218        catch (StandardException t)
1219        {
1220            // expected error continue the test.
1221        }
1222        */

1223
1224        // Test that we can't add data to columns that don't exist
1225

1226        // Currently we only error check in debug code.
1227
// RESOLVE - should this be a runtime error?
1228
if (SanityManager.DEBUG)
1229        {
1230            try
1231            {
1232                T_AccessRow two_column_row = new T_AccessRow(2);
1233                SQLInteger col1 = new SQLInteger(3);
1234                SQLInteger col2 = new SQLInteger(3);
1235                cc.insert(two_column_row.getRowArray());
1236                throw T_Fail.testFailMsg(
1237                    "(alterTable) Allowed insert of bad row.");
1238            }
1239            catch (StandardException t)
1240            {
1241                // expected error continue the test.
1242
}
1243        }
1244
1245        // Test that we can't fetch data columns that don't exist
1246

1247        // Currently we only error check for this in sanity code.
1248
// RESOLVE - (mikem) should we check for this in released runtime?
1249
if (SanityManager.DEBUG)
1250        {
1251            try
1252            {
1253                T_AccessRow two_column_row = new T_AccessRow(2);
1254                if (!cc.fetch(
1255                        rowloc1, two_column_row.getRowArray(), (FormatableBitSet) null))
1256                {
1257                    throw T_Fail.testFailMsg(
1258                        "(alterTable) Allowed fetch of bad row, bad ret val.");
1259                }
1260
1261                throw T_Fail.testFailMsg(
1262                    "(alterTable) Allowed fetch of bad row.");
1263            }
1264            catch (StandardException t)
1265            {
1266                // expected error continue the test.
1267
}
1268        }
1269
1270        // Test that we can't fetch data columns that don't exist
1271
// Currently we only error check for this in sanity code.
1272
// RESOLVE - (mikem) should we check for this in released runtime?
1273
if (SanityManager.DEBUG)
1274        {
1275            try
1276            {
1277                DataValueDescriptor[] third_column_row =
1278                    new DataValueDescriptor[3];
1279
1280                third_column_row[2] = new SQLInteger(3);
1281
1282                FormatableBitSet fetch_desc = new FormatableBitSet(3);
1283                fetch_desc.set(2);
1284
1285                if (!cc.fetch(
1286                        rowloc1, third_column_row, fetch_desc))
1287                {
1288                    throw T_Fail.testFailMsg(
1289                        "(alterTable) Allowed fetch of bad row, bad ret val.");
1290                }
1291
1292                throw T_Fail.testFailMsg(
1293                    "(alterTable) Allowed fetch of bad row.");
1294            }
1295            catch (StandardException t)
1296            {
1297                // expected error continue the test.
1298
}
1299        }
1300
1301        // Test that we can't replace data columns that don't exist
1302

1303        // Currently we only error check for this in sanity code.
1304
// RESOLVE - (mikem) should we check for this in released runtime?
1305
if (SanityManager.DEBUG)
1306        {
1307            try
1308            {
1309                T_AccessRow two_column_row = new T_AccessRow(2);
1310                SQLInteger col1 = new SQLInteger(3);
1311                SQLInteger col2 = new SQLInteger(3);
1312                cc.replace(rowloc1, two_column_row.getRowArray(), null);
1313                throw T_Fail.testFailMsg(
1314                    "(alterTable) Allowed replace of bad row.");
1315            }
1316            catch (StandardException t)
1317            {
1318                // expected error continue the test.
1319
}
1320        }
1321
1322        // Test that we can't replace data columns that don't exist
1323
if (SanityManager.DEBUG)
1324        {
1325            try
1326            {
1327                DataValueDescriptor[] second_column_row =
1328                    new DataValueDescriptor[2];
1329                second_column_row[1] = new SQLInteger(3);
1330
1331                FormatableBitSet update_desc = new FormatableBitSet(2);
1332                update_desc.set(1);
1333
1334                cc.replace(rowloc1, second_column_row, update_desc);
1335                throw T_Fail.testFailMsg(
1336                    "(alterTable) Allowed partial row update of bad column.");
1337            }
1338            catch (StandardException t)
1339            {
1340                // expected error continue the test.
1341
}
1342        }
1343
1344        // Make sure commitNoSync gets executed sometimes.
1345
tc.commitNoSync(TransactionController.RELEASE_LOCKS);
1346
1347
1348        // now alter the conglomerate, add another int column
1349
tc.addColumnToConglomerate(conglomid, 1, c1);
1350
1351        // Open the table after the close done by commit.
1352
cc = tc.openConglomerate(
1353                conglomid,
1354                false,
1355                TransactionController.OPENMODE_FORUPDATE,
1356                TransactionController.MODE_RECORD,
1357                TransactionController.ISOLATION_SERIALIZABLE);
1358
1359        T_AccessRow two_column_row = new T_AccessRow(2);
1360        SQLInteger col1 = new SQLInteger(3);
1361        SQLInteger col2 = new SQLInteger(3);
1362
1363        // fetch the rows and make sure you get null's in new fields.
1364
if (!cc.fetch(
1365                rowloc1, two_column_row.getRowArray(), (FormatableBitSet) null))
1366        {
1367            throw T_Fail.testFailMsg(
1368                "(alterTable) Row not there.");
1369        }
1370
1371        if ((((SQLInteger)two_column_row.getCol(0)).getInt() != 1) ||
1372            (!two_column_row.getCol(1).isNull()))
1373        {
1374            throw T_Fail.testFailMsg(
1375                "(alterTable) Bad column value after alter.");
1376        }
1377        if (!cc.fetch(
1378                rowloc2, two_column_row.getRowArray(), (FormatableBitSet) null))
1379        {
1380            throw T_Fail.testFailMsg(
1381                "(alterTable) Row not there.");
1382        }
1383
1384        if ((((SQLInteger)two_column_row.getCol(0)).getInt() != 2) ||
1385            (!two_column_row.getCol(1).isNull()))
1386        {
1387            throw T_Fail.testFailMsg(
1388                "(alterTable) Bad column value after alter.");
1389        }
1390
1391        // make sure insert of 2 column row works.
1392
two_column_row = new T_AccessRow(2);
1393        two_column_row.setCol(0, new SQLInteger(3));
1394        two_column_row.setCol(1, new SQLInteger(300));
1395        cc.insert(two_column_row.getRowArray());
1396
1397
1398        // At this point the table looks like:
1399
// col1 col2
1400
// ---- ----
1401
// 1 NA
1402
// 2 NA
1403
// 3 300
1404

1405        
1406        ScanController scan = tc.openScan(
1407            conglomid,
1408            false, // don't hold
1409
TransactionController.OPENMODE_FORUPDATE, // for update
1410
TransactionController.MODE_RECORD,
1411            TransactionController.ISOLATION_SERIALIZABLE,
1412            (FormatableBitSet) null, // all columns, all as objects
1413
null, // start position - first row in conglomerate
1414
0, // unused if start position is null.
1415
null, // qualifier - accept all rows
1416
null, // stop position - last row in conglomerate
1417
0); // unused if stop position is null.
1418

1419        while (scan.next())
1420        {
1421            scan.fetch(two_column_row.getRowArray());
1422
1423            key_value = ((SQLInteger)two_column_row.getCol(0)).getInt();
1424
1425            switch(key_value)
1426            {
1427                case 1:
1428                {
1429                    // Set non-existent column value to 100
1430
if (!two_column_row.getCol(1).isNull())
1431                    {
1432                        throw T_Fail.testFailMsg(
1433                            "(alterTable) Bad column value after alter.");
1434                    }
1435
1436                    // test that replace field works on alter added column
1437
// make result row be: (1, 100)
1438

1439                    two_column_row.setCol(1, new SQLInteger(100));
1440
1441                    scan.replace(two_column_row.getRowArray(), (FormatableBitSet) null);
1442                    break;
1443                }
1444                case 2:
1445                {
1446                    if (!two_column_row.getCol(1).isNull())
1447                    {
1448                        throw T_Fail.testFailMsg(
1449                            "(alterTable) Bad column value after alter.");
1450                    }
1451
1452                    // test that replace row works on alter added column row.
1453
// make result row be: (2, 200)
1454
two_column_row.setCol(1, new SQLInteger(200));
1455
1456                    scan.replace(two_column_row.getRowArray(), (FormatableBitSet) null);
1457
1458                    break;
1459                }
1460                case 3:
1461                {
1462                    break;
1463                }
1464                default:
1465                {
1466                    throw T_Fail.testFailMsg(
1467                        "(alterTable) bad row value found in table.");
1468                }
1469
1470            }
1471        }
1472
1473        // reposition the scan
1474
scan.reopenScan(
1475            null, // start position - first row in conglomerate
1476
0, // unused if start position is null.
1477
null, // qualifier - accept all rows
1478
null, // stop position - last row in conglomerate
1479
0); // unused if stop position is null.
1480

1481        while (scan.next())
1482        {
1483            scan.fetch(two_column_row.getRowArray());
1484
1485            key_value = ((SQLInteger) two_column_row.getCol(0)).getInt();
1486
1487            switch(key_value)
1488            {
1489                case 1:
1490                case 2:
1491                case 3:
1492                {
1493                    int second_col_val =
1494                        ((SQLInteger) two_column_row.getCol(1)).getInt();
1495
1496                    if (second_col_val != (key_value * 100))
1497                    {
1498                        throw T_Fail.testFailMsg(
1499                            "(alterTable) Bad column value after alter." +
1500                            "expected: (" +
1501                                key_value + ", " + key_value * 100 + ")\n" +
1502                            "got : (" +
1503                                key_value + ", " + second_col_val + ")\n");
1504                    }
1505
1506                    break;
1507                }
1508                default:
1509                {
1510                    throw T_Fail.testFailMsg(
1511                        "(alterTable) bad row value found in table.");
1512                }
1513            }
1514        }
1515
1516        scan.close();
1517
1518        tc.commit();
1519
1520        REPORT("(alterTable) completed");
1521        
1522        return true;
1523    }
1524
1525
1526    /**
1527     * Test the access level ScanInfo interface.
1528     * <p>
1529     *
1530     * @return true if the test succeeded.
1531     *
1532     * @param tc The transaction controller to use in the test.
1533     *
1534     * @exception StandardException Standard exception policy.
1535     * @exception T_Fail Unexpected behaviour from the API
1536     **/

1537    protected boolean scanInfo(
1538    TransactionController tc)
1539        throws StandardException, T_Fail
1540    {
1541        int key_value;
1542
1543        REPORT("(scanInfo) starting");
1544
1545        // Create a heap conglomerate.
1546
T_AccessRow template_row = new T_AccessRow(2);
1547        long conglomid =
1548            tc.createConglomerate(
1549                "heap", // create a heap conglomerate
1550
template_row.getRowArray(), // 1 column template.
1551
null, // column sort order not required for heap
1552
null, // default properties
1553
TransactionController.IS_DEFAULT); // not temporary
1554
// Open the conglomerate.
1555
ConglomerateController cc =
1556            tc.openConglomerate(
1557                conglomid,
1558                false,
1559                TransactionController.OPENMODE_FORUPDATE,
1560                TransactionController.MODE_RECORD,
1561                TransactionController.ISOLATION_SERIALIZABLE);
1562
1563        // Create a 1 column row. int column = 1.
1564
T_AccessRow r1 = new T_AccessRow(2);
1565        SQLInteger c1 = new SQLInteger(1);
1566        SQLInteger c2 = new SQLInteger(100);
1567        r1.setCol(0, c1);
1568        r1.setCol(1, c2);
1569
1570        // Get a location template
1571
RowLocation rowloc1 = cc.newRowLocationTemplate();
1572
1573        // Insert the row and remember its location.
1574
cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1575
1576        // create another 2 column row. int column = 2.
1577
// Get a location template
1578
r1.setCol(0, new SQLInteger(2));
1579        r1.setCol(1, new SQLInteger(200));
1580        RowLocation rowloc2 = cc.newRowLocationTemplate();
1581
1582        // Insert the row and remember its location.
1583
cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1584
1585        cc.delete(rowloc2);
1586
1587        if (tc.isPristine() || tc.isIdle())
1588        {
1589            throw T_Fail.testFailMsg(
1590                "(scanInfo) bad xact state after update xact.");
1591        }
1592
1593        tc.commit();
1594
1595        ScanController scan = tc.openScan(
1596            conglomid,
1597            false, // don't hold
1598
0, // for read
1599
TransactionController.MODE_TABLE,
1600            TransactionController.ISOLATION_SERIALIZABLE,
1601            (FormatableBitSet) null, // all columns, all as objects
1602
null, // start position - first row in conglomerate
1603
0, // unused if start position is null.
1604
null, // qualifier - accept all rows
1605
null, // stop position - last row in conglomerate
1606
0); // unused if stop position is null.
1607

1608
1609        if (!scan.isTableLocked())
1610        {
1611            throw T_Fail.testFailMsg(
1612                "(scanInfo) table should be table locked.");
1613        }
1614
1615
1616        while (scan.next())
1617        {
1618            scan.fetch(r1.getRowArray());
1619        }
1620        ScanInfo scan_info = scan.getScanInfo();
1621        Properties JavaDoc prop = scan_info.getAllScanInfo(null);
1622
1623        if (!tc.isPristine() || tc.isIdle())
1624        {
1625            throw T_Fail.testFailMsg(
1626                "(scanInfo) bad xact state after update xact.");
1627        }
1628
1629        REPORT(("return from full row scan heap.getScanInfo() = " + prop));
1630
1631        if (Integer.parseInt(prop.getProperty(
1632           MessageService.getTextMessage(SQLState.STORE_RTS_NUM_PAGES_VISITED)))
1633                != 1)
1634        {
1635            throw T_Fail.testFailMsg(
1636                "(scanInfo) wrong numPagesVisited. Expected 1, got " +
1637                Integer.parseInt(prop.getProperty(
1638                    MessageService.getTextMessage(
1639                                    SQLState.STORE_RTS_NUM_PAGES_VISITED))));
1640        }
1641        if (Integer.parseInt(prop.getProperty(
1642            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_VISITED)))
1643                != 2)
1644        {
1645            throw T_Fail.testFailMsg(
1646                "(scanInfo) wrong numRowsVisited. Expected 2, got " +
1647                Integer.parseInt(prop.getProperty(
1648                    MessageService.getTextMessage(
1649                                    SQLState.STORE_RTS_NUM_ROWS_VISITED))));
1650        }
1651        if (Integer.parseInt(prop.getProperty(
1652          MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_QUALIFIED)))
1653                != 1)
1654        {
1655            throw T_Fail.testFailMsg(
1656                "(scanInfo) wrong numRowsQualified. Expected 1, got " +
1657                Integer.parseInt(prop.getProperty(
1658                    MessageService.getTextMessage(
1659                                    SQLState.STORE_RTS_NUM_ROWS_QUALIFIED))));
1660        }
1661
1662        // Try a partial Row scan
1663

1664        // only get the 2nd column.
1665
FormatableBitSet validColumns = new FormatableBitSet(3);
1666        validColumns.set(1);
1667
1668        scan = tc.openScan(
1669            conglomid,
1670            false, // don't hold
1671
TransactionController.OPENMODE_FORUPDATE, // for update
1672
TransactionController.MODE_RECORD,
1673            TransactionController.ISOLATION_SERIALIZABLE,
1674            validColumns, // only get the second column
1675
null, // start position - first row in conglomerate
1676
0, // unused if start position is null.
1677
null, // qualifier - accept all rows
1678
null, // stop position - last row in conglomerate
1679
0); // unused if stop position is null.
1680

1681        if (scan.isTableLocked())
1682        {
1683            throw T_Fail.testFailMsg(
1684                "(scanInfo) table should be row locked.");
1685        }
1686
1687        scan_info = scan.getScanInfo();
1688        prop = scan_info.getAllScanInfo(null);
1689        REPORT(("return from partial scan heap.getScanInfo() = " + prop));
1690
1691        // RESOLVE - should test the btree one also.
1692

1693        REPORT("(scanInfo) finishing");
1694
1695        return true;
1696    }
1697
1698    /**
1699     * Test partial scans.
1700     * <p>
1701     *
1702     * @return true if the test succeeded.
1703     *
1704     * @param tc The transaction controller to use in the test.
1705     *
1706     * @exception StandardException Standard exception policy.
1707     * @exception T_Fail Unexpected behaviour from the API
1708     **/

1709    protected boolean partialScan(
1710    TransactionController tc)
1711        throws StandardException, T_Fail
1712    {
1713        int key_value;
1714
1715        REPORT("(partialScan) starting");
1716
1717        // Create a heap conglomerate.
1718
T_AccessRow template_row = new T_AccessRow(2);
1719        long conglomid =
1720            tc.createConglomerate(
1721                "heap", // create a heap conglomerate
1722
template_row.getRowArray(), // 1 column template.
1723
null, // column sort order not required for heap
1724
null, // default properties
1725
TransactionController.IS_DEFAULT); // not temporary
1726
// Open the conglomerate.
1727
ConglomerateController cc =
1728            tc.openConglomerate(
1729                conglomid,
1730                false,
1731                TransactionController.OPENMODE_FORUPDATE,
1732                TransactionController.MODE_RECORD,
1733                TransactionController.ISOLATION_SERIALIZABLE);
1734
1735        // Create a 1 column row. int column = 1.
1736
T_AccessRow r1 = new T_AccessRow(2);
1737        SQLInteger c1 = new SQLInteger(1);
1738        SQLInteger c2 = new SQLInteger(100);
1739        r1.setCol(0, c1);
1740        r1.setCol(1, c2);
1741
1742        // Get a location template
1743
RowLocation rowloc1 = cc.newRowLocationTemplate();
1744
1745        // Insert the row and remember its location.
1746
cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1747
1748        // create another 2 column row. int column = 2.
1749
// Get a location template
1750
r1.setCol(0, new SQLInteger(2));
1751        r1.setCol(1, new SQLInteger(200));
1752        RowLocation rowloc2 = cc.newRowLocationTemplate();
1753
1754        // Insert the row and remember its location.
1755
cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1756
1757        cc.delete(rowloc2);
1758
1759        tc.commit();
1760
1761        // Try a partial Row scan with no columns.
1762

1763        // only get the 2nd column.
1764
FormatableBitSet validColumns = new FormatableBitSet();
1765
1766        ScanController scan = tc.openScan(
1767            conglomid,
1768            false, // don't hold
1769
TransactionController.OPENMODE_FORUPDATE, // for update
1770
TransactionController.MODE_RECORD,
1771            TransactionController.ISOLATION_SERIALIZABLE,
1772            validColumns, // only get the second column
1773
null, // start position - first row in conglomerate
1774
0, // unused if start position is null.
1775
null, // qualifier - accept all rows
1776
null, // stop position - last row in conglomerate
1777
0); // unused if stop position is null.
1778

1779        // should see one row.
1780

1781        if (!scan.next())
1782        {
1783            throw T_Fail.testFailMsg("(partialScan) did not see first row.");
1784        }
1785
1786        if (scan.next())
1787        {
1788            throw T_Fail.testFailMsg("(partialScan) saw more than one row.");
1789        }
1790
1791        // RESOLVE - should test the btree one also.
1792

1793        REPORT("(partialScan) finishing");
1794
1795        return true;
1796    }
1797
1798
1799    // Simple insert into heap performance test
1800
protected boolean insert_bench(TransactionController tc)
1801        throws StandardException, T_Fail
1802    {
1803        ConglomerateController cc = null;
1804        ScanController scan = null;
1805        long conglomid = -1;
1806        long before, after;
1807
1808
1809        // Create a row.
1810
T_AccessRow r1 = new T_AccessRow(1);
1811        long iter = 100;
1812
1813        for (int numcols = 1; numcols < 101; numcols *= 10)
1814        {
1815            // Create a heap conglomerate.
1816
conglomid =
1817                tc.createConglomerate(
1818                    "heap", // create a heap conglomerate
1819
new T_AccessRow(numcols).getRowArray(), // 1 SQLInteger() column template.
1820
null, // column sort order not required for heap
1821
null, // default properties
1822
TransactionController.IS_DEFAULT); // not temporary
1823

1824            tc.commit();
1825
1826            // Open the conglomerate.
1827
cc = tc.openConglomerate(
1828                    conglomid,
1829                    false,
1830                    TransactionController.OPENMODE_FORUPDATE,
1831                    TransactionController.MODE_RECORD,
1832                    TransactionController.ISOLATION_SERIALIZABLE);
1833
1834            for (int i = 0; i < numcols; i++)
1835            {
1836                r1.setCol(i, new SQLInteger(numcols));
1837            }
1838
1839            // time before
1840
before = System.currentTimeMillis();
1841
1842            for (int i = 0; i < iter; i++)
1843            {
1844                if (cc.insert(r1.getRowArray()) != 0)
1845                    throw T_Fail.testFailMsg("(insert_bench) insert failed ");
1846            }
1847
1848            // time after
1849
after = System.currentTimeMillis();
1850
1851            REPORT(
1852                "insert " + iter + " rows of " + numcols + " integer cols = " +
1853                (after - before) + " milliseconds.\n");
1854
1855
1856            // time before
1857
before = System.currentTimeMillis();
1858
1859            for (int i = 0; i < iter; i++)
1860            {
1861               if (cc.insert(r1.getRowArray()) != 0)
1862                    throw T_Fail.testFailMsg("(insert_bench) insert failed ");
1863            }
1864
1865            // time after
1866
after = System.currentTimeMillis();
1867
1868            REPORT(
1869                "second insert " + iter + " rows of " + numcols +
1870                " integer cols = " +
1871                (after - before) + " milliseconds.\n");
1872
1873            // Open a scan on the conglomerate.
1874
before = System.currentTimeMillis();
1875
1876            scan = tc.openScan(
1877                conglomid,
1878                false, // don't hold
1879
0, // not for update
1880
TransactionController.MODE_RECORD,
1881                TransactionController.ISOLATION_SERIALIZABLE,
1882                (FormatableBitSet) null, // all columns, all as objects
1883
null, // start position - first row in conglomerate
1884
0, // unused if start position is null.
1885
null, // qualifier - accept all rows
1886
null, // stop position - last row in conglomerate
1887
0); // unused if stop position is null.
1888

1889            // time before
1890
before = System.currentTimeMillis();
1891
1892            // Iterate through and check that the rows are still there.
1893
while (scan.next())
1894            {
1895                scan.fetch(r1.getRowArray());
1896            }
1897
1898            // time after
1899
after = System.currentTimeMillis();
1900
1901            REPORT(
1902                "scan " + (2 * iter) + " rows of " + numcols + " integer cols = " +
1903                (after - before) + " milliseconds.\n");
1904
1905            // Close the conglomerate.
1906
cc.close();
1907            tc.commit();
1908        }
1909
1910        return(true);
1911    }
1912
1913    /**
1914     * Test the access level SortCost interface.
1915     * <p>
1916     *
1917     * @return true if the test succeeded.
1918     *
1919     * @param tc The transaction controller to use in the test.
1920     *
1921     * @exception StandardException Standard exception policy.
1922     * @exception T_Fail Unexpected behaviour from the API
1923     **/

1924    protected boolean sortCost(
1925    TransactionController tc)
1926        throws StandardException, T_Fail
1927    {
1928        int key_value;
1929
1930        REPORT("(sortCost) starting");
1931
1932        // Create a heap conglomerate.
1933
T_AccessRow template_row = new T_AccessRow(2);
1934        long conglomid =
1935            tc.createConglomerate(
1936                "heap", // create a heap conglomerate
1937
template_row.getRowArray(), // 1 column template.
1938
null, // column sort order not required for heap
1939
null, // default properties
1940
TransactionController.IS_DEFAULT); // not temporary
1941
// Open the conglomerate.
1942
ConglomerateController cc =
1943            tc.openConglomerate(
1944                conglomid,
1945                false,
1946                TransactionController.OPENMODE_FORUPDATE,
1947                TransactionController.MODE_RECORD,
1948                TransactionController.ISOLATION_SERIALIZABLE);
1949
1950        // Create a 2 column row.
1951
T_AccessRow r1 = new T_AccessRow(2);
1952        SQLInteger c1 = new SQLInteger(1);
1953        SQLInteger c2 = new SQLInteger(100);
1954        r1.setCol(0, c1);
1955        r1.setCol(1, c2);
1956
1957        // Get a location template
1958
RowLocation rowloc1 = cc.newRowLocationTemplate();
1959
1960        // Insert the row and remember its location.
1961
cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1962
1963        cc.close();
1964
1965        tc.commit();
1966
1967        // flush the cache to get the row count updated.
1968
flush_cache();
1969
1970        // Test 1 - Just call for various types of sorts. Not sure how
1971
// to test the validity.
1972
SortCostController scc = tc.openSortCostController(null);
1973
1974        double estimated_cost =
1975            scc.getSortCost(
1976                template_row.getRowArray(),
1977                null,
1978                false,
1979                10000,
1980                100,
1981                100);
1982
1983        if (estimated_cost <= 0)
1984        {
1985            throw T_Fail.testFailMsg(
1986                "(storeCost) estimated sort cost :" + estimated_cost);
1987        }
1988
1989        REPORT("(sortCost) finishing");
1990
1991        return true;
1992    }
1993
1994    /**
1995     * Test the access level StoreCost interface.
1996     * <p>
1997     *
1998     * @return true if the test succeeded.
1999     *
2000     * @param tc The transaction controller to use in the test.
2001     *
2002     * @exception StandardException Standard exception policy.
2003     * @exception T_Fail Unexpected behaviour from the API
2004     **/

2005    protected boolean storeCost(
2006    TransactionController tc)
2007        throws StandardException, T_Fail
2008    {
2009        int key_value;
2010
2011        REPORT("(storeCost) starting");
2012
2013        // Create a heap conglomerate.
2014
T_AccessRow template_row = new T_AccessRow(2);
2015        long conglomid =
2016            tc.createConglomerate(
2017                "heap", // create a heap conglomerate
2018
template_row.getRowArray(), // 1 column template.
2019
null, // column sort order not required for heap
2020
null, // default properties
2021
TransactionController.IS_DEFAULT); // not temporary
2022
// Open the conglomerate.
2023
ConglomerateController cc =
2024            tc.openConglomerate(
2025                conglomid,
2026                false,
2027                TransactionController.OPENMODE_FORUPDATE,
2028                TransactionController.MODE_RECORD,
2029                TransactionController.ISOLATION_SERIALIZABLE);
2030
2031        // Create a 2 column row.
2032
T_AccessRow r1 = new T_AccessRow(2);
2033        SQLInteger c1 = new SQLInteger(1);
2034        SQLInteger c2 = new SQLInteger(100);
2035        r1.setCol(0, c1);
2036        r1.setCol(1, c2);
2037
2038        // Get a location template
2039
RowLocation rowloc1 = cc.newRowLocationTemplate();
2040
2041        // Insert the row and remember its location.
2042
cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
2043
2044        cc.close();
2045
2046        tc.commit();
2047
2048        // flush the cache to get the row count updated.
2049
flush_cache();
2050
2051        // Test 1 - ASSERT(initial row count after 1 insert should be 1)
2052
StoreCostController scc = tc.openStoreCost(conglomid);
2053
2054
2055        if (scc.getEstimatedRowCount() != 1)
2056        {
2057            throw T_Fail.testFailMsg(
2058                "(storeCost) estimated row count not 1:" +
2059                scc.getEstimatedRowCount());
2060        }
2061
2062        // Test 2 - ASSERT(should be able to set arbitrary row count)
2063

2064        scc.setEstimatedRowCount(5);
2065
2066        if (scc.getEstimatedRowCount() != 5)
2067        {
2068            throw T_Fail.testFailMsg("(storeCost) estimated row count not 5");
2069        }
2070
2071        scc.setEstimatedRowCount(1);
2072
2073
2074        // Test 3 - ASSERT(should implement getFetchFromRowLocationCost())
2075
// should figure out some way to determine reasonable number is
2076
// returned.
2077
double fetch_cost =
2078            scc.getFetchFromRowLocationCost((FormatableBitSet) null, 0);
2079        fetch_cost =
2080            scc.getFetchFromRowLocationCost(
2081                (FormatableBitSet) new FormatableBitSet(0), 0);
2082        REPORT("fetch cost (full row) of row loc = " + fetch_cost);
2083        fetch_cost =
2084            scc.getFetchFromRowLocationCost(
2085                (FormatableBitSet) new FormatableBitSet(1), 0);
2086        FormatableBitSet bit_set = new FormatableBitSet(2);
2087        REPORT("fetch cost (no cols) of row loc = " + fetch_cost);
2088        bit_set.set(1);
2089        fetch_cost =
2090            scc.getFetchFromRowLocationCost(
2091                (FormatableBitSet) new FormatableBitSet(1), 0);
2092        REPORT("fetch cost (1 col) of row loc = " + fetch_cost);
2093
2094        // Test 4 - ASSERT(should implement getFetchFromFullKeyCost())
2095
// should figure out some way to determine reasonable number is
2096
// returned.
2097
/* - RESOLVE HEAP does not implement this.
2098        fetch_cost =
2099            scc.getFetchFromFullKeyCost((FormatableBitSet) null, (int[]) null, 0);
2100        REPORT("fetch full key cost (full row) of row loc = " + fetch_cost);
2101
2102        fetch_cost =
2103            scc.getFetchFromFullKeyCost(
2104                (FormatableBitSet) new FormatableBitSet(0), (int[]) null, 0);
2105        REPORT("fetch full key cost (no cols) of row loc = " + fetch_cost);
2106
2107        fetch_cost =
2108            scc.getFetchFromFullKeyCost(
2109                (FormatableBitSet) new FormatableBitSet(1), (int[]) null, 0);
2110        REPORT("fetch full key cost (no cols) of row loc = " + fetch_cost);
2111
2112        bit_set = new FormatableBitSet(2);
2113        bit_set.set(1);
2114        fetch_cost =
2115            scc.getFetchFromFullKeyCost(
2116                (FormatableBitSet) new FormatableBitSet(1), (int[]) null, 0);
2117        REPORT("fetch full key cost (1 col) of row loc = " + fetch_cost);
2118        */

2119
2120        // Test 5 - ASSERT(should implement getScanCost())
2121
// should figure out some way to determine reasonable number is
2122
// returned.
2123
StoreCostResult cost_result = new T_StoreCostResult();
2124
2125        scc.getScanCost(
2126            StoreCostController.STORECOST_SCAN_NORMAL,
2127            -1, // row count
2128
1, // number of rows fetched at a time from access.
2129
false, // forUpdate
2130
(FormatableBitSet) null, // validColumns
2131
new T_AccessRow(2).getRowArray(), // template
2132
null, // start position - first row in conglomerate
2133
0, // unused if start position is null.
2134
null, // stop position - last row in conglomerate
2135
0, // unused if stop position is null.
2136
false, // reopen_scan?
2137
0, // access_type
2138
cost_result); // cost result.
2139

2140        REPORT("fetch scan cost (full row) of row loc = " + cost_result);
2141
2142        scc.getScanCost(
2143            StoreCostController.STORECOST_SCAN_NORMAL,
2144            -1, // row count
2145
1, // number of rows fetched at a time from access.
2146
false, // forUpdate
2147
new FormatableBitSet(0), // validColumns
2148
new T_AccessRow(2).getRowArray(), // template
2149
null, // start position - first row in conglomerate
2150
0, // unused if start position is null.
2151
null, // stop position - last row in conglomerate
2152
0, // unused if stop position is null.
2153
false, // reopen_scan?
2154
0, // access_type
2155
cost_result); // cost result.
2156

2157        REPORT("fetch scan cost (no cols) of row loc = " + cost_result);
2158
2159        scc.getScanCost(
2160            StoreCostController.STORECOST_SCAN_NORMAL,
2161            -1, // row count
2162
1, // number of rows fetched at a time from access.
2163
false, // forUpdate
2164
new FormatableBitSet(1), // validColumns
2165
new T_AccessRow(2).getRowArray(), // template
2166
null, // start position - first row in conglomerate
2167
0, // unused if start position is null.
2168
null, // stop position - last row in conglomerate
2169
0, // unused if stop position is null.
2170
false, // reopen_scan?
2171
0, // access_type
2172
cost_result); // cost result.
2173

2174        REPORT("fetch scan cost (no cols) of row loc = " + cost_result);
2175
2176        bit_set = new FormatableBitSet(2);
2177        bit_set.set(1);
2178        scc.getScanCost(
2179            StoreCostController.STORECOST_SCAN_NORMAL,
2180            -1, // row count
2181
1, // number of rows fetched at a time from access.
2182
false, // forUpdate
2183
bit_set, // validColumns
2184
new T_AccessRow(2).getRowArray(), // template
2185
null, // start position - first row in conglomerate
2186
0, // unused if start position is null.
2187
null, // stop position - last row in conglomerate
2188
0, // unused if stop position is null.
2189
false, // reopen_scan?
2190
0, // access_type
2191
cost_result); // cost result.
2192

2193        REPORT("fetch scan cost (1 cols) of row loc = " + cost_result);
2194
2195        // make sure you can get a row location.
2196
rowloc1 = scc.newRowLocationTemplate();
2197
2198        REPORT("(storeCost) finishing");
2199
2200        return true;
2201    }
2202
2203    /**
2204        Test transactional properties
2205
2206        @exception StandardException test failure
2207        @exception T_Fail test failure
2208    */

2209    protected boolean transactionalProperties(TransactionController tc)
2210        throws StandardException, T_Fail
2211    {
2212        REPORT("start transactionalProperties");
2213
2214        // put a couple of properties in with different values and types
2215

2216        tc.setProperty("T_Key_Frog", new SQLLongint(479), false);
2217        tc.setProperty("T_Key_Tiger", "Roar, ROAR", false);
2218
2219
2220        long lvalue = ((SQLLongint) (tc.getProperty("T_Key_Frog"))).getLong();
2221        if (lvalue != 479)
2222            throw T_Fail.testFailMsg("setProperty() - expected 479 - got " + lvalue);
2223
2224        String JavaDoc svalue = (String JavaDoc) tc.getProperty("T_Key_Tiger");
2225        if (!svalue.equals("Roar, ROAR"))
2226            throw T_Fail.testFailMsg("setProperty() - expected 'Roar, ROAR' - got " + svalue);
2227
2228        tc.commit();
2229
2230        // should still be accessable after the commit
2231
lvalue = ((SQLLongint) (tc.getProperty("T_Key_Frog"))).getLong();
2232        if (lvalue != 479)
2233            throw T_Fail.testFailMsg("setProperty() - expected 479 - got " + lvalue);
2234
2235        svalue = (String JavaDoc) tc.getProperty("T_Key_Tiger");
2236        if (!svalue.equals("Roar, ROAR"))
2237            throw T_Fail.testFailMsg("setProperty() - expected 'Roar, ROAR' - got " + svalue);
2238
2239        tc.commit();
2240
2241        // see if update works
2242
tc.setProperty("T_Key_Tiger", "mieow, mieow", false);
2243        svalue = (String JavaDoc) tc.getProperty("T_Key_Tiger");
2244        if (!svalue.equals("mieow, mieow"))
2245            throw T_Fail.testFailMsg("setProperty() - expected 'mieow, mieow' - got " + svalue);
2246
2247        tc.commit();
2248        svalue = (String JavaDoc) tc.getProperty("T_Key_Tiger");
2249        if (!svalue.equals("mieow, mieow"))
2250            throw T_Fail.testFailMsg("setProperty() - expected 'mieow, mieow' - got " + svalue);
2251
2252        // see if an update to a different type works
2253
tc.setProperty("T_Key_Tiger", new SQLLongint(570), false);
2254        lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger"))).getLong();
2255
2256        if (lvalue != 570)
2257            throw T_Fail.testFailMsg("setProperty() - expected 570 - got " + lvalue);
2258
2259        tc.commit();
2260
2261        lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger"))).getLong();
2262        if (lvalue != 570)
2263            throw T_Fail.testFailMsg("setProperty() - expected 570 - got " + lvalue);
2264
2265        tc.commit();
2266
2267        // delete a key
2268
tc.setProperty("T_Key_Frog", (Serializable JavaDoc) null, false);
2269        if (tc.getProperty("T_Key_Frog") != null)
2270            throw T_Fail.testFailMsg("setProperty() - delete failed");
2271        tc.commit();
2272
2273        if (tc.getProperty("T_Key_Frog") != null)
2274            throw T_Fail.testFailMsg("setProperty() - delete failed");
2275
2276        tc.commit();
2277
2278        // now see if rollback works.
2279
tc.setProperty("T_Key_Tiger", new SQLLongint(457), false);
2280
2281        tc.abort();
2282        lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger"))).getLong();
2283        if (lvalue != 570)
2284            throw T_Fail.testFailMsg("setProperty() - expected 570 - got " + lvalue);
2285
2286        tc.commit();
2287        PASS("transactionalProperties");
2288
2289        return true;
2290    }
2291
2292
2293
2294    // Test temporary conglomerates.
2295
protected boolean tempTest(TransactionController tc)
2296        throws StandardException, T_Fail
2297    {
2298        REPORT("(tempTest) starting");
2299
2300        // Create some conglomerates, some temporary, some not.
2301
long cid5252t = createAConglom(tc, 5252, true); // temporary
2302
long cid87t = createAConglom(tc, 87, true); // temporary
2303
long cid999p = createAConglom(tc, 999, false); // permanent
2304
long cid3t = createAConglom(tc, 3, true); // temporary
2305

2306        // Create an index on two of them
2307
long cid5252ti = createBtree(tc, cid5252t, true);
2308        long cid999pi = createBtree(tc, cid999p, false);
2309
2310        int r;
2311
2312        // Make sure we can read them.
2313
if ((r = checkAConglom(
2314                    tc, (DataValueDescriptor[]) null, cid5252t, 5252)) != 1)
2315        {
2316            throw T_Fail.testFailMsg(
2317                    "(tempTest) after create checkAConglom(cid5252t) == " + r);
2318        }
2319        if ((r = checkAConglom(
2320                    tc, getBtreeTemplate(tc, cid5252t), cid5252ti, 5252)) != 1)
2321        {
2322            throw T_Fail.testFailMsg(
2323                    "(tempTest) after create checkAConglom(cid5252ti) == " + r);
2324        }
2325
2326        if ((r = checkAConglom(
2327                    tc, (DataValueDescriptor[]) null, cid999p, 999)) != 1)
2328        {
2329            throw T_Fail.testFailMsg(
2330                    "(tempTest) after create checkAConglom(cid999p) == " + r);
2331        }
2332
2333        if ((r = checkAConglom(
2334                    tc, getBtreeTemplate(tc, cid999p), cid999pi, 999)) != 1)
2335        {
2336            throw T_Fail.testFailMsg(
2337                    "(tempTest) after create checkAConglom(cid999pi) == " + r);
2338        }
2339
2340        if ((r = checkAConglom(
2341                    tc, (DataValueDescriptor[]) null, cid3t, 3)) != 1)
2342        {
2343            throw T_Fail.testFailMsg(
2344                    "(tempTest) after create checkAConglom(cid3t) == " + r);
2345        }
2346
2347        if ((r = checkAConglom(
2348                    tc, (DataValueDescriptor[]) null, cid87t, 87)) != 1)
2349        {
2350            throw T_Fail.testFailMsg(
2351                    "(tempTest) after create checkAConglom(cid87t) == " + r);
2352        }
2353
2354        // Drop two of them.
2355
tc.dropConglomerate(cid999pi);
2356        tc.dropConglomerate(cid999p);
2357        tc.dropConglomerate(cid87t);
2358
2359        // Try dropping the ones we already dropped - expect exceptions
2360
try
2361        {
2362            tc.dropConglomerate(cid999p);
2363            throw T_Fail.testFailMsg("(tempTest) drop of dropped cid999p succeeded");
2364        }
2365        catch (StandardException e)
2366        {
2367            // normal path through the test, ignore the expected error
2368
}
2369        try
2370        {
2371            tc.dropConglomerate(cid999pi);
2372            throw T_Fail.testFailMsg("(tempTest) drop of dropped cid999pi succeeded");
2373        }
2374        catch (StandardException e)
2375        {
2376            // normal path through the test, ignore the expected error
2377
}
2378        try
2379        {
2380            tc.dropConglomerate(cid87t);
2381            throw T_Fail.testFailMsg("(tempTest) drop of dropped cid87t succeeded");
2382        }
2383        catch (StandardException e)
2384        {
2385            // normal path through the test, ignore the expected error
2386
}
2387
2388        // Make sure the correct ones remain
2389
if ((r = checkAConglom(
2390                    tc, (DataValueDescriptor[]) null, cid5252t, 5252)) != 1)
2391        {
2392            throw T_Fail.testFailMsg(
2393                    "(tempTest) after drop checkAConglom(cid5252t) == " + r);
2394        }
2395
2396        if ((r = checkAConglom(
2397                    tc, getBtreeTemplate(tc, cid5252t), cid5252ti, 5252)) != 1)
2398        {
2399            throw T_Fail.testFailMsg(
2400                    "(tempTest) after drop checkAConglom(cid5252ti) == " + r);
2401        }
2402
2403        if ((r = checkAConglom(
2404                    tc, (DataValueDescriptor[]) null, cid3t, 3)) != 1)
2405        {
2406            throw T_Fail.testFailMsg(
2407                    "(tempTest) after drop checkAConglom(cid3t) == " + r);
2408        }
2409
2410        // Make sure commitNoSync gets executed sometimes.
2411
tc.commitNoSync(TransactionController.RELEASE_LOCKS);
2412
2413        // After committing the transaction, the congloms
2414
// should still be there (with their rows).
2415
if ((r = checkAConglom(
2416                    tc, (DataValueDescriptor[]) null, cid5252t, 5252)) != 1)
2417        {
2418            throw T_Fail.testFailMsg(
2419                    "(tempTest) after commit checkAConglom(cid5252t) == " + r);
2420        }
2421
2422        if ((r = checkAConglom(
2423                    tc, getBtreeTemplate(tc, cid5252t), cid5252ti, 5252)) != 1)
2424        {
2425            throw T_Fail.testFailMsg(
2426                    "(tempTest) after commit checkAConglom(cid5252ti) == " + r);
2427        }
2428
2429        if ((r = checkAConglom(
2430                    tc, (DataValueDescriptor[]) null, cid3t, 3)) != 1)
2431        {
2432            throw T_Fail.testFailMsg(
2433                    "(tempTest) after commit checkAConglom(cid3t) == " + r);
2434        }
2435
2436
2437        // open cid3t for update to force its truncation on the abort.
2438
ScanController sc = tc.openScan(
2439            cid3t,
2440            false, // don't hold
2441
TransactionController.OPENMODE_FORUPDATE, // for update
2442
TransactionController.MODE_RECORD,
2443            TransactionController.ISOLATION_SERIALIZABLE,
2444            (FormatableBitSet) null, // all columns, all as objects
2445
null, // start position - first row in conglomerate
2446
0, // unused if start position is null.
2447
null, // qualifier - accept all rows
2448
null, // stop position - last row in conglomerate
2449
0); // unused if stop position is null.
2450

2451        sc.close();
2452
2453
2454        tc.abort();
2455
2456        // After an abort, the congloms that were opened for update should be there,
2457
// but truncated
2458
if ((r = checkAConglom(
2459                    tc, (DataValueDescriptor[]) null, cid5252t, 5252)) != 1)
2460        {
2461            throw T_Fail.testFailMsg(
2462                    "(tempTest) after abort checkAConglom(cid5252t) == " + r);
2463        }
2464
2465        // RESOLVE(mikem): track 1825
2466
// don't want to open temp cantainer with IS_KEPT always.
2467
// if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t, 3)) != 0) {
2468
// throw T_Fail.testFailMsg("(tempTest) after abort checkAConglom(cid3t) == " + r);
2469
// }
2470

2471        if ((r = checkAConglom(
2472                    tc, (DataValueDescriptor[]) null, cid3t, 3)) != 1)
2473        {
2474            throw T_Fail.testFailMsg(
2475                    "(tempTest) after abort checkAConglom(cid3t) == " + r);
2476        }
2477
2478        // Due to bug STO84, temp btrees are corrupted after aborts,
2479
// so the following will cause problems:
2480
/*
2481        if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid5252ti, 5252)) != 0)
2482            throw T_Fail.testFailMsg("(tempTest) after abort checkAConglom(cid5252ti) == " + r);
2483        */

2484
2485        // Drop index on conglomerate to make sure we can do a drop after truncate.
2486
tc.dropConglomerate(cid5252ti);
2487        if (tc.conglomerateExists(cid5252ti))
2488            throw T_Fail.testFailMsg("(tempTest) after drop cid5252ti still exists");
2489
2490        // Drop one conglomerate to make sure we can do a drop after truncate.
2491
tc.dropConglomerate(cid5252t);
2492        if (tc.conglomerateExists(cid5252t))
2493            throw T_Fail.testFailMsg("(tempTest) after drop cid5252t still exists");
2494
2495        // Leave the last one - raw store is supposed to delete
2496
// it when the system reboots
2497

2498        // Success!
2499
REPORT("(tempTest) succeeded");
2500        return true;
2501    }
2502
2503    private long createAConglom(TransactionController tc, int testValue, boolean temporary)
2504        throws StandardException
2505    {
2506        // Create a heap conglomerate.
2507
long cid =
2508            tc.createConglomerate(
2509                "heap", // create a heap conglomerate
2510
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2511
null, // column sort order not required for heap
2512
null, // default properties
2513
temporary ? TransactionController.IS_TEMPORARY : TransactionController.IS_DEFAULT);
2514
2515        ConglomerateController cc =
2516            tc.openConglomerate(
2517                cid,
2518                false,
2519                TransactionController.OPENMODE_FORUPDATE,
2520                TransactionController.MODE_RECORD,
2521                TransactionController.ISOLATION_SERIALIZABLE);
2522
2523        // Create a row.
2524
T_AccessRow row = new T_AccessRow(1);
2525        SQLLongint col = new SQLLongint(testValue);
2526        row.setCol(0, col);
2527
2528        // Stuff in the test value so we can recognize this conglom later.
2529
cc.insert(row.getRowArray());
2530
2531        cc.close();
2532
2533        return cid;
2534    }
2535
2536    private DataValueDescriptor[] getBtreeTemplate(
2537    TransactionController tc,
2538    long baseConglomId)
2539        throws StandardException
2540    {
2541        // Open a scan on the base conglomerate which will return all rows.
2542
FormatableBitSet singleColumn = new FormatableBitSet(1);
2543        singleColumn.set(0);
2544        ScanController sc = tc.openScan(baseConglomId, false,
2545            0, // not for update
2546
TransactionController.MODE_RECORD,
2547            TransactionController.ISOLATION_SERIALIZABLE,
2548            singleColumn, // all columns, all as objects
2549
null, 0, null, null, 0);
2550
2551        // Create the template for the index. This method "knows" that
2552
// all rows in the base table have one IntCol
2553
T_AccessRow template = new T_AccessRow(2);
2554        SQLLongint col0 = new SQLLongint(0);
2555        RowLocation col1 = sc.newRowLocationTemplate();
2556        template.setCol(0, col0);
2557        template.setCol(1, col1);
2558
2559        sc.close();
2560
2561        return(template.getRowArray());
2562    }
2563
2564
2565    private long createBtree(TransactionController tc, long baseConglomId, boolean temporary)
2566        throws StandardException
2567    {
2568        // Create the properties for the index.
2569
// This method knows that there is just one column in the base table
2570
Properties JavaDoc indexProps = new Properties JavaDoc();
2571        indexProps.put("baseConglomerateId", Long.toString(baseConglomId));
2572        indexProps.put("nUniqueColumns", "1");
2573        indexProps.put("rowLocationColumn", "1");
2574        indexProps.put("nKeyFields", "2");
2575
2576        // Open a scan on the base conglomerate which will return all rows.
2577
FormatableBitSet singleColumn = new FormatableBitSet(1);
2578        singleColumn.set(0);
2579        ScanController sc = tc.openScan(baseConglomId, false,
2580            0, // not for update
2581
TransactionController.MODE_RECORD,
2582            TransactionController.ISOLATION_SERIALIZABLE,
2583            singleColumn, // just the first column.
2584
null, 0, null, null, 0);
2585
2586        // Create the template for the index. This method "knows" that
2587
// all rows in the base table have one IntCol
2588
T_AccessRow template = new T_AccessRow(2);
2589        SQLLongint col0 = new SQLLongint(0);
2590        RowLocation col1 = sc.newRowLocationTemplate();
2591        template.setCol(0, col0);
2592        template.setCol(1, col1);
2593
2594        DataValueDescriptor[] baseRow = new DataValueDescriptor[1];
2595        baseRow[0] = col0;
2596
2597        // Create a btree secondary index conglomerate.
2598
long iid = tc.createConglomerate("BTREE", template.getRowArray(), null, indexProps,
2599            temporary ? TransactionController.IS_TEMPORARY : TransactionController.IS_DEFAULT);
2600
2601        // Open the index so we can stuff in index rows.
2602
ConglomerateController cc =
2603            tc.openConglomerate(
2604                iid,
2605                false,
2606                TransactionController.OPENMODE_FORUPDATE,
2607                TransactionController.MODE_RECORD,
2608                TransactionController.ISOLATION_SERIALIZABLE);
2609
2610        // build the index.
2611
while (sc.next())
2612        {
2613            sc.fetch(baseRow);
2614            sc.fetchLocation(col1);
2615            cc.insert(template.getRowArray());
2616        }
2617
2618        cc.close();
2619
2620        return iid;
2621    }
2622
2623    /**
2624    Open a scan on the conglomerate for the given conglom id, and verify
2625    that it has rows with the given test value. This is a way of
2626    verifying that we got the right conglomerate. Returns the number of
2627    rows that it checked (-1 if the conglomerate doesn't exist).
2628    **/

2629    private int checkAConglom(
2630    TransactionController tc,
2631    DataValueDescriptor[] scratch_template,
2632    long conglomId,
2633    int testValue)
2634        throws StandardException
2635    {
2636        if (!tc.conglomerateExists(conglomId))
2637            return -1;
2638        
2639        ScanController sc = tc.openScan(
2640            conglomId,
2641            false, // don't hold
2642
0, // not for update
2643
TransactionController.MODE_RECORD,
2644            TransactionController.ISOLATION_SERIALIZABLE,
2645            (FormatableBitSet) null, // all columns, all as objects
2646
null, // start position - first row in conglomerate
2647
0, // unused if start position is null.
2648
null, // qualifier - accept all rows
2649
null, // stop position - last row in conglomerate
2650
0); // unused if stop position is null.
2651

2652        // An empty row
2653
T_AccessRow row = new T_AccessRow(1);
2654        SQLLongint col = new SQLLongint(0);
2655        row.setCol(0, col);
2656
2657        // Iterate through and check that the rows are still there.
2658
// Note this part of the test will inten
2659
int nrows = 0;
2660        while (sc.next())
2661        {
2662            sc.fetch(row.getRowArray());
2663            if (((SQLLongint) row.getCol(0)).getLong() != testValue)
2664                return -2;
2665            nrows++;
2666        }
2667
2668        sc.close();
2669
2670        return nrows;
2671    }
2672
2673    protected boolean updatelocks(
2674    TransactionController tc)
2675        throws StandardException, T_Fail
2676    {
2677        REPORT("(updatelocks starting.)");
2678
2679        updatelocks_0(
2680            tc, TransactionController.ISOLATION_SERIALIZABLE);
2681        updatelocks_0(
2682            tc, TransactionController.ISOLATION_READ_COMMITTED);
2683
2684        REPORT("(updatelocks ending.)");
2685
2686        return(true);
2687    }
2688
2689    protected boolean updatelocks_0(
2690    TransactionController tc,
2691    int isolation_level)
2692        throws StandardException, T_Fail
2693    {
2694        // Create a 2 column row.
2695
T_AccessRow r1 = new T_AccessRow(2);
2696        SQLInteger c1 = new SQLInteger(1);
2697        SQLInteger c2 = new SQLInteger(100);
2698        r1.setCol(0, c1);
2699        r1.setCol(1, c2);
2700
2701        // Create a heap conglomerate.
2702
long orig_conglomid =
2703            tc.createConglomerate(
2704                "heap", // create a heap conglomerate
2705
r1.getRowArray(),
2706                null, // column sort order not required for heap
2707
null, // default properties
2708
TransactionController.IS_DEFAULT); // not temporary
2709

2710        // add rows 1 and 2
2711
ConglomerateController cc =
2712            tc.openConglomerate(
2713                orig_conglomid,
2714                false,
2715                TransactionController.OPENMODE_FORUPDATE,
2716                TransactionController.MODE_RECORD,
2717                TransactionController.ISOLATION_SERIALIZABLE);
2718
2719        // insert (1, 100)
2720
r1.setCol(0, new SQLInteger(1));
2721        r1.setCol(1, new SQLInteger(100));
2722        cc.insert(r1.getRowArray());
2723
2724        // insert (2, 200)
2725
r1.setCol(0, new SQLInteger(2));
2726        r1.setCol(1, new SQLInteger(200));
2727        cc.insert(r1.getRowArray());
2728
2729        // insert (3, 300)
2730
r1.setCol(0, new SQLInteger(3));
2731        r1.setCol(1, new SQLInteger(300));
2732        cc.insert(r1.getRowArray());
2733
2734        cc.close();
2735
2736        tc.commit();
2737        
2738        REPORT("(updatelocks ending.)");
2739
2740        ScanController sc = tc.openScan(
2741            orig_conglomid,
2742            false, // don't hold
2743
(TransactionController.OPENMODE_FORUPDATE |
2744             TransactionController.OPENMODE_USE_UPDATE_LOCKS),
2745            TransactionController.MODE_RECORD,
2746            TransactionController.ISOLATION_SERIALIZABLE,
2747            (FormatableBitSet) null, // all columns, all as objects
2748
null, // start position - first row in conglomerate
2749
0, // unused if start position is null.
2750
null, // qualifier - accept all rows
2751
null, // stop position - last row in conglomerate
2752
0); // unused if stop position is null.
2753

2754        int key_value;
2755
2756        boolean found_row_2 = false;
2757
2758        while (sc.next())
2759        {
2760            sc.fetch(r1.getRowArray());
2761
2762            key_value = ((SQLInteger) r1.getCol(0)).getInt();
2763
2764            switch(key_value)
2765            {
2766                case 1:
2767                {
2768                    // delete first row
2769
sc.delete();
2770                    break;
2771                }
2772                    
2773                    
2774                case 2:
2775                {
2776                    // leave second alone - no update, lock will get coverted
2777
// down.
2778
found_row_2 = true;
2779                    break;
2780                }
2781
2782                case 3:
2783                {
2784                    // update the third row.
2785
T_AccessRow update_row = new T_AccessRow(2);
2786                    r1.setCol(0, new SQLInteger(30));
2787                    r1.setCol(1, new SQLInteger(3000));
2788                    sc.replace(r1.getRowArray(), null);
2789                    break;
2790                }
2791
2792                default:
2793                {
2794                    throw T_Fail.testFailMsg(
2795                        "(updatelock) bad row value found in table.");
2796                }
2797            }
2798            
2799        }
2800
2801        if (!found_row_2)
2802            throw T_Fail.testFailMsg(
2803                "(updatelock) did not find row in first scan.");
2804
2805        // reposition the scan
2806
sc.reopenScan(
2807            null, // start position - first row in conglomerate
2808
0, // unused if start position is null.
2809
null, // qualifier - accept all rows
2810
null, // stop position - last row in conglomerate
2811
0); // unused if stop position is null.
2812

2813
2814        found_row_2 = false;
2815
2816        while (sc.next())
2817        {
2818            sc.fetch(r1.getRowArray());
2819
2820            key_value = ((SQLInteger) r1.getCol(0)).getInt();
2821
2822            switch(key_value)
2823            {
2824                case 2:
2825                {
2826                    // leave second alone - no update, lock will get coverted
2827
// down.
2828
found_row_2 = true;
2829
2830                    break;
2831                }
2832
2833                case 30:
2834                {
2835                    // update the third row.
2836
T_AccessRow update_row = new T_AccessRow(2);
2837                    r1.setCol(0, new SQLInteger(40));
2838                    r1.setCol(1, new SQLInteger(4000));
2839                    sc.replace(r1.getRowArray(), null);
2840                    break;
2841                }
2842
2843                default:
2844                {
2845                    throw T_Fail.testFailMsg(
2846                        "(updatelock) bad row value found in table.");
2847                }
2848            }
2849            
2850        }
2851
2852        if (!found_row_2)
2853            throw T_Fail.testFailMsg(
2854                "(updatelock) did not find row in second scan.");
2855
2856        sc.close();
2857
2858        tc.commit();
2859
2860        // try the scan after the first xact has completed.
2861

2862        sc = tc.openScan(
2863            orig_conglomid,
2864            false, // don't hold
2865
(TransactionController.OPENMODE_FORUPDATE |
2866             TransactionController.OPENMODE_USE_UPDATE_LOCKS),
2867            TransactionController.MODE_RECORD,
2868            TransactionController.ISOLATION_SERIALIZABLE,
2869            (FormatableBitSet) null, // all columns, all as objects
2870
null, // start position - first row in conglomerate
2871
0, // unused if start position is null.
2872
null, // qualifier - accept all rows
2873
null, // stop position - last row in conglomerate
2874
0); // unused if stop position is null.
2875

2876        found_row_2 = false;
2877
2878        while (sc.next())
2879        {
2880            sc.fetch(r1.getRowArray());
2881
2882            key_value = ((SQLInteger) r1.getCol(0)).getInt();
2883
2884            switch(key_value)
2885            {
2886                case 2:
2887                {
2888                    // leave second alone - no update, lock will get coverted
2889
// down.
2890
found_row_2 = true;
2891                    break;
2892                }
2893
2894                case 40:
2895                {
2896                    // update the third row.
2897
T_AccessRow update_row = new T_AccessRow(2);
2898                    r1.setCol(0, new SQLInteger(30));
2899                    r1.setCol(1, new SQLInteger(3000));
2900                    sc.replace(r1.getRowArray(), null);
2901                    break;
2902                }
2903
2904                default:
2905                {
2906                    throw T_Fail.testFailMsg(
2907                        "(updatelock) bad row value found in table.");
2908                }
2909            }
2910            
2911        }
2912
2913        if (!found_row_2)
2914            throw T_Fail.testFailMsg(
2915                "(updatelock) did not find row in first scan.");
2916
2917        return(true);
2918    }
2919
2920
2921    protected boolean nestedUserTransaction(TransactionController tc)
2922        throws StandardException, T_Fail
2923    {
2924
2925        REPORT("(nestedUserTransaction) starting");
2926
2927        // Test of drop conglomerate with abort by doing the following:
2928
// create table
2929
// commit
2930
// drop table
2931
// make sure table is not still there.
2932
// abort
2933
// make sure table is still there.
2934

2935        // Create a heap conglomerate.
2936
long orig_conglomid =
2937            tc.createConglomerate(
2938                "heap", // create a heap conglomerate
2939
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2940
null, // column sort order not required for heap
2941
null, // default properties
2942
TransactionController.IS_DEFAULT); // not temporary
2943

2944        // Create a temporary heap conglomerate.
2945
long tmp_conglomid =
2946            tc.createConglomerate(
2947                "heap", // create a heap conglomerate
2948
new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2949
null, // column sort order not required for heap
2950
null, // default properties
2951
TransactionController.IS_TEMPORARY);
2952
2953        TransactionController current_xact =
2954            store.getTransaction(
2955                ContextService.getFactory().getCurrentContextManager());
2956
2957        // get a nested user transaction
2958
TransactionController child_tc = tc.startNestedUserTransaction(true);
2959
2960        TransactionController current_xact_after_nest =
2961            store.getTransaction(
2962                ContextService.getFactory().getCurrentContextManager());
2963
2964        if (current_xact_after_nest != current_xact)
2965        {
2966            throw T_Fail.testFailMsg(
2967                "(nestedUserTransaction) getTransaction() return changed after startNestedUserTransaction()." +
2968                "current_xact = " + current_xact +
2969                ";current_xact_after_nest = " + current_xact_after_nest);
2970        }
2971
2972        if ((tc.getLockObject() != child_tc.getLockObject()) ||
2973            !(tc.getLockObject().equals(child_tc.getLockObject())))
2974
2975        {
2976            throw T_Fail.testFailMsg(
2977                "(nestedUserTransaction) getLockObject should return same object from botht these calls.");
2978        }
2979
2980        // the locks of the nested transaction should not conflict, so this
2981
// open should work.
2982
ConglomerateController cc =
2983            child_tc.openConglomerate(
2984                orig_conglomid,
2985                false,
2986                TransactionController.OPENMODE_FORUPDATE,
2987                TransactionController.MODE_RECORD,
2988                TransactionController.ISOLATION_SERIALIZABLE);
2989
2990        // Make sure you can access the temporary conglomerate in the
2991
// nested transaction.
2992
ConglomerateController tmp_cc =
2993            child_tc.openConglomerate(
2994                tmp_conglomid,
2995                false,
2996                TransactionController.OPENMODE_FORUPDATE,
2997                TransactionController.MODE_RECORD,
2998                TransactionController.ISOLATION_SERIALIZABLE);
2999
3000        cc.close();
3001        tmp_cc.close();
3002
3003        child_tc.commit();
3004        child_tc.destroy();
3005
3006        tc.dropConglomerate(orig_conglomid);
3007
3008        // trying to double nest a nested transaction should not work.
3009
child_tc = tc.startNestedUserTransaction(true);
3010
3011        try
3012        {
3013            child_tc.startNestedUserTransaction(true);
3014
3015            throw T_Fail.testFailMsg(
3016                "(nestedUserTransaction) double nest xact not allowed.");
3017        }
3018        catch (StandardException se)
3019        {
3020            // expected exception, fall through.
3021
}
3022
3023        child_tc.commit();
3024        child_tc.destroy();
3025
3026        // make sure internal and ntt's work. Just add a bunch of data to
3027
// the table causing page allocation.
3028
String JavaDoc twok_string =
3029            new String JavaDoc("0123456789012345");
3030
3031        for (int i = 0; i < 7; i++)
3032        {
3033            twok_string += twok_string;
3034        }
3035
3036        T_AccessRow big_row = new T_AccessRow(2);
3037        
3038        big_row.setCol(1, new SQLChar(twok_string));
3039
3040        // Create a heap conglomerate.
3041
orig_conglomid =
3042            tc.createConglomerate(
3043                "heap", // create a heap conglomerate
3044
big_row.getRowArray(),
3045                null, // column sort order not required for heap
3046
null, // default properties
3047
TransactionController.IS_DEFAULT); // not temporary
3048

3049        child_tc = tc.startNestedUserTransaction(true);
3050
3051        // add 20 pages worth of data, causing allocation
3052

3053        // the locks of the nested transaction should not conflict, so this
3054
// open should work.
3055
cc =
3056            child_tc.openConglomerate(
3057                orig_conglomid,
3058                false,
3059                TransactionController.OPENMODE_FORUPDATE,
3060                TransactionController.MODE_RECORD,
3061                TransactionController.ISOLATION_SERIALIZABLE);
3062
3063        child_tc.abort();
3064        child_tc.destroy();
3065
3066        // after the abort the table should not still exist, the parent
3067
// xact should have been aborted.
3068

3069        try
3070        {
3071            // the locks of the nested transaction should not conflict, so this
3072
// open should work.
3073
cc =
3074                tc.openConglomerate(
3075                    orig_conglomid,
3076                    false,
3077                    TransactionController.OPENMODE_FORUPDATE,
3078                    TransactionController.MODE_RECORD,
3079                    TransactionController.ISOLATION_SERIALIZABLE);
3080
3081            throw T_Fail.testFailMsg(
3082                "(nestedUserTransaction) conglom should have been aborted.");
3083        }
3084        catch (StandardException se)
3085        {
3086            // expected exception, fall through.
3087
}
3088
3089        tc.commit();
3090
3091        // same test as above, but this time commit parent xact create to
3092
// make sure it stays around after the child abort.
3093

3094        // Create a heap conglomerate.
3095
orig_conglomid =
3096            tc.createConglomerate(
3097                "heap", // create a heap conglomerate
3098
big_row.getRowArray(),
3099                null, // column sort order not required for heap
3100
null, // default properties
3101
TransactionController.IS_DEFAULT); // not temporary
3102

3103        tc.commit();
3104
3105
3106        child_tc = tc.startNestedUserTransaction(true);
3107
3108        // add 20 pages worth of data, causing allocation
3109

3110        // the locks of the nested transaction should not conflict, so this
3111
// open should work.
3112
cc =
3113            child_tc.openConglomerate(
3114                orig_conglomid,
3115                false,
3116                TransactionController.OPENMODE_FORUPDATE,
3117                TransactionController.MODE_RECORD,
3118                TransactionController.ISOLATION_SERIALIZABLE);
3119
3120        /*
3121        for (int i = 0; i < 40; i++)
3122        {
3123            big_row.setCol(0, new SQLInteger(i));
3124            cc.insert(big_row.getRowArray());
3125        }
3126        */

3127
3128        child_tc.abort();
3129        child_tc.destroy();
3130
3131        // after the abort the table should not still exist, the parent
3132
// xact should have been aborted.
3133

3134        try
3135        {
3136            // the locks of the nested transaction should not conflict, so this
3137
// open should work.
3138
cc =
3139                tc.openConglomerate(
3140                    orig_conglomid,
3141                    false,
3142                    TransactionController.OPENMODE_FORUPDATE,
3143                    TransactionController.MODE_RECORD,
3144                    TransactionController.ISOLATION_SERIALIZABLE);
3145
3146            cc.close();
3147        }
3148        catch (StandardException se)
3149        {
3150            // expected exception, fall through.
3151

3152            throw T_Fail.testFailMsg(
3153                "(nestedUserTransaction) conglom should have not be aborted.");
3154        }
3155
3156        // start an read only nested user transaction.
3157
child_tc = tc.startNestedUserTransaction(true);
3158
3159        ConglomerateController child_cc =
3160            child_tc.openConglomerate(
3161                orig_conglomid,
3162                false,
3163                TransactionController.OPENMODE_FORUPDATE,
3164                TransactionController.MODE_RECORD,
3165                TransactionController.ISOLATION_SERIALIZABLE);
3166
3167        try
3168        {
3169            // should not be able to do an update in a read only transaction.
3170
big_row.setCol(0, new SQLInteger(1042));
3171            child_cc.insert(big_row.getRowArray());
3172
3173            throw T_Fail.testFailMsg(
3174                "(nestedUserTransaction) read only xact does not allow upd.");
3175
3176        }
3177        catch (StandardException se)
3178        {
3179            // expected exception, fall through.
3180
child_tc.commit();
3181            child_tc.destroy();
3182        }
3183
3184        tc.commit();
3185
3186        // start an update nested user transaction.
3187
child_tc = tc.startNestedUserTransaction(false);
3188
3189        child_cc =
3190            child_tc.openConglomerate(
3191                orig_conglomid,
3192                false,
3193                TransactionController.OPENMODE_FORUPDATE,
3194                TransactionController.MODE_RECORD,
3195                TransactionController.ISOLATION_SERIALIZABLE);
3196
3197        try
3198        {
3199            // should be able to do an update in a read only transaction.
3200
big_row.setCol(0, new SQLInteger(1043));
3201            child_cc.insert(big_row.getRowArray());
3202
3203
3204        }
3205        catch (StandardException se)
3206        {
3207            throw T_Fail.testFailMsg(
3208                "(nestedUserTransaction) read only xact does not allow upd.");
3209        }
3210
3211        // expected exception, fall through.
3212
child_tc.commit();
3213        child_tc.destroy();
3214
3215        tc.commit();
3216
3217
3218        cc =
3219            tc.openConglomerate(
3220                orig_conglomid,
3221                false,
3222                TransactionController.OPENMODE_FORUPDATE,
3223                TransactionController.MODE_TABLE,
3224                TransactionController.ISOLATION_SERIALIZABLE);
3225
3226        // start an update nested user transaction.
3227
child_tc = tc.startNestedUserTransaction(false);
3228
3229        try
3230        {
3231            // the following should time out, since locks are not compatible.
3232
child_cc =
3233                child_tc.openConglomerate(
3234                    orig_conglomid,
3235                    false,
3236                    TransactionController.OPENMODE_FORUPDATE,
3237                    TransactionController.MODE_RECORD,
3238                    TransactionController.ISOLATION_SERIALIZABLE);
3239
3240            throw T_Fail.testFailMsg(
3241                "(nestedUserTransaction) lock should have timed out.");
3242        }
3243        catch (StandardException se)
3244        {
3245            // expected timeout, fall through.
3246
}
3247
3248        // expected exception, fall through.
3249
child_tc.commit();
3250        child_tc.destroy();
3251
3252        tc.commit();
3253
3254        REPORT("(nestedUserTransaction) finishing");
3255
3256        return true;
3257    }
3258
3259    // test various flavors of commit
3260
protected boolean commitTest(TransactionController tc)
3261        throws StandardException, T_Fail
3262    {
3263        REPORT("(commitTest)");
3264
3265        // Create a heap conglomerate.
3266
T_AccessRow template_row = new T_AccessRow(1);
3267        long conglomid =
3268            tc.createConglomerate(
3269                "heap", // create a heap conglomerate
3270
template_row.getRowArray(), // 1 column template.
3271
null, // column sort order not required for heap
3272
null, // default properties
3273
TransactionController.IS_DEFAULT); // not temporary
3274

3275        tc.commit();
3276
3277        // Open it.
3278
ConglomerateController cc =
3279            tc.openConglomerate(
3280                conglomid,
3281                false,
3282                TransactionController.OPENMODE_FORUPDATE,
3283                TransactionController.MODE_RECORD,
3284                TransactionController.ISOLATION_SERIALIZABLE);
3285
3286        // Create a row.
3287
T_AccessRow r1 = new T_AccessRow(1);
3288        SQLInteger c1 = new SQLInteger(0);
3289        r1.setCol(0, c1);
3290
3291        // Get a location template
3292
RowLocation rowloc = cc.newRowLocationTemplate();
3293
3294        // Insert the row and remember its location.
3295
cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
3296
3297        // now commit nosync without releasing the row lock
3298
tc.commitNoSync(TransactionController.KEEP_LOCKS);
3299
3300        // cc should be closed
3301
try
3302        {
3303            cc.newRowLocationTemplate();
3304            throw T_Fail.testFailMsg("conglomerate controller is not closed after commit");
3305        }
3306        catch (StandardException se)
3307        {
3308            // expect fail
3309
}
3310
3311
3312        // get another transaction going
3313
ContextManager cm2 = ContextService.getFactory().newContextManager();
3314
3315        ContextService.getFactory().setCurrentContextManager(cm2);
3316
3317        TransactionController tc2 = null;
3318        ConglomerateController cc2 = null;
3319        try {
3320
3321            tc2 = store.getTransaction(cm2);
3322
3323            cc2 =
3324            tc2.openConglomerate(
3325                conglomid,
3326                false,
3327                TransactionController.OPENMODE_FORUPDATE,
3328                TransactionController.MODE_RECORD,
3329                TransactionController.ISOLATION_SERIALIZABLE);
3330
3331        // try to lock the row, it should fail
3332
// Mikem RESOLVE: this does not get a row lock
3333
// cc2.fetch(rowloc, r1.getRowArray(), (FormatableBitSet)null)
3334

3335            cc2.delete(rowloc);
3336            throw T_Fail.testFailMsg("expected time out did not happen");
3337        }
3338        catch (StandardException lfe)
3339        {
3340            if (!lfe.getMessageId().equals(SQLState.LOCK_TIMEOUT))
3341                throw lfe;
3342        }
3343        finally {
3344            ContextService.getFactory().resetCurrentContextManager(cm2);
3345        }
3346
3347
3348        // see whether anyone is blocked at all
3349
if (tc.anyoneBlocked())
3350        {
3351            throw T_Fail.testFailMsg(
3352                                "No transactions should be blocked");
3353        }
3354
3355        // now really commit the transaction
3356
tc.commit();
3357        
3358        ContextService.getFactory().setCurrentContextManager(cm2);
3359
3360        try {
3361        cc2.fetch(rowloc, r1.getRowArray(), (FormatableBitSet)null);
3362        // get rid of the other transaction
3363
tc2.commitNoSync(TransactionController.RELEASE_LOCKS);
3364        tc2.destroy();
3365        }
3366        finally {
3367            ContextService.getFactory().resetCurrentContextManager(cm2);
3368        }
3369
3370        REPORT("(commitTest) succeeded");
3371        return true;
3372    }
3373
3374    private void testOpsBeforeFirstNext(
3375    ScanController scan,
3376    DataValueDescriptor[] row)
3377        throws StandardException, T_Fail
3378    {
3379
3380        // none of the following operations is allowed before a next() or
3381
// fetchNext() is called.
3382
//
3383
try
3384        {
3385            scan.delete();
3386            throw T_Fail.testFailMsg(
3387                "(holdCursor) delete() does not work until next() is called.");
3388        }
3389        catch (StandardException lfe)
3390        {
3391            // expect error
3392
}
3393        try
3394        {
3395            scan.doesCurrentPositionQualify();
3396            throw T_Fail.testFailMsg(
3397                "(holdCursor) doesCurrentPositionQualify() does not work until next() is called.");
3398        }
3399        catch (StandardException lfe)
3400        {
3401            // expect error
3402
}
3403
3404        try
3405        {
3406            scan.fetch(row);
3407            throw T_Fail.testFailMsg(
3408                "(holdCursor) fetch() does not work until next() is called.");
3409        }
3410        catch (StandardException lfe)
3411        {
3412            // expect error
3413
}
3414        try
3415        {
3416            scan.fetchLocation(null);
3417            throw T_Fail.testFailMsg(
3418                "(holdCursor) fetchLocation() does not work until next() is called.");
3419        }
3420        catch (StandardException lfe)
3421        {
3422            // expect error
3423
}
3424        try
3425        {
3426            scan.isCurrentPositionDeleted();
3427            throw T_Fail.testFailMsg(
3428                "(holdCursor) isCurrentPositionDeleted() does not work until next() is called.");
3429        }
3430        catch (StandardException lfe)
3431        {
3432            // expect error
3433
}
3434        try
3435        {
3436            scan.replace(row, null);
3437            throw T_Fail.testFailMsg(
3438                "(holdCursor) isCurrentPositionDeleted() does not work until next() is called.");
3439        }
3440        catch (StandardException lfe)
3441        {
3442            // expect error
3443
}
3444    }
3445
3446    // test various flavors of commit
3447
protected boolean holdCursor(TransactionController tc)
3448        throws StandardException, T_Fail
3449    {
3450        REPORT("(holdCursor)");
3451
3452        // Create a conglomerates and an index on that conglomerate.
3453
long base_id = createAConglom(tc, 0, false);
3454
3455        // Open it.
3456
ConglomerateController cc =
3457            tc.openConglomerate(
3458                base_id,
3459                false,
3460                TransactionController.OPENMODE_FORUPDATE,
3461                TransactionController.MODE_RECORD,
3462                TransactionController.ISOLATION_SERIALIZABLE);
3463
3464        // insert 5 rows
3465

3466        T_AccessRow r1 = null;
3467        SQLLongint c1 = null;
3468
3469        for (int i = 1; i < 5; i++)
3470        {
3471            // Create a row.
3472
r1 = new T_AccessRow(1);
3473            c1 = new SQLLongint(i);
3474            r1.setCol(0, c1);
3475
3476            // Get a location template
3477
RowLocation rowloc = cc.newRowLocationTemplate();
3478
3479            // Insert the row and remember its location.
3480
cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
3481        }
3482        
3483
3484        // Create an index on the base table.
3485
long index_id = createBtree(tc, base_id, false);
3486
3487        tc.commit();
3488
3489        cc.close();
3490
3491        tc.commit();
3492
3493
3494        // HEAP - test that scan is closed on commit of non-held cursor.
3495

3496        // Open scan on the base table.
3497
ScanController base_scan = tc.openScan(
3498            base_id,
3499            false, // don't hold
3500
TransactionController.OPENMODE_FORUPDATE, // for update
3501
TransactionController.MODE_RECORD,
3502            TransactionController.ISOLATION_SERIALIZABLE,
3503            (FormatableBitSet) null, // all columns, all as objects
3504
null, // start position - first row in conglomerate
3505
0, // unused if start position is null.
3506
null, // qualifier - accept all rows
3507
null, // stop position - last row in conglomerate
3508
0); // unused if stop position is null.
3509

3510        // Open scan on the index table.
3511
ScanController index_scan = tc.openScan(
3512            index_id,
3513            false, // don't hold
3514
TransactionController.OPENMODE_FORUPDATE, // for update
3515
TransactionController.MODE_RECORD,
3516            TransactionController.ISOLATION_SERIALIZABLE,
3517            (FormatableBitSet) null, // all columns, all as objects
3518
null, // start position - first row in conglomerate
3519
0, // unused if start position is null.
3520
null, // qualifier - accept all rows
3521
null, // stop position - last row in conglomerate
3522
0); // unused if stop position is null.
3523

3524        testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3525        testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3526
3527        base_scan.next();
3528        index_scan.next();
3529
3530        base_scan.next();
3531        index_scan.next();
3532
3533        base_scan.next();
3534        index_scan.next();
3535
3536        base_scan.next();
3537        index_scan.next();
3538
3539        base_scan.next();
3540        index_scan.next();
3541
3542        base_scan.next();
3543        index_scan.next();
3544
3545        base_scan.next();
3546        index_scan.next();
3547
3548        // should be able call get and set even after next'ing through the rows.
3549
long row_count = base_scan.getEstimatedRowCount();
3550        base_scan.setEstimatedRowCount(10);
3551        row_count = base_scan.getEstimatedRowCount();
3552
3553        // should be able call get and set even after next'ing through the rows.
3554
row_count = index_scan.getEstimatedRowCount();
3555        index_scan.setEstimatedRowCount(10);
3556        row_count = index_scan.getEstimatedRowCount();
3557
3558        if (row_count != 10)
3559            throw T_Fail.testFailMsg(
3560                "(holdCursor) some problem with get/set row count.");
3561
3562        tc.commit();
3563
3564        testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3565        testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3566
3567
3568        // see if commit closed the base_scan.
3569
if (base_scan.next())
3570            throw T_Fail.testFailMsg(
3571                "(holdCursor) next() should return false, commit should close base_scan.");
3572
3573        // see if commit closed the base_scan.
3574
if (index_scan.next())
3575            throw T_Fail.testFailMsg(
3576                "(holdCursor) next() should return false, commit should close base_scan.");
3577
3578
3579        tc.commit();
3580
3581
3582        // Open another scan on the conglomerate.
3583
base_scan = tc.openScan(
3584            base_id,
3585            true, // hold cursor open across commit
3586
TransactionController.OPENMODE_FORUPDATE, // for update
3587
TransactionController.MODE_RECORD,
3588            TransactionController.ISOLATION_SERIALIZABLE,
3589            (FormatableBitSet) null, // all columns, all as objects
3590
null, // start position - first row in conglomerate
3591
0, // unused if start position is null.
3592
null, // qualifier - accept all rows
3593
null, // stop position - last row in conglomerate
3594
0); // unused if stop position is null.
3595

3596        // Open scan on the index table.
3597
index_scan = tc.openScan(
3598            index_id,
3599            true, // don't hold
3600
TransactionController.OPENMODE_FORUPDATE, // for update
3601
TransactionController.MODE_RECORD,
3602            TransactionController.ISOLATION_SERIALIZABLE,
3603            (FormatableBitSet) null, // all columns, all as objects
3604
null, // start position - first row in conglomerate
3605
0, // unused if start position is null.
3606
null, // qualifier - accept all rows
3607
null, // stop position - last row in conglomerate
3608
0); // unused if stop position is null.
3609

3610        tc.commit();
3611
3612        testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3613        testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3614
3615        // try to move scan after commit to 1st row.
3616
// move cursor to be positioned on 0
3617
if (!base_scan.next())
3618            throw T_Fail.testFailMsg(
3619                "(holdCursor) next() should not fail, commit should close hold scan.");
3620        // try to move scan after commit to 1st row.
3621
// move cursor to be positioned on 0
3622
if (!index_scan.next())
3623            throw T_Fail.testFailMsg(
3624                "(holdCursor) next() should not fail, commit should close hold scan.");
3625
3626
3627        // the 1st next should return the 1st row - ie. 0
3628

3629        base_scan.fetch(r1.getRowArray());
3630        long key_value = ((SQLLongint) r1.getCol(0)).getLong();
3631
3632        if (key_value != 0)
3633            throw T_Fail.testFailMsg(
3634                "(holdCursor) 1st row is not 0.");
3635
3636        index_scan.fetch(r1.getRowArray());
3637        key_value = ((SQLLongint) r1.getCol(0)).getLong();
3638
3639        if (key_value != 0)
3640            throw T_Fail.testFailMsg(
3641                "(holdCursor) 1st row is not 0.");
3642
3643        // move cursor to be positioned on 1
3644
base_scan.next();
3645        index_scan.next();
3646
3647        tc.commit();
3648
3649        testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3650        testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3651
3652        // should be able call get and set even after next'ing through the rows.
3653
row_count = base_scan.getEstimatedRowCount();
3654        base_scan.setEstimatedRowCount(5);
3655        row_count = base_scan.getEstimatedRowCount();
3656
3657        // should be able call get and set even after next'ing through the rows.
3658
row_count = index_scan.getEstimatedRowCount();
3659        index_scan.setEstimatedRowCount(5);
3660        row_count = index_scan.getEstimatedRowCount();
3661
3662        if (row_count != 5)
3663            throw T_Fail.testFailMsg(
3664                "(holdCursor) some problem with get/set row count.");
3665
3666
3667        // try to move to row with key "2"
3668

3669        // move cursor to be positioned on 2
3670
if (!base_scan.next())
3671            throw T_Fail.testFailMsg(
3672                "(holdCursor) next() should not fail, commit should close hold base_scan.");
3673
3674        if (!index_scan.next())
3675            throw T_Fail.testFailMsg(
3676                "(holdCursor) next() should not fail, commit should close hold base_scan.");
3677
3678
3679        // the 1st next should return the 1st row - ie. 0
3680
base_scan.fetch(r1.getRowArray());
3681        key_value = ((SQLLongint) r1.getCol(0)).getLong();
3682
3683        if (key_value != 2)
3684            throw T_Fail.testFailMsg(
3685                "(holdCursor) 1st row is not 0.");
3686
3687        index_scan.fetch(r1.getRowArray());
3688        key_value = ((SQLLongint) r1.getCol(0)).getLong();
3689
3690        if (key_value != 2)
3691            throw T_Fail.testFailMsg(
3692                "(holdCursor) 1st row is not 0.");
3693
3694
3695        // move cursor to be positioned on 3
3696
base_scan.next();
3697        base_scan.delete();
3698
3699        index_scan.next();
3700        index_scan.delete();
3701
3702
3703        // move cursor to be positioned on 4
3704
base_scan.next();
3705        index_scan.next();
3706
3707        // move cursor past the end, thus closing it.
3708
base_scan.next();
3709        index_scan.next();
3710
3711        tc.commit();
3712
3713        // should be able call get and set even after next'ing through the rows.
3714
row_count = base_scan.getEstimatedRowCount();
3715        base_scan.setEstimatedRowCount(15);
3716        row_count = base_scan.getEstimatedRowCount();
3717
3718        if (row_count != 15)
3719            throw T_Fail.testFailMsg(
3720                "(holdCursor) some problem with get/set row count.");
3721
3722        row_count = index_scan.getEstimatedRowCount();
3723        index_scan.setEstimatedRowCount(15);
3724        row_count = index_scan.getEstimatedRowCount();
3725
3726        if (row_count != 15)
3727            throw T_Fail.testFailMsg(
3728                "(holdCursor) some problem with get/set row count.");
3729
3730        testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3731        testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3732
3733        // see what happens committing a closed base_scan and trying next.
3734

3735        if (base_scan.next())
3736            throw T_Fail.testFailMsg(
3737                "(holdCursor) next() should fail, the base_scan has been closed by progressing to end.");
3738        if (index_scan.next())
3739            throw T_Fail.testFailMsg(
3740                "(holdCursor) next() should fail, the base_scan has been closed by progressing to end.");
3741
3742
3743        tc.commit();
3744
3745        base_scan.close();
3746        index_scan.close();
3747        
3748        REPORT("(holdCursor) succeeded");
3749        return true;
3750    }
3751
3752    // test position at row location, in terms of holdability
3753
protected boolean positionAtRowLocation(TransactionController tc)
3754        throws StandardException, T_Fail
3755    {
3756        REPORT("(positionAtRowLocation)");
3757        
3758        // Create a conglomerate with one row:
3759
long base_id = createAConglom(tc, 0, false);
3760        
3761        // Open it.
3762
ConglomerateController cc =
3763            tc.openConglomerate(base_id,
3764                                false,
3765                                TransactionController.OPENMODE_FORUPDATE,
3766                                TransactionController.MODE_RECORD,
3767                                TransactionController.ISOLATION_SERIALIZABLE);
3768        
3769        T_AccessRow accessRow = null;
3770        for (int i = 1; i < 5; i++)
3771        {
3772            // Create a row.
3773
accessRow = new T_AccessRow(1);
3774            SQLLongint c1 = new SQLLongint(i);
3775            accessRow.setCol(0, c1);
3776            
3777            // Insert the row and remember its location.
3778
cc.insert(accessRow.getRowArray());
3779        }
3780        tc.commit();
3781        cc.close();
3782        
3783        // Open scan on the table:
3784
ScanController base_scan =
3785            tc.openScan(base_id,
3786                        true, // do hold
3787
TransactionController.OPENMODE_FORUPDATE, // for update
3788
TransactionController.MODE_RECORD,
3789                        TransactionController.ISOLATION_SERIALIZABLE,
3790                        (FormatableBitSet) null, // all columns, all as objects
3791
null, // start position - first row in conglomerate
3792
0, // unused if start position is null.
3793
null, // qualifier - accept all rows
3794
null, // stop position - last row in conglomerate
3795
0); // unused if stop position is null.
3796

3797        
3798        // Move to the first row
3799
base_scan.next();
3800                
3801        // Get the RowLocation for the first row:
3802
RowLocation firstRow = base_scan.newRowLocationTemplate();
3803        base_scan.fetchLocation(firstRow);
3804        base_scan.fetch(accessRow.getRowArray());
3805        long key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3806        if (key_value != 0) {
3807            throw T_Fail.testFailMsg
3808                ("(positionAtRowLocation_err_1) 1st row is not 0 it is:" +
3809                 key_value);
3810        }
3811                
3812        // Move to some other rows:
3813
base_scan.next();
3814        base_scan.fetch(accessRow.getRowArray());
3815        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3816        if (key_value != 1) {
3817            throw T_Fail.testFailMsg
3818                ("(positionAtRowLocation_err_2) 2nd row is not 1 it is:" +
3819                 key_value);
3820        }
3821        
3822        base_scan.next();
3823        base_scan.fetch(accessRow.getRowArray());
3824        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3825        if (key_value != 2) {
3826            throw T_Fail.testFailMsg
3827                ("(positionAtRowLocation_err_3) 3d row is not 2 it is:" +
3828                 key_value);
3829        }
3830        
3831        if (!base_scan.positionAtRowLocation(firstRow))
3832        {
3833            throw T_Fail.testFailMsg
3834                ("(positionAtRowLocation_err_4) Failed to position at RowLocation");
3835        }
3836        base_scan.fetch(accessRow.getRowArray());
3837        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3838        if (key_value != 0) {
3839            throw T_Fail.testFailMsg
3840                ("(positionAtRowLocation_err_5) 1st row is not 0 it is:" +
3841                 key_value);
3842        }
3843        
3844        // Commit and check holdability:
3845
tc.commit();
3846        base_scan.next();
3847        base_scan.fetch(accessRow.getRowArray());
3848        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3849        if (key_value != 1) {
3850            throw T_Fail.testFailMsg
3851                ("(positionAtRowLocation_err_6) 2nd row is not 1 it is:" +
3852                 key_value);
3853        }
3854        
3855        base_scan.next();
3856        base_scan.fetch(accessRow.getRowArray());
3857        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3858        if (key_value != 2) {
3859            throw T_Fail.testFailMsg
3860                ("(positionAtRowLocation_err_7) 3d row is not 2 it is:" +
3861                 key_value);
3862        }
3863        
3864        if (!base_scan.positionAtRowLocation(firstRow))
3865        {
3866            throw T_Fail.testFailMsg
3867                ("(positionAtRowLocation_err_8) Failed to position at " +
3868                 "RowLocation after commit");
3869        }
3870        base_scan.fetch(accessRow.getRowArray());
3871        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3872        if (key_value != 0) {
3873            throw T_Fail.testFailMsg
3874                ("(positionAtRowLocation_err_9) 1st row is not 0 it is:" +
3875                 key_value);
3876        }
3877
3878        base_scan.next();
3879        base_scan.fetch(accessRow.getRowArray());
3880        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3881        if (key_value != 1) {
3882            throw T_Fail.testFailMsg
3883                ("(positionAtRowLocation_err_10) 2nd row is not 1 it is:" +
3884                 key_value);
3885        }
3886        
3887        base_scan.next();
3888        base_scan.fetch(accessRow.getRowArray());
3889        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3890        if (key_value != 2) {
3891            throw T_Fail.testFailMsg
3892                ("(positionAtRowLocation_err_10) 3d row is not 2 it is:" +
3893                 key_value);
3894        }
3895        
3896        // Using reopenScanByRowLocation(..)
3897
// instead of positionAtRowLocation(..):
3898
base_scan.reopenScanByRowLocation(firstRow, null);
3899        base_scan.next();
3900        base_scan.fetch(accessRow.getRowArray());
3901        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3902        if (key_value != 0) {
3903            throw T_Fail.testFailMsg
3904                ("(positionAtRowLocation_err_11) 1st row is not 0 it is:" +
3905                 key_value);
3906        }
3907        
3908        tc.commit();
3909        
3910        // Compress the conglomerate
3911
tc.compressConglomerate(base_id);
3912        tc.commit();
3913
3914        base_scan.next();
3915        base_scan.fetch(accessRow.getRowArray());
3916        key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3917        if (key_value != 1) {
3918            throw T_Fail.testFailMsg
3919                ("(positionAtRowLocation_err_12) 2nd row is not 1 it is:" +
3920                 key_value);
3921        }
3922        
3923        // Position at RowLocation should now fail. We cannot guarantee
3924
// that they are holdable
3925
if (base_scan.positionAtRowLocation(firstRow))
3926        {
3927            throw T_Fail.testFailMsg
3928                ("(positionAtRowLocation_err_12) Unexpectedly succeeded at " +
3929                 "positioning at RowLocation after compress");
3930        }
3931        
3932        
3933        base_scan.close();
3934        
3935        REPORT("(positionAtRowLocation) succeeded");
3936        return true;
3937    }
3938
3939    /**
3940     * Test critical cases for read uncommitted.
3941     * <p>
3942     * test 1 - test heap fetch, delete and replace of row on page which does not exist.
3943     * test 2 - test heap fetch, delete and replace of row on page where row does not exist.
3944     *
3945     * @exception StandardException Standard exception policy.
3946     **/

3947    protected boolean readUncommitted(TransactionController tc)
3948        throws StandardException, T_Fail
3949    {
3950        REPORT("(readUncommitted)");
3951
3952        /*
3953         * TEST 1 - test heap fetch of row on page which does not exist.
3954         * <p>
3955         * Do this by inserting a few pages worth of data and then deleting
3956         * all the rows, while remembering the rowlocation of one of the pages.
3957         * You need to at least get to the 2nd page, because the 1st page is
3958         * never totally reclaimed and deleted by the system in a heap (it has
3959         * some internal catalog information stored internally in row "0").
3960         */

3961
3962        String JavaDoc twok_string =
3963            new String JavaDoc("0123456789012345");
3964
3965        for (int i = 0; i < 7; i++)
3966        {
3967            twok_string += twok_string;
3968        }
3969
3970        T_AccessRow big_row = new T_AccessRow(2);
3971        
3972        big_row.setCol(1, new SQLChar(twok_string));
3973
3974        // Create a heap conglomerate.
3975
long orig_conglomid =
3976            tc.createConglomerate(
3977                "heap", // create a heap conglomerate
3978
big_row.getRowArray(),
3979                null, // column sort order not required for heap
3980
null, // default properties
3981
TransactionController.IS_DEFAULT); // not temporary
3982

3983        ConglomerateController cc =
3984            tc.openConglomerate(
3985                orig_conglomid,
3986                false,
3987                TransactionController.OPENMODE_FORUPDATE,
3988                TransactionController.MODE_RECORD,
3989                TransactionController.ISOLATION_READ_UNCOMMITTED);
3990
3991        // add 5 pages worth of data.
3992

3993        for (int i = 0; i < 10; i++)
3994        {
3995            big_row.setCol(0, new SQLInteger(i));
3996            cc.insert(big_row.getRowArray());
3997        }
3998        cc.close();
3999
4000        // Open another scan on the conglomerate.
4001
ScanController base_scan = tc.openScan(
4002            orig_conglomid,
4003            true, // hold cursor open across commit
4004
TransactionController.OPENMODE_FORUPDATE, // for update
4005
TransactionController.MODE_RECORD,
4006            TransactionController.ISOLATION_SERIALIZABLE,
4007            (FormatableBitSet) null, // all columns, all as objects
4008
null, // start position - first row in conglomerate
4009
0, // unused if start position is null.
4010
null, // qualifier - accept all rows
4011
null, // stop position - last row in conglomerate
4012
0); // unused if stop position is null.
4013

4014        // now delete all the rows and remember the row location of the
4015
// last row.
4016

4017        RowLocation deleted_page_rowloc = base_scan.newRowLocationTemplate();
4018
4019
4020        for (int i = 0; i < 10; i++)
4021        {
4022            base_scan.next();
4023            base_scan.fetchLocation(deleted_page_rowloc);
4024            base_scan.delete();
4025
4026            tc.commit();
4027        }
4028        base_scan.close();
4029        tc.commit();
4030
4031        // at this point the post commit thread should have reclaimed all the 5
4032
// pages. Open it, at read uncommitted level.
4033
cc = tc.openConglomerate(
4034                orig_conglomid,
4035                false,
4036                0,
4037                TransactionController.MODE_RECORD,
4038                TransactionController.ISOLATION_READ_UNCOMMITTED);
4039
4040        // Test heap fetch of row on page which does not exist.
4041
if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null))
4042        {
4043            throw T_Fail.testFailMsg(
4044                "(readUncommitted) fetch should ret false for reclaimed page.");
4045        }
4046             
4047        // Test heap replace of row on page which does not exist.
4048
FormatableBitSet update_desc = new FormatableBitSet(1);
4049        if (cc.replace(deleted_page_rowloc, big_row.getRowArray(), update_desc))
4050        {
4051            throw T_Fail.testFailMsg(
4052                "(readUncommitted) delete should ret false for reclaimed page.");
4053        }
4054       
4055        // Test heap fetch (overloaded call) of row on page which does not exist.
4056
if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null, true))
4057        {
4058            throw T_Fail.testFailMsg(
4059                "(readUncommitted) fetch should ret false for reclaimed page.");
4060        }
4061        
4062        // Test heap delete of row on page which does not exist.
4063
if (cc.delete(deleted_page_rowloc))
4064        {
4065            throw T_Fail.testFailMsg(
4066                "(readUncommitted) delete should ret false for reclaimed page.");
4067        }
4068                
4069        cc.close();
4070
4071        /*
4072         * TEST 2 - test heap fetch of row on page where row does not exist.
4073         * <p>
4074         * Do this by inserting enough rows to put 1 row on the 2nd page.
4075         * Then delete this one row, which will queue a post commit to reclaim
4076         * the row and page. Then insert one more row on the same page in
4077         * the same xact. Now commit the xact, which will cause post commit
4078         * to run which will reclaim the row but not the page. Then try and
4079         * fetch the row which was deleted.
4080         */

4081
4082        // string column will be 1500 bytes, allowing 2 rows per page to fit.
4083
SQLChar stringcol = new SQLChar();
4084        stringcol.setValue(T_AccessFactory.repeatString("012345678901234", 100));
4085        big_row.setCol(1, stringcol);
4086
4087        // Create a heap conglomerate.
4088
orig_conglomid =
4089            tc.createConglomerate(
4090                "heap", // create a heap conglomerate
4091
big_row.getRowArray(),
4092                null, // column sort order not required for heap
4093
null, // default properties
4094
TransactionController.IS_DEFAULT); // not temporary
4095

4096        cc =
4097            tc.openConglomerate(
4098                orig_conglomid,
4099                false,
4100                TransactionController.OPENMODE_FORUPDATE,
4101                TransactionController.MODE_RECORD,
4102                TransactionController.ISOLATION_READ_UNCOMMITTED);
4103
4104        // add 3 rows, should result in 1 row on second page.
4105

4106        for (int i = 0; i < 3; i++)
4107        {
4108            big_row.setCol(0, new SQLInteger(i));
4109            cc.insert(big_row.getRowArray());
4110        }
4111
4112        // Open another scan on the conglomerate.
4113
base_scan = tc.openScan(
4114            orig_conglomid,
4115            true, // hold cursor open across commit
4116
TransactionController.OPENMODE_FORUPDATE, // for update
4117
TransactionController.MODE_RECORD,
4118            TransactionController.ISOLATION_SERIALIZABLE,
4119            (FormatableBitSet) null, // all columns, all as objects
4120
null, // start position - first row in conglomerate
4121
0, // unused if start position is null.
4122
null, // qualifier - accept all rows
4123
null, // stop position - last row in conglomerate
4124
0); // unused if stop position is null.
4125

4126        // now delete all the rows and remember the row location of the
4127
// last row.
4128

4129        RowLocation deleted_row_rowloc = base_scan.newRowLocationTemplate();
4130
4131        for (int i = 0; i < 3; i++)
4132        {
4133            base_scan.next();
4134            base_scan.fetchLocation(deleted_row_rowloc);
4135            base_scan.delete();
4136        }
4137
4138        // insert another row on page 2 to make sure page does not go away.
4139
cc.insert(big_row.getRowArray());
4140
4141        cc.close();
4142        base_scan.close();
4143        tc.commit();
4144
4145        // at this point the post commit thread should have reclaimed all the
4146
// deleted row on page 2, but not the page.
4147
//
4148
// Open it, at read uncommitted level.
4149
cc = tc.openConglomerate(
4150                orig_conglomid,
4151                false,
4152                0,
4153                TransactionController.MODE_RECORD,
4154                TransactionController.ISOLATION_READ_UNCOMMITTED);
4155
4156        // the following will be attempting to fetch a row which has been
4157
// reclaimed by post commit, on an existing page.
4158

4159        // test heap fetch of row on page where row does not exist.
4160
if (cc.fetch(deleted_row_rowloc, big_row.getRowArray(), null))
4161        {
4162            throw T_Fail.testFailMsg(
4163                "(readUncommitted) fetch should ret false for reclaimed row.");
4164        }
4165        
4166        // test heap replace of row on page where row does not exist.
4167
if (cc.replace(deleted_page_rowloc, big_row.getRowArray(), update_desc))
4168        {
4169            throw T_Fail.testFailMsg(
4170                "(readUncommitted) delete should ret false for reclaimed page.");
4171        }
4172
4173        // test heap fetch (overloaded) of row on page where row does not exist.
4174
if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null, true))
4175        {
4176            throw T_Fail.testFailMsg(
4177                "(readUncommitted) fetch should ret false for reclaimed page.");
4178        }
4179        
4180        // test heap delete of row on page where row does not exist.
4181
if (cc.delete(deleted_page_rowloc))
4182        {
4183            throw T_Fail.testFailMsg(
4184                "(readUncommitted) delete should ret false for reclaimed page.");
4185        }
4186
4187        cc.close();
4188
4189        /*
4190         * TEST 3 - test heap scan fetch of row on page prevents page from
4191         * disappearing, but handles row being deleted.
4192         * <p>
4193         * A heap scan will maintain a scan lock on a page even if it is doing
4194         * a read uncommitted scan. This will prevent the row/page from being
4195         * reclaimed by post commit while the scan is positioned on the page.
4196         * This presents no other concurrency issues for read uncommitted, it
4197         * should be invisible to the user (deletes can still happen and the
4198         * read uncommitted scanner will not block anyone).
4199         *
4200         * You need to at least get to the 2nd page, because the 1st page is
4201         * never totally reclaimed and deleted by the system in a heap (it has
4202         * some internal catalog information stored internally in row "0").
4203         */

4204
4205        big_row = new T_AccessRow(2);
4206        
4207        big_row.setCol(1, new SQLChar(twok_string));
4208
4209        // Create a heap conglomerate.
4210
orig_conglomid =
4211            tc.createConglomerate(
4212                "heap", // create a heap conglomerate
4213
big_row.getRowArray(),
4214                null, // column sort order not required for heap
4215
null, // default properties
4216
TransactionController.IS_DEFAULT); // not temporary
4217

4218        cc =
4219            tc.openConglomerate(
4220                orig_conglomid,
4221                false,
4222                TransactionController.OPENMODE_FORUPDATE,
4223                TransactionController.MODE_RECORD,
4224                TransactionController.ISOLATION_READ_UNCOMMITTED);
4225
4226        // add 5 pages worth of data.
4227

4228        for (int i = 0; i < 10; i++)
4229        {
4230            big_row.setCol(0, new SQLInteger(i));
4231            cc.insert(big_row.getRowArray());
4232        }
4233        cc.close();
4234
4235        // Open scan on the conglomerate, and position it on the second page.
4236
base_scan = tc.openScan(
4237            orig_conglomid,
4238            true, // hold cursor open across commit
4239
0, // for read
4240
TransactionController.MODE_RECORD,
4241            TransactionController.ISOLATION_READ_UNCOMMITTED,
4242            (FormatableBitSet) null, // all columns, all as objects
4243
null, // start position - first row in conglomerate
4244
0, // unused if start position is null.
4245
null, // qualifier - accept all rows
4246
null, // stop position - last row in conglomerate
4247
0); // unused if stop position is null.
4248

4249        base_scan.next();
4250        base_scan.next();
4251        base_scan.next();
4252
4253        // test that the row is accessible from all these interfaces, before
4254
// the page disappears, and then test again after all rows have been
4255
// deleted from the page.
4256

4257        if (!base_scan.doesCurrentPositionQualify())
4258            throw T_Fail.testFailMsg(
4259                "(readUncommitted) doesCurrentPositionQualify() failed.");
4260
4261        base_scan.fetch(big_row.getRowArray());
4262
4263        base_scan.fetchLocation(deleted_row_rowloc);
4264
4265        if (base_scan.isCurrentPositionDeleted())
4266            throw T_Fail.testFailMsg(
4267                    "(readUncommitted) isCurrentPositionDeleted() failed.");
4268
4269        // Open another scan on the conglomerate.
4270
ScanController delete_scan = tc.openScan(
4271            orig_conglomid,
4272            true, // hold cursor open across commit
4273
TransactionController.OPENMODE_FORUPDATE, // for update
4274
TransactionController.MODE_RECORD,
4275            TransactionController.ISOLATION_SERIALIZABLE,
4276            (FormatableBitSet) null, // all columns, all as objects
4277
null, // start position - first row in conglomerate
4278
0, // unused if start position is null.
4279
null, // qualifier - accept all rows
4280
null, // stop position - last row in conglomerate
4281
0); // unused if stop position is null.
4282

4283        // now delete all the rows and commit.
4284

4285        for (int i = 0; i < 10; i++)
4286        {
4287            delete_scan.next();
4288            delete_scan.fetchLocation(deleted_page_rowloc);
4289            delete_scan.delete();
4290
4291        }
4292        delete_scan.close();
4293
4294        // Now test that the row is accessible from all these interfaces, after
4295
// it has been deleted.
4296

4297        if (base_scan.doesCurrentPositionQualify())
4298            throw T_Fail.testFailMsg(
4299                "(readUncommitted) doesCurrentPositionQualify() failed.");
4300
4301        try
4302        {
4303            base_scan.fetch(big_row.getRowArray());
4304            throw T_Fail.testFailMsg(
4305                "(readUncommitted) fetch of deleted row should throw exception.");
4306        }
4307        catch (StandardException se)
4308        {
4309            // expect SQLState.AM_RECORD_NOT_FOUND exception.
4310

4311            if (!se.getMessageId().equals(SQLState.AM_RECORD_NOT_FOUND))
4312            {
4313                throw T_Fail.testFailMsg(
4314                    "(readUncommitted) fetch of deleted row should throw SQLState.AM_RECORD_NOT_FOUND.");
4315            }
4316        }
4317
4318        base_scan.fetchLocation(deleted_row_rowloc);
4319
4320        if (!base_scan.isCurrentPositionDeleted())
4321            throw T_Fail.testFailMsg(
4322                    "(readUncommitted) isCurrentPositionDeleted() failed.");
4323
4324        base_scan.close();
4325        tc.commit();
4326
4327        REPORT("(readUncommitted) succeeded");
4328        return true;
4329    }
4330
4331    public static String JavaDoc repeatString(String JavaDoc data, int repeat) {
4332
4333        String JavaDoc s = data;
4334        for (int i = 1; i < repeat; i++)
4335            s += data;
4336
4337        return s;
4338    }
4339
4340}
4341
Popular Tags