Index.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /* ---------------------------------------------------------------------------
  2. Nullsoft Database Engine
  3. --------------------
  4. codename: Near Death Experience
  5. --------------------------------------------------------------------------- */
  6. /* ---------------------------------------------------------------------------
  7. Raw Index Class
  8. --------------------------------------------------------------------------- */
  9. #include "nde.h"
  10. #include <stdio.h>
  11. const char *iSign="NDEINDEX";
  12. //---------------------------------------------------------------------------
  13. Index::Index(VFILE *H, unsigned char id, int pos, int type, bool newindex, int nentries, Table *parentTable)
  14. {
  15. Handle = H;
  16. IndexTable = NULL;
  17. MaxSize=0;
  18. locateUpToDate = false;
  19. Id = id;
  20. Position = pos;
  21. // DataType = type;
  22. SecIndex = NULL;
  23. InChain=false;
  24. InInsert=false;
  25. InChainIdx = -1;
  26. pTable = parentTable;
  27. TableHandle = pTable->Handle;
  28. SetGlobalLocateUpToDate(false);
  29. if (!newindex)
  30. {
  31. Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__), SEEK_SET);
  32. Vfread(&NEntries, sizeof(NEntries), Handle);
  33. }
  34. else
  35. NEntries = nentries;
  36. LoadIndex(newindex);
  37. }
  38. //---------------------------------------------------------------------------
  39. Index::~Index()
  40. {
  41. if (IndexTable)
  42. free(IndexTable);
  43. }
  44. //---------------------------------------------------------------------------
  45. int Index::Insert(int N)
  46. {
  47. return Insert(NULL, N, false);
  48. }
  49. //---------------------------------------------------------------------------
  50. int Index::Insert(Index *parindex, int N, bool localonly)
  51. {
  52. if (InChain) return -1;
  53. Index *p = parindex;
  54. IndexField *f = 0;
  55. locateUpToDate = false;
  56. SetGlobalLocateUpToDate(false);
  57. InInsert=true;
  58. if (N > NEntries) N = NEntries;
  59. if ((NEntries+1) > (int)MaxSize)
  60. {
  61. MaxSize *=2;//+= BLOCK_SIZE;
  62. int *newBlock = (int *)calloc(MaxSize, sizeof(int)*2);
  63. memcpy(newBlock, IndexTable, NEntries*sizeof(int)*2);
  64. free(IndexTable);
  65. IndexTable = newBlock;
  66. }
  67. if (N < NEntries && Id == PRIMARY_INDEX)
  68. {
  69. memmove(IndexTable+(N+1)*2, IndexTable+(N*2), (NEntries-N)*sizeof(int)*2);
  70. NEntries++;
  71. }
  72. else
  73. {
  74. N=NEntries;
  75. NEntries++;
  76. }
  77. Update(N, 0, NULL, localonly);
  78. // Should be always safe to cat the new record since if we are primary index,
  79. // then secondary is sorted, so value will be moved at update
  80. // if we are a secondary index, then an insertion will insert at the end of the primary index anyway
  81. if (!localonly && SecIndex)
  82. {
  83. InChain=true;
  84. int pp = SecIndex->index->Insert(this, N, false);
  85. InChain=false;
  86. IndexTable[N*2+1] = pp == -1 ? N : pp;
  87. if (N < NEntries-1 && Id == PRIMARY_INDEX)
  88. {
  89. int pidx = -1;
  90. if (!parindex)
  91. {
  92. int v = pp;
  93. f = SecIndex;
  94. if (f)
  95. {
  96. while (f->index->SecIndex->index != this)
  97. {
  98. v = f->index->GetCooperative(v);
  99. f = f->index->SecIndex;
  100. }
  101. p = f->index;
  102. pidx = v;
  103. }
  104. }
  105. if (p && pidx != -1)
  106. {
  107. p->SetCooperative(pidx, N);
  108. UpdateMe(p, N, NEntries);
  109. }
  110. }
  111. }
  112. InInsert=false;
  113. return N;
  114. }
  115. //---------------------------------------------------------------------------
  116. void Index::LoadIndex(bool newindex)
  117. {
  118. if (IndexTable)
  119. free(IndexTable);
  120. MaxSize = ((NEntries) / BLOCK_SIZE + 1) * BLOCK_SIZE;
  121. IndexTable = (int *)calloc(MaxSize, sizeof(int)*2);
  122. if (!newindex)
  123. {
  124. Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__)+4+((NEntries*4*2)+4)*(Position+1), SEEK_SET);
  125. int v = 0;
  126. Vfread(&v, sizeof(v), Handle);
  127. Id = (unsigned char)v;
  128. Vfread(IndexTable, NEntries*2*sizeof(int), Handle);
  129. }
  130. }
  131. //---------------------------------------------------------------------------
  132. int Index::Update(int Idx, int Pos, RecordBase *record, bool localonly)
  133. {
  134. return Update(NULL, -1, Idx, Pos, record, false, localonly);
  135. }
  136. //---------------------------------------------------------------------------
  137. int Index::Update(Index *parindex, int paridx, int Idx, int Pos, RecordBase *record, bool forceLast, bool localonly)
  138. {
  139. if (InChain) return InChainIdx;
  140. int NewIdx=Idx;
  141. int oldSecPtr = IndexTable[Idx*2+1];
  142. if (!forceLast && Id == PRIMARY_INDEX || record == NULL || Idx < NUM_SPECIAL_RECORDS)
  143. {
  144. if (Idx < NEntries && Idx >= 0)
  145. {
  146. IndexTable[Idx*2] = Pos;
  147. if (!localonly && SecIndex && SecIndex->index != this && !InInsert)
  148. {
  149. InChain=true;
  150. InChainIdx = Idx;
  151. SecIndex->index->Update(this, Idx, IndexTable[Idx*2+1], Pos, record, forceLast, false);
  152. InChainIdx = -1;
  153. InChain=false;
  154. }
  155. }
  156. else
  157. {
  158. #ifdef WIN32
  159. MessageBox(NULL, L"Updating outside range", L"Oops", 16);
  160. #else
  161. printf("NDE Error: updating outside range!\n");
  162. #endif
  163. }
  164. }
  165. else
  166. {
  167. if (forceLast)
  168. NewIdx = NEntries;
  169. else
  170. {
  171. if (Pos != Get(Idx) || Id != PRIMARY_INDEX)
  172. {
  173. int state = 0;
  174. NewIdx = FindSortedPlace(record->GetField(Id), Idx, &state, QFIND_ENTIRE_SCOPE);
  175. }
  176. }
  177. if (NewIdx <= NEntries && NewIdx >= NUM_SPECIAL_RECORDS)
  178. {
  179. if (NewIdx != Idx)
  180. {
  181. Index *p = parindex;
  182. IndexField *f = 0;
  183. int pidx = paridx;
  184. NewIdx = MoveIndex(Idx, NewIdx);
  185. if (SecIndex->index != this)
  186. {
  187. if (!parindex)
  188. {
  189. int v = GetCooperative(NewIdx);
  190. f = SecIndex;
  191. if (f)
  192. {
  193. while (f->index->SecIndex->index != this)
  194. {
  195. v = f->index->GetCooperative(v);
  196. f = f->index->SecIndex;
  197. }
  198. p = f->index;
  199. pidx = v;
  200. }
  201. }
  202. if (p)
  203. {
  204. p->SetCooperative(pidx, NewIdx);
  205. UpdateMe(p, NewIdx, Idx);
  206. }
  207. }
  208. }
  209. IndexTable[NewIdx*2] = Pos;
  210. if (!localonly && SecIndex && SecIndex->index != this && !InInsert) // Actually, we should never be InInsert and here, but lets cover our ass
  211. {
  212. InChain=true;
  213. InChainIdx = oldSecPtr;
  214. SecIndex->index->Update(this, NewIdx, oldSecPtr, Pos, record, forceLast, false);
  215. InChainIdx = -1;
  216. InChain=false;
  217. }
  218. }
  219. else
  220. {
  221. #ifdef WIN32
  222. MessageBox(NULL, L"QSort failed and tried to update index outside range", L"Oops", 16);
  223. #else
  224. printf("NDE Error: qsort failed and tried to update index outside range!\n");
  225. #endif
  226. }
  227. }
  228. locateUpToDate = false;
  229. SetGlobalLocateUpToDate(false);
  230. pTable->IndexModified();
  231. return NewIdx;
  232. }
  233. //---------------------------------------------------------------------------
  234. int Index::Get(int Idx)
  235. {
  236. if (Idx < NEntries)
  237. return IndexTable[Idx*2];
  238. else
  239. {
  240. #ifdef WIN32
  241. MessageBox(NULL, L"Requested index outside range", L"Oops", 16);
  242. #else
  243. printf("NDE Error: requested index outside range!\n");
  244. #endif
  245. return -1;
  246. }
  247. }
  248. //---------------------------------------------------------------------------
  249. void Index::Set(int Idx, int P)
  250. {
  251. if (Idx < NEntries)
  252. IndexTable[Idx*2]=P;
  253. else
  254. {
  255. #ifdef WIN32
  256. MessageBox(NULL, L"Updating index outside range", L"Oops", 16);
  257. #else
  258. printf("NDE Error: updating index outside range!\n");
  259. #endif
  260. }
  261. }
  262. //---------------------------------------------------------------------------
  263. void Index::WriteIndex(void)
  264. {
  265. if (Id == PRIMARY_INDEX)
  266. {
  267. Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__), SEEK_SET);
  268. Vfwrite(&NEntries, sizeof(NEntries), Handle);
  269. }
  270. Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__)+4+((NEntries*4*2)+4)*(Position+1), SEEK_SET);
  271. int v=(int)Id;
  272. Vfwrite(&v, sizeof(v), Handle);
  273. Vfwrite(IndexTable, NEntries*2*sizeof(int), Handle);
  274. }
  275. //---------------------------------------------------------------------------
  276. int Index::MoveIndex(int idx, int newidx)
  277. {
  278. if (idx == newidx)
  279. return newidx;
  280. int oldPos=IndexTable[idx*2], oldPtr=IndexTable[idx*2+1];
  281. if (NEntries > idx+1)
  282. memmove(IndexTable+idx*2, IndexTable+(idx+1)*2, (NEntries-idx)*sizeof(int)*2);
  283. if (newidx > idx)
  284. newidx--;
  285. if (NEntries > newidx)
  286. memmove(IndexTable+(newidx+1)*2, IndexTable+newidx*2, (NEntries-newidx-1)*sizeof(int)*2);
  287. IndexTable[newidx*2] = oldPos;
  288. IndexTable[newidx*2+1] = oldPtr;
  289. return newidx;
  290. }
  291. //---------------------------------------------------------------------------
  292. void Index::Colaborate(IndexField *secindex)
  293. {
  294. SecIndex = secindex;
  295. for (int i=0;i<NUM_SPECIAL_RECORDS;i++)
  296. /*secindex->index->*/SetCooperative(i, i);
  297. }
  298. //---------------------------------------------------------------------------
  299. void Index::Propagate(void)
  300. {
  301. int i;
  302. if (!SecIndex || SecIndex->ID == PRIMARY_INDEX) return;
  303. SecIndex->index->NEntries=NUM_SPECIAL_RECORDS;
  304. for (i=0;i<NUM_SPECIAL_RECORDS;i++)
  305. {
  306. SecIndex->index->Set(i, Get(i));
  307. SecIndex->index->SetCooperative(i, GetCooperative(i));
  308. }
  309. Scanner *s = pTable->NewScanner();
  310. if (!s)
  311. {
  312. #ifdef WIN32
  313. MessageBox(NULL, L"Failed to create a scanner in reindex", L"Oops", 16);
  314. #else
  315. printf("NDE Error: failed to create a scanner in reindex!\n");
  316. #endif
  317. return;
  318. }
  319. int *coopSave = (int *)calloc(NEntries, sizeof(int));
  320. if (!coopSave)
  321. {
  322. #ifdef WIN32
  323. MessageBox(NULL, L"Alloc failed in reindex", L"Oops", 16);
  324. #else
  325. printf("NDE Error: alloc failed in reindex!\n");
  326. #endif
  327. return;
  328. }
  329. for (i=0;i<NEntries;i++)
  330. {
  331. coopSave[i] = GetCooperative(i);
  332. SetCooperative(i, i);
  333. }
  334. if (SecIndex->index->SecIndex->index->Id != PRIMARY_INDEX)
  335. {
  336. #ifdef WIN32
  337. MessageBox(NULL, L"Propagating existing index", L"Oops", 16);
  338. #else
  339. printf("NDE Error: propagating existing index!\n");
  340. #endif
  341. free(coopSave);
  342. return;
  343. }
  344. s->SetWorkingIndexById(-1);
  345. for (i=NUM_SPECIAL_RECORDS;i<NEntries;i++)
  346. {
  347. Record *rec = s->GetRecord(coopSave[i]);
  348. if (rec)
  349. {
  350. SecIndex->index->NEntries++;
  351. // SecIndex->index->Insert(NULL, i, true);
  352. SecIndex->index->SetCooperative(i, coopSave[i]);
  353. SecIndex->index->Set(i, Get(i));
  354. SecIndex->index->Update(i, SecIndex->index->Get(i), rec, true);
  355. /* SecIndex->index->SetCooperative(i, q);*/
  356. rec->Release();
  357. }
  358. else
  359. {
  360. #ifdef WIN32
  361. MessageBox(NULL, L"Unable to read record in reindex", L"Oops", 16);
  362. #else
  363. printf("NDE Error: unable to read record in reindex!\n");
  364. #endif
  365. }
  366. }
  367. free(coopSave);
  368. if (NEntries != SecIndex->index->NEntries) {
  369. #ifdef WIN32
  370. MessageBox(NULL, L"Secindex->NEntries desynchronized in reindex", L"Oops", 16);
  371. #else
  372. printf("NDE Error: Secindex->NEntries desynchronized in reindex!\n");
  373. #endif
  374. }
  375. pTable->DeleteScanner(s);
  376. }
  377. //---------------------------------------------------------------------------
  378. void Index::SetCooperative(int Idx, int secpos)
  379. {
  380. if (Idx < NEntries && Idx >= 0)
  381. IndexTable[Idx*2+1] = secpos;
  382. else
  383. {
  384. #ifdef WIN32
  385. MessageBox(NULL, L"Cooperative update outside range", L"Oops", 16);
  386. #else
  387. printf("NDE Error: cooperative update outside range!\n");
  388. #endif
  389. }
  390. }
  391. //---------------------------------------------------------------------------
  392. int Index::GetCooperative(int Idx)
  393. {
  394. if (Idx < NEntries && Idx >= 0)
  395. return IndexTable[Idx*2+1];
  396. else
  397. {
  398. #ifdef WIN32
  399. MessageBox(NULL, L"Cooperative request outside range", L"Oops", 16);
  400. #else
  401. printf("NDE Error: cooperative request outside range!\n");
  402. #endif
  403. }
  404. return -1;
  405. }
  406. //---------------------------------------------------------------------------
  407. int Index::NeedFix() {
  408. for (int i=NUM_SPECIAL_RECORDS;i<NEntries;i++) {
  409. if (IndexTable[i*2+1] <= 0) return 1;
  410. }
  411. return 0;
  412. }
  413. //---------------------------------------------------------------------------
  414. void Index::UpdateMe(Index *Me, int NewIdx, int OldIdx)
  415. {
  416. int j=NewIdx > OldIdx ? -1 : 1;
  417. for (int i=min(NewIdx, OldIdx);i<=max(NewIdx, OldIdx)&&i<NEntries;i++)
  418. {
  419. if (i == NewIdx) continue;
  420. int v = GetCooperative(i);
  421. IndexField *f = SecIndex;
  422. while (f->index->SecIndex->index != this)
  423. {
  424. v = f->index->GetCooperative(v);
  425. f = f->index->SecIndex;
  426. }
  427. Me->SetCooperative(v, Me->GetCooperative(v)+j);
  428. }
  429. }
  430. //---------------------------------------------------------------------------
  431. Field *Index::QuickFindField(unsigned char Idx, int Pos)
  432. {
  433. int ThisPos = Pos;
  434. while (ThisPos)
  435. {
  436. Vfseek(TableHandle, ThisPos, SEEK_SET);
  437. Field entry(ThisPos);
  438. uint32_t next_pos;
  439. entry.ReadField(pTable, ThisPos, true, &next_pos);
  440. if (entry.GetFieldId() == Idx)
  441. {
  442. return entry.ReadField(pTable, ThisPos);
  443. }
  444. ThisPos = next_pos;
  445. }
  446. return NULL;
  447. }
  448. //---------------------------------------------------------------------------
  449. // Dynamic qsort (i definitly rule)
  450. int Index::FindSortedPlace(Field *thisField, int curIdx, int *laststate, int start)
  451. {
  452. return FindSortedPlaceEx(thisField, curIdx, laststate, start, COMPARE_MODE_EXACT);
  453. }
  454. //---------------------------------------------------------------------------
  455. // and here again ugly switch
  456. int Index::FindSortedPlaceEx(Field *thisField, int curIdx, int *laststate, int start, int comp_mode)
  457. {
  458. int top=start != QFIND_ENTIRE_SCOPE ? start : NUM_SPECIAL_RECORDS;
  459. int bottom=NEntries-1;
  460. int compEntry = 0;
  461. int cePos = 0;
  462. Field *compField=NULL;
  463. int i = 0;
  464. Field *cfV=NULL;
  465. if (NEntries <= NUM_SPECIAL_RECORDS) return NUM_SPECIAL_RECORDS;
  466. switch(comp_mode)
  467. {
  468. case COMPARE_MODE_EXACT:
  469. while (bottom-top >= 1)
  470. {
  471. compEntry=(bottom-top)/2+top;
  472. if (compEntry == curIdx) compEntry++;
  473. if (compEntry == bottom) break;
  474. cePos = Get(compEntry);
  475. if (!cePos) bottom = compEntry;
  476. else
  477. {
  478. compField = QuickFindField(Id, Get(compEntry));
  479. cfV = compField;
  480. if (!thisField)
  481. {
  482. if (!compField) i = 0;
  483. else i = 1;
  484. }
  485. else i = thisField->Compare(cfV);
  486. switch (i)
  487. {
  488. case 1:
  489. top = compEntry+1;
  490. break;
  491. case -1:
  492. bottom = compEntry-1;
  493. break;
  494. case 0:
  495. *laststate=0;
  496. delete compField;
  497. return compEntry+1;
  498. }
  499. delete compField;
  500. }
  501. }
  502. compEntry=(bottom-top)/2+top;
  503. if (compEntry == curIdx) return curIdx;
  504. compField = QuickFindField(Id, Get(compEntry));
  505. cfV = compField;
  506. if (thisField) *laststate = thisField->Compare(cfV);
  507. else
  508. {
  509. if (!compField) *laststate = 0;
  510. else *laststate = 1;
  511. }
  512. break;
  513. case COMPARE_MODE_CONTAINS:
  514. while (bottom-top >= 1)
  515. {
  516. compEntry=(bottom-top)/2+top;
  517. if (compEntry == curIdx) compEntry++;
  518. if (compEntry == bottom) break;
  519. cePos = Get(compEntry);
  520. if (!cePos) bottom = compEntry;
  521. else
  522. {
  523. compField = QuickFindField(Id, Get(compEntry));
  524. cfV = compField;
  525. if (!thisField)
  526. {
  527. if (!compField) i = 0;
  528. else i = 1;
  529. }
  530. else i = thisField->Contains(cfV);
  531. switch (i)
  532. {
  533. case 1:
  534. top = compEntry+1;
  535. break;
  536. case -1:
  537. bottom = compEntry-1;
  538. break;
  539. case 0:
  540. *laststate=0;
  541. delete compField;
  542. return compEntry+1;
  543. }
  544. if (compField)
  545. {
  546. delete compField;
  547. }
  548. }
  549. }
  550. compEntry=(bottom-top)/2+top;
  551. if (compEntry == curIdx) return curIdx;
  552. compField = QuickFindField(Id, Get(compEntry));
  553. cfV = compField;
  554. if (thisField) *laststate = thisField->Contains(cfV);
  555. else
  556. {
  557. if (!compField) *laststate = 0;
  558. else *laststate = 1;
  559. }
  560. break;
  561. case COMPARE_MODE_STARTS:
  562. while (bottom-top >= 1)
  563. {
  564. compEntry=(bottom-top)/2+top;
  565. if (compEntry == curIdx) compEntry++;
  566. if (compEntry == bottom) break;
  567. cePos = Get(compEntry);
  568. if (!cePos) bottom = compEntry;
  569. else
  570. {
  571. compField = QuickFindField(Id, Get(compEntry));
  572. cfV = compField;
  573. if (!thisField)
  574. {
  575. if (!compField) i = 0;
  576. else i = 1;
  577. }
  578. else i = thisField->Starts(cfV);
  579. switch (i)
  580. {
  581. case 1:
  582. top = compEntry+1;
  583. break;
  584. case -1:
  585. bottom = compEntry-1;
  586. break;
  587. case 0:
  588. *laststate=0;
  589. delete compField;
  590. return compEntry+1;
  591. }
  592. if (compField)
  593. {
  594. delete compField;
  595. }
  596. }
  597. }
  598. compEntry=(bottom-top)/2+top;
  599. if (compEntry == curIdx) return curIdx;
  600. compField = QuickFindField(Id, Get(compEntry));
  601. cfV = compField;
  602. if (thisField) *laststate = thisField->Starts(cfV);
  603. else
  604. {
  605. if (!compField) *laststate = 0;
  606. else *laststate = 1;
  607. }
  608. break;
  609. }
  610. switch (*laststate)
  611. {
  612. case -1:
  613. delete compField;
  614. return compEntry;
  615. case 1:
  616. case 0:
  617. delete compField;
  618. return /*compEntry==NEntries-1 ? compEntry : */compEntry+1;
  619. }
  620. return NUM_SPECIAL_RECORDS; // we're not supposed to be here :/
  621. }
  622. int Index::QuickFind(int Id, Field *field, int start)
  623. {
  624. return QuickFindEx(Id, field, start, COMPARE_MODE_EXACT);
  625. }
  626. //---------------------------------------------------------------------------
  627. int Index::QuickFindEx(int Id, Field *field, int start, int comp_mode)
  628. {
  629. int laststate = 0;
  630. Field *compField=NULL, *cfV=NULL;
  631. int i = FindSortedPlaceEx(field, Id, &laststate, start, comp_mode)-1; // -1 because we don't insert but just search
  632. if (laststate != 0)
  633. return FIELD_NOT_FOUND;
  634. if (i < start)
  635. return FIELD_NOT_FOUND;
  636. switch(comp_mode)
  637. {
  638. case COMPARE_MODE_CONTAINS:
  639. while (--i>=NUM_SPECIAL_RECORDS)
  640. {
  641. compField = QuickFindField(Id, Get(i));
  642. cfV = compField;
  643. if (field->Contains(cfV) != 0)
  644. {
  645. if (compField)
  646. {
  647. delete compField;
  648. }
  649. return i+1;
  650. }
  651. if (compField)
  652. {
  653. delete compField;
  654. }
  655. }
  656. break;
  657. case COMPARE_MODE_EXACT:
  658. while (--i>=NUM_SPECIAL_RECORDS)
  659. {
  660. compField = QuickFindField(Id, Get(i));
  661. cfV = compField;
  662. if (field->Compare(cfV) != 0)
  663. {
  664. if (compField)
  665. {
  666. delete compField;
  667. }
  668. return i+1;
  669. }
  670. if (compField)
  671. {
  672. delete compField;
  673. }
  674. }
  675. break;
  676. case COMPARE_MODE_STARTS:
  677. while (--i>=NUM_SPECIAL_RECORDS)
  678. {
  679. compField = QuickFindField(Id, Get(i));
  680. cfV = compField;
  681. if (field->Starts(cfV) != 0)
  682. {
  683. delete compField;
  684. return i+1;
  685. }
  686. delete compField;
  687. }
  688. break;
  689. }
  690. return i+1;
  691. }
  692. //---------------------------------------------------------------------------
  693. int Index::TranslateIndex(int Pos, Index *index)
  694. {
  695. int v = GetCooperative(Pos);
  696. IndexField *f = SecIndex;
  697. while (f->index != this && f->index != index)
  698. {
  699. v = f->index->GetCooperative(v);
  700. f = f->index->SecIndex;
  701. }
  702. return v;
  703. }
  704. //---------------------------------------------------------------------------
  705. void Index::Delete(int Idx, int Pos, Record *record)
  706. {
  707. Update(NULL, -1, Idx, Pos, record, true, false);
  708. Shrink();
  709. }
  710. //---------------------------------------------------------------------------
  711. void Index::Shrink(void)
  712. {
  713. if (InChain) return;
  714. if (SecIndex && SecIndex->index != this) // Actually, we should never be InInsert and here, but lets cover our ass
  715. {
  716. InChain=true;
  717. SecIndex->index->Shrink();
  718. InChain=false;
  719. }
  720. NEntries--;
  721. }
  722. //---------------------------------------------------------------------------
  723. void Index::SetGlobalLocateUpToDate(bool isUptodate) {
  724. if (!pTable) return;
  725. pTable->SetGlobalLocateUpToDate(isUptodate);
  726. }
  727. unsigned char Index::GetId() {
  728. return Id;
  729. }