patch.mark.1

application/octet-stream

Filename: patch.mark.1
Type: application/octet-stream
Part: 0
Message: Re: [sqlsmith] Planner crash on foreign table join
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index bf8545d..943dbb7 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -115,6 +115,7 @@ bms_copy(const Bitmapset *a)
 
 	if (a == NULL)
 		return NULL;
+	Assert(IsA(a, Bitmapset));
 	size = BITMAPSET_SIZE(a->nwords);
 	result = (Bitmapset *) palloc(size);
 	memcpy(result, a, size);
@@ -145,6 +146,8 @@ bms_equal(const Bitmapset *a, const Bitmapset *b)
 	}
 	else if (b == NULL)
 		return bms_is_empty(a);
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Identify shorter and longer input */
 	if (a->nwords <= b->nwords)
 	{
@@ -187,6 +190,7 @@ bms_make_singleton(int x)
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
 	result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
+	result->type = T_Bitmapset;
 	result->nwords = wordnum + 1;
 	result->words[wordnum] = ((bitmapword) 1 << bitnum);
 	return result;
@@ -201,7 +205,10 @@ void
 bms_free(Bitmapset *a)
 {
 	if (a)
+	{
+		Assert(IsA(a, Bitmapset));
 		pfree(a);
+	}
 }
 
 
@@ -227,6 +234,8 @@ bms_union(const Bitmapset *a, const Bitmapset *b)
 		return bms_copy(b);
 	if (b == NULL)
 		return bms_copy(a);
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Identify shorter and longer input; copy the longer one */
 	if (a->nwords <= b->nwords)
 	{
@@ -259,6 +268,8 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b)
 	/* Handle cases where either input is NULL */
 	if (a == NULL || b == NULL)
 		return NULL;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Identify shorter and longer input; copy the shorter one */
 	if (a->nwords <= b->nwords)
 	{
@@ -292,6 +303,8 @@ bms_difference(const Bitmapset *a, const Bitmapset *b)
 		return NULL;
 	if (b == NULL)
 		return bms_copy(a);
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Copy the left input */
 	result = bms_copy(a);
 	/* And remove b's bits from result */
@@ -316,6 +329,8 @@ bms_is_subset(const Bitmapset *a, const Bitmapset *b)
 		return true;			/* empty set is a subset of anything */
 	if (b == NULL)
 		return bms_is_empty(a);
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Check common words */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
@@ -358,6 +373,8 @@ bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
 	}
 	if (b == NULL)
 		return bms_is_empty(a) ? BMS_EQUAL : BMS_SUBSET2;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Check common words */
 	result = BMS_EQUAL;			/* status so far */
 	shortlen = Min(a->nwords, b->nwords);
@@ -427,6 +444,7 @@ bms_is_member(int x, const Bitmapset *a)
 		elog(ERROR, "negative bitmapset member not allowed");
 	if (a == NULL)
 		return false;
+	Assert(IsA(a, Bitmapset));
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
 	if (wordnum >= a->nwords)
@@ -448,6 +466,8 @@ bms_overlap(const Bitmapset *a, const Bitmapset *b)
 	/* Handle cases where either input is NULL */
 	if (a == NULL || b == NULL)
 		return false;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Check words in common */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
@@ -471,6 +491,7 @@ bms_overlap_list(const Bitmapset *a, const List *b)
 	if (a == NULL || b == NIL)
 		return false;
 
+	Assert(IsA(a, Bitmapset));
 	foreach(lc, b)
 	{
 		int			x = lfirst_int(lc);
@@ -501,6 +522,8 @@ bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
 		return false;
 	if (b == NULL)
 		return !bms_is_empty(a);
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Check words in common */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
@@ -531,6 +554,7 @@ bms_singleton_member(const Bitmapset *a)
 
 	if (a == NULL)
 		elog(ERROR, "bitmapset is empty");
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -574,6 +598,7 @@ bms_get_singleton_member(const Bitmapset *a, int *member)
 
 	if (a == NULL)
 		return false;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -610,6 +635,7 @@ bms_num_members(const Bitmapset *a)
 
 	if (a == NULL)
 		return 0;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -639,6 +665,7 @@ bms_membership(const Bitmapset *a)
 
 	if (a == NULL)
 		return BMS_EMPTY_SET;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -667,6 +694,7 @@ bms_is_empty(const Bitmapset *a)
 
 	if (a == NULL)
 		return true;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -704,6 +732,7 @@ bms_add_member(Bitmapset *a, int x)
 		elog(ERROR, "negative bitmapset member not allowed");
 	if (a == NULL)
 		return bms_make_singleton(x);
+	Assert(IsA(a, Bitmapset));
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
 
@@ -741,6 +770,7 @@ bms_del_member(Bitmapset *a, int x)
 		elog(ERROR, "negative bitmapset member not allowed");
 	if (a == NULL)
 		return NULL;
+	Assert(IsA(a, Bitmapset));
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
 	if (wordnum < a->nwords)
@@ -764,6 +794,8 @@ bms_add_members(Bitmapset *a, const Bitmapset *b)
 		return bms_copy(b);
 	if (b == NULL)
 		return a;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Identify shorter and longer input; copy the longer one if needed */
 	if (a->nwords < b->nwords)
 	{
@@ -801,6 +833,8 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
 		pfree(a);
 		return NULL;
 	}
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Intersect b into a; we need never copy */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
@@ -824,6 +858,8 @@ bms_del_members(Bitmapset *a, const Bitmapset *b)
 		return NULL;
 	if (b == NULL)
 		return a;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Remove b's bits from a; we need never copy */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
@@ -847,6 +883,8 @@ bms_join(Bitmapset *a, Bitmapset *b)
 		return b;
 	if (b == NULL)
 		return a;
+	Assert(IsA(a, Bitmapset));
+	Assert(IsA(b, Bitmapset));
 	/* Identify shorter and longer input; use longer one as result */
 	if (a->nwords < b->nwords)
 	{
@@ -889,6 +927,7 @@ bms_first_member(Bitmapset *a)
 
 	if (a == NULL)
 		return -1;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	for (wordnum = 0; wordnum < nwords; wordnum++)
 	{
@@ -942,6 +981,7 @@ bms_next_member(const Bitmapset *a, int prevbit)
 
 	if (a == NULL)
 		return -2;
+	Assert(IsA(a, Bitmapset));
 	nwords = a->nwords;
 	prevbit++;
 	mask = (~(bitmapword) 0) << BITNUM(prevbit);
@@ -987,6 +1027,7 @@ bms_hash_value(const Bitmapset *a)
 
 	if (a == NULL)
 		return 0;				/* All empty sets hash to 0 */
+	Assert(IsA(a, Bitmapset));
 	for (lastword = a->nwords; --lastword >= 0;)
 	{
 		if (a->words[lastword] != 0)
diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h
index 109f7b0..d672ee5 100644
--- a/src/include/nodes/bitmapset.h
+++ b/src/include/nodes/bitmapset.h
@@ -20,6 +20,8 @@
 #ifndef BITMAPSET_H
 #define BITMAPSET_H
 
+#include "nodes/nodes.h"
+
 /*
  * Forward decl to save including pg_list.h
  */
@@ -36,6 +38,7 @@ typedef int32 signedbitmapword; /* must be the matching signed type */
 
 typedef struct Bitmapset
 {
+	NodeTag		type;
 	int			nwords;			/* number of words in array */
 	bitmapword	words[FLEXIBLE_ARRAY_MEMBER];	/* really [nwords] */
 } Bitmapset;
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index f59d719..46408c2 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -291,6 +291,7 @@ typedef enum NodeTag
 	T_List,
 	T_IntList,
 	T_OidList,
+	T_Bitmapset,
 
 	/*
 	 * TAGS FOR EXTENSIBLE NODES (extensible.h)