/* * _bitmap_formitem() -- construct a LOV entry. * * We look at an attribute value and its associated bitmap as a bitmap * index entry. */ BMLOVItem _bitmap_formitem(uint64 currTidNumber) { int nbytes_bmitem; BMLOVItem bmitem; nbytes_bmitem = sizeof(BMLOVItemData); bmitem = (BMLOVItem)palloc(nbytes_bmitem); bmitem->bm_lov_head = bmitem->bm_lov_tail = InvalidBlockNumber; bmitem->bm_last_setbit = 0; bmitem->bm_last_two_headerbits = (1<<7); /* fill up all existing bits with 0. */ if (currTidNumber < BM_HRL_WORD_SIZE) { bmitem->bm_last_compword = LITERAL_ALL_ONE; bmitem->bm_last_word = LITERAL_ALL_ZERO; bmitem->bm_last_two_headerbits = 0; } else { uint32 numOfTotalFillWords; BM_HRL_WORD numOfFillWords; numOfTotalFillWords = (currTidNumber-1)/BM_HRL_WORD_SIZE; numOfFillWords = (numOfTotalFillWords >= MAX_FILL_LENGTH) ? MAX_FILL_LENGTH : numOfTotalFillWords; bmitem->bm_last_compword = BM_MAKE_FILL_WORD (0, numOfFillWords); bmitem->bm_last_word = LITERAL_ALL_ZERO; bmitem->bm_last_two_headerbits = 2; /* If number of zeros is too much for one word, then we set bm_last_setbit so that the remaining zeros can be handled outside. */ if (numOfTotalFillWords > numOfFillWords) bmitem->bm_last_setbit = numOfFillWords*BM_HRL_WORD_SIZE; } return bmitem; }
/* * _bitmap_formitem() -- construct a LOV entry. * * If the given tid number is greater than BM_HRL_WORD_SIZE, we * construct the first fill word for this bitmap vector. */ BMLOVItem _bitmap_formitem(uint64 currTidNumber) { int nbytes_bmitem; BMLOVItem bmitem; nbytes_bmitem = sizeof(BMLOVItemData); bmitem = (BMLOVItem)palloc(sizeof(BMLOVItemData)); bmitem->bm_lov_head = bmitem->bm_lov_tail = InvalidBlockNumber; bmitem->bm_last_setbit = 0; bmitem->bm_last_compword = LITERAL_ALL_ONE; bmitem->bm_last_word = LITERAL_ALL_ZERO; bmitem->lov_words_header = 0; bmitem->bm_last_tid_location = 0; /* fill up all existing bits with 0. */ if (currTidNumber <= BM_HRL_WORD_SIZE) { bmitem->bm_last_compword = LITERAL_ALL_ONE; bmitem->bm_last_word = LITERAL_ALL_ZERO; bmitem->lov_words_header = 0; bmitem->bm_last_tid_location = 0; } else { uint64 numOfTotalFillWords; BM_HRL_WORD numOfFillWords; numOfTotalFillWords = (currTidNumber-1)/BM_HRL_WORD_SIZE; numOfFillWords = (numOfTotalFillWords >= MAX_FILL_LENGTH) ? MAX_FILL_LENGTH : numOfTotalFillWords; bmitem->bm_last_compword = BM_MAKE_FILL_WORD(0, numOfFillWords); bmitem->bm_last_word = LITERAL_ALL_ZERO; bmitem->lov_words_header = 2; bmitem->bm_last_tid_location = numOfFillWords * BM_HRL_WORD_SIZE; bmitem->bm_last_setbit = numOfFillWords*BM_HRL_WORD_SIZE; } return bmitem; }
/* * _bitmap_union() -- union 'numBatches' bitmaps * * All bitmap words are HRL compressed. The result bitmap words are also * HRL compressed, except that fill unset words may be lossily compressed. */ void _bitmap_union(BMBatchWords **batches, uint32 numBatches, BMBatchWords *result) { bool done = false; uint32 *prevstarts; uint64 nextReadNo; uint64 batchNo; Assert ((int)numBatches >= 0); if (numBatches == 0) return; /* save batch->startNo for each input bitmap vector */ prevstarts = (uint32 *)palloc0(numBatches * sizeof(uint32)); /* * Compute the next read offset. We fast forward compressed * zero words when possible. */ nextReadNo = fast_forward(numBatches, batches, result); while (!done && result->nwords < result->maxNumOfWords) { BM_HRL_WORD orWord = LITERAL_ALL_ZERO; BM_HRL_WORD word; bool orWordIsLiteral = true; for (batchNo = 0; batchNo < numBatches; batchNo++) { BMBatchWords *bch = batches[batchNo]; /* skip nextReadNo - nwordsread - 1 words */ _bitmap_findnextword(bch, nextReadNo); if (bch->nwords == 0) { done = true; break; } Assert(bch->nwordsread == nextReadNo - 1); /* Here, startNo should point to the word to be read. */ word = bch->cwords[bch->startNo]; if (CUR_WORD_IS_FILL(bch) && GET_FILL_BIT(word) == 1) { /* Fill word represents matches */ bch->nwordsread += FILL_LENGTH(word); orWord = BM_MAKE_FILL_WORD(1, bch->nwordsread - nextReadNo + 1); orWordIsLiteral = false; nextReadNo = bch->nwordsread + 1; bch->startNo++; bch->nwords--; break; } else if (CUR_WORD_IS_FILL(bch) && GET_FILL_BIT(word) == 0) { /* Fill word represents no matches */ bch->nwordsread++; prevstarts[batchNo] = bch->startNo; if (FILL_LENGTH(word) == 1) { bch->startNo++; bch->nwords--; } else bch->cwords[bch->startNo]--; orWordIsLiteral = true; } else if (!CUR_WORD_IS_FILL(bch)) { /* word is literal */ prevstarts[batchNo] = bch->startNo; orWord |= word; bch->nwordsread++; bch->startNo++; bch->nwords--; orWordIsLiteral = true; } } if (done) { uint32 i; /* reset the attributes before batchNo */ for (i = 0; i < batchNo; i++) _bitmap_resetWord(batches[i], prevstarts[i]); break; } else { if (!orWordIsLiteral) { /* Word is not literal, update the result header */ uint32 offs = result->nwords/BM_HRL_WORD_SIZE; uint32 n = result->nwords; result->hwords[offs] |= WORDNO_GET_HEADER_BIT(n); } result->cwords[result->nwords] = orWord; result->nwords++; } if (orWordIsLiteral) nextReadNo++; /* we just processed the last batch and it was empty */ if (batchNo == numBatches - 1 && batches[batchNo]->nwords == 0) done = true; } /* set the next word to read for all input vectors */ for (batchNo = 0; batchNo < numBatches; batchNo++) batches[batchNo]->nextread = nextReadNo; pfree(prevstarts); }
/* * _bitmap_intersect() -- intersect 'numBatches' bitmap words. * * All 'numBatches' bitmap words are HRL compressed. The result * bitmap words HRL compressed, except that fill set words(1s) may * be lossily compressed. */ void _bitmap_intersect(BMBatchWords **batches, uint32 numBatches, BMBatchWords *result) { bool done = false; uint32 *prevStartNos; uint64 nextReadNo; uint64 batchNo; Assert(numBatches > 0); prevStartNos = (uint32 *)palloc0(numBatches * sizeof(uint32)); nextReadNo = batches[0]->nextread; while (!done && result->nwords < result->maxNumOfWords) { BM_HRL_WORD andWord = LITERAL_ALL_ONE; BM_HRL_WORD word; bool andWordIsLiteral = true; /* * We walk through the bitmap word in each list one by one * without de-compress the bitmap words. 'nextReadNo' defines * the position of the next word that should be read in an * uncompressed format. */ for (batchNo = 0; batchNo < numBatches; batchNo++) { uint32 offs; BMBatchWords *bch = batches[batchNo]; /* skip nextReadNo - nwordsread - 1 words */ _bitmap_findnextword(bch, nextReadNo); if (bch->nwords == 0) { done = true; break; } Assert(bch->nwordsread == nextReadNo - 1); /* Here, startNo should point to the word to be read. */ offs = bch->startNo; word = bch->cwords[offs]; if (CUR_WORD_IS_FILL(bch) && (GET_FILL_BIT(word) == 0)) { uint32 n; bch->nwordsread += FILL_LENGTH(word); n = bch->nwordsread - nextReadNo + 1; andWord = BM_MAKE_FILL_WORD(0, n); andWordIsLiteral = false; nextReadNo = bch->nwordsread + 1; bch->startNo++; bch->nwords--; break; } else if (CUR_WORD_IS_FILL(bch) && (GET_FILL_BIT(word) == 1)) { bch->nwordsread++; prevStartNos[batchNo] = bch->startNo; if (FILL_LENGTH(word) == 1) { bch->startNo++; bch->nwords--; } else { uint32 s = bch->startNo; bch->cwords[s]--; } andWordIsLiteral = true; } else if (!CUR_WORD_IS_FILL(bch)) { prevStartNos[batchNo] = bch->startNo; andWord &= word; bch->nwordsread++; bch->startNo++; bch->nwords--; andWordIsLiteral = true; } } /* Since there are not enough words in this attribute break this loop */ if (done) { uint32 preBatchNo; /* reset the attributes before batchNo */ for (preBatchNo = 0; preBatchNo < batchNo; preBatchNo++) { _bitmap_resetWord(batches[preBatchNo], prevStartNos[preBatchNo]); } break; } else { if (!andWordIsLiteral) { uint32 off = result->nwords/BM_HRL_WORD_SIZE; uint32 w = result->nwords; result->hwords[off] |= WORDNO_GET_HEADER_BIT(w); } result->cwords[result->nwords] = andWord; result->nwords++; } if (andWordIsLiteral) nextReadNo++; if (batchNo == 1 && bch->nwords == 0) done = true; } /* set the nextReadNo */ for (batchNo = 0; batchNo < numBatches; batchNo++) batches[batchNo]->nextread = nextReadNo; pfree(prevStartNos); }