aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/bloom/blinsert.c25
-rw-r--r--contrib/bloom/bloom.h1
-rw-r--r--contrib/bloom/blutils.c63
-rw-r--r--contrib/bloom/expected/bloom.out58
-rw-r--r--contrib/bloom/sql/bloom.sql22
5 files changed, 144 insertions, 25 deletions
diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c
index a3602178938..15ac30d55f6 100644
--- a/contrib/bloom/blinsert.c
+++ b/contrib/bloom/blinsert.c
@@ -18,6 +18,7 @@
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
+#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -159,12 +160,26 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
void
blbuildempty(Relation index)
{
- if (RelationGetNumberOfBlocks(index) != 0)
- elog(ERROR, "index \"%s\" already contains data",
- RelationGetRelationName(index));
+ Page metapage;
- /* Initialize the meta page */
- BloomInitMetapage(index);
+ /* Construct metapage. */
+ metapage = (Page) palloc(BLCKSZ);
+ BloomFillMetapage(index, metapage);
+
+ /* Write the page. If archiving/streaming, XLOG it. */
+ PageSetChecksumInplace(metapage, BLOOM_METAPAGE_BLKNO);
+ smgrwrite(index->rd_smgr, INIT_FORKNUM, BLOOM_METAPAGE_BLKNO,
+ (char *) metapage, true);
+ if (XLogIsNeeded())
+ log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ BLOOM_METAPAGE_BLKNO, metapage, false);
+
+ /*
+ * An immediate sync is required even if we xlog'd the page, because the
+ * write did not go through shared_buffers and therefore a concurrent
+ * checkpoint may have moved the redo pointer past our xlog record.
+ */
+ smgrimmedsync(index->rd_smgr, INIT_FORKNUM);
}
/*
diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h
index cbf2eb78927..c21eebfc94d 100644
--- a/contrib/bloom/bloom.h
+++ b/contrib/bloom/bloom.h
@@ -166,6 +166,7 @@ typedef BloomScanOpaqueData *BloomScanOpaque;
extern void _PG_init(void);
extern Datum blhandler(PG_FUNCTION_ARGS);
extern void initBloomState(BloomState * state, Relation index);
+extern void BloomFillMetapage(Relation index, Page metaPage);
extern void BloomInitMetapage(Relation index);
extern void BloomInitPage(Page page, uint16 flags);
extern Buffer BloomNewBuffer(Relation index);
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index 05dbe876143..4a5b343dd02 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -346,7 +346,7 @@ BloomNewBuffer(Relation index)
}
/*
- * Initialize bloom page.
+ * Initialize any page of a bloom index.
*/
void
BloomInitPage(Page page, uint16 flags)
@@ -363,6 +363,8 @@ BloomInitPage(Page page, uint16 flags)
/*
* Adjust options of bloom index.
+ *
+ * This must produce default options when *opts is initially all-zero.
*/
static void
adjustBloomOptions(BloomOptions *opts)
@@ -378,7 +380,7 @@ adjustBloomOptions(BloomOptions *opts)
errmsg("length of bloom signature (%d) is greater than maximum %d",
opts->bloomLength, MAX_BLOOM_LENGTH)));
- /* Check singnature length */
+ /* Check signature length */
for (i = 0; i < INDEX_MAX_KEYS; i++)
{
/*
@@ -393,45 +395,66 @@ adjustBloomOptions(BloomOptions *opts)
}
/*
+ * Fill in metapage for bloom index.
+ */
+void
+BloomFillMetapage(Relation index, Page metaPage)
+{
+ BloomOptions *opts;
+ BloomMetaPageData *metadata;
+
+ /*
+ * Choose the index's options. If reloptions have been assigned, use
+ * those, otherwise create default options by applying adjustBloomOptions
+ * to a zeroed chunk of memory. We apply adjustBloomOptions to existing
+ * reloptions too, just out of paranoia; they should be valid already.
+ */
+ opts = (BloomOptions *) index->rd_options;
+ if (!opts)
+ opts = (BloomOptions *) palloc0(sizeof(BloomOptions));
+ adjustBloomOptions(opts);
+
+ /*
+ * Initialize contents of meta page, including a copy of the options,
+ * which are now frozen for the life of the index.
+ */
+ BloomInitPage(metaPage, BLOOM_META);
+ metadata = BloomPageGetMeta(metaPage);
+ memset(metadata, 0, sizeof(BloomMetaPageData));
+ metadata->magickNumber = BLOOM_MAGICK_NUMBER;
+ metadata->opts = *opts;
+ ((PageHeader) metaPage)->pd_lower += sizeof(BloomMetaPageData);
+}
+
+/*
* Initialize metapage for bloom index.
*/
void
BloomInitMetapage(Relation index)
{
- Page metaPage;
Buffer metaBuffer;
- BloomMetaPageData *metadata;
+ Page metaPage;
GenericXLogState *state;
/*
- * Make a new buffer, since it first buffer it should be associated with
+ * Make a new page; since it is first page it should be associated with
* block number 0 (BLOOM_METAPAGE_BLKNO).
*/
metaBuffer = BloomNewBuffer(index);
Assert(BufferGetBlockNumber(metaBuffer) == BLOOM_METAPAGE_BLKNO);
- /* Initialize bloom index options */
- if (!index->rd_options)
- index->rd_options = palloc0(sizeof(BloomOptions));
- adjustBloomOptions((BloomOptions *) index->rd_options);
-
/* Initialize contents of meta page */
state = GenericXLogStart(index);
- metaPage = GenericXLogRegisterBuffer(state, metaBuffer, GENERIC_XLOG_FULL_IMAGE);
-
- BloomInitPage(metaPage, BLOOM_META);
- metadata = BloomPageGetMeta(metaPage);
- memset(metadata, 0, sizeof(BloomMetaPageData));
- metadata->magickNumber = BLOOM_MAGICK_NUMBER;
- metadata->opts = *((BloomOptions *) index->rd_options);
- ((PageHeader) metaPage)->pd_lower += sizeof(BloomMetaPageData);
-
+ metaPage = GenericXLogRegisterBuffer(state, metaBuffer,
+ GENERIC_XLOG_FULL_IMAGE);
+ BloomFillMetapage(index, metaPage);
GenericXLogFinish(state);
+
UnlockReleaseBuffer(metaBuffer);
}
/*
- * Initialize options for bloom index.
+ * Parse reloptions for bloom index, producing a BloomOptions struct.
*/
bytea *
bloptions(Datum reloptions, bool validate)
diff --git a/contrib/bloom/expected/bloom.out b/contrib/bloom/expected/bloom.out
index 71700efd5ae..cbc50f757b6 100644
--- a/contrib/bloom/expected/bloom.out
+++ b/contrib/bloom/expected/bloom.out
@@ -138,6 +138,64 @@ SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
13
(1 row)
+-- Try an unlogged table too
+CREATE UNLOGGED TABLE tstu (
+ i int4,
+ t text
+);
+INSERT INTO tstu SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
+CREATE INDEX bloomidxu ON tstu USING bloom (i, t) WITH (col2 = 4);
+SET enable_seqscan=off;
+SET enable_bitmapscan=on;
+SET enable_indexscan=on;
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7;
+ QUERY PLAN
+--------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on tstu
+ Recheck Cond: (i = 7)
+ -> Bitmap Index Scan on bloomidxu
+ Index Cond: (i = 7)
+(5 rows)
+
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE t = '5';
+ QUERY PLAN
+--------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on tstu
+ Recheck Cond: (t = '5'::text)
+ -> Bitmap Index Scan on bloomidxu
+ Index Cond: (t = '5'::text)
+(5 rows)
+
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
+ QUERY PLAN
+---------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on tstu
+ Recheck Cond: ((i = 7) AND (t = '5'::text))
+ -> Bitmap Index Scan on bloomidxu
+ Index Cond: ((i = 7) AND (t = '5'::text))
+(5 rows)
+
+SELECT count(*) FROM tstu WHERE i = 7;
+ count
+-------
+ 200
+(1 row)
+
+SELECT count(*) FROM tstu WHERE t = '5';
+ count
+-------
+ 112
+(1 row)
+
+SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
+ count
+-------
+ 13
+(1 row)
+
RESET enable_seqscan;
RESET enable_bitmapscan;
RESET enable_indexscan;
diff --git a/contrib/bloom/sql/bloom.sql b/contrib/bloom/sql/bloom.sql
index e9174828fe6..22274609f20 100644
--- a/contrib/bloom/sql/bloom.sql
+++ b/contrib/bloom/sql/bloom.sql
@@ -50,6 +50,28 @@ SELECT count(*) FROM tst WHERE i = 7;
SELECT count(*) FROM tst WHERE t = '5';
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
+-- Try an unlogged table too
+
+CREATE UNLOGGED TABLE tstu (
+ i int4,
+ t text
+);
+
+INSERT INTO tstu SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
+CREATE INDEX bloomidxu ON tstu USING bloom (i, t) WITH (col2 = 4);
+
+SET enable_seqscan=off;
+SET enable_bitmapscan=on;
+SET enable_indexscan=on;
+
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7;
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE t = '5';
+EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
+
+SELECT count(*) FROM tstu WHERE i = 7;
+SELECT count(*) FROM tstu WHERE t = '5';
+SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
+
RESET enable_seqscan;
RESET enable_bitmapscan;
RESET enable_indexscan;