0001: /*
0002:
0003: Derby - Class org.apache.derbyTesting.unitTests.store.T_AccessFactory
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derbyTesting.unitTests.store;
0023:
0024: import org.apache.derbyTesting.unitTests.harness.T_Generic;
0025: import org.apache.derbyTesting.unitTests.harness.T_Fail;
0026:
0027: import org.apache.derby.iapi.store.access.*;
0028:
0029: import org.apache.derby.iapi.types.SQLLongint;
0030:
0031: import org.apache.derby.iapi.services.context.ContextManager;
0032: import org.apache.derby.iapi.services.context.ContextService;
0033:
0034: import org.apache.derby.iapi.services.io.Storable;
0035:
0036: import org.apache.derby.iapi.services.monitor.Monitor;
0037: import org.apache.derby.iapi.services.sanity.SanityManager;
0038: import org.apache.derby.iapi.services.io.FormatIdUtil;
0039:
0040: import org.apache.derby.iapi.error.StandardException;
0041:
0042: import org.apache.derby.iapi.types.DataValueDescriptor;
0043:
0044: import org.apache.derby.iapi.types.RowLocation;
0045:
0046: import org.apache.derby.iapi.store.raw.RawStoreFactory;
0047: import org.apache.derby.iapi.store.raw.Transaction;
0048: import org.apache.derby.iapi.reference.Property;
0049: import org.apache.derby.iapi.reference.SQLState;
0050: import org.apache.derby.iapi.services.io.FormatableBitSet;
0051: import org.apache.derby.iapi.services.i18n.MessageService;
0052: import java.io.File;
0053: import java.io.Serializable;
0054: import java.util.Hashtable;
0055: import java.util.Properties;
0056: import org.apache.derby.iapi.types.SQLInteger;
0057:
0058: import org.apache.derby.iapi.types.SQLChar;
0059:
0060: public class T_AccessFactory extends T_Generic {
0061: private static final String testService = "accessTest";
0062:
0063: AccessFactory store = null;
0064:
0065: public T_AccessFactory() {
0066: super ();
0067: }
0068:
0069: /*
0070: ** Methods of UnitTest.
0071: */
0072:
0073: /*
0074: ** Methods required by T_Generic
0075: */
0076:
0077: public String getModuleToTestProtocolName() {
0078: return AccessFactory.MODULE;
0079: }
0080:
0081: /**
0082: @exception T_Fail Unexpected behaviour from the API
0083: */
0084:
0085: protected void runTests() throws T_Fail {
0086: TransactionController tc = null;
0087: boolean pass = false;
0088:
0089: // Create a AccessFactory to test.
0090:
0091: // don't automatic boot this service if it gets left around
0092: if (startParams == null) {
0093: startParams = new Properties();
0094: }
0095: startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
0096: // remove the service directory to ensure a clean run
0097: startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE
0098: .toString());
0099:
0100: // see if we are testing encryption
0101: startParams = T_Util.setEncryptionParam(startParams);
0102:
0103: try {
0104: store = (AccessFactory) Monitor.createPersistentService(
0105: getModuleToTestProtocolName(), testService,
0106: startParams);
0107: } catch (StandardException mse) {
0108: throw T_Fail.exceptionFail(mse);
0109: }
0110:
0111: if (store == null) {
0112: throw T_Fail.testFailMsg(getModuleToTestProtocolName()
0113: + " service not started.");
0114: }
0115:
0116: REPORT("(unitTestMain) Testing " + testService);
0117:
0118: try {
0119:
0120: ContextManager cm = ContextService.getFactory()
0121: .getCurrentContextManager();
0122:
0123: tc = store.getAndNameTransaction(cm,
0124: AccessFactoryGlobals.USER_TRANS_NAME);
0125:
0126: if (dropTest(tc) && holdCursor(tc) && readUncommitted(tc)
0127: && updatelocks(tc) && nestedUserTransaction(tc)
0128: && positionAtRowLocation(tc) && sortCost(tc)
0129: && storeCost(tc) && partialScan(tc) && scanInfo(tc)
0130: && insertAndUpdateExample(tc)
0131: && insertAndFetchExample(tc) && scanExample(tc)
0132: && alterTable(tc) && tempTest(tc)
0133: && getTableProperties(tc) && insert_bench(tc)
0134: && transactionalProperties(tc) && commitTest(tc)) {
0135: pass = true;
0136: }
0137:
0138: // Make sure commitNoSync gets executed sometimes.
0139: tc.commitNoSync(TransactionController.RELEASE_LOCKS);
0140:
0141: tc.destroy();
0142:
0143: if (!pass)
0144: throw T_Fail.testFailMsg("test failed");
0145:
0146: } catch (StandardException e) {
0147: String msg = e.getMessage();
0148: if (msg == null)
0149: msg = e.getClass().getName();
0150: REPORT(msg);
0151: e.printStackTrace();
0152: throw T_Fail.exceptionFail(e);
0153: } catch (Throwable t) {
0154: t.printStackTrace();
0155: }
0156:
0157: }
0158:
0159: /*
0160: ** Methods of T_AccessFactory.
0161: */
0162:
0163: private void flush_cache() throws StandardException {
0164: // flush and empty cache to make sure rereading stuff works.
0165: RawStoreFactory rawstore = (RawStoreFactory) Monitor
0166: .findServiceModule(this .store, RawStoreFactory.MODULE);
0167:
0168: rawstore.checkpoint();
0169: }
0170:
0171: protected boolean insertAndFetchExample(TransactionController tc)
0172: throws StandardException, T_Fail {
0173: REPORT("(insertAndFetchExample)");
0174:
0175: // First a negative test - make sure heap requires a template:
0176:
0177: try {
0178: // Create a heap conglomerate.
0179: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0180: null, // ERROR - Heap requires a template!!!
0181: null, // column sort order not required for heap
0182: null, // default properties
0183: TransactionController.IS_DEFAULT); // not temporary
0184:
0185: throw T_Fail
0186: .testFailMsg("Allowed heap create without template.");
0187: } catch (Throwable t) {
0188: // expected error, just continue.
0189: }
0190:
0191: // Create a heap conglomerate.
0192: T_AccessRow template_row = new T_AccessRow(1);
0193: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0194: template_row.getRowArray(), // 1 column template.
0195: null, // column sort order not required for heap
0196: null, // default properties
0197: TransactionController.IS_DEFAULT); // not temporary
0198:
0199: // Insert and fetch some values.
0200: if (insertAndFetch(tc, conglomid, 33)
0201: && insertAndFetch(tc, conglomid, -1)
0202: && insertAndFetch(tc, conglomid, -1000000000)) {
0203: return true;
0204: } else {
0205: return false;
0206: }
0207: }
0208:
0209: // Insert a single row with a single column containing
0210: // the argument integer, and fetch it back, making sure that
0211: // we read the correct value.
0212: //
0213: protected boolean insertAndFetch(TransactionController tc,
0214: long conglomid, int value) throws StandardException, T_Fail {
0215: StaticCompiledOpenConglomInfo static_info = tc
0216: .getStaticCompiledConglomInfo(conglomid);
0217:
0218: DynamicCompiledOpenConglomInfo dynamic_info = tc
0219: .getDynamicCompiledConglomInfo(conglomid);
0220:
0221: String curr_xact_name = tc.getTransactionIdString();
0222:
0223: REPORT("(insertAndFetch) xact id = " + curr_xact_name);
0224:
0225: // Open the conglomerate.
0226: ConglomerateController cc = tc.openCompiledConglomerate(false,
0227: TransactionController.OPENMODE_FORUPDATE,
0228: TransactionController.MODE_RECORD,
0229: TransactionController.ISOLATION_SERIALIZABLE,
0230: static_info, dynamic_info);
0231:
0232: // Create a row.
0233: T_AccessRow r1 = new T_AccessRow(1);
0234: SQLInteger c1 = new SQLInteger(value);
0235: r1.setCol(0, c1);
0236:
0237: // Get a location template
0238: RowLocation rowloc = cc.newRowLocationTemplate();
0239:
0240: // Insert the row and remember its location.
0241: cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
0242:
0243: // quick test to make sure we can hash insert and find row location.
0244: Hashtable test_rowloc_hash = new Hashtable();
0245: test_rowloc_hash.put(rowloc, rowloc);
0246:
0247: RowLocation hash_find = (RowLocation) test_rowloc_hash
0248: .get(rowloc);
0249:
0250: if (!hash_find.equals(rowloc))
0251: throw T_Fail
0252: .testFailMsg("(insertAndFetch) bad hash lookup 1");
0253:
0254: hash_find = (RowLocation) test_rowloc_hash.remove(rowloc);
0255:
0256: if (!hash_find.equals(rowloc))
0257: throw T_Fail
0258: .testFailMsg("(insertAndFetch) bad hash lookup 2");
0259:
0260: hash_find = (RowLocation) test_rowloc_hash.remove(rowloc);
0261:
0262: if (hash_find != null)
0263: throw T_Fail
0264: .testFailMsg("(insertAndFetch) bad hash lookup 3");
0265:
0266: // Create a new row of the same type (since the interface expects
0267: // the callers to be keeping the row types straight), but with
0268: // a different column value.
0269: T_AccessRow r2 = new T_AccessRow(1);
0270: SQLInteger c2 = new SQLInteger(0);
0271: r2.setCol(0, c2);
0272:
0273: // Fetch the stored value.
0274: if (!cc
0275: .fetch(rowloc, r2.getRowArray(),
0276: (FormatableBitSet) null)) {
0277: throw T_Fail
0278: .testFailMsg("(insertAndFetch) fetch found no row.");
0279: }
0280:
0281: // Fetch using the fetch partial column interface
0282: SQLInteger c3 = new SQLInteger(0);
0283: FormatableBitSet singleColumn = new FormatableBitSet(1);
0284: singleColumn.set(0);
0285: DataValueDescriptor[] c3row = new DataValueDescriptor[1];
0286: c3row[0] = c3;
0287:
0288: if (!cc.fetch(rowloc, c3row, singleColumn)) {
0289: throw T_Fail
0290: .testFailMsg("(insertAndFetch) fetch found no row.");
0291: }
0292:
0293: // Close the conglomerate.
0294: cc.close();
0295:
0296: // Make sure we read back the value we wrote.
0297: if (c2.getInt() != value)
0298: throw T_Fail
0299: .testFailMsg("(insertAndFetch) Fetched value != inserted value.");
0300:
0301: if (c3.getInt() != value)
0302: throw T_Fail
0303: .testFailMsg("(insertAndFetch) Fetched value != inserted value.");
0304:
0305: return true;
0306: }
0307:
0308: protected boolean insertAndUpdateExample(TransactionController tc)
0309: throws StandardException, T_Fail {
0310: // Create a heap conglomerate.
0311: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0312: new T_AccessRow(1).getRowArray(), // 1 column template.
0313: null, // column sort order not required for heap
0314: null, // default properties
0315: TransactionController.IS_DEFAULT); // not temporary
0316:
0317: REPORT("(insertAndUpdateExample)");
0318:
0319: // Insert and update some values
0320: if (insertAndUpdate(tc, conglomid, -1, -1003152)
0321: && insertAndUpdate(tc, conglomid, 0, 2000000000)
0322: && deletetest(tc, conglomid, 1, 2)) {
0323: return true;
0324: }
0325:
0326: return false;
0327: }
0328:
0329: // Insert a single row with a single column containing
0330: // the first argument integer, delete it, make sure subsequent
0331: // delete, replace, and replace a single column return false.
0332: //
0333: protected boolean deletetest(TransactionController tc,
0334: long conglomid, int value1, int value2)
0335: throws StandardException, T_Fail {
0336: boolean ret_val;
0337:
0338: // Open the conglomerate.
0339: ConglomerateController cc = tc.openConglomerate(conglomid,
0340: false, TransactionController.OPENMODE_FORUPDATE,
0341: TransactionController.MODE_RECORD,
0342: TransactionController.ISOLATION_SERIALIZABLE);
0343:
0344: // Create a row.
0345: T_AccessRow r1 = new T_AccessRow(1);
0346: r1.setCol(0, new SQLInteger(value1));
0347:
0348: // Get a location template
0349: RowLocation rowloc = cc.newRowLocationTemplate();
0350:
0351: // Insert the row and remember its location.
0352: cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
0353:
0354: // delete it.
0355: if (!cc.delete(rowloc)) {
0356: throw T_Fail
0357: .testFailMsg("(deleteTest) delete of row failed");
0358: }
0359:
0360: // subsequent replace, update a single column, and delete
0361: // should return false
0362:
0363: // update single column
0364: DataValueDescriptor[] update_row = new DataValueDescriptor[1];
0365: FormatableBitSet update_desc = new FormatableBitSet(1);
0366: update_desc.set(0);
0367: if (cc.replace(rowloc, update_row, update_desc)) {
0368: throw T_Fail
0369: .testFailMsg("(deleteTest) partial column row replace returned true on del row");
0370: }
0371:
0372: // update whole row.
0373: if (cc.replace(rowloc, r1.getRowArray(),
0374: (FormatableBitSet) null)) {
0375: throw T_Fail
0376: .testFailMsg("(deleteTest) update returned true on del row");
0377: }
0378: if (cc.delete(rowloc)) {
0379: throw T_Fail
0380: .testFailMsg("(deleteTest) delete returned true on del row");
0381: }
0382:
0383: // Close the conglomerate.
0384: cc.close();
0385:
0386: return true;
0387: }
0388:
0389: // Insert a single row with a single column containing
0390: // the first argument integer, update it to the second
0391: // value, and make sure the update happened.
0392: //
0393: protected boolean insertAndUpdate(TransactionController tc,
0394: long conglomid, int value1, int value2)
0395: throws StandardException, T_Fail {
0396: // Open the conglomerate.
0397: ConglomerateController cc = tc.openConglomerate(conglomid,
0398: false, TransactionController.OPENMODE_FORUPDATE,
0399: TransactionController.MODE_RECORD,
0400: TransactionController.ISOLATION_SERIALIZABLE);
0401:
0402: // Create a row.
0403: T_AccessRow r1 = new T_AccessRow(1);
0404: r1.setCol(0, new SQLInteger(value1));
0405:
0406: // Get a location template
0407: RowLocation rowloc = cc.newRowLocationTemplate();
0408:
0409: // Insert the row and remember its location.
0410: cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
0411:
0412: // Update it to the second value
0413: DataValueDescriptor[] update_row = new DataValueDescriptor[1];
0414: update_row[0] = new SQLInteger(value2);
0415:
0416: FormatableBitSet update_desc = new FormatableBitSet(1);
0417: update_desc.set(0);
0418:
0419: cc.replace(rowloc, update_row, update_desc);
0420:
0421: // Create a new row (of the same type, since the interface expects
0422: // the callers to be keeping the row types straight.
0423: T_AccessRow r2 = new T_AccessRow(1);
0424: SQLInteger c2 = new SQLInteger(0);
0425: r2.setCol(0, c2);
0426:
0427: // Fetch the stored value.
0428: if (!cc
0429: .fetch(rowloc, r2.getRowArray(),
0430: (FormatableBitSet) null)) {
0431: throw T_Fail
0432: .testFailMsg("(insertAndUpdate) Fetch val not there.");
0433: }
0434:
0435: // Close the conglomerate.
0436: cc.close();
0437:
0438: // Make sure we read back the value we wrote.
0439: if (c2.getInt() != value2)
0440: throw T_Fail
0441: .testFailMsg("(insertAndUpdate) Fetch value != updated value.");
0442: else
0443: return true;
0444: }
0445:
0446: protected boolean scanExample(TransactionController tc)
0447: throws StandardException, T_Fail {
0448: tc.commit();
0449:
0450: if (!tc.isPristine() || !tc.isIdle() || tc.isGlobal())
0451: throw T_Fail
0452: .testFailMsg("(scanExample) bad xact state after commit.");
0453:
0454: if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0)
0455: || (tc
0456: .countOpens(TransactionController.OPEN_CONGLOMERATE) > 0)
0457: || (tc.countOpens(TransactionController.OPEN_SCAN) > 0)
0458: || (tc
0459: .countOpens(TransactionController.OPEN_CREATED_SORTS) > 0)
0460: || (tc.countOpens(TransactionController.OPEN_SORT) > 0)) {
0461: System.out.println("OPENED 0:\n" + tc.debugOpened());
0462: return (FAIL("unexpected open count."));
0463: }
0464:
0465: // Create a heap conglomerate.
0466: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0467: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
0468: null, // column sort order not required for heap
0469: null, // default properties
0470: TransactionController.IS_DEFAULT); // not temporary
0471:
0472: REPORT("(scanExample) starting");
0473:
0474: // Open it.
0475: ConglomerateController cc = tc.openConglomerate(conglomid,
0476: false, TransactionController.OPENMODE_FORUPDATE,
0477: TransactionController.MODE_RECORD,
0478: TransactionController.ISOLATION_SERIALIZABLE);
0479:
0480: // Insert some values.
0481: int values[] = { 11, 22, 33, 44, 55, 66 };
0482: T_AccessRow row = new T_AccessRow(1);
0483: for (int i = 0; i < values.length; i++) {
0484: row.setCol(0, new SQLInteger(values[i]));
0485: if (cc.insert(row.getRowArray()) != 0)
0486: throw T_Fail
0487: .testFailMsg("(scanExample after insert) insert failed ");
0488: }
0489:
0490: // For test coverage call the debugging output routine - can't diff it.
0491: REPORT("(scanExample) debug output testing: "
0492: + tc.debugOpened());
0493:
0494: // Close the conglomerate.
0495: cc.close();
0496:
0497: if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0)
0498: || (tc
0499: .countOpens(TransactionController.OPEN_CONGLOMERATE) > 0)
0500: || (tc.countOpens(TransactionController.OPEN_SCAN) > 0)
0501: || (tc
0502: .countOpens(TransactionController.OPEN_CREATED_SORTS) > 0)
0503: || (tc.countOpens(TransactionController.OPEN_SORT) > 0)) {
0504: System.out.println("OPENED 1:\n" + tc.debugOpened());
0505: return (FAIL("unexpected open count."));
0506: }
0507:
0508: REPORT("(scanExample) rows inserted");
0509:
0510: // Correlates our position in the upcoming scan to the values array.
0511: int scanindex = 0;
0512:
0513: // Put a specific column in the row so we can look at it.
0514: SQLInteger col = new SQLInteger(0);
0515: row.setCol(0, col);
0516:
0517: flush_cache();
0518:
0519: StaticCompiledOpenConglomInfo static_info = tc
0520: .getStaticCompiledConglomInfo(conglomid);
0521:
0522: // Open a scan on the conglomerate.
0523: ScanController scan1 = tc.openCompiledScan(
0524: false, // don't hold
0525: 0, // not for update
0526: TransactionController.MODE_RECORD,
0527: TransactionController.ISOLATION_SERIALIZABLE,
0528: (FormatableBitSet) null, // all columns, all as objects
0529: null, // start position - first row in conglomerate
0530: 0, // unused if start position is null.
0531: null, // qualifier - accept all rows
0532: null, // stop position - last row in conglomerate
0533: 0, // unused if stop position is null.
0534: static_info, tc
0535: .getDynamicCompiledConglomInfo(conglomid));
0536:
0537: // check out the RowCountable interface's.
0538:
0539: if (scan1.getEstimatedRowCount() != 6) {
0540: throw T_Fail
0541: .testFailMsg("(scanExample) estimated row count not 6:"
0542: + scan1.getEstimatedRowCount());
0543: }
0544:
0545: // Test 2 - ASSERT(should be able to set arbitrary row count)
0546:
0547: scan1.setEstimatedRowCount(5);
0548:
0549: if (scan1.getEstimatedRowCount() != 5) {
0550: throw T_Fail
0551: .testFailMsg("(scanExample) estimated row count not 5");
0552: }
0553:
0554: // Iterate through and check that the rows are still there.
0555: while (scan1.next()) {
0556: scan1.fetch(row.getRowArray());
0557:
0558: // Check we got the value we put in.
0559: if (col.getInt() != values[scanindex])
0560: throw T_Fail
0561: .testFailMsg("(scanExample after insert) Row "
0562: + scanindex + " should have been "
0563: + values[scanindex] + ", was "
0564: + col.getInt());
0565:
0566: scanindex++;
0567: }
0568:
0569: // make sure another next() call continues to return false.
0570: if (scan1.next())
0571: throw T_Fail
0572: .testFailMsg("(scanExample after insert) should continue to return false after reaching end of scan");
0573:
0574: // see if reopen scan interfaces work
0575: scan1.reopenScan(null, // start position - first row in conglomerate
0576: 0, // unused if start position is null.
0577: null, // qualifier - accept all rows
0578: null, // stop position - last row in conglomerate
0579: 0); // unused if stop position is null.
0580:
0581: scan1.next();
0582: scan1.next();
0583: scan1.next();
0584: RowLocation third_row_rowloc = scan1.newRowLocationTemplate();
0585: scan1.fetchLocation(third_row_rowloc);
0586:
0587: // see if reopen scan interfaces work
0588: scan1.reopenScanByRowLocation(third_row_rowloc, null);
0589:
0590: scanindex = 2;
0591: while (scan1.next()) {
0592: scan1.fetch(row.getRowArray());
0593:
0594: // Check we got the value we put in.
0595: if (col.getInt() != values[scanindex])
0596: throw T_Fail
0597: .testFailMsg("(scanExample after insert) Row "
0598: + scanindex + " should have been "
0599: + values[scanindex] + ", was "
0600: + col.getInt());
0601:
0602: scanindex++;
0603: }
0604:
0605: scan1.close();
0606:
0607: // Check we saw the right number of rows.
0608: if (scanindex != values.length)
0609: throw T_Fail
0610: .testFailMsg("(scanExample after insert) Expected "
0611: + values.length + "rows, got " + scanindex);
0612:
0613: REPORT("(scanExample) rows present and accounted for");
0614:
0615: // Open another scan on the conglomerate.
0616: ScanController scan2 = tc.openScan(
0617: conglomid,
0618: false, // don't hold
0619: TransactionController.OPENMODE_FORUPDATE, // for update
0620: TransactionController.MODE_RECORD,
0621: TransactionController.ISOLATION_SERIALIZABLE,
0622: (FormatableBitSet) null, // all columns, all as objects
0623: null, // start position - first row in conglomerate
0624: 0, // unused if start position is null.
0625: null, // qualifier - accept all rows
0626: null, // stop position - last row in conglomerate
0627: 0); // unused if stop position is null.
0628:
0629: // Iterate with the second scan and fiddle with the values so they
0630: // look like the new value array.
0631: int newvalues[] = { 22, 33, 444, 55, 6666 };
0632: while (scan2.next()) {
0633: scan2.fetch(row.getRowArray());
0634:
0635: switch (((SQLInteger) row.getCol(0)).getInt()) {
0636: case 11:
0637: if (!scan2.delete())
0638: throw T_Fail
0639: .testFailMsg("(scanExample) delete failed.");
0640: break;
0641: case 22:
0642: case 33:
0643: case 55:
0644: // leave these alone
0645: break;
0646: case 44:
0647: DataValueDescriptor[] update_row = new DataValueDescriptor[1];
0648: update_row[0] = new SQLInteger(444);
0649:
0650: FormatableBitSet update_desc = new FormatableBitSet(1);
0651: update_desc.set(0);
0652:
0653: if (!scan2.replace(update_row, update_desc)) {
0654: throw T_Fail
0655: .testFailMsg("(scanExample) partial column row replace failed.");
0656: }
0657: break;
0658: case 66:
0659: row.setCol(0, new SQLInteger(6666));
0660: if (!scan2.replace(row.getRowArray(),
0661: (FormatableBitSet) null))
0662: throw T_Fail
0663: .testFailMsg("(scanExample) replace failed.");
0664: break;
0665: default:
0666: throw T_Fail
0667: .testFailMsg("(scanExample) Read unexpected value.");
0668: }
0669: }
0670: scan2.close();
0671:
0672: REPORT("(scanExample) rows fiddled with");
0673:
0674: // Open a third scan on the conglomerate.
0675: ScanController scan3 = tc.openScan(
0676: conglomid,
0677: false, // don't hold
0678: 0, // not for update
0679: TransactionController.MODE_RECORD,
0680: TransactionController.ISOLATION_SERIALIZABLE,
0681: (FormatableBitSet) null, // all columns, all as objects
0682: null, // start position - first row in conglomerate
0683: 0, // unused if start position is null.
0684: null, // qualifier - accept all rows
0685: null, // stop position - last row in conglomerate
0686: 0); // unused if stop position is null.
0687:
0688: // Iterate through and inspect the changes.
0689: scanindex = 0;
0690: row.setCol(0, col);
0691: while (scan3.next()) {
0692: scan3.fetch(row.getRowArray());
0693:
0694: REPORT("(scanExample) scan3 fetched " + col.getInt());
0695:
0696: // Check we got the value we put in.
0697: if (col.getInt() != newvalues[scanindex])
0698: throw T_Fail
0699: .testFailMsg("(scanExample after changes) Row "
0700: + scanindex + " should have been "
0701: + newvalues[scanindex] + ", was "
0702: + col.getInt());
0703:
0704: scanindex++;
0705: }
0706: scan3.close();
0707:
0708: // Open a third scan on the conglomerate.
0709: scan3 = tc.openScan(
0710: conglomid,
0711: false, // don't hold
0712: 0, // not for update
0713: TransactionController.MODE_RECORD,
0714: TransactionController.ISOLATION_READ_UNCOMMITTED,
0715: (FormatableBitSet) null, // all columns, all as objects
0716: null, // start position - first row in conglomerate
0717: 0, // unused if start position is null.
0718: null, // qualifier - accept all rows
0719: null, // stop position - last row in conglomerate
0720: 0); // unused if stop position is null.
0721:
0722: // Iterate through and inspect the changes.
0723: scanindex = 0;
0724: row.setCol(0, col);
0725: while (scan3.next()) {
0726: scan3.fetch(row.getRowArray());
0727:
0728: REPORT("(scanExample) scan3 fetched " + col.getInt());
0729:
0730: // Check we got the value we put in.
0731: if (col.getInt() != newvalues[scanindex])
0732: throw T_Fail
0733: .testFailMsg("(scanExample after changes) Row "
0734: + scanindex + " should have been "
0735: + newvalues[scanindex] + ", was "
0736: + col.getInt());
0737:
0738: scanindex++;
0739: }
0740: scan3.close();
0741:
0742: // Check we saw the right number of rows.
0743: if (scanindex != newvalues.length)
0744: throw T_Fail
0745: .testFailMsg("(scanExample after changes) Expected "
0746: + newvalues.length
0747: + "rows, got "
0748: + scanindex);
0749:
0750: REPORT("(scanExample) fiddled rows present and accounted for");
0751:
0752: REPORT("(scanExample) testing expected delete errors");
0753:
0754: // Open 4th scan on conglomerate and test "expected" error returns
0755: // from replace, partial column replace, delete.
0756: ScanController scan4 = tc.openScan(
0757: conglomid,
0758: false, // don't hold
0759: TransactionController.OPENMODE_FORUPDATE, // for update
0760: TransactionController.MODE_RECORD,
0761: TransactionController.ISOLATION_SERIALIZABLE,
0762: (FormatableBitSet) null, // all columns, all as objects
0763: null, // start position - first row in conglomerate
0764: 0, // unused if start position is null.
0765: null, // qualifier - accept all rows
0766: null, // stop position - last row in conglomerate
0767: 0); // unused if stop position is null.
0768:
0769: // Iterate with the second scan find the "22" row, delete it and
0770: // then test that operations on that deleted entry FAIL as expected.
0771: while (scan4.next()) {
0772: scan4.fetch(row.getRowArray());
0773:
0774: if (!scan4.doesCurrentPositionQualify()) {
0775: throw T_Fail
0776: .testFailMsg("(scanExample doesCurrentPositionQualify() errors) Expected requalify of current row to succeed");
0777: }
0778:
0779: if (((SQLInteger) row.getCol(0)).getInt() == 22) {
0780: if (!scan4.delete()) {
0781: throw T_Fail
0782: .testFailMsg("(scanExample delete errors) Delete failed.");
0783: }
0784: break;
0785: }
0786: }
0787:
0788: if (scan4.doesCurrentPositionQualify()) {
0789: throw T_Fail
0790: .testFailMsg("(scanExample doesCurrentPositionQualify() errors) Expected qualify of deleted row to FAIL");
0791: }
0792:
0793: DataValueDescriptor[] update_row = new DataValueDescriptor[1];
0794:
0795: FormatableBitSet update_desc = new FormatableBitSet(1);
0796: update_desc.set(0);
0797:
0798: if (scan4.replace(update_row, update_desc)) {
0799: throw T_Fail
0800: .testFailMsg("(scanExample delete errors) Expected partial column replace to FAIL");
0801: }
0802: if (scan4.replace(row.getRowArray(), (FormatableBitSet) null)) {
0803: throw T_Fail
0804: .testFailMsg("(scanExample after changes) Expected replace to FAIL");
0805: }
0806: if (scan4.delete()) {
0807: throw T_Fail
0808: .testFailMsg("(scanExample after changes) Expected delete to FAIL");
0809: }
0810:
0811: scan4.close();
0812:
0813: if ((tc.countOpens(TransactionController.OPEN_TOTAL) > 0)
0814: || (tc
0815: .countOpens(TransactionController.OPEN_CONGLOMERATE) > 0)
0816: || (tc.countOpens(TransactionController.OPEN_SCAN) > 0)
0817: || (tc
0818: .countOpens(TransactionController.OPEN_CREATED_SORTS) > 0)
0819: || (tc.countOpens(TransactionController.OPEN_SORT) > 0)) {
0820: System.out.println("OPENED:\n" + tc.debugOpened());
0821: return (FAIL("unexpected open count."));
0822: }
0823:
0824: REPORT("(scanExample) completed");
0825: return true;
0826: }
0827:
0828: protected boolean dropTest(TransactionController tc)
0829: throws StandardException, T_Fail {
0830: ConglomerateController cc;
0831:
0832: REPORT("(dropTest) starting");
0833:
0834: // Test of drop conglomerate with abort by doing the following:
0835: // create table
0836: // commit
0837: // drop table
0838: // make sure table is not still there.
0839: // abort
0840: // make sure table is still there.
0841:
0842: // Create a heap conglomerate.
0843: long orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0844: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
0845: null, // column sort order not required for heap
0846: null, // default properties
0847: TransactionController.IS_DEFAULT); // not temporary
0848:
0849: tc.commit();
0850:
0851: tc.dropConglomerate(orig_conglomid);
0852:
0853: // Try and Open it - it should fail.
0854: try {
0855: cc = tc.openConglomerate(orig_conglomid, false,
0856: TransactionController.OPENMODE_FORUPDATE,
0857: TransactionController.MODE_RECORD,
0858: TransactionController.ISOLATION_SERIALIZABLE);
0859:
0860: throw T_Fail
0861: .testFailMsg("Open conglom on deleted conglom worked.");
0862: } catch (StandardException e) {
0863: if (!e.getMessageId().equals(
0864: SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST)) {
0865: throw e;
0866: }
0867:
0868: // normal path through the test - conglomerate does not exist,
0869: // ignore the expected error
0870: }
0871:
0872: // Try and Open a random non-existant conglomerate - it should fail.
0873: try {
0874: cc = tc.openConglomerate(42424242, false,
0875: TransactionController.OPENMODE_FORUPDATE,
0876: TransactionController.MODE_RECORD,
0877: TransactionController.ISOLATION_SERIALIZABLE);
0878:
0879: throw T_Fail
0880: .testFailMsg("Open conglom on deleted conglom worked.");
0881: } catch (StandardException e) {
0882: if (!e.getMessageId().equals(
0883: SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST)) {
0884: throw e;
0885: }
0886:
0887: // normal path through the test - conglomerate does not exist,
0888: // ignore the expected error
0889: }
0890:
0891: // Try and delete it again - it should fail.
0892: try {
0893: tc.dropConglomerate(orig_conglomid);
0894:
0895: throw T_Fail
0896: .testFailMsg("Delete conglom on deleted conglom worked.");
0897: } catch (StandardException e) {
0898: // normal path through the test, ignore the expected error
0899: }
0900:
0901: // cursory test to make sure conglom directory is not screwed up.
0902:
0903: // Create a heap conglomerate.
0904: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0905: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
0906: null, // column sort order not required for heap
0907: null, // default properties
0908: TransactionController.IS_DEFAULT); // not temporary
0909:
0910: cc = tc.openConglomerate(conglomid, false,
0911: TransactionController.OPENMODE_FORUPDATE,
0912: TransactionController.MODE_RECORD,
0913: TransactionController.ISOLATION_SERIALIZABLE);
0914:
0915: tc.abort();
0916:
0917: // the original conglomerate should be still around after the abort.
0918: cc = tc.openConglomerate(orig_conglomid, false,
0919: TransactionController.OPENMODE_FORUPDATE,
0920: TransactionController.MODE_RECORD,
0921: TransactionController.ISOLATION_SERIALIZABLE);
0922:
0923: cc.close();
0924:
0925: return true;
0926: }
0927:
0928: /**
0929: * Test the access level getTableProperties() call.
0930: * <p>
0931: *
0932: * @return true if the test succeeded.
0933: *
0934: * @param tc The transaction controller to use in the test.
0935: *
0936: * @exception StandardException Standard exception policy.
0937: * @exception T_Fail Unexpected behaviour from the API
0938: **/
0939: protected boolean getTableProperties(TransactionController tc)
0940: throws StandardException, T_Fail {
0941: int key_value;
0942:
0943: Properties prop = new Properties();
0944:
0945: prop.put(Property.PAGE_SIZE_PARAMETER, "8192");
0946: prop.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, "99");
0947: prop.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, "42");
0948: prop.put(RawStoreFactory.CONTAINER_INITIAL_PAGES, "22");
0949:
0950: // Create a heap conglomerate.
0951: T_AccessRow template_row = new T_AccessRow(1);
0952: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
0953: template_row.getRowArray(), // 1 column template.
0954: null, // column sort order not required for heap
0955: prop, // default properties
0956: TransactionController.IS_DEFAULT); // not temporary
0957: // Open the conglomerate.
0958: ConglomerateController cc = tc.openConglomerate(conglomid,
0959: false, TransactionController.OPENMODE_FORUPDATE,
0960: TransactionController.MODE_RECORD,
0961: TransactionController.ISOLATION_SERIALIZABLE);
0962:
0963: // verify that input properties were used.
0964: Properties ret_prop = tc.getUserCreateConglomPropList();
0965:
0966: cc.getTableProperties(ret_prop);
0967:
0968: if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER)
0969: .compareTo("8192") != 0
0970: || ret_prop.getProperty(
0971: RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
0972: .compareTo("99") != 0
0973: || ret_prop.getProperty(
0974: RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
0975: .compareTo("42") != 0
0976: || ret_prop.getProperty(
0977: RawStoreFactory.CONTAINER_INITIAL_PAGES)
0978: .compareTo("22") != 0) {
0979: throw T_Fail
0980: .testFailMsg("(getTableProperties) Did not get expected table propertes(1)."
0981: + "\nGot pageSize = "
0982: + ret_prop
0983: .getProperty(Property.PAGE_SIZE_PARAMETER)
0984: + "\nGot reserved = "
0985: + ret_prop
0986: .getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
0987: + "\nGot minimum record size = "
0988: + ret_prop
0989: .getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
0990: + "\nGot initial pages = "
0991: + ret_prop
0992: .getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES));
0993: }
0994:
0995: ret_prop = cc.getInternalTablePropertySet(null);
0996:
0997: if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER)
0998: .compareTo("8192") != 0
0999: || ret_prop.getProperty(
1000: RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
1001: .compareTo("99") != 0
1002: || ret_prop.getProperty(
1003: RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
1004: .compareTo("42") != 0
1005: || ret_prop.getProperty(
1006: RawStoreFactory.CONTAINER_INITIAL_PAGES)
1007: .compareTo("22") != 0) {
1008: throw T_Fail
1009: .testFailMsg("(getTableProperties) Did not get expected table propertes(2)."
1010: + "\nGot pageSize = "
1011: + ret_prop
1012: .getProperty(Property.PAGE_SIZE_PARAMETER)
1013: + "\nGot reserved = "
1014: + ret_prop
1015: .getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
1016: + "\nGot minimum record size = "
1017: + ret_prop
1018: .getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
1019: + "\nGot initial pages = "
1020: + ret_prop
1021: .getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES));
1022: }
1023:
1024: ret_prop = new Properties();
1025:
1026: ret_prop = cc.getInternalTablePropertySet(ret_prop);
1027:
1028: if (ret_prop.getProperty(Property.PAGE_SIZE_PARAMETER)
1029: .compareTo("8192") != 0
1030: || ret_prop.getProperty(
1031: RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
1032: .compareTo("99") != 0
1033: || ret_prop.getProperty(
1034: RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
1035: .compareTo("42") != 0
1036: || ret_prop.getProperty(
1037: RawStoreFactory.CONTAINER_INITIAL_PAGES)
1038: .compareTo("22") != 0) {
1039: throw T_Fail
1040: .testFailMsg("(getTableProperties) Did not get expected table propertes(3)."
1041: + "\nGot pageSize = "
1042: + ret_prop
1043: .getProperty(Property.PAGE_SIZE_PARAMETER)
1044: + "\nGot reserved = "
1045: + ret_prop
1046: .getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER)
1047: + "\nGot minimum record size = "
1048: + ret_prop
1049: .getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER)
1050: + "\nGot initial pages = "
1051: + ret_prop
1052: .getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES));
1053: }
1054:
1055: return (true);
1056: }
1057:
1058: /**
1059: * Test the access level alter table interface for adding columns.
1060: * <p>
1061: *
1062: * @return true if the test succeeded.
1063: *
1064: * @param tc The transaction controller to use in the test.
1065: *
1066: * @exception StandardException Standard exception policy.
1067: * @exception T_Fail Unexpected behaviour from the API
1068: **/
1069: protected boolean alterTable(TransactionController tc)
1070: throws StandardException, T_Fail {
1071: int key_value;
1072:
1073: REPORT("(alterTable) starting");
1074:
1075: // Create a heap conglomerate.
1076: T_AccessRow template_row = new T_AccessRow(1);
1077: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1078: template_row.getRowArray(), // 1 column template.
1079: null, // column sort order not required for heap
1080: null, // default properties
1081: TransactionController.IS_DEFAULT); // not temporary
1082: // Open the conglomerate.
1083: ConglomerateController cc = tc.openConglomerate(conglomid,
1084: false, TransactionController.OPENMODE_FORUPDATE,
1085: TransactionController.MODE_RECORD,
1086: TransactionController.ISOLATION_SERIALIZABLE);
1087:
1088: // Create a 1 column row. int column = 1.
1089: T_AccessRow r1 = new T_AccessRow(1);
1090: SQLInteger c1 = new SQLInteger(1);
1091: r1.setCol(0, c1);
1092:
1093: // Get a location template
1094: RowLocation rowloc1 = cc.newRowLocationTemplate();
1095:
1096: // Insert the row and remember its location.
1097: cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1098:
1099: // create another 1 column row. int column = 2.
1100: // Get a location template
1101: r1.setCol(0, new SQLInteger(2));
1102: RowLocation rowloc2 = cc.newRowLocationTemplate();
1103:
1104: // Insert the row and remember its location.
1105: cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1106:
1107: // At this point the table looks like:
1108: // col1
1109: // ----
1110: // 1
1111: // 2
1112:
1113: // RESOLVE - currently the store can't catch the following error:
1114: /*
1115: // Test that we can't alter while it is open.
1116: try
1117: {
1118: tc.addColumnToConglomerate(conglomid, 1, c1);
1119: throw T_Fail.testFailMsg(
1120: "(alterTable) Allowed alter table while table was open.");
1121: }
1122: catch (StandardException t)
1123: {
1124: // expected error continue the test.
1125: }
1126: */
1127:
1128: // Test that we can't add data to columns that don't exist
1129: // Currently we only error check in debug code.
1130: // RESOLVE - should this be a runtime error?
1131: if (SanityManager.DEBUG) {
1132: try {
1133: T_AccessRow two_column_row = new T_AccessRow(2);
1134: SQLInteger col1 = new SQLInteger(3);
1135: SQLInteger col2 = new SQLInteger(3);
1136: cc.insert(two_column_row.getRowArray());
1137: throw T_Fail
1138: .testFailMsg("(alterTable) Allowed insert of bad row.");
1139: } catch (StandardException t) {
1140: // expected error continue the test.
1141: }
1142: }
1143:
1144: // Test that we can't fetch data columns that don't exist
1145:
1146: // Currently we only error check for this in sanity code.
1147: // RESOLVE - (mikem) should we check for this in released runtime?
1148: if (SanityManager.DEBUG) {
1149: try {
1150: T_AccessRow two_column_row = new T_AccessRow(2);
1151: if (!cc.fetch(rowloc1, two_column_row.getRowArray(),
1152: (FormatableBitSet) null)) {
1153: throw T_Fail
1154: .testFailMsg("(alterTable) Allowed fetch of bad row, bad ret val.");
1155: }
1156:
1157: throw T_Fail
1158: .testFailMsg("(alterTable) Allowed fetch of bad row.");
1159: } catch (StandardException t) {
1160: // expected error continue the test.
1161: }
1162: }
1163:
1164: // Test that we can't fetch data columns that don't exist
1165: // Currently we only error check for this in sanity code.
1166: // RESOLVE - (mikem) should we check for this in released runtime?
1167: if (SanityManager.DEBUG) {
1168: try {
1169: DataValueDescriptor[] third_column_row = new DataValueDescriptor[3];
1170:
1171: third_column_row[2] = new SQLInteger(3);
1172:
1173: FormatableBitSet fetch_desc = new FormatableBitSet(3);
1174: fetch_desc.set(2);
1175:
1176: if (!cc.fetch(rowloc1, third_column_row, fetch_desc)) {
1177: throw T_Fail
1178: .testFailMsg("(alterTable) Allowed fetch of bad row, bad ret val.");
1179: }
1180:
1181: throw T_Fail
1182: .testFailMsg("(alterTable) Allowed fetch of bad row.");
1183: } catch (StandardException t) {
1184: // expected error continue the test.
1185: }
1186: }
1187:
1188: // Test that we can't replace data columns that don't exist
1189:
1190: // Currently we only error check for this in sanity code.
1191: // RESOLVE - (mikem) should we check for this in released runtime?
1192: if (SanityManager.DEBUG) {
1193: try {
1194: T_AccessRow two_column_row = new T_AccessRow(2);
1195: SQLInteger col1 = new SQLInteger(3);
1196: SQLInteger col2 = new SQLInteger(3);
1197: cc.replace(rowloc1, two_column_row.getRowArray(), null);
1198: throw T_Fail
1199: .testFailMsg("(alterTable) Allowed replace of bad row.");
1200: } catch (StandardException t) {
1201: // expected error continue the test.
1202: }
1203: }
1204:
1205: // Test that we can't replace data columns that don't exist
1206: if (SanityManager.DEBUG) {
1207: try {
1208: DataValueDescriptor[] second_column_row = new DataValueDescriptor[2];
1209: second_column_row[1] = new SQLInteger(3);
1210:
1211: FormatableBitSet update_desc = new FormatableBitSet(2);
1212: update_desc.set(1);
1213:
1214: cc.replace(rowloc1, second_column_row, update_desc);
1215: throw T_Fail
1216: .testFailMsg("(alterTable) Allowed partial row update of bad column.");
1217: } catch (StandardException t) {
1218: // expected error continue the test.
1219: }
1220: }
1221:
1222: // Make sure commitNoSync gets executed sometimes.
1223: tc.commitNoSync(TransactionController.RELEASE_LOCKS);
1224:
1225: // now alter the conglomerate, add another int column
1226: tc.addColumnToConglomerate(conglomid, 1, c1);
1227:
1228: // Open the table after the close done by commit.
1229: cc = tc.openConglomerate(conglomid, false,
1230: TransactionController.OPENMODE_FORUPDATE,
1231: TransactionController.MODE_RECORD,
1232: TransactionController.ISOLATION_SERIALIZABLE);
1233:
1234: T_AccessRow two_column_row = new T_AccessRow(2);
1235: SQLInteger col1 = new SQLInteger(3);
1236: SQLInteger col2 = new SQLInteger(3);
1237:
1238: // fetch the rows and make sure you get null's in new fields.
1239: if (!cc.fetch(rowloc1, two_column_row.getRowArray(),
1240: (FormatableBitSet) null)) {
1241: throw T_Fail.testFailMsg("(alterTable) Row not there.");
1242: }
1243:
1244: if ((((SQLInteger) two_column_row.getCol(0)).getInt() != 1)
1245: || (!two_column_row.getCol(1).isNull())) {
1246: throw T_Fail
1247: .testFailMsg("(alterTable) Bad column value after alter.");
1248: }
1249: if (!cc.fetch(rowloc2, two_column_row.getRowArray(),
1250: (FormatableBitSet) null)) {
1251: throw T_Fail.testFailMsg("(alterTable) Row not there.");
1252: }
1253:
1254: if ((((SQLInteger) two_column_row.getCol(0)).getInt() != 2)
1255: || (!two_column_row.getCol(1).isNull())) {
1256: throw T_Fail
1257: .testFailMsg("(alterTable) Bad column value after alter.");
1258: }
1259:
1260: // make sure insert of 2 column row works.
1261: two_column_row = new T_AccessRow(2);
1262: two_column_row.setCol(0, new SQLInteger(3));
1263: two_column_row.setCol(1, new SQLInteger(300));
1264: cc.insert(two_column_row.getRowArray());
1265:
1266: // At this point the table looks like:
1267: // col1 col2
1268: // ---- ----
1269: // 1 NA
1270: // 2 NA
1271: // 3 300
1272:
1273: ScanController scan = tc.openScan(
1274: conglomid,
1275: false, // don't hold
1276: TransactionController.OPENMODE_FORUPDATE, // for update
1277: TransactionController.MODE_RECORD,
1278: TransactionController.ISOLATION_SERIALIZABLE,
1279: (FormatableBitSet) null, // all columns, all as objects
1280: null, // start position - first row in conglomerate
1281: 0, // unused if start position is null.
1282: null, // qualifier - accept all rows
1283: null, // stop position - last row in conglomerate
1284: 0); // unused if stop position is null.
1285:
1286: while (scan.next()) {
1287: scan.fetch(two_column_row.getRowArray());
1288:
1289: key_value = ((SQLInteger) two_column_row.getCol(0))
1290: .getInt();
1291:
1292: switch (key_value) {
1293: case 1: {
1294: // Set non-existent column value to 100
1295: if (!two_column_row.getCol(1).isNull()) {
1296: throw T_Fail
1297: .testFailMsg("(alterTable) Bad column value after alter.");
1298: }
1299:
1300: // test that replace field works on alter added column
1301: // make result row be: (1, 100)
1302:
1303: two_column_row.setCol(1, new SQLInteger(100));
1304:
1305: scan.replace(two_column_row.getRowArray(),
1306: (FormatableBitSet) null);
1307: break;
1308: }
1309: case 2: {
1310: if (!two_column_row.getCol(1).isNull()) {
1311: throw T_Fail
1312: .testFailMsg("(alterTable) Bad column value after alter.");
1313: }
1314:
1315: // test that replace row works on alter added column row.
1316: // make result row be: (2, 200)
1317: two_column_row.setCol(1, new SQLInteger(200));
1318:
1319: scan.replace(two_column_row.getRowArray(),
1320: (FormatableBitSet) null);
1321:
1322: break;
1323: }
1324: case 3: {
1325: break;
1326: }
1327: default: {
1328: throw T_Fail
1329: .testFailMsg("(alterTable) bad row value found in table.");
1330: }
1331:
1332: }
1333: }
1334:
1335: // reposition the scan
1336: scan.reopenScan(null, // start position - first row in conglomerate
1337: 0, // unused if start position is null.
1338: null, // qualifier - accept all rows
1339: null, // stop position - last row in conglomerate
1340: 0); // unused if stop position is null.
1341:
1342: while (scan.next()) {
1343: scan.fetch(two_column_row.getRowArray());
1344:
1345: key_value = ((SQLInteger) two_column_row.getCol(0))
1346: .getInt();
1347:
1348: switch (key_value) {
1349: case 1:
1350: case 2:
1351: case 3: {
1352: int second_col_val = ((SQLInteger) two_column_row
1353: .getCol(1)).getInt();
1354:
1355: if (second_col_val != (key_value * 100)) {
1356: throw T_Fail
1357: .testFailMsg("(alterTable) Bad column value after alter."
1358: + "expected: ("
1359: + key_value
1360: + ", "
1361: + key_value
1362: * 100
1363: + ")\n"
1364: + "got : ("
1365: + key_value
1366: + ", "
1367: + second_col_val + ")\n");
1368: }
1369:
1370: break;
1371: }
1372: default: {
1373: throw T_Fail
1374: .testFailMsg("(alterTable) bad row value found in table.");
1375: }
1376: }
1377: }
1378:
1379: scan.close();
1380:
1381: tc.commit();
1382:
1383: REPORT("(alterTable) completed");
1384:
1385: return true;
1386: }
1387:
1388: /**
1389: * Test the access level ScanInfo interface.
1390: * <p>
1391: *
1392: * @return true if the test succeeded.
1393: *
1394: * @param tc The transaction controller to use in the test.
1395: *
1396: * @exception StandardException Standard exception policy.
1397: * @exception T_Fail Unexpected behaviour from the API
1398: **/
1399: protected boolean scanInfo(TransactionController tc)
1400: throws StandardException, T_Fail {
1401: int key_value;
1402:
1403: REPORT("(scanInfo) starting");
1404:
1405: // Create a heap conglomerate.
1406: T_AccessRow template_row = new T_AccessRow(2);
1407: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1408: template_row.getRowArray(), // 1 column template.
1409: null, // column sort order not required for heap
1410: null, // default properties
1411: TransactionController.IS_DEFAULT); // not temporary
1412: // Open the conglomerate.
1413: ConglomerateController cc = tc.openConglomerate(conglomid,
1414: false, TransactionController.OPENMODE_FORUPDATE,
1415: TransactionController.MODE_RECORD,
1416: TransactionController.ISOLATION_SERIALIZABLE);
1417:
1418: // Create a 1 column row. int column = 1.
1419: T_AccessRow r1 = new T_AccessRow(2);
1420: SQLInteger c1 = new SQLInteger(1);
1421: SQLInteger c2 = new SQLInteger(100);
1422: r1.setCol(0, c1);
1423: r1.setCol(1, c2);
1424:
1425: // Get a location template
1426: RowLocation rowloc1 = cc.newRowLocationTemplate();
1427:
1428: // Insert the row and remember its location.
1429: cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1430:
1431: // create another 2 column row. int column = 2.
1432: // Get a location template
1433: r1.setCol(0, new SQLInteger(2));
1434: r1.setCol(1, new SQLInteger(200));
1435: RowLocation rowloc2 = cc.newRowLocationTemplate();
1436:
1437: // Insert the row and remember its location.
1438: cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1439:
1440: cc.delete(rowloc2);
1441:
1442: if (tc.isPristine() || tc.isIdle()) {
1443: throw T_Fail
1444: .testFailMsg("(scanInfo) bad xact state after update xact.");
1445: }
1446:
1447: tc.commit();
1448:
1449: ScanController scan = tc.openScan(
1450: conglomid,
1451: false, // don't hold
1452: 0, // for read
1453: TransactionController.MODE_TABLE,
1454: TransactionController.ISOLATION_SERIALIZABLE,
1455: (FormatableBitSet) null, // all columns, all as objects
1456: null, // start position - first row in conglomerate
1457: 0, // unused if start position is null.
1458: null, // qualifier - accept all rows
1459: null, // stop position - last row in conglomerate
1460: 0); // unused if stop position is null.
1461:
1462: if (!scan.isTableLocked()) {
1463: throw T_Fail
1464: .testFailMsg("(scanInfo) table should be table locked.");
1465: }
1466:
1467: while (scan.next()) {
1468: scan.fetch(r1.getRowArray());
1469: }
1470: ScanInfo scan_info = scan.getScanInfo();
1471: Properties prop = scan_info.getAllScanInfo(null);
1472:
1473: if (!tc.isPristine() || tc.isIdle()) {
1474: throw T_Fail
1475: .testFailMsg("(scanInfo) bad xact state after update xact.");
1476: }
1477:
1478: REPORT(("return from full row scan heap.getScanInfo() = " + prop));
1479:
1480: if (Integer.parseInt(prop.getProperty(MessageService
1481: .getTextMessage(SQLState.STORE_RTS_NUM_PAGES_VISITED))) != 1) {
1482: throw T_Fail
1483: .testFailMsg("(scanInfo) wrong numPagesVisited. Expected 1, got "
1484: + Integer
1485: .parseInt(prop
1486: .getProperty(MessageService
1487: .getTextMessage(SQLState.STORE_RTS_NUM_PAGES_VISITED))));
1488: }
1489: if (Integer.parseInt(prop.getProperty(MessageService
1490: .getTextMessage(SQLState.STORE_RTS_NUM_ROWS_VISITED))) != 2) {
1491: throw T_Fail
1492: .testFailMsg("(scanInfo) wrong numRowsVisited. Expected 2, got "
1493: + Integer
1494: .parseInt(prop
1495: .getProperty(MessageService
1496: .getTextMessage(SQLState.STORE_RTS_NUM_ROWS_VISITED))));
1497: }
1498: if (Integer
1499: .parseInt(prop
1500: .getProperty(MessageService
1501: .getTextMessage(SQLState.STORE_RTS_NUM_ROWS_QUALIFIED))) != 1) {
1502: throw T_Fail
1503: .testFailMsg("(scanInfo) wrong numRowsQualified. Expected 1, got "
1504: + Integer
1505: .parseInt(prop
1506: .getProperty(MessageService
1507: .getTextMessage(SQLState.STORE_RTS_NUM_ROWS_QUALIFIED))));
1508: }
1509:
1510: // Try a partial Row scan
1511:
1512: // only get the 2nd column.
1513: FormatableBitSet validColumns = new FormatableBitSet(3);
1514: validColumns.set(1);
1515:
1516: scan = tc.openScan(
1517: conglomid,
1518: false, // don't hold
1519: TransactionController.OPENMODE_FORUPDATE, // for update
1520: TransactionController.MODE_RECORD,
1521: TransactionController.ISOLATION_SERIALIZABLE,
1522: validColumns, // only get the second column
1523: null, // start position - first row in conglomerate
1524: 0, // unused if start position is null.
1525: null, // qualifier - accept all rows
1526: null, // stop position - last row in conglomerate
1527: 0); // unused if stop position is null.
1528:
1529: if (scan.isTableLocked()) {
1530: throw T_Fail
1531: .testFailMsg("(scanInfo) table should be row locked.");
1532: }
1533:
1534: scan_info = scan.getScanInfo();
1535: prop = scan_info.getAllScanInfo(null);
1536: REPORT(("return from partial scan heap.getScanInfo() = " + prop));
1537:
1538: // RESOLVE - should test the btree one also.
1539:
1540: REPORT("(scanInfo) finishing");
1541:
1542: return true;
1543: }
1544:
1545: /**
1546: * Test partial scans.
1547: * <p>
1548: *
1549: * @return true if the test succeeded.
1550: *
1551: * @param tc The transaction controller to use in the test.
1552: *
1553: * @exception StandardException Standard exception policy.
1554: * @exception T_Fail Unexpected behaviour from the API
1555: **/
1556: protected boolean partialScan(TransactionController tc)
1557: throws StandardException, T_Fail {
1558: int key_value;
1559:
1560: REPORT("(partialScan) starting");
1561:
1562: // Create a heap conglomerate.
1563: T_AccessRow template_row = new T_AccessRow(2);
1564: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1565: template_row.getRowArray(), // 1 column template.
1566: null, // column sort order not required for heap
1567: null, // default properties
1568: TransactionController.IS_DEFAULT); // not temporary
1569: // Open the conglomerate.
1570: ConglomerateController cc = tc.openConglomerate(conglomid,
1571: false, TransactionController.OPENMODE_FORUPDATE,
1572: TransactionController.MODE_RECORD,
1573: TransactionController.ISOLATION_SERIALIZABLE);
1574:
1575: // Create a 1 column row. int column = 1.
1576: T_AccessRow r1 = new T_AccessRow(2);
1577: SQLInteger c1 = new SQLInteger(1);
1578: SQLInteger c2 = new SQLInteger(100);
1579: r1.setCol(0, c1);
1580: r1.setCol(1, c2);
1581:
1582: // Get a location template
1583: RowLocation rowloc1 = cc.newRowLocationTemplate();
1584:
1585: // Insert the row and remember its location.
1586: cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1587:
1588: // create another 2 column row. int column = 2.
1589: // Get a location template
1590: r1.setCol(0, new SQLInteger(2));
1591: r1.setCol(1, new SQLInteger(200));
1592: RowLocation rowloc2 = cc.newRowLocationTemplate();
1593:
1594: // Insert the row and remember its location.
1595: cc.insertAndFetchLocation(r1.getRowArray(), rowloc2);
1596:
1597: cc.delete(rowloc2);
1598:
1599: tc.commit();
1600:
1601: // Try a partial Row scan with no columns.
1602:
1603: // only get the 2nd column.
1604: FormatableBitSet validColumns = new FormatableBitSet();
1605:
1606: ScanController scan = tc.openScan(
1607: conglomid,
1608: false, // don't hold
1609: TransactionController.OPENMODE_FORUPDATE, // for update
1610: TransactionController.MODE_RECORD,
1611: TransactionController.ISOLATION_SERIALIZABLE,
1612: validColumns, // only get the second column
1613: null, // start position - first row in conglomerate
1614: 0, // unused if start position is null.
1615: null, // qualifier - accept all rows
1616: null, // stop position - last row in conglomerate
1617: 0); // unused if stop position is null.
1618:
1619: // should see one row.
1620:
1621: if (!scan.next()) {
1622: throw T_Fail
1623: .testFailMsg("(partialScan) did not see first row.");
1624: }
1625:
1626: if (scan.next()) {
1627: throw T_Fail
1628: .testFailMsg("(partialScan) saw more than one row.");
1629: }
1630:
1631: // RESOLVE - should test the btree one also.
1632:
1633: REPORT("(partialScan) finishing");
1634:
1635: return true;
1636: }
1637:
1638: // Simple insert into heap performance test
1639: protected boolean insert_bench(TransactionController tc)
1640: throws StandardException, T_Fail {
1641: ConglomerateController cc = null;
1642: ScanController scan = null;
1643: long conglomid = -1;
1644: long before, after;
1645:
1646: // Create a row.
1647: T_AccessRow r1 = new T_AccessRow(1);
1648: long iter = 100;
1649:
1650: for (int numcols = 1; numcols < 101; numcols *= 10) {
1651: // Create a heap conglomerate.
1652: conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1653: new T_AccessRow(numcols).getRowArray(), // 1 SQLInteger() column template.
1654: null, // column sort order not required for heap
1655: null, // default properties
1656: TransactionController.IS_DEFAULT); // not temporary
1657:
1658: tc.commit();
1659:
1660: // Open the conglomerate.
1661: cc = tc.openConglomerate(conglomid, false,
1662: TransactionController.OPENMODE_FORUPDATE,
1663: TransactionController.MODE_RECORD,
1664: TransactionController.ISOLATION_SERIALIZABLE);
1665:
1666: for (int i = 0; i < numcols; i++) {
1667: r1.setCol(i, new SQLInteger(numcols));
1668: }
1669:
1670: // time before
1671: before = System.currentTimeMillis();
1672:
1673: for (int i = 0; i < iter; i++) {
1674: if (cc.insert(r1.getRowArray()) != 0)
1675: throw T_Fail
1676: .testFailMsg("(insert_bench) insert failed ");
1677: }
1678:
1679: // time after
1680: after = System.currentTimeMillis();
1681:
1682: REPORT("insert " + iter + " rows of " + numcols
1683: + " integer cols = " + (after - before)
1684: + " milliseconds.\n");
1685:
1686: // time before
1687: before = System.currentTimeMillis();
1688:
1689: for (int i = 0; i < iter; i++) {
1690: if (cc.insert(r1.getRowArray()) != 0)
1691: throw T_Fail
1692: .testFailMsg("(insert_bench) insert failed ");
1693: }
1694:
1695: // time after
1696: after = System.currentTimeMillis();
1697:
1698: REPORT("second insert " + iter + " rows of " + numcols
1699: + " integer cols = " + (after - before)
1700: + " milliseconds.\n");
1701:
1702: // Open a scan on the conglomerate.
1703: before = System.currentTimeMillis();
1704:
1705: scan = tc.openScan(
1706: conglomid,
1707: false, // don't hold
1708: 0, // not for update
1709: TransactionController.MODE_RECORD,
1710: TransactionController.ISOLATION_SERIALIZABLE,
1711: (FormatableBitSet) null, // all columns, all as objects
1712: null, // start position - first row in conglomerate
1713: 0, // unused if start position is null.
1714: null, // qualifier - accept all rows
1715: null, // stop position - last row in conglomerate
1716: 0); // unused if stop position is null.
1717:
1718: // time before
1719: before = System.currentTimeMillis();
1720:
1721: // Iterate through and check that the rows are still there.
1722: while (scan.next()) {
1723: scan.fetch(r1.getRowArray());
1724: }
1725:
1726: // time after
1727: after = System.currentTimeMillis();
1728:
1729: REPORT("scan " + (2 * iter) + " rows of " + numcols
1730: + " integer cols = " + (after - before)
1731: + " milliseconds.\n");
1732:
1733: // Close the conglomerate.
1734: cc.close();
1735: tc.commit();
1736: }
1737:
1738: return (true);
1739: }
1740:
1741: /**
1742: * Test the access level SortCost interface.
1743: * <p>
1744: *
1745: * @return true if the test succeeded.
1746: *
1747: * @param tc The transaction controller to use in the test.
1748: *
1749: * @exception StandardException Standard exception policy.
1750: * @exception T_Fail Unexpected behaviour from the API
1751: **/
1752: protected boolean sortCost(TransactionController tc)
1753: throws StandardException, T_Fail {
1754: int key_value;
1755:
1756: REPORT("(sortCost) starting");
1757:
1758: // Create a heap conglomerate.
1759: T_AccessRow template_row = new T_AccessRow(2);
1760: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1761: template_row.getRowArray(), // 1 column template.
1762: null, // column sort order not required for heap
1763: null, // default properties
1764: TransactionController.IS_DEFAULT); // not temporary
1765: // Open the conglomerate.
1766: ConglomerateController cc = tc.openConglomerate(conglomid,
1767: false, TransactionController.OPENMODE_FORUPDATE,
1768: TransactionController.MODE_RECORD,
1769: TransactionController.ISOLATION_SERIALIZABLE);
1770:
1771: // Create a 2 column row.
1772: T_AccessRow r1 = new T_AccessRow(2);
1773: SQLInteger c1 = new SQLInteger(1);
1774: SQLInteger c2 = new SQLInteger(100);
1775: r1.setCol(0, c1);
1776: r1.setCol(1, c2);
1777:
1778: // Get a location template
1779: RowLocation rowloc1 = cc.newRowLocationTemplate();
1780:
1781: // Insert the row and remember its location.
1782: cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1783:
1784: cc.close();
1785:
1786: tc.commit();
1787:
1788: // flush the cache to get the row count updated.
1789: flush_cache();
1790:
1791: // Test 1 - Just call for various types of sorts. Not sure how
1792: // to test the validity.
1793: SortCostController scc = tc.openSortCostController(null);
1794:
1795: double estimated_cost = scc.getSortCost(template_row
1796: .getRowArray(), null, false, 10000, 100, 100);
1797:
1798: if (estimated_cost <= 0) {
1799: throw T_Fail
1800: .testFailMsg("(storeCost) estimated sort cost :"
1801: + estimated_cost);
1802: }
1803:
1804: REPORT("(sortCost) finishing");
1805:
1806: return true;
1807: }
1808:
1809: /**
1810: * Test the access level StoreCost interface.
1811: * <p>
1812: *
1813: * @return true if the test succeeded.
1814: *
1815: * @param tc The transaction controller to use in the test.
1816: *
1817: * @exception StandardException Standard exception policy.
1818: * @exception T_Fail Unexpected behaviour from the API
1819: **/
1820: protected boolean storeCost(TransactionController tc)
1821: throws StandardException, T_Fail {
1822: int key_value;
1823:
1824: REPORT("(storeCost) starting");
1825:
1826: // Create a heap conglomerate.
1827: T_AccessRow template_row = new T_AccessRow(2);
1828: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
1829: template_row.getRowArray(), // 1 column template.
1830: null, // column sort order not required for heap
1831: null, // default properties
1832: TransactionController.IS_DEFAULT); // not temporary
1833: // Open the conglomerate.
1834: ConglomerateController cc = tc.openConglomerate(conglomid,
1835: false, TransactionController.OPENMODE_FORUPDATE,
1836: TransactionController.MODE_RECORD,
1837: TransactionController.ISOLATION_SERIALIZABLE);
1838:
1839: // Create a 2 column row.
1840: T_AccessRow r1 = new T_AccessRow(2);
1841: SQLInteger c1 = new SQLInteger(1);
1842: SQLInteger c2 = new SQLInteger(100);
1843: r1.setCol(0, c1);
1844: r1.setCol(1, c2);
1845:
1846: // Get a location template
1847: RowLocation rowloc1 = cc.newRowLocationTemplate();
1848:
1849: // Insert the row and remember its location.
1850: cc.insertAndFetchLocation(r1.getRowArray(), rowloc1);
1851:
1852: cc.close();
1853:
1854: tc.commit();
1855:
1856: // flush the cache to get the row count updated.
1857: flush_cache();
1858:
1859: // Test 1 - ASSERT(initial row count after 1 insert should be 1)
1860: StoreCostController scc = tc.openStoreCost(conglomid);
1861:
1862: if (scc.getEstimatedRowCount() != 1) {
1863: throw T_Fail
1864: .testFailMsg("(storeCost) estimated row count not 1:"
1865: + scc.getEstimatedRowCount());
1866: }
1867:
1868: // Test 2 - ASSERT(should be able to set arbitrary row count)
1869:
1870: scc.setEstimatedRowCount(5);
1871:
1872: if (scc.getEstimatedRowCount() != 5) {
1873: throw T_Fail
1874: .testFailMsg("(storeCost) estimated row count not 5");
1875: }
1876:
1877: scc.setEstimatedRowCount(1);
1878:
1879: // Test 3 - ASSERT(should implement getFetchFromRowLocationCost())
1880: // should figure out some way to determine reasonable number is
1881: // returned.
1882: double fetch_cost = scc.getFetchFromRowLocationCost(
1883: (FormatableBitSet) null, 0);
1884: fetch_cost = scc.getFetchFromRowLocationCost(
1885: (FormatableBitSet) new FormatableBitSet(0), 0);
1886: REPORT("fetch cost (full row) of row loc = " + fetch_cost);
1887: fetch_cost = scc.getFetchFromRowLocationCost(
1888: (FormatableBitSet) new FormatableBitSet(1), 0);
1889: FormatableBitSet bit_set = new FormatableBitSet(2);
1890: REPORT("fetch cost (no cols) of row loc = " + fetch_cost);
1891: bit_set.set(1);
1892: fetch_cost = scc.getFetchFromRowLocationCost(
1893: (FormatableBitSet) new FormatableBitSet(1), 0);
1894: REPORT("fetch cost (1 col) of row loc = " + fetch_cost);
1895:
1896: // Test 4 - ASSERT(should implement getFetchFromFullKeyCost())
1897: // should figure out some way to determine reasonable number is
1898: // returned.
1899: /* - RESOLVE HEAP does not implement this.
1900: fetch_cost =
1901: scc.getFetchFromFullKeyCost((FormatableBitSet) null, (int[]) null, 0);
1902: REPORT("fetch full key cost (full row) of row loc = " + fetch_cost);
1903:
1904: fetch_cost =
1905: scc.getFetchFromFullKeyCost(
1906: (FormatableBitSet) new FormatableBitSet(0), (int[]) null, 0);
1907: REPORT("fetch full key cost (no cols) of row loc = " + fetch_cost);
1908:
1909: fetch_cost =
1910: scc.getFetchFromFullKeyCost(
1911: (FormatableBitSet) new FormatableBitSet(1), (int[]) null, 0);
1912: REPORT("fetch full key cost (no cols) of row loc = " + fetch_cost);
1913:
1914: bit_set = new FormatableBitSet(2);
1915: bit_set.set(1);
1916: fetch_cost =
1917: scc.getFetchFromFullKeyCost(
1918: (FormatableBitSet) new FormatableBitSet(1), (int[]) null, 0);
1919: REPORT("fetch full key cost (1 col) of row loc = " + fetch_cost);
1920: */
1921:
1922: // Test 5 - ASSERT(should implement getScanCost())
1923: // should figure out some way to determine reasonable number is
1924: // returned.
1925: StoreCostResult cost_result = new T_StoreCostResult();
1926:
1927: scc.getScanCost(StoreCostController.STORECOST_SCAN_NORMAL, -1, // row count
1928: 1, // number of rows fetched at a time from access.
1929: false, // forUpdate
1930: (FormatableBitSet) null, // validColumns
1931: new T_AccessRow(2).getRowArray(), // template
1932: null, // start position - first row in conglomerate
1933: 0, // unused if start position is null.
1934: null, // stop position - last row in conglomerate
1935: 0, // unused if stop position is null.
1936: false, // reopen_scan?
1937: 0, // access_type
1938: cost_result); // cost result.
1939:
1940: REPORT("fetch scan cost (full row) of row loc = " + cost_result);
1941:
1942: scc.getScanCost(StoreCostController.STORECOST_SCAN_NORMAL, -1, // row count
1943: 1, // number of rows fetched at a time from access.
1944: false, // forUpdate
1945: new FormatableBitSet(0), // validColumns
1946: new T_AccessRow(2).getRowArray(), // template
1947: null, // start position - first row in conglomerate
1948: 0, // unused if start position is null.
1949: null, // stop position - last row in conglomerate
1950: 0, // unused if stop position is null.
1951: false, // reopen_scan?
1952: 0, // access_type
1953: cost_result); // cost result.
1954:
1955: REPORT("fetch scan cost (no cols) of row loc = " + cost_result);
1956:
1957: scc.getScanCost(StoreCostController.STORECOST_SCAN_NORMAL, -1, // row count
1958: 1, // number of rows fetched at a time from access.
1959: false, // forUpdate
1960: new FormatableBitSet(1), // validColumns
1961: new T_AccessRow(2).getRowArray(), // template
1962: null, // start position - first row in conglomerate
1963: 0, // unused if start position is null.
1964: null, // stop position - last row in conglomerate
1965: 0, // unused if stop position is null.
1966: false, // reopen_scan?
1967: 0, // access_type
1968: cost_result); // cost result.
1969:
1970: REPORT("fetch scan cost (no cols) of row loc = " + cost_result);
1971:
1972: bit_set = new FormatableBitSet(2);
1973: bit_set.set(1);
1974: scc.getScanCost(StoreCostController.STORECOST_SCAN_NORMAL, -1, // row count
1975: 1, // number of rows fetched at a time from access.
1976: false, // forUpdate
1977: bit_set, // validColumns
1978: new T_AccessRow(2).getRowArray(), // template
1979: null, // start position - first row in conglomerate
1980: 0, // unused if start position is null.
1981: null, // stop position - last row in conglomerate
1982: 0, // unused if stop position is null.
1983: false, // reopen_scan?
1984: 0, // access_type
1985: cost_result); // cost result.
1986:
1987: REPORT("fetch scan cost (1 cols) of row loc = " + cost_result);
1988:
1989: // make sure you can get a row location.
1990: rowloc1 = scc.newRowLocationTemplate();
1991:
1992: REPORT("(storeCost) finishing");
1993:
1994: return true;
1995: }
1996:
1997: /**
1998: Test transactional properties
1999:
2000: @exception StandardException test failure
2001: @exception T_Fail test failure
2002: */
2003: protected boolean transactionalProperties(TransactionController tc)
2004: throws StandardException, T_Fail {
2005: REPORT("start transactionalProperties");
2006:
2007: // put a couple of properties in with different values and types
2008:
2009: tc.setProperty("T_Key_Frog", new SQLLongint(479), false);
2010: tc.setProperty("T_Key_Tiger", "Roar, ROAR", false);
2011:
2012: long lvalue = ((SQLLongint) (tc.getProperty("T_Key_Frog")))
2013: .getLong();
2014: if (lvalue != 479)
2015: throw T_Fail
2016: .testFailMsg("setProperty() - expected 479 - got "
2017: + lvalue);
2018:
2019: String svalue = (String) tc.getProperty("T_Key_Tiger");
2020: if (!svalue.equals("Roar, ROAR"))
2021: throw T_Fail
2022: .testFailMsg("setProperty() - expected 'Roar, ROAR' - got "
2023: + svalue);
2024:
2025: tc.commit();
2026:
2027: // should still be accessable after the commit
2028: lvalue = ((SQLLongint) (tc.getProperty("T_Key_Frog")))
2029: .getLong();
2030: if (lvalue != 479)
2031: throw T_Fail
2032: .testFailMsg("setProperty() - expected 479 - got "
2033: + lvalue);
2034:
2035: svalue = (String) tc.getProperty("T_Key_Tiger");
2036: if (!svalue.equals("Roar, ROAR"))
2037: throw T_Fail
2038: .testFailMsg("setProperty() - expected 'Roar, ROAR' - got "
2039: + svalue);
2040:
2041: tc.commit();
2042:
2043: // see if update works
2044: tc.setProperty("T_Key_Tiger", "mieow, mieow", false);
2045: svalue = (String) tc.getProperty("T_Key_Tiger");
2046: if (!svalue.equals("mieow, mieow"))
2047: throw T_Fail
2048: .testFailMsg("setProperty() - expected 'mieow, mieow' - got "
2049: + svalue);
2050:
2051: tc.commit();
2052: svalue = (String) tc.getProperty("T_Key_Tiger");
2053: if (!svalue.equals("mieow, mieow"))
2054: throw T_Fail
2055: .testFailMsg("setProperty() - expected 'mieow, mieow' - got "
2056: + svalue);
2057:
2058: // see if an update to a different type works
2059: tc.setProperty("T_Key_Tiger", new SQLLongint(570), false);
2060: lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger")))
2061: .getLong();
2062:
2063: if (lvalue != 570)
2064: throw T_Fail
2065: .testFailMsg("setProperty() - expected 570 - got "
2066: + lvalue);
2067:
2068: tc.commit();
2069:
2070: lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger")))
2071: .getLong();
2072: if (lvalue != 570)
2073: throw T_Fail
2074: .testFailMsg("setProperty() - expected 570 - got "
2075: + lvalue);
2076:
2077: tc.commit();
2078:
2079: // delete a key
2080: tc.setProperty("T_Key_Frog", (Serializable) null, false);
2081: if (tc.getProperty("T_Key_Frog") != null)
2082: throw T_Fail.testFailMsg("setProperty() - delete failed");
2083: tc.commit();
2084:
2085: if (tc.getProperty("T_Key_Frog") != null)
2086: throw T_Fail.testFailMsg("setProperty() - delete failed");
2087:
2088: tc.commit();
2089:
2090: // now see if rollback works.
2091: tc.setProperty("T_Key_Tiger", new SQLLongint(457), false);
2092:
2093: tc.abort();
2094: lvalue = ((SQLLongint) (tc.getProperty("T_Key_Tiger")))
2095: .getLong();
2096: if (lvalue != 570)
2097: throw T_Fail
2098: .testFailMsg("setProperty() - expected 570 - got "
2099: + lvalue);
2100:
2101: tc.commit();
2102: PASS("transactionalProperties");
2103:
2104: return true;
2105: }
2106:
2107: // Test temporary conglomerates.
2108: protected boolean tempTest(TransactionController tc)
2109: throws StandardException, T_Fail {
2110: REPORT("(tempTest) starting");
2111:
2112: // Create some conglomerates, some temporary, some not.
2113: long cid5252t = createAConglom(tc, 5252, true); // temporary
2114: long cid87t = createAConglom(tc, 87, true); // temporary
2115: long cid999p = createAConglom(tc, 999, false); // permanent
2116: long cid3t = createAConglom(tc, 3, true); // temporary
2117:
2118: // Create an index on two of them
2119: long cid5252ti = createBtree(tc, cid5252t, true);
2120: long cid999pi = createBtree(tc, cid999p, false);
2121:
2122: int r;
2123:
2124: // Make sure we can read them.
2125: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2126: cid5252t, 5252)) != 1) {
2127: throw T_Fail
2128: .testFailMsg("(tempTest) after create checkAConglom(cid5252t) == "
2129: + r);
2130: }
2131: if ((r = checkAConglom(tc, getBtreeTemplate(tc, cid5252t),
2132: cid5252ti, 5252)) != 1) {
2133: throw T_Fail
2134: .testFailMsg("(tempTest) after create checkAConglom(cid5252ti) == "
2135: + r);
2136: }
2137:
2138: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2139: cid999p, 999)) != 1) {
2140: throw T_Fail
2141: .testFailMsg("(tempTest) after create checkAConglom(cid999p) == "
2142: + r);
2143: }
2144:
2145: if ((r = checkAConglom(tc, getBtreeTemplate(tc, cid999p),
2146: cid999pi, 999)) != 1) {
2147: throw T_Fail
2148: .testFailMsg("(tempTest) after create checkAConglom(cid999pi) == "
2149: + r);
2150: }
2151:
2152: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t,
2153: 3)) != 1) {
2154: throw T_Fail
2155: .testFailMsg("(tempTest) after create checkAConglom(cid3t) == "
2156: + r);
2157: }
2158:
2159: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2160: cid87t, 87)) != 1) {
2161: throw T_Fail
2162: .testFailMsg("(tempTest) after create checkAConglom(cid87t) == "
2163: + r);
2164: }
2165:
2166: // Drop two of them.
2167: tc.dropConglomerate(cid999pi);
2168: tc.dropConglomerate(cid999p);
2169: tc.dropConglomerate(cid87t);
2170:
2171: // Try dropping the ones we already dropped - expect exceptions
2172: try {
2173: tc.dropConglomerate(cid999p);
2174: throw T_Fail
2175: .testFailMsg("(tempTest) drop of dropped cid999p succeeded");
2176: } catch (StandardException e) {
2177: // normal path through the test, ignore the expected error
2178: }
2179: try {
2180: tc.dropConglomerate(cid999pi);
2181: throw T_Fail
2182: .testFailMsg("(tempTest) drop of dropped cid999pi succeeded");
2183: } catch (StandardException e) {
2184: // normal path through the test, ignore the expected error
2185: }
2186: try {
2187: tc.dropConglomerate(cid87t);
2188: throw T_Fail
2189: .testFailMsg("(tempTest) drop of dropped cid87t succeeded");
2190: } catch (StandardException e) {
2191: // normal path through the test, ignore the expected error
2192: }
2193:
2194: // Make sure the correct ones remain
2195: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2196: cid5252t, 5252)) != 1) {
2197: throw T_Fail
2198: .testFailMsg("(tempTest) after drop checkAConglom(cid5252t) == "
2199: + r);
2200: }
2201:
2202: if ((r = checkAConglom(tc, getBtreeTemplate(tc, cid5252t),
2203: cid5252ti, 5252)) != 1) {
2204: throw T_Fail
2205: .testFailMsg("(tempTest) after drop checkAConglom(cid5252ti) == "
2206: + r);
2207: }
2208:
2209: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t,
2210: 3)) != 1) {
2211: throw T_Fail
2212: .testFailMsg("(tempTest) after drop checkAConglom(cid3t) == "
2213: + r);
2214: }
2215:
2216: // Make sure commitNoSync gets executed sometimes.
2217: tc.commitNoSync(TransactionController.RELEASE_LOCKS);
2218:
2219: // After committing the transaction, the congloms
2220: // should still be there (with their rows).
2221: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2222: cid5252t, 5252)) != 1) {
2223: throw T_Fail
2224: .testFailMsg("(tempTest) after commit checkAConglom(cid5252t) == "
2225: + r);
2226: }
2227:
2228: if ((r = checkAConglom(tc, getBtreeTemplate(tc, cid5252t),
2229: cid5252ti, 5252)) != 1) {
2230: throw T_Fail
2231: .testFailMsg("(tempTest) after commit checkAConglom(cid5252ti) == "
2232: + r);
2233: }
2234:
2235: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t,
2236: 3)) != 1) {
2237: throw T_Fail
2238: .testFailMsg("(tempTest) after commit checkAConglom(cid3t) == "
2239: + r);
2240: }
2241:
2242: // open cid3t for update to force its truncation on the abort.
2243: ScanController sc = tc.openScan(
2244: cid3t,
2245: false, // don't hold
2246: TransactionController.OPENMODE_FORUPDATE, // for update
2247: TransactionController.MODE_RECORD,
2248: TransactionController.ISOLATION_SERIALIZABLE,
2249: (FormatableBitSet) null, // all columns, all as objects
2250: null, // start position - first row in conglomerate
2251: 0, // unused if start position is null.
2252: null, // qualifier - accept all rows
2253: null, // stop position - last row in conglomerate
2254: 0); // unused if stop position is null.
2255:
2256: sc.close();
2257:
2258: tc.abort();
2259:
2260: // After an abort, the congloms that were opened for update should be there,
2261: // but truncated
2262: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null,
2263: cid5252t, 5252)) != 1) {
2264: throw T_Fail
2265: .testFailMsg("(tempTest) after abort checkAConglom(cid5252t) == "
2266: + r);
2267: }
2268:
2269: // RESOLVE(mikem): track 1825
2270: // don't want to open temp cantainer with IS_KEPT always.
2271: // if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t, 3)) != 0) {
2272: // throw T_Fail.testFailMsg("(tempTest) after abort checkAConglom(cid3t) == " + r);
2273: // }
2274:
2275: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid3t,
2276: 3)) != 1) {
2277: throw T_Fail
2278: .testFailMsg("(tempTest) after abort checkAConglom(cid3t) == "
2279: + r);
2280: }
2281:
2282: // Due to bug STO84, temp btrees are corrupted after aborts,
2283: // so the following will cause problems:
2284: /*
2285: if ((r = checkAConglom(tc, (DataValueDescriptor[]) null, cid5252ti, 5252)) != 0)
2286: throw T_Fail.testFailMsg("(tempTest) after abort checkAConglom(cid5252ti) == " + r);
2287: */
2288:
2289: // Drop index on conglomerate to make sure we can do a drop after truncate.
2290: tc.dropConglomerate(cid5252ti);
2291: if (tc.conglomerateExists(cid5252ti))
2292: throw T_Fail
2293: .testFailMsg("(tempTest) after drop cid5252ti still exists");
2294:
2295: // Drop one conglomerate to make sure we can do a drop after truncate.
2296: tc.dropConglomerate(cid5252t);
2297: if (tc.conglomerateExists(cid5252t))
2298: throw T_Fail
2299: .testFailMsg("(tempTest) after drop cid5252t still exists");
2300:
2301: // Leave the last one - raw store is supposed to delete
2302: // it when the system reboots
2303:
2304: // Success!
2305: REPORT("(tempTest) succeeded");
2306: return true;
2307: }
2308:
2309: private long createAConglom(TransactionController tc,
2310: int testValue, boolean temporary) throws StandardException {
2311: // Create a heap conglomerate.
2312: long cid = tc.createConglomerate("heap", // create a heap conglomerate
2313: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2314: null, // column sort order not required for heap
2315: null, // default properties
2316: temporary ? TransactionController.IS_TEMPORARY
2317: : TransactionController.IS_DEFAULT);
2318:
2319: ConglomerateController cc = tc.openConglomerate(cid, false,
2320: TransactionController.OPENMODE_FORUPDATE,
2321: TransactionController.MODE_RECORD,
2322: TransactionController.ISOLATION_SERIALIZABLE);
2323:
2324: // Create a row.
2325: T_AccessRow row = new T_AccessRow(1);
2326: SQLLongint col = new SQLLongint(testValue);
2327: row.setCol(0, col);
2328:
2329: // Stuff in the test value so we can recognize this conglom later.
2330: cc.insert(row.getRowArray());
2331:
2332: cc.close();
2333:
2334: return cid;
2335: }
2336:
2337: private DataValueDescriptor[] getBtreeTemplate(
2338: TransactionController tc, long baseConglomId)
2339: throws StandardException {
2340: // Open a scan on the base conglomerate which will return all rows.
2341: FormatableBitSet singleColumn = new FormatableBitSet(1);
2342: singleColumn.set(0);
2343: ScanController sc = tc.openScan(baseConglomId,
2344: false,
2345: 0, // not for update
2346: TransactionController.MODE_RECORD,
2347: TransactionController.ISOLATION_SERIALIZABLE,
2348: singleColumn, // all columns, all as objects
2349: null, 0, null, null, 0);
2350:
2351: // Create the template for the index. This method "knows" that
2352: // all rows in the base table have one IntCol
2353: T_AccessRow template = new T_AccessRow(2);
2354: SQLLongint col0 = new SQLLongint(0);
2355: RowLocation col1 = sc.newRowLocationTemplate();
2356: template.setCol(0, col0);
2357: template.setCol(1, col1);
2358:
2359: sc.close();
2360:
2361: return (template.getRowArray());
2362: }
2363:
2364: private long createBtree(TransactionController tc,
2365: long baseConglomId, boolean temporary)
2366: throws StandardException {
2367: // Create the properties for the index.
2368: // This method knows that there is just one column in the base table
2369: Properties indexProps = new Properties();
2370: indexProps.put("baseConglomerateId", Long
2371: .toString(baseConglomId));
2372: indexProps.put("nUniqueColumns", "1");
2373: indexProps.put("rowLocationColumn", "1");
2374: indexProps.put("nKeyFields", "2");
2375:
2376: // Open a scan on the base conglomerate which will return all rows.
2377: FormatableBitSet singleColumn = new FormatableBitSet(1);
2378: singleColumn.set(0);
2379: ScanController sc = tc.openScan(baseConglomId,
2380: false,
2381: 0, // not for update
2382: TransactionController.MODE_RECORD,
2383: TransactionController.ISOLATION_SERIALIZABLE,
2384: singleColumn, // just the first column.
2385: null, 0, null, null, 0);
2386:
2387: // Create the template for the index. This method "knows" that
2388: // all rows in the base table have one IntCol
2389: T_AccessRow template = new T_AccessRow(2);
2390: SQLLongint col0 = new SQLLongint(0);
2391: RowLocation col1 = sc.newRowLocationTemplate();
2392: template.setCol(0, col0);
2393: template.setCol(1, col1);
2394:
2395: DataValueDescriptor[] baseRow = new DataValueDescriptor[1];
2396: baseRow[0] = col0;
2397:
2398: // Create a btree secondary index conglomerate.
2399: long iid = tc.createConglomerate("BTREE", template
2400: .getRowArray(), null, indexProps,
2401: temporary ? TransactionController.IS_TEMPORARY
2402: : TransactionController.IS_DEFAULT);
2403:
2404: // Open the index so we can stuff in index rows.
2405: ConglomerateController cc = tc.openConglomerate(iid, false,
2406: TransactionController.OPENMODE_FORUPDATE,
2407: TransactionController.MODE_RECORD,
2408: TransactionController.ISOLATION_SERIALIZABLE);
2409:
2410: // build the index.
2411: while (sc.next()) {
2412: sc.fetch(baseRow);
2413: sc.fetchLocation(col1);
2414: cc.insert(template.getRowArray());
2415: }
2416:
2417: cc.close();
2418:
2419: return iid;
2420: }
2421:
2422: /**
2423: Open a scan on the conglomerate for the given conglom id, and verify
2424: that it has rows with the given test value. This is a way of
2425: verifying that we got the right conglomerate. Returns the number of
2426: rows that it checked (-1 if the conglomerate doesn't exist).
2427: **/
2428: private int checkAConglom(TransactionController tc,
2429: DataValueDescriptor[] scratch_template, long conglomId,
2430: int testValue) throws StandardException {
2431: if (!tc.conglomerateExists(conglomId))
2432: return -1;
2433:
2434: ScanController sc = tc.openScan(
2435: conglomId,
2436: false, // don't hold
2437: 0, // not for update
2438: TransactionController.MODE_RECORD,
2439: TransactionController.ISOLATION_SERIALIZABLE,
2440: (FormatableBitSet) null, // all columns, all as objects
2441: null, // start position - first row in conglomerate
2442: 0, // unused if start position is null.
2443: null, // qualifier - accept all rows
2444: null, // stop position - last row in conglomerate
2445: 0); // unused if stop position is null.
2446:
2447: // An empty row
2448: T_AccessRow row = new T_AccessRow(1);
2449: SQLLongint col = new SQLLongint(0);
2450: row.setCol(0, col);
2451:
2452: // Iterate through and check that the rows are still there.
2453: // Note this part of the test will inten
2454: int nrows = 0;
2455: while (sc.next()) {
2456: sc.fetch(row.getRowArray());
2457: if (((SQLLongint) row.getCol(0)).getLong() != testValue)
2458: return -2;
2459: nrows++;
2460: }
2461:
2462: sc.close();
2463:
2464: return nrows;
2465: }
2466:
2467: protected boolean updatelocks(TransactionController tc)
2468: throws StandardException, T_Fail {
2469: REPORT("(updatelocks starting.)");
2470:
2471: updatelocks_0(tc, TransactionController.ISOLATION_SERIALIZABLE);
2472: updatelocks_0(tc,
2473: TransactionController.ISOLATION_READ_COMMITTED);
2474:
2475: REPORT("(updatelocks ending.)");
2476:
2477: return (true);
2478: }
2479:
2480: protected boolean updatelocks_0(TransactionController tc,
2481: int isolation_level) throws StandardException, T_Fail {
2482: // Create a 2 column row.
2483: T_AccessRow r1 = new T_AccessRow(2);
2484: SQLInteger c1 = new SQLInteger(1);
2485: SQLInteger c2 = new SQLInteger(100);
2486: r1.setCol(0, c1);
2487: r1.setCol(1, c2);
2488:
2489: // Create a heap conglomerate.
2490: long orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2491: r1.getRowArray(), null, // column sort order not required for heap
2492: null, // default properties
2493: TransactionController.IS_DEFAULT); // not temporary
2494:
2495: // add rows 1 and 2
2496: ConglomerateController cc = tc.openConglomerate(orig_conglomid,
2497: false, TransactionController.OPENMODE_FORUPDATE,
2498: TransactionController.MODE_RECORD,
2499: TransactionController.ISOLATION_SERIALIZABLE);
2500:
2501: // insert (1, 100)
2502: r1.setCol(0, new SQLInteger(1));
2503: r1.setCol(1, new SQLInteger(100));
2504: cc.insert(r1.getRowArray());
2505:
2506: // insert (2, 200)
2507: r1.setCol(0, new SQLInteger(2));
2508: r1.setCol(1, new SQLInteger(200));
2509: cc.insert(r1.getRowArray());
2510:
2511: // insert (3, 300)
2512: r1.setCol(0, new SQLInteger(3));
2513: r1.setCol(1, new SQLInteger(300));
2514: cc.insert(r1.getRowArray());
2515:
2516: cc.close();
2517:
2518: tc.commit();
2519:
2520: REPORT("(updatelocks ending.)");
2521:
2522: ScanController sc = tc
2523: .openScan(
2524: orig_conglomid,
2525: false, // don't hold
2526: (TransactionController.OPENMODE_FORUPDATE | TransactionController.OPENMODE_USE_UPDATE_LOCKS),
2527: TransactionController.MODE_RECORD,
2528: TransactionController.ISOLATION_SERIALIZABLE,
2529: (FormatableBitSet) null, // all columns, all as objects
2530: null, // start position - first row in conglomerate
2531: 0, // unused if start position is null.
2532: null, // qualifier - accept all rows
2533: null, // stop position - last row in conglomerate
2534: 0); // unused if stop position is null.
2535:
2536: int key_value;
2537:
2538: boolean found_row_2 = false;
2539:
2540: while (sc.next()) {
2541: sc.fetch(r1.getRowArray());
2542:
2543: key_value = ((SQLInteger) r1.getCol(0)).getInt();
2544:
2545: switch (key_value) {
2546: case 1: {
2547: // delete first row
2548: sc.delete();
2549: break;
2550: }
2551:
2552: case 2: {
2553: // leave second alone - no update, lock will get coverted
2554: // down.
2555: found_row_2 = true;
2556: break;
2557: }
2558:
2559: case 3: {
2560: // update the third row.
2561: T_AccessRow update_row = new T_AccessRow(2);
2562: r1.setCol(0, new SQLInteger(30));
2563: r1.setCol(1, new SQLInteger(3000));
2564: sc.replace(r1.getRowArray(), null);
2565: break;
2566: }
2567:
2568: default: {
2569: throw T_Fail
2570: .testFailMsg("(updatelock) bad row value found in table.");
2571: }
2572: }
2573:
2574: }
2575:
2576: if (!found_row_2)
2577: throw T_Fail
2578: .testFailMsg("(updatelock) did not find row in first scan.");
2579:
2580: // reposition the scan
2581: sc.reopenScan(null, // start position - first row in conglomerate
2582: 0, // unused if start position is null.
2583: null, // qualifier - accept all rows
2584: null, // stop position - last row in conglomerate
2585: 0); // unused if stop position is null.
2586:
2587: found_row_2 = false;
2588:
2589: while (sc.next()) {
2590: sc.fetch(r1.getRowArray());
2591:
2592: key_value = ((SQLInteger) r1.getCol(0)).getInt();
2593:
2594: switch (key_value) {
2595: case 2: {
2596: // leave second alone - no update, lock will get coverted
2597: // down.
2598: found_row_2 = true;
2599:
2600: break;
2601: }
2602:
2603: case 30: {
2604: // update the third row.
2605: T_AccessRow update_row = new T_AccessRow(2);
2606: r1.setCol(0, new SQLInteger(40));
2607: r1.setCol(1, new SQLInteger(4000));
2608: sc.replace(r1.getRowArray(), null);
2609: break;
2610: }
2611:
2612: default: {
2613: throw T_Fail
2614: .testFailMsg("(updatelock) bad row value found in table.");
2615: }
2616: }
2617:
2618: }
2619:
2620: if (!found_row_2)
2621: throw T_Fail
2622: .testFailMsg("(updatelock) did not find row in second scan.");
2623:
2624: sc.close();
2625:
2626: tc.commit();
2627:
2628: // try the scan after the first xact has completed.
2629:
2630: sc = tc
2631: .openScan(
2632: orig_conglomid,
2633: false, // don't hold
2634: (TransactionController.OPENMODE_FORUPDATE | TransactionController.OPENMODE_USE_UPDATE_LOCKS),
2635: TransactionController.MODE_RECORD,
2636: TransactionController.ISOLATION_SERIALIZABLE,
2637: (FormatableBitSet) null, // all columns, all as objects
2638: null, // start position - first row in conglomerate
2639: 0, // unused if start position is null.
2640: null, // qualifier - accept all rows
2641: null, // stop position - last row in conglomerate
2642: 0); // unused if stop position is null.
2643:
2644: found_row_2 = false;
2645:
2646: while (sc.next()) {
2647: sc.fetch(r1.getRowArray());
2648:
2649: key_value = ((SQLInteger) r1.getCol(0)).getInt();
2650:
2651: switch (key_value) {
2652: case 2: {
2653: // leave second alone - no update, lock will get coverted
2654: // down.
2655: found_row_2 = true;
2656: break;
2657: }
2658:
2659: case 40: {
2660: // update the third row.
2661: T_AccessRow update_row = new T_AccessRow(2);
2662: r1.setCol(0, new SQLInteger(30));
2663: r1.setCol(1, new SQLInteger(3000));
2664: sc.replace(r1.getRowArray(), null);
2665: break;
2666: }
2667:
2668: default: {
2669: throw T_Fail
2670: .testFailMsg("(updatelock) bad row value found in table.");
2671: }
2672: }
2673:
2674: }
2675:
2676: if (!found_row_2)
2677: throw T_Fail
2678: .testFailMsg("(updatelock) did not find row in first scan.");
2679:
2680: return (true);
2681: }
2682:
2683: protected boolean nestedUserTransaction(TransactionController tc)
2684: throws StandardException, T_Fail {
2685:
2686: REPORT("(nestedUserTransaction) starting");
2687:
2688: // Test of drop conglomerate with abort by doing the following:
2689: // create table
2690: // commit
2691: // drop table
2692: // make sure table is not still there.
2693: // abort
2694: // make sure table is still there.
2695:
2696: // Create a heap conglomerate.
2697: long orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2698: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2699: null, // column sort order not required for heap
2700: null, // default properties
2701: TransactionController.IS_DEFAULT); // not temporary
2702:
2703: // Create a temporary heap conglomerate.
2704: long tmp_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2705: new T_AccessRow(1).getRowArray(), // 1 SQLInteger() column template.
2706: null, // column sort order not required for heap
2707: null, // default properties
2708: TransactionController.IS_TEMPORARY);
2709:
2710: TransactionController current_xact = store
2711: .getTransaction(ContextService.getFactory()
2712: .getCurrentContextManager());
2713:
2714: // get a nested user transaction
2715: TransactionController child_tc = tc
2716: .startNestedUserTransaction(true);
2717:
2718: TransactionController current_xact_after_nest = store
2719: .getTransaction(ContextService.getFactory()
2720: .getCurrentContextManager());
2721:
2722: if (current_xact_after_nest != current_xact) {
2723: throw T_Fail
2724: .testFailMsg("(nestedUserTransaction) getTransaction() return changed after startNestedUserTransaction()."
2725: + "current_xact = "
2726: + current_xact
2727: + ";current_xact_after_nest = "
2728: + current_xact_after_nest);
2729: }
2730:
2731: if ((tc.getLockObject() != child_tc.getLockObject())
2732: || !(tc.getLockObject()
2733: .equals(child_tc.getLockObject())))
2734:
2735: {
2736: throw T_Fail
2737: .testFailMsg("(nestedUserTransaction) getLockObject should return same object from botht these calls.");
2738: }
2739:
2740: // the locks of the nested transaction should not conflict, so this
2741: // open should work.
2742: ConglomerateController cc = child_tc.openConglomerate(
2743: orig_conglomid, false,
2744: TransactionController.OPENMODE_FORUPDATE,
2745: TransactionController.MODE_RECORD,
2746: TransactionController.ISOLATION_SERIALIZABLE);
2747:
2748: // Make sure you can access the temporary conglomerate in the
2749: // nested transaction.
2750: ConglomerateController tmp_cc = child_tc.openConglomerate(
2751: tmp_conglomid, false,
2752: TransactionController.OPENMODE_FORUPDATE,
2753: TransactionController.MODE_RECORD,
2754: TransactionController.ISOLATION_SERIALIZABLE);
2755:
2756: cc.close();
2757: tmp_cc.close();
2758:
2759: child_tc.commit();
2760: child_tc.destroy();
2761:
2762: tc.dropConglomerate(orig_conglomid);
2763:
2764: // trying to double nest a nested transaction should not work.
2765: child_tc = tc.startNestedUserTransaction(true);
2766:
2767: try {
2768: child_tc.startNestedUserTransaction(true);
2769:
2770: throw T_Fail
2771: .testFailMsg("(nestedUserTransaction) double nest xact not allowed.");
2772: } catch (StandardException se) {
2773: // expected exception, fall through.
2774: }
2775:
2776: child_tc.commit();
2777: child_tc.destroy();
2778:
2779: // make sure internal and ntt's work. Just add a bunch of data to
2780: // the table causing page allocation.
2781: String twok_string = new String("0123456789012345");
2782:
2783: for (int i = 0; i < 7; i++) {
2784: twok_string += twok_string;
2785: }
2786:
2787: T_AccessRow big_row = new T_AccessRow(2);
2788:
2789: big_row.setCol(1, new SQLChar(twok_string));
2790:
2791: // Create a heap conglomerate.
2792: orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2793: big_row.getRowArray(), null, // column sort order not required for heap
2794: null, // default properties
2795: TransactionController.IS_DEFAULT); // not temporary
2796:
2797: child_tc = tc.startNestedUserTransaction(true);
2798:
2799: // add 20 pages worth of data, causing allocation
2800:
2801: // the locks of the nested transaction should not conflict, so this
2802: // open should work.
2803: cc = child_tc.openConglomerate(orig_conglomid, false,
2804: TransactionController.OPENMODE_FORUPDATE,
2805: TransactionController.MODE_RECORD,
2806: TransactionController.ISOLATION_SERIALIZABLE);
2807:
2808: child_tc.abort();
2809: child_tc.destroy();
2810:
2811: // after the abort the table should not still exist, the parent
2812: // xact should have been aborted.
2813:
2814: try {
2815: // the locks of the nested transaction should not conflict, so this
2816: // open should work.
2817: cc = tc.openConglomerate(orig_conglomid, false,
2818: TransactionController.OPENMODE_FORUPDATE,
2819: TransactionController.MODE_RECORD,
2820: TransactionController.ISOLATION_SERIALIZABLE);
2821:
2822: throw T_Fail
2823: .testFailMsg("(nestedUserTransaction) conglom should have been aborted.");
2824: } catch (StandardException se) {
2825: // expected exception, fall through.
2826: }
2827:
2828: tc.commit();
2829:
2830: // same test as above, but this time commit parent xact create to
2831: // make sure it stays around after the child abort.
2832:
2833: // Create a heap conglomerate.
2834: orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2835: big_row.getRowArray(), null, // column sort order not required for heap
2836: null, // default properties
2837: TransactionController.IS_DEFAULT); // not temporary
2838:
2839: tc.commit();
2840:
2841: child_tc = tc.startNestedUserTransaction(true);
2842:
2843: // add 20 pages worth of data, causing allocation
2844:
2845: // the locks of the nested transaction should not conflict, so this
2846: // open should work.
2847: cc = child_tc.openConglomerate(orig_conglomid, false,
2848: TransactionController.OPENMODE_FORUPDATE,
2849: TransactionController.MODE_RECORD,
2850: TransactionController.ISOLATION_SERIALIZABLE);
2851:
2852: /*
2853: for (int i = 0; i < 40; i++)
2854: {
2855: big_row.setCol(0, new SQLInteger(i));
2856: cc.insert(big_row.getRowArray());
2857: }
2858: */
2859:
2860: child_tc.abort();
2861: child_tc.destroy();
2862:
2863: // after the abort the table should not still exist, the parent
2864: // xact should have been aborted.
2865:
2866: try {
2867: // the locks of the nested transaction should not conflict, so this
2868: // open should work.
2869: cc = tc.openConglomerate(orig_conglomid, false,
2870: TransactionController.OPENMODE_FORUPDATE,
2871: TransactionController.MODE_RECORD,
2872: TransactionController.ISOLATION_SERIALIZABLE);
2873:
2874: cc.close();
2875: } catch (StandardException se) {
2876: // expected exception, fall through.
2877:
2878: throw T_Fail
2879: .testFailMsg("(nestedUserTransaction) conglom should have not be aborted.");
2880: }
2881:
2882: // start an read only nested user transaction.
2883: child_tc = tc.startNestedUserTransaction(true);
2884:
2885: ConglomerateController child_cc = child_tc.openConglomerate(
2886: orig_conglomid, false,
2887: TransactionController.OPENMODE_FORUPDATE,
2888: TransactionController.MODE_RECORD,
2889: TransactionController.ISOLATION_SERIALIZABLE);
2890:
2891: try {
2892: // should not be able to do an update in a read only transaction.
2893: big_row.setCol(0, new SQLInteger(1042));
2894: child_cc.insert(big_row.getRowArray());
2895:
2896: throw T_Fail
2897: .testFailMsg("(nestedUserTransaction) read only xact does not allow upd.");
2898:
2899: } catch (StandardException se) {
2900: // expected exception, fall through.
2901: child_tc.commit();
2902: child_tc.destroy();
2903: }
2904:
2905: tc.commit();
2906:
2907: // start an update nested user transaction.
2908: child_tc = tc.startNestedUserTransaction(false);
2909:
2910: child_cc = child_tc.openConglomerate(orig_conglomid, false,
2911: TransactionController.OPENMODE_FORUPDATE,
2912: TransactionController.MODE_RECORD,
2913: TransactionController.ISOLATION_SERIALIZABLE);
2914:
2915: try {
2916: // should be able to do an update in a read only transaction.
2917: big_row.setCol(0, new SQLInteger(1043));
2918: child_cc.insert(big_row.getRowArray());
2919:
2920: } catch (StandardException se) {
2921: throw T_Fail
2922: .testFailMsg("(nestedUserTransaction) read only xact does not allow upd.");
2923: }
2924:
2925: // expected exception, fall through.
2926: child_tc.commit();
2927: child_tc.destroy();
2928:
2929: tc.commit();
2930:
2931: cc = tc.openConglomerate(orig_conglomid, false,
2932: TransactionController.OPENMODE_FORUPDATE,
2933: TransactionController.MODE_TABLE,
2934: TransactionController.ISOLATION_SERIALIZABLE);
2935:
2936: // start an update nested user transaction.
2937: child_tc = tc.startNestedUserTransaction(false);
2938:
2939: try {
2940: // the following should time out, since locks are not compatible.
2941: child_cc = child_tc.openConglomerate(orig_conglomid, false,
2942: TransactionController.OPENMODE_FORUPDATE,
2943: TransactionController.MODE_RECORD,
2944: TransactionController.ISOLATION_SERIALIZABLE);
2945:
2946: throw T_Fail
2947: .testFailMsg("(nestedUserTransaction) lock should have timed out.");
2948: } catch (StandardException se) {
2949: // expected timeout, fall through.
2950: }
2951:
2952: // expected exception, fall through.
2953: child_tc.commit();
2954: child_tc.destroy();
2955:
2956: tc.commit();
2957:
2958: REPORT("(nestedUserTransaction) finishing");
2959:
2960: return true;
2961: }
2962:
2963: // test various flavors of commit
2964: protected boolean commitTest(TransactionController tc)
2965: throws StandardException, T_Fail {
2966: REPORT("(commitTest)");
2967:
2968: // Create a heap conglomerate.
2969: T_AccessRow template_row = new T_AccessRow(1);
2970: long conglomid = tc.createConglomerate("heap", // create a heap conglomerate
2971: template_row.getRowArray(), // 1 column template.
2972: null, // column sort order not required for heap
2973: null, // default properties
2974: TransactionController.IS_DEFAULT); // not temporary
2975:
2976: tc.commit();
2977:
2978: // Open it.
2979: ConglomerateController cc = tc.openConglomerate(conglomid,
2980: false, TransactionController.OPENMODE_FORUPDATE,
2981: TransactionController.MODE_RECORD,
2982: TransactionController.ISOLATION_SERIALIZABLE);
2983:
2984: // Create a row.
2985: T_AccessRow r1 = new T_AccessRow(1);
2986: SQLInteger c1 = new SQLInteger(0);
2987: r1.setCol(0, c1);
2988:
2989: // Get a location template
2990: RowLocation rowloc = cc.newRowLocationTemplate();
2991:
2992: // Insert the row and remember its location.
2993: cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
2994:
2995: // now commit nosync without releasing the row lock
2996: tc.commitNoSync(TransactionController.KEEP_LOCKS);
2997:
2998: // cc should be closed
2999: try {
3000: cc.newRowLocationTemplate();
3001: throw T_Fail
3002: .testFailMsg("conglomerate controller is not closed after commit");
3003: } catch (StandardException se) {
3004: // expect fail
3005: }
3006:
3007: // get another transaction going
3008: ContextManager cm2 = ContextService.getFactory()
3009: .newContextManager();
3010:
3011: ContextService.getFactory().setCurrentContextManager(cm2);
3012:
3013: TransactionController tc2 = null;
3014: ConglomerateController cc2 = null;
3015: try {
3016:
3017: tc2 = store.getTransaction(cm2);
3018:
3019: cc2 = tc2.openConglomerate(conglomid, false,
3020: TransactionController.OPENMODE_FORUPDATE,
3021: TransactionController.MODE_RECORD,
3022: TransactionController.ISOLATION_SERIALIZABLE);
3023:
3024: // try to lock the row, it should fail
3025: // Mikem RESOLVE: this does not get a row lock
3026: // cc2.fetch(rowloc, r1.getRowArray(), (FormatableBitSet)null)
3027:
3028: cc2.delete(rowloc);
3029: throw T_Fail
3030: .testFailMsg("expected time out did not happen");
3031: } catch (StandardException lfe) {
3032: if (!lfe.getMessageId().equals(SQLState.LOCK_TIMEOUT))
3033: throw lfe;
3034: } finally {
3035: ContextService.getFactory().resetCurrentContextManager(cm2);
3036: }
3037:
3038: // see whether anyone is blocked at all
3039: if (tc.anyoneBlocked()) {
3040: throw T_Fail
3041: .testFailMsg("No transactions should be blocked");
3042: }
3043:
3044: // now really commit the transaction
3045: tc.commit();
3046:
3047: ContextService.getFactory().setCurrentContextManager(cm2);
3048:
3049: try {
3050: cc2
3051: .fetch(rowloc, r1.getRowArray(),
3052: (FormatableBitSet) null);
3053: // get rid of the other transaction
3054: tc2.commitNoSync(TransactionController.RELEASE_LOCKS);
3055: tc2.destroy();
3056: } finally {
3057: ContextService.getFactory().resetCurrentContextManager(cm2);
3058: }
3059:
3060: REPORT("(commitTest) succeeded");
3061: return true;
3062: }
3063:
3064: private void testOpsBeforeFirstNext(ScanController scan,
3065: DataValueDescriptor[] row) throws StandardException, T_Fail {
3066:
3067: // none of the following operations is allowed before a next() or
3068: // fetchNext() is called.
3069: //
3070: try {
3071: scan.delete();
3072: throw T_Fail
3073: .testFailMsg("(holdCursor) delete() does not work until next() is called.");
3074: } catch (StandardException lfe) {
3075: // expect error
3076: }
3077: try {
3078: scan.doesCurrentPositionQualify();
3079: throw T_Fail
3080: .testFailMsg("(holdCursor) doesCurrentPositionQualify() does not work until next() is called.");
3081: } catch (StandardException lfe) {
3082: // expect error
3083: }
3084:
3085: try {
3086: scan.fetch(row);
3087: throw T_Fail
3088: .testFailMsg("(holdCursor) fetch() does not work until next() is called.");
3089: } catch (StandardException lfe) {
3090: // expect error
3091: }
3092: try {
3093: scan.fetchLocation(null);
3094: throw T_Fail
3095: .testFailMsg("(holdCursor) fetchLocation() does not work until next() is called.");
3096: } catch (StandardException lfe) {
3097: // expect error
3098: }
3099: try {
3100: scan.isCurrentPositionDeleted();
3101: throw T_Fail
3102: .testFailMsg("(holdCursor) isCurrentPositionDeleted() does not work until next() is called.");
3103: } catch (StandardException lfe) {
3104: // expect error
3105: }
3106: try {
3107: scan.replace(row, null);
3108: throw T_Fail
3109: .testFailMsg("(holdCursor) isCurrentPositionDeleted() does not work until next() is called.");
3110: } catch (StandardException lfe) {
3111: // expect error
3112: }
3113: }
3114:
3115: // test various flavors of commit
3116: protected boolean holdCursor(TransactionController tc)
3117: throws StandardException, T_Fail {
3118: REPORT("(holdCursor)");
3119:
3120: // Create a conglomerates and an index on that conglomerate.
3121: long base_id = createAConglom(tc, 0, false);
3122:
3123: // Open it.
3124: ConglomerateController cc = tc.openConglomerate(base_id, false,
3125: TransactionController.OPENMODE_FORUPDATE,
3126: TransactionController.MODE_RECORD,
3127: TransactionController.ISOLATION_SERIALIZABLE);
3128:
3129: // insert 5 rows
3130:
3131: T_AccessRow r1 = null;
3132: SQLLongint c1 = null;
3133:
3134: for (int i = 1; i < 5; i++) {
3135: // Create a row.
3136: r1 = new T_AccessRow(1);
3137: c1 = new SQLLongint(i);
3138: r1.setCol(0, c1);
3139:
3140: // Get a location template
3141: RowLocation rowloc = cc.newRowLocationTemplate();
3142:
3143: // Insert the row and remember its location.
3144: cc.insertAndFetchLocation(r1.getRowArray(), rowloc);
3145: }
3146:
3147: // Create an index on the base table.
3148: long index_id = createBtree(tc, base_id, false);
3149:
3150: tc.commit();
3151:
3152: cc.close();
3153:
3154: tc.commit();
3155:
3156: // HEAP - test that scan is closed on commit of non-held cursor.
3157:
3158: // Open scan on the base table.
3159: ScanController base_scan = tc.openScan(
3160: base_id,
3161: false, // don't hold
3162: TransactionController.OPENMODE_FORUPDATE, // for update
3163: TransactionController.MODE_RECORD,
3164: TransactionController.ISOLATION_SERIALIZABLE,
3165: (FormatableBitSet) null, // all columns, all as objects
3166: null, // start position - first row in conglomerate
3167: 0, // unused if start position is null.
3168: null, // qualifier - accept all rows
3169: null, // stop position - last row in conglomerate
3170: 0); // unused if stop position is null.
3171:
3172: // Open scan on the index table.
3173: ScanController index_scan = tc.openScan(
3174: index_id,
3175: false, // don't hold
3176: TransactionController.OPENMODE_FORUPDATE, // for update
3177: TransactionController.MODE_RECORD,
3178: TransactionController.ISOLATION_SERIALIZABLE,
3179: (FormatableBitSet) null, // all columns, all as objects
3180: null, // start position - first row in conglomerate
3181: 0, // unused if start position is null.
3182: null, // qualifier - accept all rows
3183: null, // stop position - last row in conglomerate
3184: 0); // unused if stop position is null.
3185:
3186: testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3187: testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3188:
3189: base_scan.next();
3190: index_scan.next();
3191:
3192: base_scan.next();
3193: index_scan.next();
3194:
3195: base_scan.next();
3196: index_scan.next();
3197:
3198: base_scan.next();
3199: index_scan.next();
3200:
3201: base_scan.next();
3202: index_scan.next();
3203:
3204: base_scan.next();
3205: index_scan.next();
3206:
3207: base_scan.next();
3208: index_scan.next();
3209:
3210: // should be able call get and set even after next'ing through the rows.
3211: long row_count = base_scan.getEstimatedRowCount();
3212: base_scan.setEstimatedRowCount(10);
3213: row_count = base_scan.getEstimatedRowCount();
3214:
3215: // should be able call get and set even after next'ing through the rows.
3216: row_count = index_scan.getEstimatedRowCount();
3217: index_scan.setEstimatedRowCount(10);
3218: row_count = index_scan.getEstimatedRowCount();
3219:
3220: if (row_count != 10)
3221: throw T_Fail
3222: .testFailMsg("(holdCursor) some problem with get/set row count.");
3223:
3224: tc.commit();
3225:
3226: testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3227: testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3228:
3229: // see if commit closed the base_scan.
3230: if (base_scan.next())
3231: throw T_Fail
3232: .testFailMsg("(holdCursor) next() should return false, commit should close base_scan.");
3233:
3234: // see if commit closed the base_scan.
3235: if (index_scan.next())
3236: throw T_Fail
3237: .testFailMsg("(holdCursor) next() should return false, commit should close base_scan.");
3238:
3239: tc.commit();
3240:
3241: // Open another scan on the conglomerate.
3242: base_scan = tc.openScan(
3243: base_id,
3244: true, // hold cursor open across commit
3245: TransactionController.OPENMODE_FORUPDATE, // for update
3246: TransactionController.MODE_RECORD,
3247: TransactionController.ISOLATION_SERIALIZABLE,
3248: (FormatableBitSet) null, // all columns, all as objects
3249: null, // start position - first row in conglomerate
3250: 0, // unused if start position is null.
3251: null, // qualifier - accept all rows
3252: null, // stop position - last row in conglomerate
3253: 0); // unused if stop position is null.
3254:
3255: // Open scan on the index table.
3256: index_scan = tc.openScan(
3257: index_id,
3258: true, // don't hold
3259: TransactionController.OPENMODE_FORUPDATE, // for update
3260: TransactionController.MODE_RECORD,
3261: TransactionController.ISOLATION_SERIALIZABLE,
3262: (FormatableBitSet) null, // all columns, all as objects
3263: null, // start position - first row in conglomerate
3264: 0, // unused if start position is null.
3265: null, // qualifier - accept all rows
3266: null, // stop position - last row in conglomerate
3267: 0); // unused if stop position is null.
3268:
3269: tc.commit();
3270:
3271: testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3272: testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3273:
3274: // try to move scan after commit to 1st row.
3275: // move cursor to be positioned on 0
3276: if (!base_scan.next())
3277: throw T_Fail
3278: .testFailMsg("(holdCursor) next() should not fail, commit should close hold scan.");
3279: // try to move scan after commit to 1st row.
3280: // move cursor to be positioned on 0
3281: if (!index_scan.next())
3282: throw T_Fail
3283: .testFailMsg("(holdCursor) next() should not fail, commit should close hold scan.");
3284:
3285: // the 1st next should return the 1st row - ie. 0
3286:
3287: base_scan.fetch(r1.getRowArray());
3288: long key_value = ((SQLLongint) r1.getCol(0)).getLong();
3289:
3290: if (key_value != 0)
3291: throw T_Fail.testFailMsg("(holdCursor) 1st row is not 0.");
3292:
3293: index_scan.fetch(r1.getRowArray());
3294: key_value = ((SQLLongint) r1.getCol(0)).getLong();
3295:
3296: if (key_value != 0)
3297: throw T_Fail.testFailMsg("(holdCursor) 1st row is not 0.");
3298:
3299: // move cursor to be positioned on 1
3300: base_scan.next();
3301: index_scan.next();
3302:
3303: tc.commit();
3304:
3305: testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3306: testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3307:
3308: // should be able call get and set even after next'ing through the rows.
3309: row_count = base_scan.getEstimatedRowCount();
3310: base_scan.setEstimatedRowCount(5);
3311: row_count = base_scan.getEstimatedRowCount();
3312:
3313: // should be able call get and set even after next'ing through the rows.
3314: row_count = index_scan.getEstimatedRowCount();
3315: index_scan.setEstimatedRowCount(5);
3316: row_count = index_scan.getEstimatedRowCount();
3317:
3318: if (row_count != 5)
3319: throw T_Fail
3320: .testFailMsg("(holdCursor) some problem with get/set row count.");
3321:
3322: // try to move to row with key "2"
3323:
3324: // move cursor to be positioned on 2
3325: if (!base_scan.next())
3326: throw T_Fail
3327: .testFailMsg("(holdCursor) next() should not fail, commit should close hold base_scan.");
3328:
3329: if (!index_scan.next())
3330: throw T_Fail
3331: .testFailMsg("(holdCursor) next() should not fail, commit should close hold base_scan.");
3332:
3333: // the 1st next should return the 1st row - ie. 0
3334: base_scan.fetch(r1.getRowArray());
3335: key_value = ((SQLLongint) r1.getCol(0)).getLong();
3336:
3337: if (key_value != 2)
3338: throw T_Fail.testFailMsg("(holdCursor) 1st row is not 0.");
3339:
3340: index_scan.fetch(r1.getRowArray());
3341: key_value = ((SQLLongint) r1.getCol(0)).getLong();
3342:
3343: if (key_value != 2)
3344: throw T_Fail.testFailMsg("(holdCursor) 1st row is not 0.");
3345:
3346: // move cursor to be positioned on 3
3347: base_scan.next();
3348: base_scan.delete();
3349:
3350: index_scan.next();
3351: index_scan.delete();
3352:
3353: // move cursor to be positioned on 4
3354: base_scan.next();
3355: index_scan.next();
3356:
3357: // move cursor past the end, thus closing it.
3358: base_scan.next();
3359: index_scan.next();
3360:
3361: tc.commit();
3362:
3363: // should be able call get and set even after next'ing through the rows.
3364: row_count = base_scan.getEstimatedRowCount();
3365: base_scan.setEstimatedRowCount(15);
3366: row_count = base_scan.getEstimatedRowCount();
3367:
3368: if (row_count != 15)
3369: throw T_Fail
3370: .testFailMsg("(holdCursor) some problem with get/set row count.");
3371:
3372: row_count = index_scan.getEstimatedRowCount();
3373: index_scan.setEstimatedRowCount(15);
3374: row_count = index_scan.getEstimatedRowCount();
3375:
3376: if (row_count != 15)
3377: throw T_Fail
3378: .testFailMsg("(holdCursor) some problem with get/set row count.");
3379:
3380: testOpsBeforeFirstNext(base_scan, r1.getRowArray());
3381: testOpsBeforeFirstNext(index_scan, r1.getRowArray());
3382:
3383: // see what happens committing a closed base_scan and trying next.
3384:
3385: if (base_scan.next())
3386: throw T_Fail
3387: .testFailMsg("(holdCursor) next() should fail, the base_scan has been closed by progressing to end.");
3388: if (index_scan.next())
3389: throw T_Fail
3390: .testFailMsg("(holdCursor) next() should fail, the base_scan has been closed by progressing to end.");
3391:
3392: tc.commit();
3393:
3394: base_scan.close();
3395: index_scan.close();
3396:
3397: REPORT("(holdCursor) succeeded");
3398: return true;
3399: }
3400:
3401: // test position at row location, in terms of holdability
3402: protected boolean positionAtRowLocation(TransactionController tc)
3403: throws StandardException, T_Fail {
3404: REPORT("(positionAtRowLocation)");
3405:
3406: // Create a conglomerate with one row:
3407: long base_id = createAConglom(tc, 0, false);
3408:
3409: // Open it.
3410: ConglomerateController cc = tc.openConglomerate(base_id, false,
3411: TransactionController.OPENMODE_FORUPDATE,
3412: TransactionController.MODE_RECORD,
3413: TransactionController.ISOLATION_SERIALIZABLE);
3414:
3415: T_AccessRow accessRow = null;
3416: for (int i = 1; i < 5; i++) {
3417: // Create a row.
3418: accessRow = new T_AccessRow(1);
3419: SQLLongint c1 = new SQLLongint(i);
3420: accessRow.setCol(0, c1);
3421:
3422: // Insert the row and remember its location.
3423: cc.insert(accessRow.getRowArray());
3424: }
3425: tc.commit();
3426: cc.close();
3427:
3428: // Open scan on the table:
3429: ScanController base_scan = tc.openScan(
3430: base_id,
3431: true, // do hold
3432: TransactionController.OPENMODE_FORUPDATE, // for update
3433: TransactionController.MODE_RECORD,
3434: TransactionController.ISOLATION_SERIALIZABLE,
3435: (FormatableBitSet) null, // all columns, all as objects
3436: null, // start position - first row in conglomerate
3437: 0, // unused if start position is null.
3438: null, // qualifier - accept all rows
3439: null, // stop position - last row in conglomerate
3440: 0); // unused if stop position is null.
3441:
3442: // Move to the first row
3443: base_scan.next();
3444:
3445: // Get the RowLocation for the first row:
3446: RowLocation firstRow = base_scan.newRowLocationTemplate();
3447: base_scan.fetchLocation(firstRow);
3448: base_scan.fetch(accessRow.getRowArray());
3449: long key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3450: if (key_value != 0) {
3451: throw T_Fail
3452: .testFailMsg("(positionAtRowLocation_err_1) 1st row is not 0 it is:"
3453: + key_value);
3454: }
3455:
3456: // Move to some other rows:
3457: base_scan.next();
3458: base_scan.fetch(accessRow.getRowArray());
3459: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3460: if (key_value != 1) {
3461: throw T_Fail
3462: .testFailMsg("(positionAtRowLocation_err_2) 2nd row is not 1 it is:"
3463: + key_value);
3464: }
3465:
3466: base_scan.next();
3467: base_scan.fetch(accessRow.getRowArray());
3468: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3469: if (key_value != 2) {
3470: throw T_Fail
3471: .testFailMsg("(positionAtRowLocation_err_3) 3d row is not 2 it is:"
3472: + key_value);
3473: }
3474:
3475: if (!base_scan.positionAtRowLocation(firstRow)) {
3476: throw T_Fail
3477: .testFailMsg("(positionAtRowLocation_err_4) Failed to position at RowLocation");
3478: }
3479: base_scan.fetch(accessRow.getRowArray());
3480: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3481: if (key_value != 0) {
3482: throw T_Fail
3483: .testFailMsg("(positionAtRowLocation_err_5) 1st row is not 0 it is:"
3484: + key_value);
3485: }
3486:
3487: // Commit and check holdability:
3488: tc.commit();
3489: base_scan.next();
3490: base_scan.fetch(accessRow.getRowArray());
3491: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3492: if (key_value != 1) {
3493: throw T_Fail
3494: .testFailMsg("(positionAtRowLocation_err_6) 2nd row is not 1 it is:"
3495: + key_value);
3496: }
3497:
3498: base_scan.next();
3499: base_scan.fetch(accessRow.getRowArray());
3500: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3501: if (key_value != 2) {
3502: throw T_Fail
3503: .testFailMsg("(positionAtRowLocation_err_7) 3d row is not 2 it is:"
3504: + key_value);
3505: }
3506:
3507: if (!base_scan.positionAtRowLocation(firstRow)) {
3508: throw T_Fail
3509: .testFailMsg("(positionAtRowLocation_err_8) Failed to position at "
3510: + "RowLocation after commit");
3511: }
3512: base_scan.fetch(accessRow.getRowArray());
3513: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3514: if (key_value != 0) {
3515: throw T_Fail
3516: .testFailMsg("(positionAtRowLocation_err_9) 1st row is not 0 it is:"
3517: + key_value);
3518: }
3519:
3520: base_scan.next();
3521: base_scan.fetch(accessRow.getRowArray());
3522: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3523: if (key_value != 1) {
3524: throw T_Fail
3525: .testFailMsg("(positionAtRowLocation_err_10) 2nd row is not 1 it is:"
3526: + key_value);
3527: }
3528:
3529: base_scan.next();
3530: base_scan.fetch(accessRow.getRowArray());
3531: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3532: if (key_value != 2) {
3533: throw T_Fail
3534: .testFailMsg("(positionAtRowLocation_err_10) 3d row is not 2 it is:"
3535: + key_value);
3536: }
3537:
3538: // Using reopenScanByRowLocation(..)
3539: // instead of positionAtRowLocation(..):
3540: base_scan.reopenScanByRowLocation(firstRow, null);
3541: base_scan.next();
3542: base_scan.fetch(accessRow.getRowArray());
3543: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3544: if (key_value != 0) {
3545: throw T_Fail
3546: .testFailMsg("(positionAtRowLocation_err_11) 1st row is not 0 it is:"
3547: + key_value);
3548: }
3549:
3550: tc.commit();
3551:
3552: // Compress the conglomerate
3553: tc.compressConglomerate(base_id);
3554: tc.commit();
3555:
3556: base_scan.next();
3557: base_scan.fetch(accessRow.getRowArray());
3558: key_value = ((SQLLongint) accessRow.getCol(0)).getLong();
3559: if (key_value != 1) {
3560: throw T_Fail
3561: .testFailMsg("(positionAtRowLocation_err_12) 2nd row is not 1 it is:"
3562: + key_value);
3563: }
3564:
3565: // Position at RowLocation should now fail. We cannot guarantee
3566: // that they are holdable
3567: if (base_scan.positionAtRowLocation(firstRow)) {
3568: throw T_Fail
3569: .testFailMsg("(positionAtRowLocation_err_12) Unexpectedly succeeded at "
3570: + "positioning at RowLocation after compress");
3571: }
3572:
3573: base_scan.close();
3574:
3575: REPORT("(positionAtRowLocation) succeeded");
3576: return true;
3577: }
3578:
3579: /**
3580: * Test critical cases for read uncommitted.
3581: * <p>
3582: * test 1 - test heap fetch, delete and replace of row on page which does not exist.
3583: * test 2 - test heap fetch, delete and replace of row on page where row does not exist.
3584: *
3585: * @exception StandardException Standard exception policy.
3586: **/
3587: protected boolean readUncommitted(TransactionController tc)
3588: throws StandardException, T_Fail {
3589: REPORT("(readUncommitted)");
3590:
3591: /*
3592: * TEST 1 - test heap fetch of row on page which does not exist.
3593: * <p>
3594: * Do this by inserting a few pages worth of data and then deleting
3595: * all the rows, while remembering the rowlocation of one of the pages.
3596: * You need to at least get to the 2nd page, because the 1st page is
3597: * never totally reclaimed and deleted by the system in a heap (it has
3598: * some internal catalog information stored internally in row "0").
3599: */
3600:
3601: String twok_string = new String("0123456789012345");
3602:
3603: for (int i = 0; i < 7; i++) {
3604: twok_string += twok_string;
3605: }
3606:
3607: T_AccessRow big_row = new T_AccessRow(2);
3608:
3609: big_row.setCol(1, new SQLChar(twok_string));
3610:
3611: // Create a heap conglomerate.
3612: long orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
3613: big_row.getRowArray(), null, // column sort order not required for heap
3614: null, // default properties
3615: TransactionController.IS_DEFAULT); // not temporary
3616:
3617: ConglomerateController cc = tc.openConglomerate(orig_conglomid,
3618: false, TransactionController.OPENMODE_FORUPDATE,
3619: TransactionController.MODE_RECORD,
3620: TransactionController.ISOLATION_READ_UNCOMMITTED);
3621:
3622: // add 5 pages worth of data.
3623:
3624: for (int i = 0; i < 10; i++) {
3625: big_row.setCol(0, new SQLInteger(i));
3626: cc.insert(big_row.getRowArray());
3627: }
3628: cc.close();
3629:
3630: // Open another scan on the conglomerate.
3631: ScanController base_scan = tc.openScan(
3632: orig_conglomid,
3633: true, // hold cursor open across commit
3634: TransactionController.OPENMODE_FORUPDATE, // for update
3635: TransactionController.MODE_RECORD,
3636: TransactionController.ISOLATION_SERIALIZABLE,
3637: (FormatableBitSet) null, // all columns, all as objects
3638: null, // start position - first row in conglomerate
3639: 0, // unused if start position is null.
3640: null, // qualifier - accept all rows
3641: null, // stop position - last row in conglomerate
3642: 0); // unused if stop position is null.
3643:
3644: // now delete all the rows and remember the row location of the
3645: // last row.
3646:
3647: RowLocation deleted_page_rowloc = base_scan
3648: .newRowLocationTemplate();
3649:
3650: for (int i = 0; i < 10; i++) {
3651: base_scan.next();
3652: base_scan.fetchLocation(deleted_page_rowloc);
3653: base_scan.delete();
3654:
3655: tc.commit();
3656: }
3657: base_scan.close();
3658: tc.commit();
3659:
3660: // at this point the post commit thread should have reclaimed all the 5
3661: // pages. Open it, at read uncommitted level.
3662: cc = tc.openConglomerate(orig_conglomid, false, 0,
3663: TransactionController.MODE_RECORD,
3664: TransactionController.ISOLATION_READ_UNCOMMITTED);
3665:
3666: // Test heap fetch of row on page which does not exist.
3667: if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null)) {
3668: throw T_Fail
3669: .testFailMsg("(readUncommitted) fetch should ret false for reclaimed page.");
3670: }
3671:
3672: // Test heap replace of row on page which does not exist.
3673: FormatableBitSet update_desc = new FormatableBitSet(1);
3674: if (cc.replace(deleted_page_rowloc, big_row.getRowArray(),
3675: update_desc)) {
3676: throw T_Fail
3677: .testFailMsg("(readUncommitted) delete should ret false for reclaimed page.");
3678: }
3679:
3680: // Test heap fetch (overloaded call) of row on page which does not exist.
3681: if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null,
3682: true)) {
3683: throw T_Fail
3684: .testFailMsg("(readUncommitted) fetch should ret false for reclaimed page.");
3685: }
3686:
3687: // Test heap delete of row on page which does not exist.
3688: if (cc.delete(deleted_page_rowloc)) {
3689: throw T_Fail
3690: .testFailMsg("(readUncommitted) delete should ret false for reclaimed page.");
3691: }
3692:
3693: cc.close();
3694:
3695: /*
3696: * TEST 2 - test heap fetch of row on page where row does not exist.
3697: * <p>
3698: * Do this by inserting enough rows to put 1 row on the 2nd page.
3699: * Then delete this one row, which will queue a post commit to reclaim
3700: * the row and page. Then insert one more row on the same page in
3701: * the same xact. Now commit the xact, which will cause post commit
3702: * to run which will reclaim the row but not the page. Then try and
3703: * fetch the row which was deleted.
3704: */
3705:
3706: // string column will be 1500 bytes, allowing 2 rows per page to fit.
3707: SQLChar stringcol = new SQLChar();
3708: stringcol.setValue(T_AccessFactory.repeatString(
3709: "012345678901234", 100));
3710: big_row.setCol(1, stringcol);
3711:
3712: // Create a heap conglomerate.
3713: orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
3714: big_row.getRowArray(), null, // column sort order not required for heap
3715: null, // default properties
3716: TransactionController.IS_DEFAULT); // not temporary
3717:
3718: cc = tc.openConglomerate(orig_conglomid, false,
3719: TransactionController.OPENMODE_FORUPDATE,
3720: TransactionController.MODE_RECORD,
3721: TransactionController.ISOLATION_READ_UNCOMMITTED);
3722:
3723: // add 3 rows, should result in 1 row on second page.
3724:
3725: for (int i = 0; i < 3; i++) {
3726: big_row.setCol(0, new SQLInteger(i));
3727: cc.insert(big_row.getRowArray());
3728: }
3729:
3730: // Open another scan on the conglomerate.
3731: base_scan = tc.openScan(
3732: orig_conglomid,
3733: true, // hold cursor open across commit
3734: TransactionController.OPENMODE_FORUPDATE, // for update
3735: TransactionController.MODE_RECORD,
3736: TransactionController.ISOLATION_SERIALIZABLE,
3737: (FormatableBitSet) null, // all columns, all as objects
3738: null, // start position - first row in conglomerate
3739: 0, // unused if start position is null.
3740: null, // qualifier - accept all rows
3741: null, // stop position - last row in conglomerate
3742: 0); // unused if stop position is null.
3743:
3744: // now delete all the rows and remember the row location of the
3745: // last row.
3746:
3747: RowLocation deleted_row_rowloc = base_scan
3748: .newRowLocationTemplate();
3749:
3750: for (int i = 0; i < 3; i++) {
3751: base_scan.next();
3752: base_scan.fetchLocation(deleted_row_rowloc);
3753: base_scan.delete();
3754: }
3755:
3756: // insert another row on page 2 to make sure page does not go away.
3757: cc.insert(big_row.getRowArray());
3758:
3759: cc.close();
3760: base_scan.close();
3761: tc.commit();
3762:
3763: // at this point the post commit thread should have reclaimed all the
3764: // deleted row on page 2, but not the page.
3765: //
3766: // Open it, at read uncommitted level.
3767: cc = tc.openConglomerate(orig_conglomid, false, 0,
3768: TransactionController.MODE_RECORD,
3769: TransactionController.ISOLATION_READ_UNCOMMITTED);
3770:
3771: // the following will be attempting to fetch a row which has been
3772: // reclaimed by post commit, on an existing page.
3773:
3774: // test heap fetch of row on page where row does not exist.
3775: if (cc.fetch(deleted_row_rowloc, big_row.getRowArray(), null)) {
3776: throw T_Fail
3777: .testFailMsg("(readUncommitted) fetch should ret false for reclaimed row.");
3778: }
3779:
3780: // test heap replace of row on page where row does not exist.
3781: if (cc.replace(deleted_page_rowloc, big_row.getRowArray(),
3782: update_desc)) {
3783: throw T_Fail
3784: .testFailMsg("(readUncommitted) delete should ret false for reclaimed page.");
3785: }
3786:
3787: // test heap fetch (overloaded) of row on page where row does not exist.
3788: if (cc.fetch(deleted_page_rowloc, big_row.getRowArray(), null,
3789: true)) {
3790: throw T_Fail
3791: .testFailMsg("(readUncommitted) fetch should ret false for reclaimed page.");
3792: }
3793:
3794: // test heap delete of row on page where row does not exist.
3795: if (cc.delete(deleted_page_rowloc)) {
3796: throw T_Fail
3797: .testFailMsg("(readUncommitted) delete should ret false for reclaimed page.");
3798: }
3799:
3800: cc.close();
3801:
3802: /*
3803: * TEST 3 - test heap scan fetch of row on page prevents page from
3804: * disappearing, but handles row being deleted.
3805: * <p>
3806: * A heap scan will maintain a scan lock on a page even if it is doing
3807: * a read uncommitted scan. This will prevent the row/page from being
3808: * reclaimed by post commit while the scan is positioned on the page.
3809: * This presents no other concurrency issues for read uncommitted, it
3810: * should be invisible to the user (deletes can still happen and the
3811: * read uncommitted scanner will not block anyone).
3812: *
3813: * You need to at least get to the 2nd page, because the 1st page is
3814: * never totally reclaimed and deleted by the system in a heap (it has
3815: * some internal catalog information stored internally in row "0").
3816: */
3817:
3818: big_row = new T_AccessRow(2);
3819:
3820: big_row.setCol(1, new SQLChar(twok_string));
3821:
3822: // Create a heap conglomerate.
3823: orig_conglomid = tc.createConglomerate("heap", // create a heap conglomerate
3824: big_row.getRowArray(), null, // column sort order not required for heap
3825: null, // default properties
3826: TransactionController.IS_DEFAULT); // not temporary
3827:
3828: cc = tc.openConglomerate(orig_conglomid, false,
3829: TransactionController.OPENMODE_FORUPDATE,
3830: TransactionController.MODE_RECORD,
3831: TransactionController.ISOLATION_READ_UNCOMMITTED);
3832:
3833: // add 5 pages worth of data.
3834:
3835: for (int i = 0; i < 10; i++) {
3836: big_row.setCol(0, new SQLInteger(i));
3837: cc.insert(big_row.getRowArray());
3838: }
3839: cc.close();
3840:
3841: // Open scan on the conglomerate, and position it on the second page.
3842: base_scan = tc.openScan(
3843: orig_conglomid,
3844: true, // hold cursor open across commit
3845: 0, // for read
3846: TransactionController.MODE_RECORD,
3847: TransactionController.ISOLATION_READ_UNCOMMITTED,
3848: (FormatableBitSet) null, // all columns, all as objects
3849: null, // start position - first row in conglomerate
3850: 0, // unused if start position is null.
3851: null, // qualifier - accept all rows
3852: null, // stop position - last row in conglomerate
3853: 0); // unused if stop position is null.
3854:
3855: base_scan.next();
3856: base_scan.next();
3857: base_scan.next();
3858:
3859: // test that the row is accessible from all these interfaces, before
3860: // the page disappears, and then test again after all rows have been
3861: // deleted from the page.
3862:
3863: if (!base_scan.doesCurrentPositionQualify())
3864: throw T_Fail
3865: .testFailMsg("(readUncommitted) doesCurrentPositionQualify() failed.");
3866:
3867: base_scan.fetch(big_row.getRowArray());
3868:
3869: base_scan.fetchLocation(deleted_row_rowloc);
3870:
3871: if (base_scan.isCurrentPositionDeleted())
3872: throw T_Fail
3873: .testFailMsg("(readUncommitted) isCurrentPositionDeleted() failed.");
3874:
3875: // Open another scan on the conglomerate.
3876: ScanController delete_scan = tc.openScan(
3877: orig_conglomid,
3878: true, // hold cursor open across commit
3879: TransactionController.OPENMODE_FORUPDATE, // for update
3880: TransactionController.MODE_RECORD,
3881: TransactionController.ISOLATION_SERIALIZABLE,
3882: (FormatableBitSet) null, // all columns, all as objects
3883: null, // start position - first row in conglomerate
3884: 0, // unused if start position is null.
3885: null, // qualifier - accept all rows
3886: null, // stop position - last row in conglomerate
3887: 0); // unused if stop position is null.
3888:
3889: // now delete all the rows and commit.
3890:
3891: for (int i = 0; i < 10; i++) {
3892: delete_scan.next();
3893: delete_scan.fetchLocation(deleted_page_rowloc);
3894: delete_scan.delete();
3895:
3896: }
3897: delete_scan.close();
3898:
3899: // Now test that the row is accessible from all these interfaces, after
3900: // it has been deleted.
3901:
3902: if (base_scan.doesCurrentPositionQualify())
3903: throw T_Fail
3904: .testFailMsg("(readUncommitted) doesCurrentPositionQualify() failed.");
3905:
3906: try {
3907: base_scan.fetch(big_row.getRowArray());
3908: throw T_Fail
3909: .testFailMsg("(readUncommitted) fetch of deleted row should throw exception.");
3910: } catch (StandardException se) {
3911: // expect SQLState.AM_RECORD_NOT_FOUND exception.
3912:
3913: if (!se.getMessageId().equals(SQLState.AM_RECORD_NOT_FOUND)) {
3914: throw T_Fail
3915: .testFailMsg("(readUncommitted) fetch of deleted row should throw SQLState.AM_RECORD_NOT_FOUND.");
3916: }
3917: }
3918:
3919: base_scan.fetchLocation(deleted_row_rowloc);
3920:
3921: if (!base_scan.isCurrentPositionDeleted())
3922: throw T_Fail
3923: .testFailMsg("(readUncommitted) isCurrentPositionDeleted() failed.");
3924:
3925: base_scan.close();
3926: tc.commit();
3927:
3928: REPORT("(readUncommitted) succeeded");
3929: return true;
3930: }
3931:
3932: public static String repeatString(String data, int repeat) {
3933:
3934: String s = data;
3935: for (int i = 1; i < repeat; i++)
3936: s += data;
3937:
3938: return s;
3939: }
3940:
3941: }
|