You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

blscan.c 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*-------------------------------------------------------------------------
  2. *
  3. * blscan.c
  4. * Bloom index scan functions.
  5. *
  6. * Copyright (c) 2016-2019, PostgreSQL Global Development Group
  7. *
  8. * IDENTIFICATION
  9. * contrib/bloom/blscan.c
  10. *
  11. *-------------------------------------------------------------------------
  12. */
  13. #include "postgres.h"
  14. #include "access/relscan.h"
  15. #include "pgstat.h"
  16. #include "miscadmin.h"
  17. #include "storage/bufmgr.h"
  18. #include "storage/lmgr.h"
  19. #include "utils/memutils.h"
  20. #include "utils/rel.h"
  21. #include "bloom.h"
  22. /*
  23. * Begin scan of bloom index.
  24. */
  25. IndexScanDesc
  26. blbeginscan(Relation r, int nkeys, int norderbys)
  27. {
  28. IndexScanDesc scan;
  29. BloomScanOpaque so;
  30. scan = RelationGetIndexScan(r, nkeys, norderbys);
  31. so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
  32. initBloomState(&so->state, scan->indexRelation);
  33. so->sign = NULL;
  34. scan->opaque = so;
  35. return scan;
  36. }
  37. /*
  38. * Rescan a bloom index.
  39. */
  40. void
  41. blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
  42. ScanKey orderbys, int norderbys)
  43. {
  44. BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
  45. if (so->sign)
  46. pfree(so->sign);
  47. so->sign = NULL;
  48. if (scankey && scan->numberOfKeys > 0)
  49. {
  50. memmove(scan->keyData, scankey,
  51. scan->numberOfKeys * sizeof(ScanKeyData));
  52. }
  53. }
  54. /*
  55. * End scan of bloom index.
  56. */
  57. void
  58. blendscan(IndexScanDesc scan)
  59. {
  60. BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
  61. if (so->sign)
  62. pfree(so->sign);
  63. so->sign = NULL;
  64. }
  65. /*
  66. * Insert all matching tuples into a bitmap.
  67. */
  68. int64
  69. blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
  70. {
  71. int64 ntids = 0;
  72. BlockNumber blkno = BLOOM_HEAD_BLKNO,
  73. npages;
  74. int i;
  75. BufferAccessStrategy bas;
  76. BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
  77. if (so->sign == NULL)
  78. {
  79. /* New search: have to calculate search signature */
  80. ScanKey skey = scan->keyData;
  81. so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
  82. for (i = 0; i < scan->numberOfKeys; i++)
  83. {
  84. /*
  85. * Assume bloom-indexable operators to be strict, so nothing could
  86. * be found for NULL key.
  87. */
  88. if (skey->sk_flags & SK_ISNULL)
  89. {
  90. pfree(so->sign);
  91. so->sign = NULL;
  92. return 0;
  93. }
  94. /* Add next value to the signature */
  95. signValue(&so->state, so->sign, skey->sk_argument,
  96. skey->sk_attno - 1);
  97. skey++;
  98. }
  99. }
  100. /*
  101. * We're going to read the whole index. This is why we use appropriate
  102. * buffer access strategy.
  103. */
  104. bas = GetAccessStrategy(BAS_BULKREAD);
  105. npages = RelationGetNumberOfBlocks(scan->indexRelation);
  106. for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
  107. {
  108. Buffer buffer;
  109. Page page;
  110. buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
  111. blkno, RBM_NORMAL, bas);
  112. LockBuffer(buffer, BUFFER_LOCK_SHARE);
  113. page = BufferGetPage(buffer);
  114. TestForOldSnapshot(scan->xs_snapshot, scan->indexRelation, page);
  115. if (!PageIsNew(page) && !BloomPageIsDeleted(page))
  116. {
  117. OffsetNumber offset,
  118. maxOffset = BloomPageGetMaxOffset(page);
  119. for (offset = 1; offset <= maxOffset; offset++)
  120. {
  121. BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
  122. bool res = true;
  123. /* Check index signature with scan signature */
  124. for (i = 0; i < so->state.opts.bloomLength; i++)
  125. {
  126. if ((itup->sign[i] & so->sign[i]) != so->sign[i])
  127. {
  128. res = false;
  129. break;
  130. }
  131. }
  132. /* Add matching tuples to bitmap */
  133. if (res)
  134. {
  135. tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
  136. ntids++;
  137. }
  138. }
  139. }
  140. UnlockReleaseBuffer(buffer);
  141. CHECK_FOR_INTERRUPTS();
  142. }
  143. FreeAccessStrategy(bas);
  144. return ntids;
  145. }