Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

CursorTest.java 50KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601
  1. /*
  2. Copyright (c) 2007 Health Market Science, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package com.healthmarketscience.jackcess;
  14. import java.util.ArrayList;
  15. import java.util.Arrays;
  16. import java.util.Collections;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.NoSuchElementException;
  21. import java.util.TreeSet;
  22. import java.util.stream.Collectors;
  23. import static com.healthmarketscience.jackcess.Database.*;
  24. import com.healthmarketscience.jackcess.impl.ColumnImpl;
  25. import com.healthmarketscience.jackcess.impl.JetFormatTest;
  26. import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
  27. import com.healthmarketscience.jackcess.impl.RowIdImpl;
  28. import com.healthmarketscience.jackcess.impl.TableImpl;
  29. import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher;
  30. import com.healthmarketscience.jackcess.util.ColumnMatcher;
  31. import com.healthmarketscience.jackcess.util.RowFilterTest;
  32. import com.healthmarketscience.jackcess.util.SimpleColumnMatcher;
  33. import junit.framework.TestCase;
  34. import static com.healthmarketscience.jackcess.TestUtil.*;
  35. import static com.healthmarketscience.jackcess.DatabaseBuilder.*;
  36. /**
  37. * @author James Ahlborn
  38. */
  39. public class CursorTest extends TestCase {
  40. static final List<TestDB> INDEX_CURSOR_DBS =
  41. TestDB.getSupportedForBasename(Basename.INDEX_CURSOR);
  42. public CursorTest(String name) throws Exception {
  43. super(name);
  44. }
  45. @Override
  46. protected void setUp() {
  47. TestUtil.setTestAutoSync(false);
  48. }
  49. @Override
  50. protected void tearDown() {
  51. TestUtil.clearTestAutoSync();
  52. }
  53. private static List<Map<String,Object>> createTestTableData()
  54. throws Exception
  55. {
  56. List<Map<String,Object>> expectedRows =
  57. new ArrayList<Map<String,Object>>();
  58. for(int i = 0; i < 10; ++i) {
  59. expectedRows.add(createExpectedRow("id", i, "value", "data" + i));
  60. }
  61. return expectedRows;
  62. }
  63. private static List<Map<String,Object>> createTestTableData(
  64. int startIdx,
  65. int endIdx)
  66. throws Exception
  67. {
  68. List<Map<String,Object>> expectedRows = createTestTableData();
  69. expectedRows.subList(endIdx, expectedRows.size()).clear();
  70. expectedRows.subList(0, startIdx).clear();
  71. return expectedRows;
  72. }
  73. private static Database createTestTable(final FileFormat fileFormat)
  74. throws Exception
  75. {
  76. Database db = createMem(fileFormat);
  77. Table table = newTable("test")
  78. .addColumn(newColumn("id", DataType.LONG))
  79. .addColumn(newColumn("value", DataType.TEXT))
  80. .toTable(db);
  81. for(Map<String,Object> row : createTestTableData()) {
  82. table.addRow(row.get("id"), row.get("value"));
  83. }
  84. return db;
  85. }
  86. private static List<Map<String,Object>> createUnorderedTestTableData()
  87. throws Exception
  88. {
  89. List<Map<String,Object>> expectedRows =
  90. new ArrayList<Map<String,Object>>();
  91. int[] ids = new int[]{3, 7, 6, 1, 2, 9, 0, 5, 4, 8};
  92. for(int i : ids) {
  93. expectedRows.add(createExpectedRow("id", i, "value", "data" + i));
  94. }
  95. return expectedRows;
  96. }
  97. static Database createTestIndexTable(final TestDB indexCursorDB)
  98. throws Exception
  99. {
  100. Database db = openMem(indexCursorDB);
  101. Table table = db.getTable("test");
  102. for(Map<String,Object> row : createUnorderedTestTableData()) {
  103. table.addRow(row.get("id"), row.get("value"));
  104. }
  105. return db;
  106. }
  107. private static List<Map<String,Object>> createDupeTestTableData()
  108. throws Exception
  109. {
  110. List<Map<String,Object>> expectedRows =
  111. new ArrayList<Map<String,Object>>();
  112. int[] ids = new int[]{3, 7, 6, 1, 2, 9, 0, 5, 4, 8};
  113. for(int i : ids) {
  114. expectedRows.add(createExpectedRow("id", i, "value", "data" + (i % 3)));
  115. }
  116. for(int i : ids) {
  117. expectedRows.add(createExpectedRow("id", i, "value", "data" + (i % 5)));
  118. }
  119. return expectedRows;
  120. }
  121. private static Database createDupeTestTable(final FileFormat fileFormat)
  122. throws Exception
  123. {
  124. Database db = createMem(fileFormat);
  125. Table table = newTable("test")
  126. .addColumn(newColumn("id", DataType.LONG))
  127. .addColumn(newColumn("value", DataType.TEXT))
  128. .toTable(db);
  129. for(Map<String,Object> row : createDupeTestTableData()) {
  130. table.addRow(row.get("id"), row.get("value"));
  131. }
  132. return db;
  133. }
  134. static Database createDupeTestTable(final TestDB indexCursorDB)
  135. throws Exception
  136. {
  137. Database db = openMem(indexCursorDB);
  138. Table table = db.getTable("test");
  139. for(Map<String,Object> row : createDupeTestTableData()) {
  140. table.addRow(row.get("id"), row.get("value"));
  141. }
  142. return db;
  143. }
  144. private static Cursor createIndexSubRangeCursor(Table table,
  145. Index idx,
  146. int type)
  147. throws Exception
  148. {
  149. return table.newCursor()
  150. .setIndex(idx)
  151. .setStartEntry(3 - type)
  152. .setStartRowInclusive(type == 0)
  153. .setEndEntry(8 + type)
  154. .setEndRowInclusive(type == 0)
  155. .toCursor();
  156. }
  157. public void testRowId() throws Exception {
  158. // test special cases
  159. RowIdImpl rowId1 = new RowIdImpl(1, 2);
  160. RowIdImpl rowId2 = new RowIdImpl(1, 3);
  161. RowIdImpl rowId3 = new RowIdImpl(2, 1);
  162. List<RowIdImpl> sortedRowIds =
  163. new ArrayList<RowIdImpl>(new TreeSet<RowIdImpl>(
  164. Arrays.asList(rowId1, rowId2, rowId3, RowIdImpl.FIRST_ROW_ID,
  165. RowIdImpl.LAST_ROW_ID)));
  166. assertEquals(Arrays.asList(RowIdImpl.FIRST_ROW_ID, rowId1, rowId2, rowId3,
  167. RowIdImpl.LAST_ROW_ID),
  168. sortedRowIds);
  169. }
  170. public void testSimple() throws Exception {
  171. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  172. Database db = createTestTable(fileFormat);
  173. Table table = db.getTable("test");
  174. Cursor cursor = CursorBuilder.createCursor(table);
  175. doTestSimple(cursor, null);
  176. db.close();
  177. }
  178. }
  179. private static void doTestSimple(Cursor cursor,
  180. List<Map<String, Object>> expectedRows)
  181. throws Exception
  182. {
  183. if(expectedRows == null) {
  184. expectedRows = createTestTableData();
  185. }
  186. List<Map<String, Object>> foundRows =
  187. new ArrayList<Map<String, Object>>();
  188. for(Map<String, Object> row : cursor) {
  189. foundRows.add(row);
  190. }
  191. assertEquals(expectedRows, foundRows);
  192. }
  193. public void testMove() throws Exception {
  194. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  195. Database db = createTestTable(fileFormat);
  196. Table table = db.getTable("test");
  197. Cursor cursor = CursorBuilder.createCursor(table);
  198. doTestMove(cursor, null);
  199. db.close();
  200. }
  201. }
  202. private static void doTestMove(Cursor cursor,
  203. List<Map<String, Object>> expectedRows)
  204. throws Exception
  205. {
  206. if(expectedRows == null) {
  207. expectedRows = createTestTableData();
  208. }
  209. expectedRows.subList(1, 4).clear();
  210. List<Map<String, Object>> foundRows =
  211. new ArrayList<Map<String, Object>>();
  212. assertTrue(cursor.isBeforeFirst());
  213. assertFalse(cursor.isAfterLast());
  214. foundRows.add(cursor.getNextRow());
  215. assertEquals(3, cursor.moveNextRows(3));
  216. assertFalse(cursor.isBeforeFirst());
  217. assertFalse(cursor.isAfterLast());
  218. Map<String,Object> expectedRow = cursor.getCurrentRow();
  219. Cursor.Savepoint savepoint = cursor.getSavepoint();
  220. assertEquals(2, cursor.movePreviousRows(2));
  221. assertEquals(2, cursor.moveNextRows(2));
  222. assertTrue(cursor.moveToNextRow());
  223. assertTrue(cursor.moveToPreviousRow());
  224. assertEquals(expectedRow, cursor.getCurrentRow());
  225. while(cursor.moveToNextRow()) {
  226. foundRows.add(cursor.getCurrentRow());
  227. }
  228. assertEquals(expectedRows, foundRows);
  229. assertFalse(cursor.isBeforeFirst());
  230. assertTrue(cursor.isAfterLast());
  231. assertEquals(0, cursor.moveNextRows(3));
  232. cursor.beforeFirst();
  233. assertTrue(cursor.isBeforeFirst());
  234. assertFalse(cursor.isAfterLast());
  235. cursor.afterLast();
  236. assertFalse(cursor.isBeforeFirst());
  237. assertTrue(cursor.isAfterLast());
  238. cursor.restoreSavepoint(savepoint);
  239. assertEquals(expectedRow, cursor.getCurrentRow());
  240. }
  241. public void testMoveNoReset() throws Exception {
  242. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  243. Database db = createTestTable(fileFormat);
  244. Table table = db.getTable("test");
  245. Cursor cursor = CursorBuilder.createCursor(table);
  246. doTestMoveNoReset(cursor);
  247. db.close();
  248. }
  249. }
  250. private static void doTestMoveNoReset(Cursor cursor)
  251. throws Exception
  252. {
  253. List<Map<String, Object>> expectedRows = createTestTableData();
  254. List<Map<String, Object>> foundRows = new ArrayList<Map<String, Object>>();
  255. Iterator<Row> iter = cursor.newIterable().iterator();
  256. for(int i = 0; i < 6; ++i) {
  257. foundRows.add(iter.next());
  258. }
  259. iter = cursor.newIterable().reset(false).reverse().iterator();
  260. iter.next();
  261. Map<String, Object> row = iter.next();
  262. assertEquals(expectedRows.get(4), row);
  263. iter = cursor.newIterable().reset(false).iterator();
  264. iter.next();
  265. row = iter.next();
  266. assertEquals(expectedRows.get(5), row);
  267. iter.next();
  268. iter = cursor.newIterable().reset(false).iterator();
  269. for(int i = 6; i < 10; ++i) {
  270. foundRows.add(iter.next());
  271. }
  272. assertEquals(expectedRows, foundRows);
  273. }
  274. public void testSearch() throws Exception {
  275. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  276. Database db = createTestTable(fileFormat);
  277. Table table = db.getTable("test");
  278. Cursor cursor = CursorBuilder.createCursor(table);
  279. doTestSearch(table, cursor, null, 42, -13);
  280. db.close();
  281. }
  282. }
  283. private static void doTestSearch(Table table, Cursor cursor, Index index,
  284. Integer... outOfRangeValues)
  285. throws Exception
  286. {
  287. assertTrue(cursor.findFirstRow(table.getColumn("id"), 3));
  288. assertEquals(createExpectedRow("id", 3,
  289. "value", "data" + 3),
  290. cursor.getCurrentRow());
  291. assertTrue(cursor.findFirstRow(createExpectedRow(
  292. "id", 6,
  293. "value", "data" + 6)));
  294. assertEquals(createExpectedRow("id", 6,
  295. "value", "data" + 6),
  296. cursor.getCurrentRow());
  297. assertFalse(cursor.findFirstRow(createExpectedRow(
  298. "id", 8,
  299. "value", "data" + 13)));
  300. assertFalse(cursor.findFirstRow(table.getColumn("id"), 13));
  301. assertEquals(createExpectedRow("id", 6,
  302. "value", "data" + 6),
  303. cursor.getCurrentRow());
  304. assertTrue(cursor.findFirstRow(createExpectedRow(
  305. "value", "data" + 7)));
  306. assertEquals(createExpectedRow("id", 7,
  307. "value", "data" + 7),
  308. cursor.getCurrentRow());
  309. assertTrue(cursor.findFirstRow(table.getColumn("value"), "data" + 4));
  310. assertEquals(createExpectedRow("id", 4,
  311. "value", "data" + 4),
  312. cursor.getCurrentRow());
  313. for(Integer outOfRangeValue : outOfRangeValues) {
  314. assertFalse(cursor.findFirstRow(table.getColumn("id"),
  315. outOfRangeValue));
  316. assertFalse(cursor.findFirstRow(table.getColumn("value"),
  317. "data" + outOfRangeValue));
  318. assertFalse(cursor.findFirstRow(createExpectedRow(
  319. "id", outOfRangeValue,
  320. "value", "data" + outOfRangeValue)));
  321. }
  322. assertEquals("data" + 5,
  323. CursorBuilder.findValue(table,
  324. table.getColumn("value"),
  325. table.getColumn("id"), 5));
  326. assertEquals(createExpectedRow("id", 5,
  327. "value", "data" + 5),
  328. CursorBuilder.findRow(table,
  329. createExpectedRow("id", 5)));
  330. if(index != null) {
  331. assertEquals("data" + 5,
  332. CursorBuilder.findValue(index,
  333. table.getColumn("value"),
  334. table.getColumn("id"), 5));
  335. assertEquals(createExpectedRow("id", 5,
  336. "value", "data" + 5),
  337. CursorBuilder.findRow(index,
  338. createExpectedRow("id", 5)));
  339. assertNull(CursorBuilder.findValue(index,
  340. table.getColumn("value"),
  341. table.getColumn("id"),
  342. -17));
  343. assertNull(CursorBuilder.findRow(index,
  344. createExpectedRow("id", 13)));
  345. }
  346. }
  347. public void testReverse() throws Exception {
  348. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  349. Database db = createTestTable(fileFormat);
  350. Table table = db.getTable("test");
  351. Cursor cursor = CursorBuilder.createCursor(table);
  352. doTestReverse(cursor, null);
  353. db.close();
  354. }
  355. }
  356. private static void doTestReverse(Cursor cursor,
  357. List<Map<String, Object>> expectedRows)
  358. throws Exception
  359. {
  360. if(expectedRows == null) {
  361. expectedRows = createTestTableData();
  362. }
  363. Collections.reverse(expectedRows);
  364. List<Map<String, Object>> foundRows =
  365. new ArrayList<Map<String, Object>>();
  366. for(Map<String, Object> row : cursor.newIterable().reverse()) {
  367. foundRows.add(row);
  368. }
  369. assertEquals(expectedRows, foundRows);
  370. }
  371. public void testLiveAddition() throws Exception {
  372. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  373. Database db = createTestTable(fileFormat);
  374. Table table = db.getTable("test");
  375. Cursor cursor1 = CursorBuilder.createCursor(table);
  376. Cursor cursor2 = CursorBuilder.createCursor(table);
  377. doTestLiveAddition(table, cursor1, cursor2, 11);
  378. db.close();
  379. }
  380. }
  381. private static void doTestLiveAddition(Table table,
  382. Cursor cursor1,
  383. Cursor cursor2,
  384. Integer newRowNum) throws Exception
  385. {
  386. cursor1.moveNextRows(11);
  387. cursor2.moveNextRows(11);
  388. assertTrue(cursor1.isAfterLast());
  389. assertTrue(cursor2.isAfterLast());
  390. table.addRow(newRowNum, "data" + newRowNum);
  391. Map<String,Object> expectedRow =
  392. createExpectedRow("id", newRowNum, "value", "data" + newRowNum);
  393. assertFalse(cursor1.isAfterLast());
  394. assertFalse(cursor2.isAfterLast());
  395. assertEquals(expectedRow, cursor1.getCurrentRow());
  396. assertEquals(expectedRow, cursor2.getCurrentRow());
  397. assertFalse(cursor1.moveToNextRow());
  398. assertFalse(cursor2.moveToNextRow());
  399. assertTrue(cursor1.isAfterLast());
  400. assertTrue(cursor2.isAfterLast());
  401. }
  402. public void testLiveDeletion() throws Exception {
  403. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  404. Database db = createTestTable(fileFormat);
  405. Table table = db.getTable("test");
  406. Cursor cursor1 = CursorBuilder.createCursor(table);
  407. Cursor cursor2 = CursorBuilder.createCursor(table);
  408. Cursor cursor3 = CursorBuilder.createCursor(table);
  409. Cursor cursor4 = CursorBuilder.createCursor(table);
  410. doTestLiveDeletion(cursor1, cursor2, cursor3, cursor4, 1);
  411. db.close();
  412. }
  413. }
  414. private static void doTestLiveDeletion(
  415. Cursor cursor1,
  416. Cursor cursor2,
  417. Cursor cursor3,
  418. Cursor cursor4,
  419. int firstValue) throws Exception
  420. {
  421. assertEquals(2, cursor1.moveNextRows(2));
  422. assertEquals(3, cursor2.moveNextRows(3));
  423. assertEquals(3, cursor3.moveNextRows(3));
  424. assertEquals(4, cursor4.moveNextRows(4));
  425. Map<String,Object> expectedPrevRow =
  426. createExpectedRow("id", firstValue, "value", "data" + firstValue);
  427. ++firstValue;
  428. Map<String,Object> expectedDeletedRow =
  429. createExpectedRow("id", firstValue, "value", "data" + firstValue);
  430. ++firstValue;
  431. Map<String,Object> expectedNextRow =
  432. createExpectedRow("id", firstValue, "value", "data" + firstValue);
  433. assertEquals(expectedDeletedRow, cursor2.getCurrentRow());
  434. assertEquals(expectedDeletedRow, cursor3.getCurrentRow());
  435. assertFalse(cursor2.isCurrentRowDeleted());
  436. assertFalse(cursor3.isCurrentRowDeleted());
  437. cursor2.deleteCurrentRow();
  438. assertTrue(cursor2.isCurrentRowDeleted());
  439. assertTrue(cursor3.isCurrentRowDeleted());
  440. assertEquals(expectedNextRow, cursor1.getNextRow());
  441. assertEquals(expectedNextRow, cursor2.getNextRow());
  442. assertEquals(expectedNextRow, cursor3.getNextRow());
  443. assertEquals(expectedPrevRow, cursor3.getPreviousRow());
  444. assertTrue(cursor3.moveToNextRow());
  445. cursor3.deleteCurrentRow();
  446. assertTrue(cursor3.isCurrentRowDeleted());
  447. firstValue += 2;
  448. expectedNextRow =
  449. createExpectedRow("id", firstValue, "value", "data" + firstValue);
  450. assertTrue(cursor3.moveToNextRow());
  451. assertEquals(expectedNextRow, cursor3.getNextRow());
  452. cursor1.beforeFirst();
  453. assertTrue(cursor1.moveToNextRow());
  454. cursor1.deleteCurrentRow();
  455. assertFalse(cursor1.isBeforeFirst());
  456. assertFalse(cursor1.isAfterLast());
  457. assertFalse(cursor1.moveToPreviousRow());
  458. assertTrue(cursor1.isBeforeFirst());
  459. assertFalse(cursor1.isAfterLast());
  460. cursor1.afterLast();
  461. assertTrue(cursor1.moveToPreviousRow());
  462. cursor1.deleteCurrentRow();
  463. assertFalse(cursor1.isBeforeFirst());
  464. assertFalse(cursor1.isAfterLast());
  465. assertFalse(cursor1.moveToNextRow());
  466. assertFalse(cursor1.isBeforeFirst());
  467. assertTrue(cursor1.isAfterLast());
  468. cursor1.beforeFirst();
  469. while(cursor1.moveToNextRow()) {
  470. cursor1.deleteCurrentRow();
  471. }
  472. assertTrue(cursor1.isAfterLast());
  473. assertTrue(cursor2.isCurrentRowDeleted());
  474. assertTrue(cursor3.isCurrentRowDeleted());
  475. assertTrue(cursor4.isCurrentRowDeleted());
  476. }
  477. public void testSimpleIndex() throws Exception {
  478. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  479. Database db = createTestIndexTable(indexCursorDB);
  480. Table table = db.getTable("test");
  481. Index idx = table.getIndexes().get(0);
  482. assertTable(createUnorderedTestTableData(), table);
  483. Cursor cursor = CursorBuilder.createCursor(idx);
  484. doTestSimple(cursor, null);
  485. db.close();
  486. }
  487. }
  488. public void testMoveIndex() throws Exception {
  489. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  490. Database db = createTestIndexTable(indexCursorDB);
  491. Table table = db.getTable("test");
  492. Index idx = table.getIndexes().get(0);
  493. Cursor cursor = CursorBuilder.createCursor(idx);
  494. doTestMove(cursor, null);
  495. db.close();
  496. }
  497. }
  498. public void testReverseIndex() throws Exception {
  499. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  500. Database db = createTestIndexTable(indexCursorDB);
  501. Table table = db.getTable("test");
  502. Index idx = table.getIndexes().get(0);
  503. Cursor cursor = CursorBuilder.createCursor(idx);
  504. doTestReverse(cursor, null);
  505. db.close();
  506. }
  507. }
  508. public void testSearchIndex() throws Exception {
  509. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  510. Database db = createTestIndexTable(indexCursorDB);
  511. Table table = db.getTable("test");
  512. Index idx = table.getIndexes().get(0);
  513. Cursor cursor = CursorBuilder.createCursor(idx);
  514. doTestSearch(table, cursor, idx, 42, -13);
  515. db.close();
  516. }
  517. }
  518. public void testLiveAdditionIndex() throws Exception {
  519. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  520. Database db = createTestIndexTable(indexCursorDB);
  521. Table table = db.getTable("test");
  522. Index idx = table.getIndexes().get(0);
  523. Cursor cursor1 = CursorBuilder.createCursor(idx);
  524. Cursor cursor2 = CursorBuilder.createCursor(idx);
  525. doTestLiveAddition(table, cursor1, cursor2, 11);
  526. db.close();
  527. }
  528. }
  529. public void testLiveDeletionIndex() throws Exception {
  530. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  531. Database db = createTestIndexTable(indexCursorDB);
  532. Table table = db.getTable("test");
  533. Index idx = table.getIndexes().get(0);
  534. Cursor cursor1 = CursorBuilder.createCursor(idx);
  535. Cursor cursor2 = CursorBuilder.createCursor(idx);
  536. Cursor cursor3 = CursorBuilder.createCursor(idx);
  537. Cursor cursor4 = CursorBuilder.createCursor(idx);
  538. doTestLiveDeletion(cursor1, cursor2, cursor3, cursor4, 1);
  539. db.close();
  540. }
  541. }
  542. public void testSimpleIndexSubRange() throws Exception {
  543. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  544. for(int i = 0; i < 2; ++i) {
  545. Database db = createTestIndexTable(indexCursorDB);
  546. Table table = db.getTable("test");
  547. Index idx = table.getIndexes().get(0);
  548. Cursor cursor = createIndexSubRangeCursor(table, idx, i);
  549. List<Map<String,Object>> expectedRows =
  550. createTestTableData(3, 9);
  551. doTestSimple(cursor, expectedRows);
  552. db.close();
  553. }
  554. }
  555. }
  556. public void testMoveIndexSubRange() throws Exception {
  557. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  558. for(int i = 0; i < 2; ++i) {
  559. Database db = createTestIndexTable(indexCursorDB);
  560. Table table = db.getTable("test");
  561. Index idx = table.getIndexes().get(0);
  562. Cursor cursor = createIndexSubRangeCursor(table, idx, i);
  563. List<Map<String,Object>> expectedRows =
  564. createTestTableData(3, 9);
  565. doTestMove(cursor, expectedRows);
  566. db.close();
  567. }
  568. }
  569. }
  570. public void testSearchIndexSubRange() throws Exception {
  571. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  572. for(int i = 0; i < 2; ++i) {
  573. Database db = createTestIndexTable(indexCursorDB);
  574. Table table = db.getTable("test");
  575. Index idx = table.getIndexes().get(0);
  576. Cursor cursor = createIndexSubRangeCursor(table, idx, i);
  577. doTestSearch(table, cursor, idx, 2, 9);
  578. db.close();
  579. }
  580. }
  581. }
  582. public void testReverseIndexSubRange() throws Exception {
  583. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  584. for(int i = 0; i < 2; ++i) {
  585. Database db = createTestIndexTable(indexCursorDB);
  586. Table table = db.getTable("test");
  587. Index idx = table.getIndexes().get(0);
  588. Cursor cursor = createIndexSubRangeCursor(table, idx, i);
  589. List<Map<String,Object>> expectedRows =
  590. createTestTableData(3, 9);
  591. doTestReverse(cursor, expectedRows);
  592. db.close();
  593. }
  594. }
  595. }
  596. public void testLiveAdditionIndexSubRange() throws Exception {
  597. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  598. for(int i = 0; i < 2; ++i) {
  599. Database db = createTestIndexTable(indexCursorDB);
  600. Table table = db.getTable("test");
  601. Index idx = table.getIndexes().get(0);
  602. Cursor cursor1 = createIndexSubRangeCursor(table, idx, i);
  603. Cursor cursor2 = createIndexSubRangeCursor(table, idx, i);
  604. doTestLiveAddition(table, cursor1, cursor2, 8);
  605. db.close();
  606. }
  607. }
  608. }
  609. public void testLiveDeletionIndexSubRange() throws Exception {
  610. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  611. for(int i = 0; i < 2; ++i) {
  612. Database db = createTestIndexTable(indexCursorDB);
  613. Table table = db.getTable("test");
  614. Index idx = table.getIndexes().get(0);
  615. Cursor cursor1 = createIndexSubRangeCursor(table, idx, i);
  616. Cursor cursor2 = createIndexSubRangeCursor(table, idx, i);
  617. Cursor cursor3 = createIndexSubRangeCursor(table, idx, i);
  618. Cursor cursor4 = createIndexSubRangeCursor(table, idx, i);
  619. doTestLiveDeletion(cursor1, cursor2, cursor3, cursor4, 4);
  620. db.close();
  621. }
  622. }
  623. }
  624. public void testFindAllIndex() throws Exception {
  625. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  626. Database db = createDupeTestTable(fileFormat);
  627. Table table = db.getTable("test");
  628. Cursor cursor = CursorBuilder.createCursor(table);
  629. doTestFindAll(table, cursor, null);
  630. db.close();
  631. }
  632. }
  633. public void testFindAll() throws Exception {
  634. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  635. Database db = createDupeTestTable(indexCursorDB);
  636. Table table = db.getTable("test");
  637. Index idx = table.getIndexes().get(0);
  638. Cursor cursor = CursorBuilder.createCursor(idx);
  639. doTestFindAll(table, cursor, idx);
  640. db.close();
  641. }
  642. }
  643. private static void doTestFindAll(Table table, Cursor cursor, Index index)
  644. throws Exception
  645. {
  646. List<? extends Map<String,Object>> rows = RowFilterTest.toList(
  647. cursor.newIterable().setMatchPattern("value", "data2"));
  648. List<? extends Map<String, Object>> expectedRows = null;
  649. if(index == null) {
  650. expectedRows =
  651. createExpectedTable(
  652. createExpectedRow(
  653. "id", 2, "value", "data2"),
  654. createExpectedRow(
  655. "id", 5, "value", "data2"),
  656. createExpectedRow(
  657. "id", 8, "value", "data2"),
  658. createExpectedRow(
  659. "id", 7, "value", "data2"),
  660. createExpectedRow(
  661. "id", 2, "value", "data2"));
  662. } else {
  663. expectedRows =
  664. createExpectedTable(
  665. createExpectedRow(
  666. "id", 2, "value", "data2"),
  667. createExpectedRow(
  668. "id", 2, "value", "data2"),
  669. createExpectedRow(
  670. "id", 5, "value", "data2"),
  671. createExpectedRow(
  672. "id", 7, "value", "data2"),
  673. createExpectedRow(
  674. "id", 8, "value", "data2"));
  675. }
  676. assertEquals(expectedRows, rows);
  677. Column valCol = table.getColumn("value");
  678. rows = RowFilterTest.toList(
  679. cursor.newIterable().setMatchPattern(valCol, "data4"));
  680. if(index == null) {
  681. expectedRows =
  682. createExpectedTable(
  683. createExpectedRow(
  684. "id", 9, "value", "data4"),
  685. createExpectedRow(
  686. "id", 4, "value", "data4"));
  687. } else {
  688. expectedRows =
  689. createExpectedTable(
  690. createExpectedRow(
  691. "id", 4, "value", "data4"),
  692. createExpectedRow(
  693. "id", 9, "value", "data4"));
  694. }
  695. assertEquals(expectedRows, rows);
  696. rows = RowFilterTest.toList(
  697. cursor.newIterable().setMatchPattern(valCol, "data9"));
  698. assertTrue(rows.isEmpty());
  699. rows = RowFilterTest.toList(
  700. cursor.newIterable().setMatchPattern(
  701. Collections.singletonMap("id", 8)));
  702. expectedRows =
  703. createExpectedTable(
  704. createExpectedRow(
  705. "id", 8, "value", "data2"),
  706. createExpectedRow(
  707. "id", 8, "value", "data3"));
  708. assertEquals(expectedRows, rows);
  709. for(Map<String,Object> row : table) {
  710. List<Map<String,Object>> tmpRows = new ArrayList<Map<String,Object>>();
  711. for(Map<String,Object> tmpRow : cursor) {
  712. if(row.equals(tmpRow)) {
  713. tmpRows.add(tmpRow);
  714. }
  715. }
  716. expectedRows = tmpRows;
  717. assertFalse(expectedRows.isEmpty());
  718. rows = RowFilterTest.toList(cursor.newIterable().setMatchPattern(row));
  719. assertEquals(expectedRows, rows);
  720. }
  721. rows = RowFilterTest.toList(
  722. cursor.newIterable().addMatchPattern("id", 8)
  723. .addMatchPattern("value", "data13"));
  724. assertTrue(rows.isEmpty());
  725. }
  726. public void testId() throws Exception
  727. {
  728. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  729. Database db = createTestIndexTable(indexCursorDB);
  730. Table table = db.getTable("test");
  731. Index idx = table.getIndexes().get(0);
  732. Cursor tCursor = CursorBuilder.createCursor(table);
  733. Cursor iCursor = CursorBuilder.createCursor(idx);
  734. Cursor.Savepoint tSave = tCursor.getSavepoint();
  735. Cursor.Savepoint iSave = iCursor.getSavepoint();
  736. tCursor.restoreSavepoint(tSave);
  737. iCursor.restoreSavepoint(iSave);
  738. try {
  739. tCursor.restoreSavepoint(iSave);
  740. fail("IllegalArgumentException should have been thrown");
  741. } catch(IllegalArgumentException e) {
  742. // success
  743. }
  744. try {
  745. iCursor.restoreSavepoint(tSave);
  746. fail("IllegalArgumentException should have been thrown");
  747. } catch(IllegalArgumentException e) {
  748. // success
  749. }
  750. Cursor tCursor2 = CursorBuilder.createCursor(table);
  751. Cursor iCursor2 = CursorBuilder.createCursor(idx);
  752. tCursor2.restoreSavepoint(tSave);
  753. iCursor2.restoreSavepoint(iSave);
  754. db.close();
  755. }
  756. }
  757. public void testColumnMatcher() throws Exception {
  758. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  759. Database db = createTestTable(fileFormat);
  760. Table table = db.getTable("test");
  761. doTestMatchers(table, SimpleColumnMatcher.INSTANCE, false);
  762. doTestMatchers(table, CaseInsensitiveColumnMatcher.INSTANCE, true);
  763. Cursor cursor = CursorBuilder.createCursor(table);
  764. doTestMatcher(table, cursor, SimpleColumnMatcher.INSTANCE, false);
  765. doTestMatcher(table, cursor, CaseInsensitiveColumnMatcher.INSTANCE,
  766. true);
  767. db.close();
  768. }
  769. }
  770. private static void doTestMatchers(Table table, ColumnMatcher columnMatcher,
  771. boolean caseInsensitive)
  772. throws Exception
  773. {
  774. assertTrue(columnMatcher.matches(table, "value", null, null));
  775. assertFalse(columnMatcher.matches(table, "value", "foo", null));
  776. assertFalse(columnMatcher.matches(table, "value", null, "foo"));
  777. assertTrue(columnMatcher.matches(table, "value", "foo", "foo"));
  778. assertTrue(columnMatcher.matches(table, "value", "foo", "Foo")
  779. == caseInsensitive);
  780. assertFalse(columnMatcher.matches(table, "value", 13, null));
  781. assertFalse(columnMatcher.matches(table, "value", null, 13));
  782. assertTrue(columnMatcher.matches(table, "value", 13, 13));
  783. }
  784. private static void doTestMatcher(Table table, Cursor cursor,
  785. ColumnMatcher columnMatcher,
  786. boolean caseInsensitive)
  787. throws Exception
  788. {
  789. cursor.setColumnMatcher(columnMatcher);
  790. assertTrue(cursor.findFirstRow(table.getColumn("id"), 3));
  791. assertEquals(createExpectedRow("id", 3,
  792. "value", "data" + 3),
  793. cursor.getCurrentRow());
  794. assertTrue(cursor.findFirstRow(createExpectedRow(
  795. "id", 6,
  796. "value", "data" + 6)));
  797. assertEquals(createExpectedRow("id", 6,
  798. "value", "data" + 6),
  799. cursor.getCurrentRow());
  800. assertTrue(cursor.findFirstRow(createExpectedRow(
  801. "id", 6,
  802. "value", "Data" + 6)) == caseInsensitive);
  803. if(caseInsensitive) {
  804. assertEquals(createExpectedRow("id", 6,
  805. "value", "data" + 6),
  806. cursor.getCurrentRow());
  807. }
  808. assertFalse(cursor.findFirstRow(createExpectedRow(
  809. "id", 8,
  810. "value", "data" + 13)));
  811. assertFalse(cursor.findFirstRow(table.getColumn("id"), 13));
  812. assertEquals(createExpectedRow("id", 6,
  813. "value", "data" + 6),
  814. cursor.getCurrentRow());
  815. assertTrue(cursor.findFirstRow(createExpectedRow(
  816. "value", "data" + 7)));
  817. assertEquals(createExpectedRow("id", 7,
  818. "value", "data" + 7),
  819. cursor.getCurrentRow());
  820. assertTrue(cursor.findFirstRow(createExpectedRow(
  821. "value", "Data" + 7)) == caseInsensitive);
  822. if(caseInsensitive) {
  823. assertEquals(createExpectedRow("id", 7,
  824. "value", "data" + 7),
  825. cursor.getCurrentRow());
  826. }
  827. assertTrue(cursor.findFirstRow(table.getColumn("value"), "data" + 4));
  828. assertEquals(createExpectedRow("id", 4,
  829. "value", "data" + 4),
  830. cursor.getCurrentRow());
  831. assertTrue(cursor.findFirstRow(table.getColumn("value"), "Data" + 4)
  832. == caseInsensitive);
  833. if(caseInsensitive) {
  834. assertEquals(createExpectedRow("id", 4,
  835. "value", "data" + 4),
  836. cursor.getCurrentRow());
  837. }
  838. assertEquals(Arrays.asList(createExpectedRow("id", 4,
  839. "value", "data" + 4)),
  840. RowFilterTest.toList(
  841. cursor.newIterable()
  842. .setMatchPattern("value", "data4")
  843. .setColumnMatcher(SimpleColumnMatcher.INSTANCE)));
  844. assertEquals(Arrays.asList(createExpectedRow("id", 3,
  845. "value", "data" + 3)),
  846. RowFilterTest.toList(
  847. cursor.newIterable()
  848. .setMatchPattern("value", "DaTa3")
  849. .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)));
  850. assertEquals(Arrays.asList(createExpectedRow("id", 2,
  851. "value", "data" + 2)),
  852. RowFilterTest.toList(
  853. cursor.newIterable()
  854. .addMatchPattern("value", "DaTa2")
  855. .addMatchPattern("id", 2)
  856. .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)));
  857. }
  858. public void testIndexCursor() throws Exception
  859. {
  860. for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX, true)) {
  861. Database db = openMem(testDB);
  862. Table t1 = db.getTable("Table1");
  863. Index idx = t1.getIndex(IndexBuilder.PRIMARY_KEY_NAME);
  864. IndexCursor cursor = CursorBuilder.createCursor(idx);
  865. assertFalse(cursor.findFirstRowByEntry(-1));
  866. cursor.findClosestRowByEntry(-1);
  867. assertEquals(0, cursor.getCurrentRow().get("id"));
  868. assertTrue(cursor.findFirstRowByEntry(1));
  869. assertEquals(1, cursor.getCurrentRow().get("id"));
  870. cursor.findClosestRowByEntry(2);
  871. assertEquals(2, cursor.getCurrentRow().get("id"));
  872. assertFalse(cursor.findFirstRowByEntry(4));
  873. cursor.findClosestRowByEntry(4);
  874. assertTrue(cursor.isAfterLast());
  875. db.close();
  876. }
  877. }
  878. public void testIndexCursorDelete() throws Exception
  879. {
  880. for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) {
  881. Database db = openMem(testDB);
  882. Table t1 = db.getTable("Table1");
  883. Index idx = t1.getIndex("Table2Table1");
  884. IndexCursor cursor = CursorBuilder.createCursor(idx);
  885. List<String> expectedData = cursor.newEntryIterable(1)
  886. .addColumnNames("data")
  887. .stream().map(r -> r.getString("data"))
  888. .collect(Collectors.toList());
  889. assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
  890. expectedData = new ArrayList<String>();
  891. for(Iterator<? extends Row> iter =
  892. cursor.newEntryIterable(1).iterator();
  893. iter.hasNext(); ) {
  894. expectedData.add(iter.next().getString("data"));
  895. iter.remove();
  896. try {
  897. iter.remove();
  898. fail("IllegalArgumentException should have been thrown");
  899. } catch(IllegalStateException e) {
  900. // success
  901. }
  902. if(!iter.hasNext()) {
  903. try {
  904. iter.next();
  905. fail("NoSuchElementException should have been thrown");
  906. } catch(NoSuchElementException e) {
  907. // success
  908. }
  909. }
  910. }
  911. assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
  912. expectedData = new ArrayList<String>();
  913. for(Row row : cursor.newEntryIterable(1)
  914. .addColumnNames("data")) {
  915. expectedData.add(row.getString("data"));
  916. }
  917. assertTrue(expectedData.isEmpty());
  918. db.close();
  919. }
  920. }
  921. public void testCursorDelete() throws Exception
  922. {
  923. for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) {
  924. Database db = openMem(testDB);
  925. Table t1 = db.getTable("Table1");
  926. Cursor cursor = CursorBuilder.createCursor(t1);
  927. List<String> expectedData = cursor.newIterable().setColumnNames(
  928. Arrays.asList("otherfk1", "data")).stream()
  929. .filter(r -> r.get("otherfk1").equals(1))
  930. .map(r -> r.getString("data"))
  931. .collect(Collectors.toList());
  932. assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
  933. expectedData = new ArrayList<String>();
  934. for(Iterator<? extends Row> iter = cursor.iterator();
  935. iter.hasNext(); ) {
  936. Row row = iter.next();
  937. if(row.get("otherfk1").equals(1)) {
  938. expectedData.add(row.getString("data"));
  939. iter.remove();
  940. try {
  941. iter.remove();
  942. fail("IllegalArgumentException should have been thrown");
  943. } catch(IllegalStateException e) {
  944. // success
  945. }
  946. }
  947. if(!iter.hasNext()) {
  948. try {
  949. iter.next();
  950. fail("NoSuchElementException should have been thrown");
  951. } catch(NoSuchElementException e) {
  952. // success
  953. }
  954. }
  955. }
  956. assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
  957. expectedData = new ArrayList<String>();
  958. for(Row row : cursor.newIterable().setColumnNames(
  959. Arrays.asList("otherfk1", "data"))) {
  960. if(row.get("otherfk1").equals(1)) {
  961. expectedData.add(row.getString("data"));
  962. }
  963. }
  964. assertTrue(expectedData.isEmpty());
  965. db.close();
  966. }
  967. }
  968. public void testFindByRowId() throws Exception {
  969. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  970. Database db = createTestTable(fileFormat);
  971. Table table = db.getTable("test");
  972. Cursor cursor = CursorBuilder.createCursor(table);
  973. doTestFindByRowId(cursor);
  974. db.close();
  975. }
  976. }
  977. public void testFindByRowIdIndex() throws Exception {
  978. for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
  979. Database db = createTestIndexTable(indexCursorDB);
  980. Table table = db.getTable("test");
  981. Index idx = table.getIndexes().get(0);
  982. assertTable(createUnorderedTestTableData(), table);
  983. Cursor cursor = CursorBuilder.createCursor(idx);
  984. doTestFindByRowId(cursor);
  985. db.close();
  986. }
  987. }
  988. private static void doTestFindByRowId(Cursor cursor)
  989. throws Exception
  990. {
  991. for(int i = 0; i < 3; ++i) {
  992. cursor.moveToNextRow();
  993. }
  994. Row r1 = cursor.getCurrentRow();
  995. for(int i = 0; i < 3; ++i) {
  996. cursor.moveToNextRow();
  997. }
  998. Row r2 = cursor.getCurrentRow();
  999. doTestFindByRowId(cursor, r1, 2);
  1000. doTestFindByRowId(cursor, r2, 5);
  1001. }
  1002. private static void doTestFindByRowId(Cursor cursor, Row row, int id)
  1003. throws Exception
  1004. {
  1005. cursor.reset();
  1006. assertTrue(cursor.findRow(row.getId()));
  1007. Row rFound = cursor.getCurrentRow();
  1008. assertEquals(id, rFound.get("id"));
  1009. assertEquals(row, rFound);
  1010. Cursor.Savepoint save = cursor.getSavepoint();
  1011. assertTrue(cursor.moveToNextRow());
  1012. assertEquals(id + 1, cursor.getCurrentRow().get("id"));
  1013. cursor.restoreSavepoint(save);
  1014. assertTrue(cursor.moveToPreviousRow());
  1015. assertEquals(id - 1, cursor.getCurrentRow().get("id"));
  1016. assertFalse(cursor.findRow(RowIdImpl.FIRST_ROW_ID));
  1017. assertEquals(id - 1, cursor.getCurrentRow().get("id"));
  1018. }
  1019. public void testIterationEarlyExit() throws Exception {
  1020. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  1021. Database db = createMem(fileFormat);
  1022. Table table = newTable("test")
  1023. .addColumn(newColumn("id", DataType.LONG))
  1024. .addColumn(newColumn("value", DataType.TEXT))
  1025. .addColumn(newColumn("memo", DataType.MEMO))
  1026. .addIndex(newIndex("value_idx")
  1027. .addColumns("value"))
  1028. .toTable(db);
  1029. for(int i = 0; i < 20; ++i) {
  1030. Object memo = "memo-" + i;
  1031. table.addRow(i, "val-" + (i/2), memo);
  1032. }
  1033. // generate an "invalid" memo
  1034. byte[] b = new byte[12];
  1035. b[3] = (byte)0xC0;
  1036. table.addRow(20, "val-9", ColumnImpl.rawDataWrapper(b));
  1037. IndexCursor cursor = CursorBuilder.createCursor(
  1038. table.getIndex("value_idx"));
  1039. try {
  1040. cursor.newIterable()
  1041. .addMatchPattern("value", "val-9")
  1042. .addMatchPattern("memo", "anything")
  1043. .iterator().hasNext();
  1044. fail("RuntimeIOException should have been thrown");
  1045. } catch(RuntimeIOException ignored) {
  1046. // success
  1047. }
  1048. List<Row> rows = new ArrayList<Row>();
  1049. for (Row row : cursor.newIterable()
  1050. .addMatchPattern("value", "val-5")
  1051. .addMatchPattern("memo", "memo-11")) {
  1052. rows.add(row);
  1053. }
  1054. assertEquals(rows, createExpectedTable(
  1055. createExpectedRow("id", 11,
  1056. "value", "val-5",
  1057. "memo", "memo-11")));
  1058. assertFalse(cursor.newIterable()
  1059. .addMatchPattern("value", "val-31")
  1060. .addMatchPattern("memo", "anything")
  1061. .iterator().hasNext());
  1062. db.close();
  1063. }
  1064. }
  1065. public void testPartialIndexFind() throws Exception
  1066. {
  1067. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  1068. Database db = createMem(fileFormat);
  1069. TableImpl t = (TableImpl)newTable("Test")
  1070. .addColumn(newColumn("id", DataType.LONG))
  1071. .addColumn(newColumn("data1", DataType.TEXT))
  1072. .addColumn(newColumn("num2", DataType.LONG))
  1073. .addColumn(newColumn("key3", DataType.TEXT))
  1074. .addColumn(newColumn("value", DataType.TEXT))
  1075. .addIndex(newIndex("idx3").addColumns("data1", "num2", "key3"))
  1076. .toTable(db);
  1077. Index idx = t.findIndexForColumns(Arrays.asList("data1"),
  1078. TableImpl.IndexFeature.ANY_MATCH);
  1079. assertEquals("idx3", idx.getName());
  1080. idx = t.findIndexForColumns(Arrays.asList("data1", "num2"),
  1081. TableImpl.IndexFeature.ANY_MATCH);
  1082. assertEquals("idx3", idx.getName());
  1083. idx = t.findIndexForColumns(Arrays.asList("data1", "num2", "key3"),
  1084. TableImpl.IndexFeature.ANY_MATCH);
  1085. assertEquals("idx3", idx.getName());
  1086. assertNull(t.findIndexForColumns(Arrays.asList("num2"),
  1087. TableImpl.IndexFeature.ANY_MATCH));
  1088. assertNull(t.findIndexForColumns(Arrays.asList("data1", "key3"),
  1089. TableImpl.IndexFeature.ANY_MATCH));
  1090. assertNull(t.findIndexForColumns(Arrays.asList("data1"),
  1091. TableImpl.IndexFeature.EXACT_MATCH));
  1092. newIndex("idx2")
  1093. .addColumns("data1", "num2")
  1094. .addToTable(t);
  1095. idx = t.findIndexForColumns(Arrays.asList("data1"),
  1096. TableImpl.IndexFeature.ANY_MATCH);
  1097. assertEquals("idx2", idx.getName());
  1098. idx = t.findIndexForColumns(Arrays.asList("data1", "num2"),
  1099. TableImpl.IndexFeature.ANY_MATCH);
  1100. assertEquals("idx2", idx.getName());
  1101. idx = t.findIndexForColumns(Arrays.asList("data1", "num2", "key3"),
  1102. TableImpl.IndexFeature.ANY_MATCH);
  1103. assertEquals("idx3", idx.getName());
  1104. assertNull(t.findIndexForColumns(Arrays.asList("num2"),
  1105. TableImpl.IndexFeature.ANY_MATCH));
  1106. assertNull(t.findIndexForColumns(Arrays.asList("data1", "key3"),
  1107. TableImpl.IndexFeature.ANY_MATCH));
  1108. assertNull(t.findIndexForColumns(Arrays.asList("data1"),
  1109. TableImpl.IndexFeature.EXACT_MATCH));
  1110. newIndex("idx1")
  1111. .addColumns("data1")
  1112. .addToTable(t);
  1113. idx = t.findIndexForColumns(Arrays.asList("data1"),
  1114. TableImpl.IndexFeature.ANY_MATCH);
  1115. assertEquals("idx1", idx.getName());
  1116. idx = t.findIndexForColumns(Arrays.asList("data1", "num2"),
  1117. TableImpl.IndexFeature.ANY_MATCH);
  1118. assertEquals("idx2", idx.getName());
  1119. idx = t.findIndexForColumns(Arrays.asList("data1", "num2", "key3"),
  1120. TableImpl.IndexFeature.ANY_MATCH);
  1121. assertEquals("idx3", idx.getName());
  1122. assertNull(t.findIndexForColumns(Arrays.asList("num2"),
  1123. TableImpl.IndexFeature.ANY_MATCH));
  1124. assertNull(t.findIndexForColumns(Arrays.asList("data1", "key3"),
  1125. TableImpl.IndexFeature.ANY_MATCH));
  1126. db.close();
  1127. }
  1128. }
  1129. public void testPartialIndexLookup() throws Exception
  1130. {
  1131. for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
  1132. Database db = createMem(fileFormat);
  1133. TableImpl t = (TableImpl)newTable("Test")
  1134. .addColumn(newColumn("id", DataType.LONG))
  1135. .addColumn(newColumn("data1", DataType.TEXT))
  1136. .addColumn(newColumn("num2", DataType.LONG))
  1137. .addColumn(newColumn("key3", DataType.TEXT))
  1138. .addColumn(newColumn("value", DataType.TEXT))
  1139. .addIndex(newIndex("idx3")
  1140. .addColumns(true, "data1")
  1141. .addColumns(false, "num2")
  1142. .addColumns(true, "key3")
  1143. )
  1144. .toTable(db);
  1145. int id = 1;
  1146. for(String str : Arrays.asList("A", "B", "C", "D")) {
  1147. for(int i = 4; i >= 0; --i) {
  1148. // for(int i = 0; i < 5; ++i) {
  1149. for(int j = 1; j < 3; ++j) {
  1150. t.addRow(id, str, i, "K" + j, "value" + id);
  1151. ++id;
  1152. }
  1153. }
  1154. }
  1155. Index idx = t.getIndex("idx3");
  1156. doPartialIndexLookup(idx);
  1157. idx = newIndex("idx2")
  1158. .addColumns(true, "data1")
  1159. .addColumns(false, "num2")
  1160. .addToTable(t);
  1161. doPartialIndexLookup(idx);
  1162. idx = newIndex("idx1")
  1163. .addColumns(true, "data1")
  1164. .addToTable(t);
  1165. doPartialIndexLookup(idx);
  1166. db.close();
  1167. }
  1168. }
  1169. private static void doPartialIndexLookup(Index idx) throws Exception
  1170. {
  1171. int colCount = idx.getColumnCount();
  1172. IndexCursor c = idx.newCursor().toIndexCursor();
  1173. doFindFirstByEntry(c, 21, "C");
  1174. doFindFirstByEntry(c, null, "Z");
  1175. if(colCount > 1) {
  1176. doFindFirstByEntry(c, 23, "C", 3);
  1177. doFindFirstByEntry(c, null, "C", 20);
  1178. }
  1179. if(colCount > 2) {
  1180. doFindFirstByEntry(c, 27, "C", 1, "K1");
  1181. doFindFirstByEntry(c, null, "C", 4, "K3");
  1182. }
  1183. try {
  1184. if(colCount > 2) {
  1185. c.findFirstRowByEntry("C", 4, "K1", 14);
  1186. } else if(colCount > 1) {
  1187. c.findFirstRowByEntry("C", 4, "K1");
  1188. } else {
  1189. c.findFirstRowByEntry("C", 4);
  1190. }
  1191. fail("IllegalArgumentException should have been thrown");
  1192. } catch(IllegalArgumentException expected) {
  1193. // scucess
  1194. }
  1195. doFindByEntryRange(c, 11, 20, "B");
  1196. doFindByEntry(c, new int[]{}, "Z");
  1197. if(colCount > 1) {
  1198. doFindByEntryRange(c, 13, 14, "B", 3);
  1199. doFindByEntry(c, new int[]{}, "B", 20);
  1200. }
  1201. if(colCount > 2) {
  1202. doFindByEntryRange(c, 14, 14, "B", 3, "K2");
  1203. doFindByEntry(c, new int[]{}, "B", 3, "K3");
  1204. }
  1205. doFindByRow(idx, 13,
  1206. "data1", "B", "value", "value13");
  1207. doFindByRow(idx, 13,
  1208. "data1", "B", "key3", "K1", "value", "value13");
  1209. doFindByRow(idx, 13,
  1210. "data1", "B", "num2", 3, "key3", "K1", "value", "value13");
  1211. doFindByRow(idx, 13,
  1212. "num2", 3, "value", "value13");
  1213. doFindByRow(idx, 13,
  1214. "value", "value13");
  1215. doFindByRow(idx, null,
  1216. "data1", "B", "num2", 5, "key3", "K1", "value", "value13");
  1217. doFindByRow(idx, null,
  1218. "data1", "B", "value", "value4");
  1219. Column col = idx.getTable().getColumn("data1");
  1220. doFindValue(idx, 21, col, "C");
  1221. doFindValue(idx, null, col, "Z");
  1222. col = idx.getTable().getColumn("value");
  1223. doFindValue(idx, 21, col, "value21");
  1224. doFindValue(idx, null, col, "valueZ");
  1225. }
  1226. private static void doFindFirstByEntry(IndexCursor c, Integer expectedId,
  1227. Object... entry)
  1228. throws Exception
  1229. {
  1230. if(expectedId != null) {
  1231. assertTrue(c.findFirstRowByEntry(entry));
  1232. assertEquals(expectedId, c.getCurrentRow().get("id"));
  1233. } else {
  1234. assertFalse(c.findFirstRowByEntry(entry));
  1235. }
  1236. }
  1237. private static void doFindByEntryRange(IndexCursor c, int start, int end,
  1238. Object... entry)
  1239. {
  1240. List<Integer> expectedIds = new ArrayList<Integer>();
  1241. for(int i = start; i <= end; ++i) {
  1242. expectedIds.add(i);
  1243. }
  1244. doFindByEntry(c, expectedIds, entry);
  1245. }
  1246. private static void doFindByEntry(IndexCursor c, int[] ids,
  1247. Object... entry)
  1248. {
  1249. List<Integer> expectedIds = new ArrayList<Integer>();
  1250. for(int id : ids) {
  1251. expectedIds.add(id);
  1252. }
  1253. doFindByEntry(c, expectedIds, entry);
  1254. }
  1255. private static void doFindByEntry(IndexCursor c, List<Integer> expectedIds,
  1256. Object... entry)
  1257. {
  1258. List<Integer> foundIds = new ArrayList<Integer>();
  1259. for(Row row : c.newEntryIterable(entry)) {
  1260. foundIds.add((Integer)row.get("id"));
  1261. }
  1262. assertEquals(expectedIds, foundIds);
  1263. }
  1264. private static void doFindByRow(Index idx, Integer id, Object... rowPairs)
  1265. throws Exception
  1266. {
  1267. Map<String,Object> map = createExpectedRow(
  1268. rowPairs);
  1269. Row r = CursorBuilder.findRow(idx, map);
  1270. if(id != null) {
  1271. assertEquals(id, r.get("id"));
  1272. } else {
  1273. assertNull(r);
  1274. }
  1275. }
  1276. private static void doFindValue(Index idx, Integer id,
  1277. Column columnPattern, Object valuePattern)
  1278. throws Exception
  1279. {
  1280. Object value = CursorBuilder.findValue(
  1281. idx, idx.getTable().getColumn("id"), columnPattern, valuePattern);
  1282. if(id != null) {
  1283. assertEquals(id, value);
  1284. } else {
  1285. assertNull(value);
  1286. }
  1287. }
  1288. }