001: /*
002: * $Id: TestTransactableTableImpl.java,v 1.18 2005/12/20 18:32:47 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2003 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.engine;
042:
043: import junit.framework.Test;
044: import junit.framework.TestCase;
045: import junit.framework.TestSuite;
046:
047: import org.apache.commons.collections.HashBag;
048: import org.axiondb.Column;
049: import org.axiondb.ColumnIdentifier;
050: import org.axiondb.Function;
051: import org.axiondb.Literal;
052: import org.axiondb.Row;
053: import org.axiondb.RowIterator;
054: import org.axiondb.Table;
055: import org.axiondb.TableIdentifier;
056: import org.axiondb.engine.indexes.IntArrayIndex;
057: import org.axiondb.engine.rows.SimpleRow;
058: import org.axiondb.engine.tables.MemoryTable;
059: import org.axiondb.functions.LessThanFunction;
060: import org.axiondb.types.CharacterVaryingType;
061: import org.axiondb.types.IntegerType;
062:
063: /**
064: * @version $Revision: 1.18 $ $Date: 2005/12/20 18:32:47 $
065: * @author Rodney Waldhoff
066: */
067: public class TestTransactableTableImpl extends TestCase {
068:
069: //------------------------------------------------------------ Conventional
070:
071: public TestTransactableTableImpl(String testName) {
072: super (testName);
073: }
074:
075: public static Test suite() {
076: return new TestSuite(TestTransactableTableImpl.class);
077: }
078:
079: //--------------------------------------------------------------- Lifecycle
080:
081: private Table _table = null;
082: private TransactableTableImpl _ttable = null;
083:
084: public void setUp() throws Exception {
085: super .setUp();
086: _table = new MemoryTable("TEST");
087: _table.addColumn(new Column("ID", new IntegerType()));
088: _table.addColumn(new Column("NAME",
089: new CharacterVaryingType(10)));
090: _table.addIndex(new IntArrayIndex("ID_INDEX", _table
091: .getColumn(0), false));
092: {
093: Row row = new SimpleRow(2);
094: row.set(0, new Integer(1));
095: row.set(1, "one");
096: _table.addRow(row);
097: }
098: {
099: Row row = new SimpleRow(2);
100: row.set(0, new Integer(2));
101: row.set(1, "two");
102: _table.addRow(row);
103: }
104: _ttable = new TransactableTableImpl(_table);
105: }
106:
107: public void tearDown() throws Exception {
108: super .tearDown();
109: _ttable.shutdown();
110: _table = null;
111: _ttable = null;
112: }
113:
114: //------------------------------------------------------------------- Tests
115:
116: public void testSelectFromUnmodifiedIndex() throws Exception {
117: Function where = new LessThanFunction();
118: where.addArgument(new ColumnIdentifier(new TableIdentifier(
119: "TEST"), "ID", null, new IntegerType()));
120: where.addArgument(new Literal(new Integer(10),
121: new IntegerType()));
122: RowIterator iter = _ttable.getIndexedRows(where, true);
123: assertNotNull("Should have been able to obtain iterator", iter);
124: boolean[] found = new boolean[2];
125: for (int i = 0; i < 2; i++) {
126: assertTrue("Should have a next row", iter.hasNext());
127: Row row = iter.next();
128: assertNotNull("Row should not be null", row);
129: found[((Number) (row.get(0))).intValue() - 1] = true;
130: }
131: assertTrue(found[0]);
132: assertTrue(found[0]);
133: }
134:
135: public void testGetMatchingRowsForNull() throws Exception {
136: RowIterator iter = _ttable.getMatchingRows(null, null, true);
137: assertNotNull(iter);
138: }
139:
140: public void testDrop() throws Exception {
141: _ttable.drop();
142: }
143:
144: public void testRemount() throws Exception {
145: _ttable.remount(null, true);
146: }
147:
148: public void testSelectFromIndexAfterInsert() throws Exception {
149: // add rows to the ttable
150: {
151: Row row = new SimpleRow(2);
152: row.set(0, new Integer(4));
153: row.set(1, "four");
154: _ttable.addRow(row);
155: }
156: {
157: Row row = new SimpleRow(2);
158: row.set(0, new Integer(3));
159: row.set(1, "three");
160: _ttable.addRow(row);
161: }
162:
163: Function where = new LessThanFunction();
164: where.addArgument(new ColumnIdentifier(new TableIdentifier(
165: "TEST"), "ID", null, new IntegerType()));
166: where.addArgument(new Literal(new Integer(10),
167: new IntegerType()));
168:
169: RowIterator iter = _ttable.getIndexedRows(where, true);
170: assertNotNull("Should have been able to obtain iterator", iter);
171: HashBag expected = new HashBag();
172: HashBag found = new HashBag();
173: for (int i = 0; i < 4; i++) {
174: assertTrue("Should have a next row", iter.hasNext());
175: Row row = iter.next();
176: assertNotNull("Row should not be null", row);
177: assertTrue("Row should be unique, value " + row.get(0)
178: + " already exists in bag " + found, !found
179: .contains(row.get(0)));
180: found.add(row.get(0));
181: expected.add(new Integer(i + 1));
182: }
183: assertEquals(expected, found);
184: }
185:
186: public void testSelectFromIndexAfterDelete() throws Exception {
187: {
188: RowIterator iter = _ttable.getRowIterator(false);
189: assertTrue(iter.hasNext());
190: Row row = iter.next();
191: assertNotNull(row);
192: iter.remove();
193: }
194:
195: Function where = new LessThanFunction();
196: where.addArgument(new ColumnIdentifier(new TableIdentifier(
197: "TEST"), "ID", null, new IntegerType()));
198: where.addArgument(new Literal(new Integer(10),
199: new IntegerType()));
200:
201: RowIterator iter = _ttable.getIndexedRows(where, true);
202: assertNotNull("Should have been able to obtain iterator", iter);
203: for (int i = 1; i < 2; i++) {
204: assertTrue("Should have a next row", iter.hasNext());
205: Row row = iter.next();
206: assertNotNull("Row should not be null", row);
207: assertEquals(new Integer(i + 1), row.get(0));
208: }
209: }
210:
211: public void testSelectFromIndexAfterUpdate() throws Exception {
212: {
213: RowIterator iter = _ttable.getRowIterator(false);
214: assertTrue(iter.hasNext());
215: Row row = iter.next();
216: assertNotNull(row);
217: Row updatedRow = new SimpleRow(row);
218: updatedRow.set(0, new Integer(11));
219: iter.set(updatedRow);
220: }
221:
222: Function where = new LessThanFunction();
223: where.addArgument(new ColumnIdentifier(new TableIdentifier(
224: "TEST"), "ID", null, new IntegerType()));
225: where.addArgument(new Literal(new Integer(10),
226: new IntegerType()));
227:
228: RowIterator iter = _ttable.getIndexedRows(where, true);
229: assertNotNull("Should have been able to obtain iterator", iter);
230: for (int i = 1; i < 2; i++) {
231: assertTrue("Should have a next row", iter.hasNext());
232: Row row = iter.next();
233: assertNotNull("Row should not be null", row);
234: assertEquals(new Integer(i + 1), row.get(0));
235: }
236: }
237:
238: public void testDelegation() throws Exception {
239: assertEquals(2, _ttable.getRowCount());
240:
241: RowIterator iter = _table.getRowIterator(true);
242: assertNotNull(iter);
243: RowIterator titer = _ttable.getRowIterator(true);
244: assertNotNull(titer);
245: for (int i = 0; i < 2; i++) {
246: assertTrue(iter.hasNext());
247: Row row = iter.next();
248: assertNotNull(row);
249: Row trow = titer.next();
250: assertNotNull(trow);
251: assertEquals(row, trow);
252: }
253: assertTrue(!iter.hasNext());
254: assertTrue(!titer.hasNext());
255: }
256:
257: public void testInsertIsolation() throws Exception {
258: assertEquals(2, _table.getRowCount());
259: assertEquals(2, _ttable.getRowCount());
260:
261: // add a row to the ttable
262: {
263: Row row = new SimpleRow(2);
264: row.set(0, new Integer(3));
265: row.set(1, "three");
266: _ttable.addRow(row);
267: }
268:
269: int insertedRowId = -1;
270: // see that we can find it in the ttable
271: {
272: assertEquals(3, _ttable.getRowCount());
273: RowIterator iter = _ttable.getRowIterator(true);
274: assertNotNull(iter);
275: boolean foundit = false;
276: for (int i = 0; i < 3; i++) {
277: assertTrue(iter.hasNext());
278: Row row = iter.next();
279: assertNotNull(row);
280: if ("three".equals(row.get(1))) {
281: foundit = true;
282: insertedRowId = row.getIdentifier();
283: }
284: }
285: assertTrue(!iter.hasNext());
286: assertTrue(foundit);
287:
288: Row row = _ttable.getRow(insertedRowId);
289: assertNotNull(row);
290: assertEquals("three", row.get(1));
291: }
292:
293: // but not in the underlying table
294: {
295: boolean foundit = false;
296: assertEquals(2, _table.getRowCount());
297: RowIterator iter = _table.getRowIterator(true);
298: assertNotNull(iter);
299: for (int i = 0; i < 2; i++) {
300: assertTrue(iter.hasNext());
301: Row row = iter.next();
302: assertNotNull(row);
303: if ("three".equals(row.get(1))) {
304: foundit = true;
305: }
306: }
307: assertTrue(!iter.hasNext());
308: assertTrue(!foundit);
309:
310: assertNull(_table.getRow(insertedRowId));
311: }
312: }
313:
314: public void testDeleteIsolation() throws Exception {
315: assertEquals(2, _table.getRowCount());
316: assertEquals(2, _ttable.getRowCount());
317:
318: // delete a row from the ttable
319: Object deletedValue = null;
320: int deletedRowId = -1;
321: {
322: RowIterator iter = _ttable.getRowIterator(false);
323: assertTrue(iter.hasNext());
324: Row row = iter.next();
325: assertNotNull(row);
326: deletedValue = row.get(0);
327: deletedRowId = row.getIdentifier();
328: iter.remove();
329: }
330:
331: // check that it was deleted from the ttable
332: {
333: assertEquals(1, _ttable.getRowCount());
334: RowIterator iter = _ttable.getRowIterator(true);
335: assertNotNull(iter);
336: for (int i = 0; i < 1; i++) {
337: assertTrue(iter.hasNext());
338: Row row = iter.next();
339: assertNotNull(row);
340: assertTrue(!deletedValue.equals(row.get(0)));
341: }
342: assertTrue(!iter.hasNext());
343: assertNull(_ttable.getRow(deletedRowId));
344: }
345:
346: // but not in the underlying table
347: boolean foundval = false;
348: {
349: assertEquals(2, _table.getRowCount());
350: RowIterator iter = _table.getRowIterator(true);
351: assertNotNull(iter);
352: for (int i = 0; i < 2; i++) {
353: assertTrue(iter.hasNext());
354: Row row = iter.next();
355: assertNotNull(row);
356: if (deletedValue.equals(row.get(0))) {
357: foundval = true;
358: }
359: }
360: assertTrue(!iter.hasNext());
361: assertTrue(foundval);
362: assertNotNull(_table.getRow(deletedRowId));
363: }
364: }
365:
366: public void testUpdateIsolation() throws Exception {
367: assertEquals(2, _table.getRowCount());
368: assertEquals(2, _ttable.getRowCount());
369:
370: // update a row from the ttable
371: Object keyValue = null;
372: Object oldValue = null;
373: Object newValue = "updated";
374: int updatedRowId = -1;
375: {
376: RowIterator iter = _ttable.getRowIterator(false);
377: assertTrue(iter.hasNext());
378: Row row = iter.next();
379: assertNotNull(row);
380: keyValue = row.get(0);
381: oldValue = row.get(1);
382: updatedRowId = row.getIdentifier();
383: Row updatedRow = new SimpleRow(row);
384: updatedRow.set(1, newValue);
385: iter.set(updatedRow);
386: }
387:
388: // check that it was updated in the ttable
389: {
390: assertEquals(2, _ttable.getRowCount());
391: RowIterator iter = _ttable.getRowIterator(true);
392: assertNotNull(iter);
393: for (int i = 0; i < 2; i++) {
394: assertTrue(iter.hasNext());
395: Row row = iter.next();
396: assertNotNull(row);
397: if (keyValue.equals(row.get(0))) {
398: assertEquals(newValue, row.get(1));
399: }
400: }
401: assertTrue(!iter.hasNext());
402:
403: Row row = _ttable.getRow(updatedRowId);
404: assertNotNull(row);
405: assertEquals(newValue, row.get(1));
406: }
407:
408: // but not in the underlying table
409: {
410: assertEquals(2, _table.getRowCount());
411: RowIterator iter = _table.getRowIterator(true);
412: assertNotNull(iter);
413: for (int i = 0; i < 2; i++) {
414: assertTrue(iter.hasNext());
415: Row row = iter.next();
416: assertNotNull(row);
417: if (keyValue.equals(row.get(0))) {
418: assertTrue(!newValue.equals(row.get(1)));
419: }
420: }
421: assertTrue(!iter.hasNext());
422:
423: Row row = _table.getRow(updatedRowId);
424: assertNotNull(row);
425: assertEquals(oldValue, row.get(1));
426: }
427: }
428:
429: public void testRowIdsAreFreedOnDelete() throws Exception {
430: assertEquals(2, _ttable.getRowCount());
431: // add a row to the ttable
432: {
433: Row row = new SimpleRow(2);
434: row.set(0, new Integer(3));
435: row.set(1, "three");
436: _ttable.addRow(row);
437: }
438: assertEquals(3, _ttable.getRowCount());
439:
440: // find the new row, its row id, and delete it
441: int insertedRowId = -1;
442: {
443: RowIterator iter = _ttable.getRowIterator(true);
444: assertNotNull(iter);
445: boolean foundit = false;
446: for (int i = 0; i < 3; i++) {
447: assertTrue(iter.hasNext());
448: Row row = iter.next();
449: assertNotNull(row);
450: if ("three".equals(row.get(1))) {
451: foundit = true;
452: insertedRowId = row.getIdentifier();
453: iter.remove();
454: break;
455: }
456: }
457: assertTrue(foundit);
458: }
459: assertEquals(2, _table.getRowCount());
460: assertEquals(2, _ttable.getRowCount());
461:
462: // add a row to the ttable
463: {
464: Row row = new SimpleRow(2);
465: row.set(0, new Integer(3));
466: row.set(1, "three");
467: _ttable.addRow(row);
468: }
469:
470: // confirm that the row id is the same
471: {
472: assertEquals(3, _ttable.getRowCount());
473: RowIterator iter = _ttable.getRowIterator(true);
474: assertNotNull(iter);
475: boolean foundit = false;
476: for (int i = 0; i < 3; i++) {
477: assertTrue(iter.hasNext());
478: Row row = iter.next();
479: assertNotNull(row);
480: if ("three".equals(row.get(1))) {
481: foundit = true;
482: assertEquals(insertedRowId, row.getIdentifier());
483: }
484: }
485: assertTrue(!iter.hasNext());
486: assertTrue(foundit);
487: }
488: }
489:
490: public void testRowIdsAreFreedOnRollback() throws Exception {
491: assertEquals(2, _ttable.getRowCount());
492: // add a row to the ttable
493: {
494: Row row = new SimpleRow(2);
495: row.set(0, new Integer(3));
496: row.set(1, "three");
497: _ttable.addRow(row);
498: }
499: assertEquals(3, _ttable.getRowCount());
500:
501: // find the new row and its row id
502: int insertedRowId = -1;
503: {
504: RowIterator iter = _ttable.getRowIterator(true);
505: assertNotNull(iter);
506: boolean foundit = false;
507: for (int i = 0; i < 3; i++) {
508: assertTrue(iter.hasNext());
509: Row row = iter.next();
510: assertNotNull(row);
511: if ("three".equals(row.get(1))) {
512: foundit = true;
513: insertedRowId = row.getIdentifier();
514: iter.remove();
515: break;
516: }
517: }
518: assertTrue(foundit);
519: }
520:
521: // rollback
522: _ttable.rollback();
523:
524: assertEquals(2, _table.getRowCount());
525:
526: // see that the row id was returend to the _table
527: assertEquals(insertedRowId, _table.getNextRowId());
528: }
529:
530: public void testApply() throws Exception {
531: // TODO: should add update/delete actions to this also
532: assertEquals(2, _table.getRowCount());
533: assertEquals(2, _ttable.getRowCount());
534:
535: // add a row to the ttable
536: {
537: Row row = new SimpleRow(2);
538: row.set(0, new Integer(3));
539: row.set(1, "three");
540: _ttable.addRow(row);
541: }
542:
543: int insertedRowId = -1;
544: // see that we can find it in the ttable
545: {
546: assertEquals(3, _ttable.getRowCount());
547: RowIterator iter = _ttable.getRowIterator(true);
548: assertNotNull(iter);
549: boolean foundit = false;
550: for (int i = 0; i < 3; i++) {
551: assertTrue(iter.hasNext());
552: Row row = iter.next();
553: assertNotNull(row);
554: if ("three".equals(row.get(1))) {
555: foundit = true;
556: insertedRowId = row.getIdentifier();
557: }
558: }
559: assertTrue(!iter.hasNext());
560: assertTrue(foundit);
561:
562: Row row = _ttable.getRow(insertedRowId);
563: assertNotNull(row);
564: assertEquals("three", row.get(1));
565: }
566:
567: // but not in the underlying table
568: {
569: boolean foundit = false;
570: assertEquals(2, _table.getRowCount());
571: RowIterator iter = _table.getRowIterator(true);
572: assertNotNull(iter);
573: for (int i = 0; i < 2; i++) {
574: assertTrue(iter.hasNext());
575: Row row = iter.next();
576: assertNotNull(row);
577: if ("three".equals(row.get(1))) {
578: foundit = true;
579: }
580: }
581: assertTrue(!iter.hasNext());
582: assertTrue(!foundit);
583:
584: assertNull(_table.getRow(insertedRowId));
585: }
586:
587: // apply the change
588: _ttable.commit();
589: _ttable.apply();
590:
591: // see that we can find it in the table now
592: {
593: assertEquals(3, _table.getRowCount());
594: RowIterator iter = _table.getRowIterator(true);
595: assertNotNull(iter);
596: boolean foundit = false;
597: for (int i = 0; i < 3; i++) {
598: assertTrue(iter.hasNext());
599: Row row = iter.next();
600: assertNotNull(row);
601: if ("three".equals(row.get(1))) {
602: foundit = true;
603: insertedRowId = row.getIdentifier();
604: }
605: }
606: assertTrue(!iter.hasNext());
607: assertTrue(foundit);
608:
609: Row row = _table.getRow(insertedRowId);
610: assertNotNull(row);
611: assertEquals("three", row.get(1));
612: }
613:
614: // see that we can find it in the index also
615: {
616: Function where = new LessThanFunction();
617: where.addArgument(new ColumnIdentifier(new TableIdentifier(
618: "TEST"), "ID", null, new IntegerType()));
619: where.addArgument(new Literal(new Integer(10),
620: new IntegerType()));
621:
622: RowIterator iter = _table.getIndexedRows(where, true);
623: assertNotNull(iter);
624: boolean foundit = false;
625: for (int i = 0; i < 3; i++) {
626: assertTrue(iter.hasNext());
627: Row row = iter.next();
628: assertNotNull(row);
629: if ("three".equals(row.get(1))) {
630: foundit = true;
631: insertedRowId = row.getIdentifier();
632: }
633: }
634: assertTrue(!iter.hasNext());
635: assertTrue(foundit);
636:
637: Row row = _table.getRow(insertedRowId);
638: assertNotNull(row);
639: assertEquals("three", row.get(1));
640: }
641:
642: }
643:
644: }
|