0002-put-excludeOnly-keys-last.patch

text/x-diff

Filename: 0002-put-excludeOnly-keys-last.patch
Type: text/x-diff
Part: 1
Message: Re: BUG #19031: pg_trgm infinite loop on certain cases

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch 0002
File+
src/backend/access/gin/ginscan.c 43 0
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index c2d1771bd77..26081693383 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -271,6 +271,7 @@ ginNewScanKey(IndexScanDesc scan)
 	ScanKey		scankey = scan->keyData;
 	GinScanOpaque so = (GinScanOpaque) scan->opaque;
 	int			i;
+	int			numExcludeOnly;
 	bool		hasNullQuery = false;
 	bool		attrHasNormalScan[INDEX_MAX_KEYS] = {false};
 	MemoryContext oldCtx;
@@ -393,6 +394,7 @@ ginNewScanKey(IndexScanDesc scan)
 	 * excludeOnly scan key must receive a GIN_CAT_EMPTY_QUERY hidden entry
 	 * and be set to normal (excludeOnly = false).
 	 */
+	numExcludeOnly = 0;
 	for (i = 0; i < so->nkeys; i++)
 	{
 		GinScanKey	key = &so->keys[i];
@@ -406,6 +408,47 @@ ginNewScanKey(IndexScanDesc scan)
 			ginScanKeyAddHiddenEntry(so, key, GIN_CAT_EMPTY_QUERY);
 			attrHasNormalScan[key->attnum - 1] = true;
 		}
+		else
+			numExcludeOnly++;
+	}
+
+	/*
+	 * If we left any excludeOnly scan keys as-is, move them to the end of the
+	 * scan key array: they must appear after normal key(s).
+	 */
+	if (numExcludeOnly > 0)
+	{
+		GinScanKey	tmpkeys;
+		int			iNormalKey;
+		int			iExcludeOnly;
+
+		/* We'd better have made at least one normal key */
+		Assert(numExcludeOnly < so->nkeys);
+		/* Make a temporary array to hold the re-ordered scan keys */
+		tmpkeys = (GinScanKey) palloc(so->nkeys * sizeof(GinScanKeyData));
+		/* Re-order the keys ... */
+		iNormalKey = 0;
+		iExcludeOnly = so->nkeys - numExcludeOnly;
+		for (i = 0; i < so->nkeys; i++)
+		{
+			GinScanKey	key = &so->keys[i];
+
+			if (key->excludeOnly)
+			{
+				memcpy(tmpkeys + iExcludeOnly, key, sizeof(GinScanKeyData));
+				iExcludeOnly++;
+			}
+			else
+			{
+				memcpy(tmpkeys + iNormalKey, key, sizeof(GinScanKeyData));
+				iNormalKey++;
+			}
+		}
+		Assert(iNormalKey == so->nkeys - numExcludeOnly);
+		Assert(iExcludeOnly == so->nkeys);
+		/* ... and copy them back to so->keys[] */
+		memcpy(so->keys, tmpkeys, so->nkeys * sizeof(GinScanKeyData));
+		pfree(tmpkeys);
 	}
 
 	/*