Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wQ7I5-001IhN-0T for pgsql-hackers@arkaria.postgresql.org; Thu, 21 May 2026 17:34:37 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wQ7I1-00AfYv-1h for pgsql-hackers@arkaria.postgresql.org; Thu, 21 May 2026 17:34:34 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wQ7I0-00AfYm-3A for pgsql-hackers@lists.postgresql.org; Thu, 21 May 2026 17:34:34 +0000 Received: from mail-pg1-x52f.google.com ([2607:f8b0:4864:20::52f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wQ7Hy-00000000lVO-06WN for pgsql-hackers@lists.postgresql.org; Thu, 21 May 2026 17:34:32 +0000 Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-c8173b2af32so5101810a12.0 for ; Thu, 21 May 2026 10:34:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb.com; s=google; t=1779384867; x=1779989667; darn=lists.postgresql.org; h=message-id:in-reply-to:to:references:date:subject:mime-version:from :from:to:cc:subject:date:message-id:reply-to; bh=KWCuf/eTmUSQu2XuZKtOpJRqDZd9E0O13GNtibemIpQ=; b=hkUM3Z3xFj3htRvQpCG4reOiYwk/PtCj9s6aVxIjWhISXSFxpA6YDiEQ2NeMtqayL3 FUWBQCYjN2ky69x9RwOYSDfZGziDnM+F4aEhWguW7mqNzM5MKu4IB/OUyt1q5Rw3wSCs 8VVb5+VUMsNN7Q5a9Y9+re6MZzv5xHvazJuxFmSnSpKQHcVij0MZv4KiFK3mIf7pKExk F2IjWinuXGDCSH25HqSLJt5RFDvt0jBmlPiWkPZyc62YreO/Uugfm/ci/TqTmk/aFTLm P5OeeyrM1+hcYjdRuDW14UKfLJ8DHcXeAkmuwh3namwjra9u9AM1CPOLeo6F/ToPpkbG gGOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779384867; x=1779989667; h=message-id:in-reply-to:to:references:date:subject:mime-version:from :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=KWCuf/eTmUSQu2XuZKtOpJRqDZd9E0O13GNtibemIpQ=; b=PwFNocbATV0KhKP3K6fGW1iwgcKyx8ucr1kC/wcUA0EX5cHg9ySUT8TR8c9a8NGS/B xlLBTlTtbc+tcYI+GCvv1w1tqLQMpJ6Kz5rMYz8FA2gQb/dS3ttYC5a+WGo8nZXGgAse JSL+xcusWVm78mco0oLG5p4RFoZ8BrLZvx3X6oW8A5UZm3OGr2PnGMa3rSqm/yqqaiS1 l8g2KGU3nkyBMjC5Tg42mLYeai1XhgZ/DKbzmae/PBn/Ob7CyfZGnPET7j4H0BlzzD93 nqeXj/yVw4UmDQDXPU9UFQmPNtruTjrL4bLUpnrhnHRAcufCvV/U6K3skEOokgebkKee 2bag== X-Gm-Message-State: AOJu0YwmmurE4rm9li/i1tRSwOyqWkjCDltdNwrofJ3Ur2T5Kga6Go9y YevlM/+kfs57fVG0tC1FTJo+sFlVt5vDHOKfZjoaWXwsIrPR84iaik4bRTn82VfTZ1ztNrDHhLw GKFWAwBp1Rtg9mK/LykWkAuP/2XFLRi/rowuS0kVL//MF1KYi7XlQasLAxvey9vZ5UEljEt2yiY phGwzXqU7x9929LU9iTkOAFb9wcUIwV+oOuBx4aBezFUaPZJot4at2D42XlVWUJ4h7wsTnwEU+e Mjp X-Gm-Gg: Acq92OEQTg85n5e/nGJ8LxV1mwj7vI7DCraSGnFneHC/MaaDACdufwJgH0A0KcrScJv c/LbVW8akH6zdTmEx7JK+kI7fnOvGu8e7oauz6JeXjSD+lbCzIGTZXBMDiVrq1RQWLpZxD5tntp TWfpxzRYnF50qlo926+4G0ru6ZseIsHjbiR4VKUDxy23RCiqxdHRQt8PAlYRg0++lPWSEVXis45 RftCf6v/x/YO0K2nMZ07+CpgtfmewTIIJ49AGRAHDuea3hcR0zxqzAz4sqqCoCshOhleopDanmg NpYSDkT2eJSZATDwzTFa+k3ztsG/1R/cyOzf/E38ENF2RWEiLSFkq5qbMLqmnfvOlB6fOzS3ax9 rWiHEP1biLDhOZSjdKJ6ddCntdicjczgNrZ0jcyi+YGNJntKYZkHkJoT72ww1Dfyl2tgzIv1IHt yMFV0p8GkD+/MEUhsx1WhZEs6arx2DKiNPMHaqVCjkV5ZXGMZz8xYlVrnY/nSqVLtb X-Received: by 2002:a05:6a00:391e:b0:82f:4566:bbdf with SMTP id d2e1a72fcca58-8415f176302mr288480b3a.14.1779384866470; Thu, 21 May 2026 10:34:26 -0700 (PDT) Received: from smtpclient.apple ([163.116.239.147]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-841549be20fsm2345520b3a.12.2026.05.21.10.34.25 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 May 2026 10:34:25 -0700 (PDT) From: Maxime Schoemans Content-Type: multipart/mixed; boundary="Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.500.181\)) Subject: Re: Multi-Entry Indexing for GiST & SP-GiST Date: Thu, 21 May 2026 10:34:14 -0700 References: <8E23543E-F1E4-40AE-BDA0-8A5BEA7DADA1@enterprisedb.com> To: pgsql-hackers@lists.postgresql.org In-Reply-To: <8E23543E-F1E4-40AE-BDA0-8A5BEA7DADA1@enterprisedb.com> Message-Id: <74190D40-5373-46C5-AB7F-4EF12E33015B@enterprisedb.com> X-Mailer: Apple Mail (2.3864.500.181) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii This time with the patches attached. Best, Maxime --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841 Content-Disposition: attachment; filename=v1-0001-Add-multi-entry-support-to-GiST.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0001-Add-multi-entry-support-to-GiST.patch" Content-Transfer-Encoding: quoted-printable =46rom=207388571d02681075ed7e9b00507fd02b3103e44c=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Maxime=20Schoemans=20= =0ADate:=20Thu,=202=20Apr=202026=20= 18:11:44=20+0200=0ASubject:=20[PATCH=20v1=201/4]=20Add=20multi-entry=20= support=20to=20GiST=0A=0AAdd=20infrastructure=20for=20GiST=20indexes=20= to=20store=20multiple=20index=20entries=20per=0Aheap=20tuple,=20similar=20= to=20how=20GIN=20decomposes=20values=20via=20extractValue=20but=0Awithin=20= GiST's=20R-tree=20framework.=0A=0AA=20new=20optional=20support=20= function,=20extractValue=20(support=20procedure=2013),=20is=0Aadded.=20=20= When=20an=20opclass=20provides=20it,=20the=20function=20is=20called=20= during=20insert=0Aand=20index=20build=20to=20decompose=20each=20datum=20= into=20multiple=20sub-entries,=20each=0Astored=20as=20a=20separate=20= index=20tuple=20pointing=20to=20the=20same=20heap=20TID.=0A=0AOn=20the=20= scan=20side,=20a=20simplehash-based=20TID=20deduplication=20hash=20table=20= ensures=0Aeach=20heap=20tuple=20is=20returned=20only=20once=20despite=20= having=20multiple=20index=0Aentries.=20=20Three=20scan=20modes=20are=20= handled:=0A=0A=20=20-=20Bitmap=20scans:=20the=20TIDBitmap=20handles=20= deduplication=20inherently.=0A=20=20-=20Non-ordered=20scans:=20the=20= hash=20table=20filters=20duplicates=20in=20pageData.=0A=20=20-=20Ordered=20= (KNN)=20scans:=20the=20hash=20table=20filters=20duplicates=20both=20when=0A= =20=20=20=20enqueuing=20leaf=20items=20and=20when=20dequeuing=20from=20= the=20pairing=20heap,=0A=20=20=20=20ensuring=20the=20first=20(nearest)=20= distance=20wins.=0A=0AOther=20changes:=0A=0A=20=20-=20gistcanreturn()=20= disables=20index-only=20scans=20on=20key=20columns=20that=20use=0A=20=20=20= =20extractValue,=20since=20the=20original=20datum=20cannot=20be=20= reconstructed=20from=0A=20=20=20=20a=20single=20component.=0A=20=20-=20= Multi-entry=20is=20restricted=20to=20single-key-column=20indexes=20= (INCLUDE=0A=20=20=20=20columns=20are=20allowed).=20=20Multi-column=20= support=20is=20left=20for=20future=20work.=0A=20=20-=20gistvalidate.c=20= marks=20extractValue=20as=20optional=20and=20validates=20its=0A=20=20=20=20= signature=20(internal,=20internal,=20internal)=20->=20internal.=0A---=0A=20= src/backend/access/gist/gist.c=20=20=20=20=20=20=20=20=20|=20=2058=20= ++++++++++-=0A=20src/backend/access/gist/gistbuild.c=20=20=20=20|=20=20= 72=20+++++++++-----=0A=20src/backend/access/gist/gistget.c=20=20=20=20=20= =20|=20130=20++++++++++++++++++++++++-=0A=20= src/backend/access/gist/gistscan.c=20=20=20=20=20|=20=20=204=20+=0A=20= src/backend/access/gist/gistutil.c=20=20=20=20=20|=20=2068=20= +++++++++++++=0A=20src/backend/access/gist/gistvalidate.c=20|=20=20=209=20= +-=0A=20src/include/access/gist.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=203=20+-=0A=20src/include/access/gist_private.h=20=20=20=20=20=20= |=20=2014=20+++=0A=208=20files=20changed,=20327=20insertions(+),=2031=20= deletions(-)=0A=0Adiff=20--git=20a/src/backend/access/gist/gist.c=20= b/src/backend/access/gist/gist.c=0Aindex=208565e225be7..bb280e6ea5a=20= 100644=0A---=20a/src/backend/access/gist/gist.c=0A+++=20= b/src/backend/access/gist/gist.c=0A@@=20-161,6=20+161,10=20@@=20= gistbuildempty(Relation=20index)=0A=20=20*=0A=20=20*=09=20=20This=20is=20= the=20public=20interface=20routine=20for=20tuple=20insertion=20in=20= GiSTs.=0A=20=20*=09=20=20It=20doesn't=20do=20any=20work;=20just=20locks=20= the=20relation=20and=20passes=20the=20buck.=0A+=20*=0A+=20*=09=20=20If=20= the=20opclass=20provides=20an=20extractValue=20function=20(multi-entry=20= mode),=0A+=20*=09=20=20a=20single=20heap=20tuple=20may=20produce=20= multiple=20index=20entries.=20=20Each=20entry=0A+=20*=09=20=20is=20= inserted=20separately,=20all=20pointing=20to=20the=20same=20heap=20TID.=0A= =20=20*/=0A=20bool=0A=20gistinsert(Relation=20r,=20Datum=20*values,=20= bool=20*isnull,=0A@@=20-170,7=20+174,6=20@@=20gistinsert(Relation=20r,=20= Datum=20*values,=20bool=20*isnull,=0A=20=09=09=20=20=20IndexInfo=20= *indexInfo)=0A=20{=0A=20=09GISTSTATE=20=20*giststate=20=3D=20(GISTSTATE=20= *)=20indexInfo->ii_AmCache;=0A-=09IndexTuple=09itup;=0A=20=09= MemoryContext=20oldCxt;=0A=20=0A=20=09/*=20Initialize=20GISTSTATE=20= cache=20if=20first=20call=20in=20this=20statement=20*/=0A@@=20-185,10=20= +188,31=20@@=20gistinsert(Relation=20r,=20Datum=20*values,=20bool=20= *isnull,=0A=20=0A=20=09oldCxt=20=3D=20= MemoryContextSwitchTo(giststate->tempCxt);=0A=20=0A-=09itup=20=3D=20= gistFormTuple(giststate,=20r,=20values,=20isnull,=20true);=0A-=09= itup->t_tid=20=3D=20*ht_ctid;=0A+=09/*=0A+=09=20*=20If=20the=20opclass=20= provides=20an=20extractValue=20function,=20extract=20multiple=0A+=09=20*=20= entries=20and=20insert=20each=20one=20separately.=0A+=09=20*/=0A+=09if=20= (OidIsValid(giststate->extractValueFn[0].fn_oid))=0A+=09{=0A+=09=09= IndexTuple=20*itups;=0A+=09=09int32=09=09nitups;=0A+=09=09int=09=09=09i;=0A= =20=0A-=09gistdoinsert(r,=20itup,=200,=20giststate,=20heapRel,=20false);=0A= +=09=09itups=20=3D=20gistExtractEntries(giststate,=20r,=20values,=20= isnull,=20&nitups);=0A+=09=09for=20(i=20=3D=200;=20i=20<=20nitups;=20= i++)=0A+=09=09{=0A+=09=09=09itups[i]->t_tid=20=3D=20*ht_ctid;=0A+=09=09=09= gistdoinsert(r,=20itups[i],=200,=20giststate,=20heapRel,=20false);=0A+=09= =09}=0A+=09}=0A+=09else=0A+=09{=0A+=09=09IndexTuple=09itup;=0A+=0A+=09=09= itup=20=3D=20gistFormTuple(giststate,=20r,=20values,=20isnull,=20true);=0A= +=09=09itup->t_tid=20=3D=20*ht_ctid;=0A+=09=09gistdoinsert(r,=20itup,=20= 0,=20giststate,=20heapRel,=20false);=0A+=09}=0A=20=0A=20=09/*=20cleanup=20= */=0A=20=09MemoryContextSwitchTo(oldCxt);=0A@@=20-1623,6=20+1647,14=20@@=20= initGISTstate(Relation=20index)=0A=20=09=09else=0A=20=09=09=09= giststate->fetchFn[i].fn_oid=20=3D=20InvalidOid;=0A=20=0A+=09=09/*=20= opclasses=20are=20not=20required=20to=20provide=20an=20ExtractValue=20= method=20*/=0A+=09=09if=20(OidIsValid(index_getprocid(index,=20i=20+=20= 1,=20GIST_EXTRACTVALUE_PROC)))=0A+=09=09=09= fmgr_info_copy(&(giststate->extractValueFn[i]),=0A+=09=09=09=09=09=09=20=20= =20index_getprocinfo(index,=20i=20+=201,=20GIST_EXTRACTVALUE_PROC),=0A+=09= =09=09=09=09=09=20=20=20scanCxt);=0A+=09=09else=0A+=09=09=09= giststate->extractValueFn[i].fn_oid=20=3D=20InvalidOid;=0A+=0A=20=09=09= /*=0A=20=09=09=20*=20If=20the=20index=20column=20has=20a=20specified=20= collation,=20we=20should=20honor=20that=0A=20=09=09=20*=20while=20doing=20= comparisons.=20=20However,=20we=20may=20have=20a=20collatable=20storage=0A= @@=20-1640,6=20+1672,23=20@@=20initGISTstate(Relation=20index)=0A=20=09=09= =09giststate->supportCollation[i]=20=3D=20DEFAULT_COLLATION_OID;=0A=20=09= }=0A=20=0A+=09/*=0A+=09=20*=20Multi-entry=20indexes=20(those=20with=20= extractValue)=20are=20currently=20only=0A+=09=20*=20supported=20for=20= single-column=20indexes.=20=20The=20semantics=20of=20decomposing=0A+=09=20= *=20multiple=20columns=20simultaneously=20are=20unclear=20(cross=20= product?=20parallel=0A+=09=20*=20arrays?),=20so=20we=20disallow=20it=20= for=20now.=0A+=09=20*/=0A+=09if=20= (IndexRelationGetNumberOfKeyAttributes(index)=20>=201)=0A+=09{=0A+=09=09= for=20(i=20=3D=200;=20i=20<=20= IndexRelationGetNumberOfKeyAttributes(index);=20i++)=0A+=09=09{=0A+=09=09= =09if=20(OidIsValid(giststate->extractValueFn[i].fn_oid))=0A+=09=09=09=09= ereport(ERROR,=0A+=09=09=09=09=09=09= (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),=0A+=09=09=09=09=09=09=20= errmsg("multi-entry=20GiST=20indexes=20do=20not=20support=20multiple=20= key=20columns")));=0A+=09=09}=0A+=09}=0A+=0A=20=09/*=20No=20opclass=20= information=20for=20INCLUDE=20attributes=20*/=0A=20=09for=20(;=20i=20<=20= index->rd_att->natts;=20i++)=0A=20=09{=0A@@=20-1652,6=20+1701,7=20@@=20= initGISTstate(Relation=20index)=0A=20=09=09giststate->equalFn[i].fn_oid=20= =3D=20InvalidOid;=0A=20=09=09giststate->distanceFn[i].fn_oid=20=3D=20= InvalidOid;=0A=20=09=09giststate->fetchFn[i].fn_oid=20=3D=20InvalidOid;=0A= +=09=09giststate->extractValueFn[i].fn_oid=20=3D=20InvalidOid;=0A=20=09=09= giststate->supportCollation[i]=20=3D=20InvalidOid;=0A=20=09}=0A=20=0A= diff=20--git=20a/src/backend/access/gist/gistbuild.c=20= b/src/backend/access/gist/gistbuild.c=0Aindex=207f57c787f4c..ef786682b84=20= 100644=0A---=20a/src/backend/access/gist/gistbuild.c=0A+++=20= b/src/backend/access/gist/gistbuild.c=0A@@=20-827,21=20+827,8=20@@=20= gistBuildCallback(Relation=20index,=0A=20=09=09=09=09=20=20void=20= *state)=0A=20{=0A=20=09GISTBuildState=20*buildstate=20=3D=20= (GISTBuildState=20*)=20state;=0A-=09IndexTuple=09itup;=0A=20=09= MemoryContext=20oldCtx;=0A=20=0A-=09oldCtx=20=3D=20= MemoryContextSwitchTo(buildstate->giststate->tempCxt);=0A-=0A-=09/*=20= form=20an=20index=20tuple=20and=20point=20it=20at=20the=20heap=20tuple=20= */=0A-=09itup=20=3D=20gistFormTuple(buildstate->giststate,=20index,=0A-=09= =09=09=09=09=09=20values,=20isnull,=0A-=09=09=09=09=09=09=20true);=0A-=09= itup->t_tid=20=3D=20*tid;=0A-=0A-=09/*=20Update=20tuple=20count=20and=20= total=20size.=20*/=0A-=09buildstate->indtuples=20+=3D=201;=0A-=09= buildstate->indtuplesSize=20+=3D=20IndexTupleSize(itup);=0A-=0A=20=09/*=0A= =20=09=20*=20XXX=20In=20buffering=20builds,=20the=20tempCxt=20is=20also=20= reset=20down=20inside=0A=20=09=20*=20gistProcessEmptyingQueue().=20=20= This=20is=20not=20great=20because=20it=20risks=0A@@=20-850,20=20+837,61=20= @@=20gistBuildCallback(Relation=20index,=0A=20=09=20*=20better=20that=20= a=20memory=20context=20be=20"owned"=20by=20only=20one=20function.=20=20= However,=0A=20=09=20*=20currently=20this=20isn't=20causing=20issues=20so=20= it=20doesn't=20seem=20worth=20the=20amount=0A=20=09=20*=20of=20= refactoring=20that=20would=20be=20needed=20to=20avoid=20it.=0A+=09=20*=0A= +=09=20*=20If=20the=20opclass=20provides=20an=20extractValue=20function,=20= extract=20multiple=0A+=09=20*=20entries=20and=20insert=20each=20one.=20=20= Otherwise,=20form=20a=20single=20index=20tuple.=0A+=09=20*=0A+=09=20*=20= We=20extract=20entries=20in=20the=20caller's=20memory=20context=20so=20= that=20the=20itups=0A+=09=20*=20array=20survives=20= MemoryContextReset(tempCxt)=20inside=0A+=09=20*=20= gistProcessEmptyingQueue=20during=20buffering=20builds.=0A=20=09=20*/=0A= -=09if=20(buildstate->buildMode=20=3D=3D=20GIST_BUFFERING_ACTIVE)=0A+=09= if=20(OidIsValid(buildstate->giststate->extractValueFn[0].fn_oid))=0A=20=09= {=0A-=09=09/*=20We=20have=20buffers,=20so=20use=20them.=20*/=0A-=09=09= gistBufferingBuildInsert(buildstate,=20itup);=0A+=09=09IndexTuple=20= *itups;=0A+=09=09int32=09=09nitups;=0A+=09=09int=09=09=09i;=0A+=0A+=09=09= itups=20=3D=20gistExtractEntries(buildstate->giststate,=20index,=0A+=09=09= =09=09=09=09=09=09=20=20values,=20isnull,=20&nitups);=0A+=0A+=09=09= oldCtx=20=3D=20MemoryContextSwitchTo(buildstate->giststate->tempCxt);=0A= +=0A+=09=09for=20(i=20=3D=200;=20i=20<=20nitups;=20i++)=0A+=09=09{=0A+=09= =09=09itups[i]->t_tid=20=3D=20*tid;=0A+=0A+=09=09=09/*=20Update=20tuple=20= count=20and=20total=20size=20*/=0A+=09=09=09buildstate->indtuples=20+=3D=20= 1;=0A+=09=09=09buildstate->indtuplesSize=20+=3D=20= IndexTupleSize(itups[i]);=0A+=0A+=09=09=09if=20(buildstate->buildMode=20= =3D=3D=20GIST_BUFFERING_ACTIVE)=0A+=09=09=09=09= gistBufferingBuildInsert(buildstate,=20itups[i]);=0A+=09=09=09else=0A+=09= =09=09=09gistdoinsert(index,=20itups[i],=20buildstate->freespace,=0A+=09=09= =09=09=09=09=09=20buildstate->giststate,=20buildstate->heaprel,=20true);=0A= +=09=09}=0A=20=09}=0A=20=09else=0A=20=09{=0A-=09=09/*=0A-=09=09=20*=20= There's=20no=20buffers=20(yet).=20Since=20we=20already=20have=20the=20= index=20relation=0A-=09=09=20*=20locked,=20we=20call=20gistdoinsert=20= directly.=0A-=09=09=20*/=0A-=09=09gistdoinsert(index,=20itup,=20= buildstate->freespace,=0A-=09=09=09=09=09=20buildstate->giststate,=20= buildstate->heaprel,=20true);=0A+=09=09IndexTuple=09itup;=0A+=0A+=09=09= oldCtx=20=3D=20MemoryContextSwitchTo(buildstate->giststate->tempCxt);=0A= +=0A+=09=09/*=20form=20an=20index=20tuple=20and=20point=20it=20at=20the=20= heap=20tuple=20*/=0A+=09=09itup=20=3D=20= gistFormTuple(buildstate->giststate,=20index,=0A+=09=09=09=09=09=09=09=20= values,=20isnull,=0A+=09=09=09=09=09=09=09=20true);=0A+=09=09itup->t_tid=20= =3D=20*tid;=0A+=0A+=09=09/*=20Update=20tuple=20count=20and=20total=20= size.=20*/=0A+=09=09buildstate->indtuples=20+=3D=201;=0A+=09=09= buildstate->indtuplesSize=20+=3D=20IndexTupleSize(itup);=0A+=0A+=09=09if=20= (buildstate->buildMode=20=3D=3D=20GIST_BUFFERING_ACTIVE)=0A+=09=09=09= gistBufferingBuildInsert(buildstate,=20itup);=0A+=09=09else=0A+=09=09=09= gistdoinsert(index,=20itup,=20buildstate->freespace,=0A+=09=09=09=09=09=09= =20buildstate->giststate,=20buildstate->heaprel,=20true);=0A=20=09}=0A=20= =0A=20=09MemoryContextSwitchTo(oldCtx);=0Adiff=20--git=20= a/src/backend/access/gist/gistget.c=20= b/src/backend/access/gist/gistget.c=0Aindex=204d7c100d737..a039cfd4575=20= 100644=0A---=20a/src/backend/access/gist/gistget.c=0A+++=20= b/src/backend/access/gist/gistget.c=0A@@=20-17,6=20+17,7=20@@=0A=20= #include=20"access/genam.h"=0A=20#include=20"access/gist_private.h"=0A=20= #include=20"access/relscan.h"=0A+#include=20"common/hashfn.h"=0A=20= #include=20"executor/instrument_node.h"=0A=20#include=20= "lib/pairingheap.h"=0A=20#include=20"miscadmin.h"=0A@@=20-26,6=20+27,49=20= @@=0A=20#include=20"utils/memutils.h"=0A=20#include=20"utils/rel.h"=0A=20= =0A+/*=0A+=20*=20Simplehash=20implementation=20for=20TID=20deduplication=20= in=20multi-entry=20scans.=0A+=20*=0A+=20*=20When=20an=20opclass=20= provides=20an=20extractValue=20function,=20each=20heap=20tuple=20= produces=0A+=20*=20multiple=20index=20entries.=20=20During=20scans,=20we=20= must=20deduplicate=20results=20so=20that=0A+=20*=20each=20heap=20TID=20= is=20returned=20only=20once.=0A+=20*/=0A+=0A+/*=20Hash=20table=20entry=20= for=20basic=20TID=20dedup=20*/=0A+typedef=20struct=20GISTTIDHashEntry=0A= +{=0A+=09ItemPointerData=20tid;=09=09/*=20TID=20(hashtable=20key)=20*/=0A= +=09uint32=09=09hash;=09=09=09/*=20hash=20value=20(cached)=20*/=0A+=09= char=09=09status;=09=09=09/*=20hash=20status=20*/=0A+}=20= GISTTIDHashEntry;=0A+=0A+static=20inline=20uint32=0A= +gist_tid_hash_fn(ItemPointerData=20tid)=0A+{=0A+=09uint32=09=09h=20=3D=20= murmurhash32(ItemPointerGetBlockNumber(&tid));=0A+=0A+=09return=20= murmurhash32(h=20+=20ItemPointerGetOffsetNumber(&tid));=0A+}=0A+=0A= +static=20inline=20bool=0A+gist_tid_match_fn(ItemPointerData=20a,=20= ItemPointerData=20b)=0A+{=0A+=09return=20ItemPointerEquals(&a,=20&b);=0A= +}=0A+=0A+/*=20---=20gisttid=20hash=20table=20(declare=20+=20define)=20= ---=20*/=0A+#define=20SH_PREFIX=20gisttid=0A+#define=20SH_ELEMENT_TYPE=20= GISTTIDHashEntry=0A+#define=20SH_KEY_TYPE=20ItemPointerData=0A+#define=20= SH_KEY=20tid=0A+#define=20SH_HASH_KEY(tb,=20key)=20gist_tid_hash_fn(key)=0A= +#define=20SH_EQUAL(tb,=20a,=20b)=20gist_tid_match_fn(a,=20b)=0A+#define=20= SH_SCOPE=20static=20inline=0A+#define=20SH_DECLARE=0A+#define=20= SH_DEFINE=0A+#include=20"lib/simplehash.h"=0A+=0A+=0A=20/*=0A=20=20*=20= gistkillitems()=20--=20set=20LP_DEAD=20state=20for=20items=20an=20= indexscan=20caller=20has=0A=20=20*=20told=20us=20were=20killed.=0A@@=20= -456,7=20+500,8=20@@=20gistScanPage(IndexScanDesc=20scan,=20= GISTSearchItem=20*pageItem,=0A=20=09=09{=0A=20=09=09=09/*=0A=20=09=09=09=20= *=20getbitmap=20scan,=20so=20just=20push=20heap=20tuple=20TIDs=20into=20= the=20bitmap=0A-=09=09=09=20*=20without=20worrying=20about=20ordering=0A= +=09=09=09=20*=20without=20worrying=20about=20ordering.=20=20The=20= bitmap=20itself=20handles=0A+=09=09=09=20*=20deduplication,=20so=20no=20= extra=20work=20needed=20for=20multi-entry.=0A=20=09=09=09=20*/=0A=20=09=09= =09tbm_add_tuples(tbm,=20&it->t_tid,=201,=20recheck);=0A=20=09=09=09= (*ntids)++;=0A@@=20-464,8=20+509,20=20@@=20gistScanPage(IndexScanDesc=20= scan,=20GISTSearchItem=20*pageItem,=0A=20=09=09else=20if=20= (scan->numberOfOrderBys=20=3D=3D=200=20&&=20GistPageIsLeaf(page))=0A=20=09= =09{=0A=20=09=09=09/*=0A-=09=09=09=20*=20Non-ordered=20scan,=20so=20= report=20tuples=20in=20so->pageData[]=0A+=09=09=09=20*=20Non-ordered=20= scan,=20so=20report=20tuples=20in=20so->pageData[].=0A+=09=09=09=20*=0A+=09= =09=09=20*=20For=20multi-entry=20indexes,=20check=20the=20TID=20hash=20= table=20to=20avoid=0A+=09=09=09=20*=20returning=20duplicate=20heap=20= TIDs.=0A=20=09=09=09=20*/=0A+=09=09=09if=20(so->tidHash)=0A+=09=09=09{=0A= +=09=09=09=09bool=09=09found;=0A+=0A+=09=09=09=09= gisttid_insert(so->tidHash,=20it->t_tid,=20&found);=0A+=09=09=09=09if=20= (found)=0A+=09=09=09=09=09continue;=09/*=20already=20seen=20this=20TID=20= */=0A+=09=09=09}=0A+=0A=20=09=09=09so->pageData[so->nPageData].heapPtr=20= =3D=20it->t_tid;=0A=20=09=09=09so->pageData[so->nPageData].recheck=20=3D=20= recheck;=0A=20=09=09=09so->pageData[so->nPageData].offnum=20=3D=20i;=0A= @@=20-495,6=20+552,20=20@@=20gistScanPage(IndexScanDesc=20scan,=20= GISTSearchItem=20*pageItem,=0A=20=0A=20=09=09=09oldcxt=20=3D=20= MemoryContextSwitchTo(so->queueCxt);=0A=20=0A+=09=09=09/*=0A+=09=09=09=20= *=20For=20multi-entry=20ordered=20scans,=20skip=20heap=20tuples=20whose=20= TIDs=0A+=09=09=09=20*=20were=20already=20returned=20by=20getNextNearest.=20= =20We=20use=20lookup=0A+=09=09=09=20*=20(not=20insert)=20here:=20a=20TID=20= must=20remain=20enqueueable=20until=20it=0A+=09=09=09=20*=20is=20= actually=20dequeued,=20so=20that=20the=20pairing=20heap=20can=20pick=20= the=0A+=09=09=09=20*=20copy=20with=20the=20smallest=20distance.=0A+=09=09= =09=20*/=0A+=09=09=09if=20(GistPageIsLeaf(page)=20&&=0A+=09=09=09=09= so->tidHash=20&&=20gisttid_lookup(so->tidHash,=20it->t_tid))=0A+=09=09=09= {=0A+=09=09=09=09MemoryContextSwitchTo(oldcxt);=0A+=09=09=09=09continue;=0A= +=09=09=09}=0A+=0A=20=09=09=09/*=20Create=20new=20GISTSearchItem=20for=20= this=20item=20*/=0A=20=09=09=09item=20=3D=20= palloc(SizeOfGISTSearchItem(scan->numberOfOrderBys));=0A=20=0A@@=20= -587,7=20+658,27=20@@=20getNextNearest(IndexScanDesc=20scan)=0A=20=0A=20=09= =09if=20(GISTSearchItemIsHeap(*item))=0A=20=09=09{=0A-=09=09=09/*=20= found=20a=20heap=20item=20at=20currently=20minimal=20distance=20*/=0A+=09= =09=09/*=0A+=09=09=09=20*=20Found=20a=20heap=20item=20at=20currently=20= minimal=20distance.=0A+=09=09=09=20*=0A+=09=09=09=20*=20For=20= multi-entry=20ordered=20scans,=20deduplicate=20using=20tidHash=20to=0A+=09= =09=09=20*=20ensure=20each=20TID=20is=20returned=20only=20once.=20=20= Duplicate=20entries=0A+=09=09=09=20*=20for=20the=20same=20TID=20may=20= exist=20in=20the=20queue=20with=20different=0A+=09=09=09=20*=20= distances;=20the=20pairing=20heap=20ensures=20we=20see=20the=20smallest=0A= +=09=09=09=20*=20distance=20first,=20and=20tidHash=20skips=20subsequent=20= duplicates.=0A+=09=09=09=20*/=0A+=09=09=09if=20(so->tidHash)=0A+=09=09=09= {=0A+=09=09=09=09bool=09=09found;=0A+=0A+=09=09=09=09= gisttid_insert(so->tidHash,=20item->data.heap.heapPtr,=20&found);=0A+=09=09= =09=09if=20(found)=0A+=09=09=09=09{=0A+=09=09=09=09=09pfree(item);=0A+=09= =09=09=09=09continue;=09/*=20already=20returned=20this=20TID=20*/=0A+=09=09= =09=09}=0A+=09=09=09}=0A+=0A=20=09=09=09scan->xs_heaptid=20=3D=20= item->data.heap.heapPtr;=0A=20=09=09=09scan->xs_recheck=20=3D=20= item->data.heap.recheck;=0A=20=0A@@=20-643,6=20+734,30=20@@=20= gistgettuple(IndexScanDesc=20scan,=20ScanDirection=20dir)=0A=20=09=09if=20= (so->pageDataCxt)=0A=20=09=09=09MemoryContextReset(so->pageDataCxt);=0A=20= =0A+=09=09/*=0A+=09=09=20*=20For=20multi-entry=20indexes,=20set=20up=20= TID=20deduplication=20hash=20tables.=0A+=09=09=20*=20We=20check=20column=20= 0=20for=20extractValueFn=20as=20a=20proxy=20for=20multi-entry.=0A+=09=09=20= */=0A+=09=09if=20(OidIsValid(so->giststate->extractValueFn[0].fn_oid))=0A= +=09=09{=0A+=09=09=09MemoryContext=20oldHashCxt;=0A+=0A+=09=09=09/*=0A+=09= =09=09=20*=20Create=20a=20dedicated=20context=20for=20the=20hash=20= tables=20so=20they=20can=0A+=09=09=09=20*=20be=20reset=20independently.=0A= +=09=09=09=20*/=0A+=09=09=09if=20(so->tidHashCxt=20=3D=3D=20= so->giststate->scanCxt)=0A+=09=09=09=09so->tidHashCxt=20=3D=20= AllocSetContextCreate(so->giststate->scanCxt,=0A+=09=09=09=09=09=09=09=09= =09=09=09=09=09=20=20=20"GiST=20TID=20hash=20context",=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=20=20=20ALLOCSET_DEFAULT_SIZES);=0A+=09=09=09= else=0A+=09=09=09=09MemoryContextReset(so->tidHashCxt);=0A+=0A+=09=09=09= oldHashCxt=20=3D=20MemoryContextSwitchTo(so->tidHashCxt);=0A+=09=09=09= so->tidHash=20=3D=20gisttid_create(so->tidHashCxt,=20256,=20NULL);=0A+=09= =09=09MemoryContextSwitchTo(oldHashCxt);=0A+=09=09}=0A+=0A=20=09=09= fakeItem.blkno=20=3D=20GIST_ROOT_BLKNO;=0A=20=09=09= memset(&fakeItem.data.parentlsn,=200,=20sizeof(GistNSN));=0A=20=09=09= gistScanPage(scan,=20&fakeItem,=20NULL,=20NULL,=20NULL);=0A@@=20-805,6=20= +920,15=20@@=20gistgetbitmap(IndexScanDesc=20scan,=20TIDBitmap=20*tbm)=0A= =20bool=0A=20gistcanreturn(Relation=20index,=20int=20attno)=0A=20{=0A+=09= /*=0A+=09=20*=20Multi-entry=20indexes=20store=20decomposed=20sub-entries=20= in=20key=20columns,=20not=20the=0A+=09=20*=20original=20datum,=20so=20= key=20columns=20cannot=20be=20returned=20in=20an=20index-only=20scan.=0A= +=09=20*=20INCLUDE=20columns=20are=20still=20returnable.=0A+=09=20*/=0A+=09= if=20(attno=20<=3D=20IndexRelationGetNumberOfKeyAttributes(index)=20&&=0A= +=09=09OidIsValid(index_getprocid(index,=20attno,=20= GIST_EXTRACTVALUE_PROC)))=0A+=09=09return=20false;=0A+=0A=20=09if=20= (attno=20>=20IndexRelationGetNumberOfKeyAttributes(index)=20||=0A=20=09=09= OidIsValid(index_getprocid(index,=20attno,=20GIST_FETCH_PROC))=20||=0A=20= =09=09!OidIsValid(index_getprocid(index,=20attno,=20= GIST_COMPRESS_PROC)))=0Adiff=20--git=20= a/src/backend/access/gist/gistscan.c=20= b/src/backend/access/gist/gistscan.c=0Aindex=20c65f93abdae..4d9a4a148cd=20= 100644=0A---=20a/src/backend/access/gist/gistscan.c=0A+++=20= b/src/backend/access/gist/gistscan.c=0A@@=20-96,6=20+96,10=20@@=20= gistbeginscan(Relation=20r,=20int=20nkeys,=20int=20norderbys)=0A=20=09= so->queue=20=3D=20NULL;=0A=20=09so->queueCxt=20=3D=20giststate->scanCxt;=09= /*=20see=20gistrescan=20*/=0A=20=0A+=09/*=20Initialize=20multi-entry=20= TID=20dedup=20fields=20(NULL=20if=20not=20multi-entry)=20*/=0A+=09= so->tidHash=20=3D=20NULL;=0A+=09so->tidHashCxt=20=3D=20= giststate->scanCxt;=0A+=0A=20=09/*=20workspaces=20with=20size=20= dependent=20on=20numberOfOrderBys:=20*/=0A=20=09so->distances=20=3D=20= palloc(sizeof(so->distances[0])=20*=20scan->numberOfOrderBys);=0A=20=09= so->qual_ok=20=3D=20true;=09=09=09/*=20in=20case=20there=20are=20zero=20= keys=20*/=0Adiff=20--git=20a/src/backend/access/gist/gistutil.c=20= b/src/backend/access/gist/gistutil.c=0Aindex=200f58f61879f..42ab801f7bf=20= 100644=0A---=20a/src/backend/access/gist/gistutil.c=0A+++=20= b/src/backend/access/gist/gistutil.c=0A@@=20-1007,6=20+1007,74=20@@=20= gistproperty(Oid=20index_oid,=20int=20attno,=0A=20=09return=20true;=0A=20= }=0A=20=0A+/*=0A+=20*=20gistExtractEntries=20--=20extract=20multiple=20= index=20entries=20from=20one=20heap=20tuple.=0A+=20*=0A+=20*=20Calls=20= the=20opclass's=20extractValue=20function=20to=20decompose=20the=20= indexed=20datum=0A+=20*=20into=20multiple=20sub-entries.=20=20Returns=20= an=20array=20of=20IndexTuples,=20one=20per=0A+=20*=20sub-entry.=0A+=20*=0A= +=20*=20Currently=20only=20single-key-column=20indexes=20are=20supported=20= (enforced=20by=0A+=20*=20initGISTstate).=20=20INCLUDE=20columns=20are=20= preserved=20on=20every=20entry.=0A+=20*=20If=20the=20datum=20is=20NULL=20= or=20extractValue=20returns=20no=20entries,=20a=20single=20NULL=0A+=20*=20= index=20entry=20is=20produced.=0A+=20*/=0A+IndexTuple=20*=0A= +gistExtractEntries(GISTSTATE=20*giststate,=20Relation=20index,=0A+=09=09= =09=09=20=20=20Datum=20*values,=20bool=20*isnull,=20int32=20*nentries)=0A= +{=0A+=09Datum=09=20=20=20*entries;=0A+=09bool=09=20=20=20*nullFlags;=0A= +=09IndexTuple=20*result;=0A+=09int=09=09=09i;=0A+=0A+=09= Assert(IndexRelationGetNumberOfKeyAttributes(index)=20=3D=3D=201);=0A+=0A= +=09/*=20NULL=20datum=20produces=20a=20single=20NULL=20index=20entry=20= */=0A+=09if=20(isnull[0])=0A+=09{=0A+=09=09*nentries=20=3D=201;=0A+=09=09= result=20=3D=20palloc(sizeof(IndexTuple));=0A+=09=09result[0]=20=3D=20= gistFormTuple(giststate,=20index,=20values,=20isnull,=20true);=0A+=09=09= return=20result;=0A+=09}=0A+=0A+=09/*=20Call=20the=20opclass's=20= extractValue=20function=20*/=0A+=09nullFlags=20=3D=20NULL;=0A+=09entries=20= =3D=20(Datum=20*)=0A+=09=09= DatumGetPointer(FunctionCall3Coll(&giststate->extractValueFn[0],=0A+=09=09= =09=09=09=09=09=09=09=09=20=20giststate->supportCollation[0],=0A+=09=09=09= =09=09=09=09=09=09=09=20=20values[0],=0A+=09=09=09=09=09=09=09=09=09=09=20= =20PointerGetDatum(nentries),=0A+=09=09=09=09=09=09=09=09=09=09=20=20= PointerGetDatum(&nullFlags)));=0A+=0A+=09/*=20Handle=20empty=20or=20NULL=20= result:=20produce=20a=20single=20NULL=20entry=20*/=0A+=09if=20(entries=20= =3D=3D=20NULL=20||=20*nentries=20<=3D=200)=0A+=09{=0A+=09=09*nentries=20= =3D=201;=0A+=09=09values[0]=20=3D=20(Datum)=200;=0A+=09=09isnull[0]=20=3D=20= true;=0A+=09=09result=20=3D=20palloc(sizeof(IndexTuple));=0A+=09=09= result[0]=20=3D=20gistFormTuple(giststate,=20index,=20values,=20isnull,=20= true);=0A+=09=09return=20result;=0A+=09}=0A+=0A+=09/*=20Create=20= nullFlags=20array=20if=20the=20function=20didn't=20*/=0A+=09if=20= (nullFlags=20=3D=3D=20NULL)=0A+=09=09nullFlags=20=3D=20= palloc0_array(bool,=20*nentries);=0A+=0A+=09/*=20Form=20one=20index=20= tuple=20per=20extracted=20entry=20*/=0A+=09result=20=3D=20= palloc_array(IndexTuple,=20*nentries);=0A+=09for=20(i=20=3D=200;=20i=20<=20= *nentries;=20i++)=0A+=09{=0A+=09=09values[0]=20=3D=20entries[i];=0A+=09=09= isnull[0]=20=3D=20nullFlags[i];=0A+=09=09result[i]=20=3D=20= gistFormTuple(giststate,=20index,=20values,=20isnull,=20true);=0A+=09}=0A= +=0A+=09return=20result;=0A+}=0A+=0A=20/*=0A=20=20*=20This=20is=20a=20= stratnum=20translation=20support=20function=20for=20GiST=20opclasses=20= that=20use=0A=20=20*=20the=20RT*StrategyNumber=20constants.=0Adiff=20= --git=20a/src/backend/access/gist/gistvalidate.c=20= b/src/backend/access/gist/gistvalidate.c=0Aindex=20= 56feb8d8400..bffb048b1a9=20100644=0A---=20= a/src/backend/access/gist/gistvalidate.c=0A+++=20= b/src/backend/access/gist/gistvalidate.c=0A@@=20-144,6=20+144,11=20@@=20= gistvalidate(Oid=20opclassoid)=0A=20=09=09=09=09=09= procform->amproclefttype=20=3D=3D=20ANYOID=20&&=0A=20=09=09=09=09=09= procform->amprocrighttype=20=3D=3D=20ANYOID;=0A=20=09=09=09=09break;=0A+=09= =09=09case=20GIST_EXTRACTVALUE_PROC:=0A+=09=09=09=09ok=20=3D=20= check_amproc_signature(procform->amproc,=20INTERNALOID,=20true,=0A+=09=09= =09=09=09=09=09=09=09=09=093,=203,=20INTERNALOID,=20INTERNALOID,=0A+=09=09= =09=09=09=09=09=09=09=09=09INTERNALOID);=0A+=09=09=09=09break;=0A=20=09=09= =09default:=0A=20=09=09=09=09ereport(INFO,=0A=20=09=09=09=09=09=09= (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),=0A@@=20-265,7=20+270,8=20@@=20= gistvalidate(Oid=20opclassoid)=0A=20=09=09if=20(i=20=3D=3D=20= GIST_DISTANCE_PROC=20||=20i=20=3D=3D=20GIST_FETCH_PROC=20||=0A=20=09=09=09= i=20=3D=3D=20GIST_COMPRESS_PROC=20||=20i=20=3D=3D=20GIST_DECOMPRESS_PROC=20= ||=0A=20=09=09=09i=20=3D=3D=20GIST_OPTIONS_PROC=20||=20i=20=3D=3D=20= GIST_SORTSUPPORT_PROC=20||=0A-=09=09=09i=20=3D=3D=20= GIST_TRANSLATE_CMPTYPE_PROC)=0A+=09=09=09i=20=3D=3D=20= GIST_TRANSLATE_CMPTYPE_PROC=20||=0A+=09=09=09i=20=3D=3D=20= GIST_EXTRACTVALUE_PROC)=0A=20=09=09=09continue;=09=09=09/*=20optional=20= methods=20*/=0A=20=09=09ereport(INFO,=0A=20=09=09=09=09= (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),=0A@@=20-337,6=20+343,7=20@@=20= gistadjustmembers(Oid=20opfamilyoid,=0A=20=09=09=09case=20= GIST_OPTIONS_PROC:=0A=20=09=09=09case=20GIST_SORTSUPPORT_PROC:=0A=20=09=09= =09case=20GIST_TRANSLATE_CMPTYPE_PROC:=0A+=09=09=09case=20= GIST_EXTRACTVALUE_PROC:=0A=20=09=09=09=09/*=20Optional,=20so=20force=20= it=20to=20be=20a=20soft=20family=20dependency=20*/=0A=20=09=09=09=09= op->ref_is_hard=20=3D=20false;=0A=20=09=09=09=09op->ref_is_family=20=3D=20= true;=0Adiff=20--git=20a/src/include/access/gist.h=20= b/src/include/access/gist.h=0Aindex=209b385b13a88..68f8eca550e=20100644=0A= ---=20a/src/include/access/gist.h=0A+++=20b/src/include/access/gist.h=0A= @@=20-41,7=20+41,8=20@@=0A=20#define=20GIST_OPTIONS_PROC=09=09=09=0910=0A= =20#define=20GIST_SORTSUPPORT_PROC=09=09=0911=0A=20#define=20= GIST_TRANSLATE_CMPTYPE_PROC=09=0912=0A-#define=20GISTNProcs=09=09=09=09=09= 12=0A+#define=20GIST_EXTRACTVALUE_PROC=09=09=0913=0A+#define=20= GISTNProcs=09=09=09=09=0913=0A=20=0A=20/*=0A=20=20*=20Page=20opaque=20= data=20in=20a=20GiST=20index=20page.=0Adiff=20--git=20= a/src/include/access/gist_private.h=20= b/src/include/access/gist_private.h=0Aindex=2044514f1cb8d..5caf7a1956e=20= 100644=0A---=20a/src/include/access/gist_private.h=0A+++=20= b/src/include/access/gist_private.h=0A@@=20-92,6=20+92,7=20@@=20typedef=20= struct=20GISTSTATE=0A=20=09FmgrInfo=09equalFn[INDEX_MAX_KEYS];=0A=20=09= FmgrInfo=09distanceFn[INDEX_MAX_KEYS];=0A=20=09FmgrInfo=09= fetchFn[INDEX_MAX_KEYS];=0A+=09FmgrInfo=09= extractValueFn[INDEX_MAX_KEYS];=0A=20=0A=20=09/*=20Collations=20to=20= pass=20to=20the=20support=20functions=20*/=0A=20=09Oid=09=09=09= supportCollation[INDEX_MAX_KEYS];=0A@@=20-156,6=20+157,14=20@@=20typedef=20= struct=20GISTScanOpaqueData=0A=20=09GISTSTATE=20=20*giststate;=09=09/*=20= index=20information,=20see=20above=20*/=0A=20=09Oid=09=09=20=20=20= *orderByTypes;=09/*=20datatypes=20of=20ORDER=20BY=20expressions=20*/=0A=20= =0A+=09/*=0A+=09=20*=20For=20multi-entry=20indexes:=20hash=20table=20for=20= TID=20deduplication.=20=20Each=20heap=0A+=09=20*=20tuple=20produces=20= multiple=20index=20entries,=20so=20we=20track=20which=20TIDs=20have=20= been=0A+=09=20*=20returned.=20=20NULL=20for=20standard=20= (non-multi-entry)=20indexes.=0A+=09=20*/=0A+=09struct=20gisttid_hash=20= *tidHash;=0A+=09MemoryContext=20tidHashCxt;=09/*=20context=20holding=20= the=20hash=20table=20*/=0A+=0A=20=09pairingheap=20*queue;=09=09=09/*=20= queue=20of=20unvisited=20items=20*/=0A=20=09MemoryContext=20queueCxt;=09=09= /*=20context=20holding=20the=20queue=20*/=0A=20=09bool=09=09qual_ok;=09=09= /*=20false=20if=20qual=20can=20never=20be=20satisfied=20*/=0A@@=20-547,6=20= +556,11=20@@=20extern=20void=20gistSplitByKey(Relation=20r,=20Page=20= page,=20IndexTuple=20*itup,=0A=20extern=20IndexBuildResult=20= *gistbuild(Relation=20heap,=20Relation=20index,=0A=20=09=09=09=09=09=09=09= =09=20=20=20struct=20IndexInfo=20*indexInfo);=0A=20=0A+/*=20gistutil.c=20= */=0A+extern=20IndexTuple=20*gistExtractEntries(GISTSTATE=20*giststate,=20= Relation=20index,=0A+=09=09=09=09=09=09=09=09=09=20=20Datum=20*values,=20= bool=20*isnull,=0A+=09=09=09=09=09=09=09=09=09=20=20int32=20*nentries);=0A= +=0A=20/*=20gistbuildbuffers.c=20*/=0A=20extern=20GISTBuildBuffers=20= *gistInitBuildBuffers(int=20pagesPerBuffer,=20int=20levelStep,=0A=20=09=09= =09=09=09=09=09=09=09=09=09=20=20int=20maxLevel);=0A--=20=0A2.50.1=20= (Apple=20Git-155)=0A=0A= --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841 Content-Disposition: attachment; filename=v1-0002-Add-multirange_me_ops-GiST-opclass-using-multi-en.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0002-Add-multirange_me_ops-GiST-opclass-using-multi-en.patch" Content-Transfer-Encoding: quoted-printable =46rom=2018f4cb4bd7af1c7d7763262a7465431cbde46379=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Maxime=20Schoemans=20= =0ADate:=20Thu,=202=20Apr=202026=20= 18:15:00=20+0200=0ASubject:=20[PATCH=20v1=202/4]=20Add=20= multirange_me_ops=20GiST=20opclass=20using=20multi-entry=0A=0AAdd=20a=20= new=20GiST=20opclass,=20multirange_me_ops,=20that=20uses=20the=20= multi-entry=0Ainfrastructure=20from=20the=20previous=20commit=20to=20= decompose=20multiranges=20into=0Atheir=20component=20ranges=20for=20= indexing.=20=20Unlike=20the=20existing=20multirange_ops=0Awhich=20= compresses=20a=20multirange=20into=20its=20bounding=20union=20range=20= (losing=20gap=0Ainformation),=20this=20opclass=20stores=20each=20= component=20range=20as=20a=20separate=0Aindex=20entry,=20giving=20the=20= R-tree=20much=20tighter=20bounds=20and=20significantly=0Areducing=20= false-positive=20rechecks.=0A=0AThe=20opclass=20provides:=0A=0A=20=20-=20= extractValue:=20decomposes=20a=20multirange=20into=20component=20ranges.=20= =20Empty=0A=20=20=20=20multiranges=20are=20stored=20as=20empty=20range=20= sentinels=20(not=20NULLs)=20so=20they=0A=20=20=20=20remain=20visible=20= to=20operator=20queries.=0A=0A=20=20-=20Leaf=20consistent=20functions:=20= account=20for=20the=20fact=20that=20each=20leaf=20entry=0A=20=20=20=20is=20= a=20single=20component,=20not=20the=20full=20multirange.=20=20OVERLAPS=20= and=0A=20=20=20=20CONTAINS_ELEM=20are=20recheck-free=20(a=20component=20= match=20implies=20a=0A=20=20=20=20multirange=20match);=20all=20other=20= strategies=20set=20recheck.=0A=0A=20=20-=20Internal=20consistent=20= functions:=20like=20the=20standard=20range=20GiST=20internal=0A=20=20=20=20= checks,=20but=20CONTAINS=20and=20EQ=20are=20relaxed=20to=20use=20overlap=20= instead=20of=0A=20=20=20=20containment,=20since=20a=20matching=20= multirange's=20components=20may=20be=20spread=0A=20=20=20=20across=20= multiple=20subtrees.=0A=0AThe=20opclass=20is=20non-default=20= (multirange_ops=20remains=20the=20default)=20and=0Asupports=20the=20same=20= operator=20set:=20<<,=20&<,=20&&,=20&>,=20>>,=20-|-,=20@>,=20<@,=20= @>elem,=0Aand=20=3D.=0A=0ARegression=20tests=20verify=20index=20= correctness=20against=20sequential=20scan=20results=0Afor=20all=20= operators,=20including=20empty=20range/multirange=20edge=20cases,=20= bitmap=0Ascans,=20multi-column=20restriction=20enforcement,=20and=20NULL=20= handling.=0A---=0A=20src/backend/utils/adt/rangetypes_gist.c=20=20=20=20=20= =20=20|=20466=20++++++++++++=0A=20src/include/catalog/pg_amop.dat=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=2056=20++=0A=20= src/include/catalog/pg_amproc.dat=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=2021=20+=0A=20src/include/catalog/pg_opclass.dat=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=203=20+=0A=20src/include/catalog/pg_opfamily.dat=20= =20=20=20=20=20=20=20=20=20=20|=20=20=202=20+=0A=20= src/include/catalog/pg_proc.dat=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=20=208=20+=0A=20src/test/regress/expected/multirangetypes.out=20= |=20672=20++++++++++++++++++=0A=20= src/test/regress/sql/multirangetypes.sql=20=20=20=20=20=20|=20154=20++++=0A= =208=20files=20changed,=201382=20insertions(+)=0A=0Adiff=20--git=20= a/src/backend/utils/adt/rangetypes_gist.c=20= b/src/backend/utils/adt/rangetypes_gist.c=0Aindex=20= 1a01a8f4c3c..222103cbb57=20100644=0A---=20= a/src/backend/utils/adt/rangetypes_gist.c=0A+++=20= b/src/backend/utils/adt/rangetypes_gist.c=0A@@=20-160,6=20+160,30=20@@=20= static=20bool=20range_gist_consistent_leaf_element(TypeCacheEntry=20= *typcache,=0A=20=09=09=09=09=09=09=09=09=09=09=09=20=20=20StrategyNumber=20= strategy,=0A=20=09=09=09=09=09=09=09=09=09=09=09=20=20=20const=20= RangeType=20*key,=0A=20=09=09=09=09=09=09=09=09=09=09=09=20=20=20Datum=20= query);=0A+static=20bool=20range_me_consistent_int_range(TypeCacheEntry=20= *typcache,=0A+=09=09=09=09=09=09=09=09=09=09=20=20StrategyNumber=20= strategy,=0A+=09=09=09=09=09=09=09=09=09=09=20=20const=20RangeType=20= *key,=0A+=09=09=09=09=09=09=09=09=09=09=20=20const=20RangeType=20= *query);=0A+static=20bool=20= range_me_consistent_int_multirange(TypeCacheEntry=20*typcache,=0A+=09=09=09= =09=09=09=09=09=09=09=09=20=20=20StrategyNumber=20strategy,=0A+=09=09=09=09= =09=09=09=09=09=09=09=20=20=20const=20RangeType=20*key,=0A+=09=09=09=09=09= =09=09=09=09=09=09=20=20=20const=20MultirangeType=20*query);=0A+static=20= bool=20range_me_consistent_int_element(TypeCacheEntry=20*typcache,=0A+=09= =09=09=09=09=09=09=09=09=09=09StrategyNumber=20strategy,=0A+=09=09=09=09=09= =09=09=09=09=09=09const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09=09= =09=09Datum=20query);=0A+static=20bool=20= range_me_consistent_leaf_range(TypeCacheEntry=20*typcache,=0A+=09=09=09=09= =09=09=09=09=09=09=20=20=20StrategyNumber=20strategy,=0A+=09=09=09=09=09=09= =09=09=09=09=20=20=20const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09= =09=09=20=20=20const=20RangeType=20*query);=0A+static=20bool=20= range_me_consistent_leaf_multirange(TypeCacheEntry=20*typcache,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09StrategyNumber=20strategy,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09= =09=09=09=09const=20MultirangeType=20*query);=0A+static=20bool=20= range_me_consistent_leaf_element(TypeCacheEntry=20*typcache,=0A+=09=09=09= =09=09=09=09=09=09=09=09=20StrategyNumber=20strategy,=0A+=09=09=09=09=09=09= =09=09=09=09=09=20const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09=09= =09=09=20Datum=20query);=0A=20static=20void=20= range_gist_fallback_split(TypeCacheEntry=20*typcache,=0A=20=09=09=09=09=09= =09=09=09=09=20=20GistEntryVector=20*entryvec,=0A=20=09=09=09=09=09=09=09= =09=09=20=20GIST_SPLITVEC=20*v);=0A@@=20-1796,3=20+1820,445=20@@=20= call_subtype_diff(TypeCacheEntry=20*typcache,=20Datum=20val1,=20Datum=20= val2)=0A=20=09=09return=20value;=0A=20=09return=200.0;=0A=20}=0A+=0A+=0A= +/*=0A+=20*----------------------------------------------------------=0A= +=20*=20MULTI-ENTRY=20GiST=20SUPPORT=20FOR=20MULTIRANGES=0A+=20*=0A+=20*=20= When=20an=20extractValue=20support=20function=20is=20registered,=20GiST=20= decomposes=0A+=20*=20each=20multirange=20into=20its=20component=20ranges=20= and=20stores=20each=20as=20a=20separate=0A+=20*=20index=20entry.=20=20= This=20requires=20a=20different=20consistent=20function=20because=0A+=20= *=20leaf=20entries=20are=20individual=20component=20ranges,=20not=20the=20= union=20range.=0A+=20= *----------------------------------------------------------=0A+=20*/=0A+=0A= +/*=0A+=20*=20Multi-entry=20GiST=20extractValue=20function=20for=20= multirange=20types.=0A+=20*=0A+=20*=20Decomposes=20a=20multirange=20into=20= its=20component=20ranges.=20=20Returns=20an=20array=0A+=20*=20of=20Datum=20= values=20(one=20per=20range)=20via=20the=20return=20value,=20and=20sets=20= *nkeys=0A+=20*=20to=20the=20number=20of=20entries.=0A+=20*/=0A+Datum=0A= +multirange_gist_extractvalue(PG_FUNCTION_ARGS)=0A+{=0A+=09= MultirangeType=20*mr=20=3D=20PG_GETARG_MULTIRANGE_P(0);=0A+=09int32=09=20= =20=20*nkeys=20=3D=20(int32=20*)=20PG_GETARG_POINTER(1);=0A+=09= TypeCacheEntry=20*typcache;=0A+=09int32=09=09range_count;=0A+=09= RangeType=20**ranges;=0A+=09Datum=09=20=20=20*entries;=0A+=09int=09=09=09= i;=0A+=0A+=09typcache=20=3D=20multirange_get_typcache(fcinfo,=20= MultirangeTypeGetOid(mr));=0A+=0A+=09if=20(MultirangeIsEmpty(mr))=0A+=09= {=0A+=09=09/*=0A+=09=09=20*=20Store=20an=20empty=20range=20as=20a=20= sentinel=20for=20empty=20multiranges=20so=20they=0A+=09=09=20*=20remain=20= visible=20to=20operator=20queries=20(NULL=20entries=20only=20match=20IS=20= NULL).=0A+=09=09=20*/=0A+=09=09RangeBound=09lower=20=3D=20{0};=0A+=09=09= RangeBound=09upper=20=3D=20{0};=0A+=0A+=09=09lower.lower=20=3D=20true;=0A= +=09=09entries=20=3D=20palloc(sizeof(Datum));=0A+=09=09entries[0]=20=3D=20= RangeTypePGetDatum(=0A+=09=09=09make_range(typcache->rngtype,=20&lower,=20= &upper,=20true,=20NULL));=0A+=09=09*nkeys=20=3D=201;=0A+=09=09= PG_RETURN_POINTER(entries);=0A+=09}=0A+=0A+=09= multirange_deserialize(typcache->rngtype,=20mr,=20&range_count,=20= &ranges);=0A+=0A+=09entries=20=3D=20palloc(sizeof(Datum)=20*=20= range_count);=0A+=09for=20(i=20=3D=200;=20i=20<=20range_count;=20i++)=0A= +=09=09entries[i]=20=3D=20RangeTypePGetDatum(ranges[i]);=0A+=0A+=09= *nkeys=20=3D=20range_count;=0A+=09PG_RETURN_POINTER(entries);=0A+}=0A+=0A= +/*=0A+=20*=20Multi-entry=20GiST=20consistent=20function=20for=20= multirange=20types.=0A+=20*=0A+=20*=20This=20is=20used=20when=20the=20= multirange=20opclass=20has=20an=20extractValue=20function.=0A+=20*=20= Leaf=20entries=20are=20individual=20component=20ranges=20(not=20the=20= union=20range),=20so=0A+=20*=20most=20leaf=20checks=20set=20recheck=3Dtrue= =20since=20a=20single=20component=20cannot=20fully=0A+=20*=20determine=20= the=20relationship=20with=20the=20query.=20=20OVERLAPS=20and=20= CONTAINS_ELEM=0A+=20*=20are=20exact=20per-component=20and=20skip=20= recheck=20(see=20comments=20in=20the=20leaf=0A+=20*=20consistent=20= functions=20below).=20=20Internal=20nodes=20still=20store=20union=20= ranges,=0A+=20*=20so=20the=20internal=20consistent=20checks=20are=20= unchanged.=0A+=20*/=0A+Datum=0A= +multirange_gist_me_consistent(PG_FUNCTION_ARGS)=0A+{=0A+=09GISTENTRY=20=20= *entry=20=3D=20(GISTENTRY=20*)=20PG_GETARG_POINTER(0);=0A+=09Datum=09=09= query=20=3D=20PG_GETARG_DATUM(1);=0A+=09StrategyNumber=20strategy=20=3D=20= (StrategyNumber)=20PG_GETARG_UINT16(2);=0A+=09bool=09=09result;=0A+=09= Oid=09=09=09subtype=20=3D=20PG_GETARG_OID(3);=0A+=09bool=09=20=20=20= *recheck=20=3D=20(bool=20*)=20PG_GETARG_POINTER(4);=0A+=09RangeType=20=20= *key=20=3D=20DatumGetRangeTypeP(entry->key);=0A+=09TypeCacheEntry=20= *typcache;=0A+=0A+=09typcache=20=3D=20range_get_typcache(fcinfo,=20= RangeTypeGetOid(key));=0A+=0A+=09if=20(GIST_LEAF(entry))=0A+=09{=0A+=09=09= /*=0A+=09=09=20*=20Leaf=20entries=20are=20individual=20component=20= ranges=20from=20the=20multirange.=0A+=09=09=20*=20Use=20multi-entry=20= leaf=20consistent=20functions=20which=20account=20for=20the=0A+=09=09=20= *=20fact=20that=20we're=20seeing=20only=20one=20component,=20not=20the=20= full=20value.=0A+=09=09=20*=0A+=09=09=20*=20Most=20strategies=20need=20= recheck=20because=20a=20single=20component=20cannot=0A+=09=09=20*=20= determine=20the=20full=20multirange's=20relationship=20with=20the=20= query.=0A+=09=09=20*=20However,=20some=20strategies=20are=20exact=20= per-component:=0A+=09=09=20*=0A+=09=09=20*=20-=20OVERLAPS:=20if=20= component=20Ri=20overlaps=20Q,=20then=20M=20overlaps=20Q,=20because=0A+=09= =09=20*=20=20=20the=20shared=20points=20between=20Ri=20and=20Q=20are=20= also=20in=20M.=0A+=09=09=20*=20-=20CONTAINS_ELEM:=20if=20Ri=20contains=20= elem,=20M=20contains=20elem,=20because=0A+=09=09=20*=20=20=20Ri=20is=20a=20= subset=20of=20M.=0A+=09=09=20*/=0A+=09=09if=20(strategy=20=3D=3D=20= RANGESTRAT_OVERLAPS=20||=0A+=09=09=09strategy=20=3D=3D=20= RANGESTRAT_CONTAINS_ELEM)=0A+=09=09=09*recheck=20=3D=20false;=0A+=09=09= else=0A+=09=09=09*recheck=20=3D=20true;=0A+=0A+=09=09if=20= (!OidIsValid(subtype)=20||=20subtype=20=3D=3D=20ANYMULTIRANGEOID)=0A+=09=09= =09result=20=3D=20range_me_consistent_leaf_multirange(typcache,=20= strategy,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09=20key,=0A+=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=20DatumGetMultirangeTypeP(query));=0A+=09= =09else=20if=20(subtype=20=3D=3D=20ANYRANGEOID)=0A+=09=09=09result=20=3D=20= range_me_consistent_leaf_range(typcache,=20strategy,=20key,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09DatumGetRangeTypeP(query));=0A+=09=09else=0A+=09= =09=09result=20=3D=20range_me_consistent_leaf_element(typcache,=20= strategy,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=20=20key,=20query);=0A= +=09}=0A+=09else=0A+=09{=0A+=09=09/*=0A+=09=09=20*=20Internal=20nodes=20= store=20union=20ranges=20of=20components=20from=20potentially=0A+=09=09=20= *=20many=20different=20multiranges.=20=20We=20use=20multi-entry-aware=20= internal=0A+=09=09=20*=20consistent=20functions=20that=20relax=20= CONTAINS=20and=20EQ=20checks:=20the=0A+=09=09=20*=20standard=20functions=20= require=20the=20union=20key=20to=20fully=20contain=20the=0A+=09=09=20*=20= query,=20but=20in=20multi-entry=20a=20matching=20multirange's=20= components=20may=0A+=09=09=20*=20be=20spread=20across=20multiple=20= subtrees.=0A+=09=09=20*/=0A+=09=09if=20(!OidIsValid(subtype)=20||=20= subtype=20=3D=3D=20ANYMULTIRANGEOID)=0A+=09=09=09result=20=3D=20= range_me_consistent_int_multirange(typcache,=20strategy,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09key,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09= =09DatumGetMultirangeTypeP(query));=0A+=09=09else=20if=20(subtype=20=3D=3D= =20ANYRANGEOID)=0A+=09=09=09result=20=3D=20= range_me_consistent_int_range(typcache,=20strategy,=20key,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=20=20=20DatumGetRangeTypeP(query));=0A+=09=09= else=0A+=09=09=09result=20=3D=20= range_me_consistent_int_element(typcache,=20strategy,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20key,=20query);=0A+=09}=0A+=09= PG_RETURN_BOOL(result);=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20leaf=20= consistent=20test=20with=20a=20range=20query.=0A+=20*=0A+=20*=20The=20= key=20is=20one=20component=20range=20from=20the=20indexed=20multirange=20= M.=20=20We=20must=0A+=20*=20avoid=20false=20negatives:=20if=20the=20= operator=20holds=20for=20M=20and=20query=20Q,=20at=20least=0A+=20*=20one=20= component=20must=20return=20true=20here.=20=20False=20positives=20are=20= filtered=20by=0A+=20*=20recheck.=20=20See=20= multirange_gist_me_consistent=20for=20which=20strategies=20are=0A+=20*=20= recheck-free.=0A+=20*/=0A+static=20bool=0A= +range_me_consistent_leaf_range(TypeCacheEntry=20*typcache,=0A+=09=09=09=09= =09=09=09=20=20=20StrategyNumber=20strategy,=0A+=09=09=09=09=09=09=09=20=20= =20const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=20=20=20const=20= RangeType=20*query)=0A+{=0A+=09/*=20Empty=20key=20is=20the=20sentinel=20= for=20an=20empty=20multirange=20*/=0A+=09if=20(RangeIsEmpty(key))=0A+=09= {=0A+=09=09if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINED_BY)=0A+=09=09=09= return=20true;=0A+=09=09if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS)=0A= +=09=09=09return=20RangeIsEmpty(query);=0A+=09=09return=20false;=0A+=09}=0A= +=0A+=09/*=20Empty=20range=20is=20contained=20by=20everything,=20has=20= no=20other=20relationships=20*/=0A+=09if=20(RangeIsEmpty(query))=0A+=09{=0A= +=09=09if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS)=0A+=09=09=09return=20= true;=0A+=09=09return=20false;=0A+=09}=0A+=0A+=09switch=20(strategy)=0A+=09= {=0A+=09=09=09/*=0A+=09=09=09=20*=20Bound=20operators:=20if=20M=20= satisfies=20the=20bound,=20every=20component=0A+=09=09=09=20*=20does=20= too,=20so=20the=20exact=20per-component=20check=20has=20no=20false=0A+=09= =09=09=20*=20negatives.=20=20Still=20needs=20recheck=20since=20other=20= components=20may=0A+=09=09=09=20*=20violate=20the=20bound.=0A+=09=09=09=20= */=0A+=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09=09return=20= range_before_internal(typcache,=20key,=20query);=0A+=09=09case=20= RANGESTRAT_OVERLEFT:=0A+=09=09=09return=20= range_overleft_internal(typcache,=20key,=20query);=0A+=09=09case=20= RANGESTRAT_OVERRIGHT:=0A+=09=09=09return=20= range_overright_internal(typcache,=20key,=20query);=0A+=09=09case=20= RANGESTRAT_AFTER:=0A+=09=09=09return=20range_after_internal(typcache,=20= key,=20query);=0A+=0A+=09=09=09/*=20Exact=20and=20recheck-free:=20if=20= component=20overlaps=20Q,=20so=20does=20M=20*/=0A+=09=09case=20= RANGESTRAT_OVERLAPS:=0A+=09=09=09return=20= range_overlaps_internal(typcache,=20key,=20query);=0A+=0A+=09=09=09/*=20= Exact=20check,=20but=20another=20component=20might=20overlap=20Q=20*/=0A= +=09=09case=20RANGESTRAT_ADJACENT:=0A+=09=09=09return=20= range_adjacent_internal(typcache,=20key,=20query);=0A+=0A+=09=09=09/*=0A= +=09=09=09=20*=20Use=20overlaps=20as=20a=20necessary=20condition.=20=20= For=20@>:=20Q=20is=0A+=09=09=09=20*=20contiguous=20and=20must=20lie=20= within=20some=20component,=20so=20that=0A+=09=09=09=20*=20component=20= overlaps=20Q.=20=20For=20<@:=20every=20component=20is=20a=20subset=0A+=09= =09=09=20*=20of=20Q,=20so=20every=20component=20overlaps=20Q.=0A+=09=09=09= =20*/=0A+=09=09case=20RANGESTRAT_CONTAINS:=0A+=09=09case=20= RANGESTRAT_CONTAINED_BY:=0A+=09=09case=20RANGESTRAT_EQ:=0A+=09=09=09= return=20range_overlaps_internal(typcache,=20key,=20query);=0A+=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20= %d",=20strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20= quiet=20*/=0A+=09}=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20leaf=20= consistent=20test=20with=20a=20multirange=20query.=0A+=20*=0A+=20*=20= Same=20framework=20as=20range_me_consistent_leaf_range:=20no=20false=20= negatives=0A+=20*=20allowed,=20false=20positives=20filtered=20by=20= recheck.=0A+=20*/=0A+static=20bool=0A= +range_me_consistent_leaf_multirange(TypeCacheEntry=20*typcache,=0A+=09=09= =09=09=09=09=09=09=09StrategyNumber=20strategy,=0A+=09=09=09=09=09=09=09=09= =09const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09=09const=20= MultirangeType=20*query)=0A+{=0A+=09/*=20Empty=20key=20is=20the=20= sentinel=20for=20an=20empty=20multirange=20*/=0A+=09if=20= (RangeIsEmpty(key))=0A+=09{=0A+=09=09if=20(strategy=20=3D=3D=20= RANGESTRAT_CONTAINED_BY)=0A+=09=09=09return=20true;=0A+=09=09if=20= (strategy=20=3D=3D=20RANGESTRAT_CONTAINS=20||=20strategy=20=3D=3D=20= RANGESTRAT_EQ)=0A+=09=09=09return=20MultirangeIsEmpty(query);=0A+=09=09= return=20false;=0A+=09}=0A+=0A+=09/*=20Empty=20multirange=20is=20= contained=20by=20everything,=20has=20no=20other=20relationships=20*/=0A+=09= if=20(MultirangeIsEmpty(query))=0A+=09{=0A+=09=09if=20(strategy=20=3D=3D=20= RANGESTRAT_CONTAINS)=0A+=09=09=09return=20true;=0A+=09=09return=20false;=0A= +=09}=0A+=0A+=09switch=20(strategy)=0A+=09{=0A+=09=09=09/*=20Bound=20= operators:=20same=20reasoning=20as=20the=20range=20query=20case=20*/=0A+=09= =09case=20RANGESTRAT_BEFORE:=0A+=09=09=09return=20= range_before_multirange_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09return=20= range_overleft_multirange_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_OVERRIGHT:=0A+=09=09=09return=20= range_overright_multirange_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_AFTER:=0A+=09=09=09return=20= range_after_multirange_internal(typcache,=20key,=20query);=0A+=0A+=09=09=09= /*=20Exact=20check,=20but=20another=20component=20might=20overlap=20Q=20= */=0A+=09=09case=20RANGESTRAT_ADJACENT:=0A+=09=09=09return=20= range_adjacent_multirange_internal(typcache,=20key,=20query);=0A+=0A+=09=09= =09/*=20Overlaps=20is=20recheck-free;=20the=20rest=20use=20it=20as=20= necessary=20condition=20*/=0A+=09=09case=20RANGESTRAT_OVERLAPS:=0A+=09=09= case=20RANGESTRAT_CONTAINS:=0A+=09=09case=20RANGESTRAT_CONTAINED_BY:=0A+=09= =09case=20RANGESTRAT_EQ:=0A+=09=09=09return=20= range_overlaps_multirange_internal(typcache,=20key,=20query);=0A+=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20= %d",=20strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20= quiet=20*/=0A+=09}=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20leaf=20= consistent=20test=20with=20an=20element=20query.=0A+=20*=0A+=20*=20= Recheck-free:=20if=20component=20Ri=20contains=20elem,=20so=20does=20M.=0A= +=20*/=0A+static=20bool=0A= +range_me_consistent_leaf_element(TypeCacheEntry=20*typcache,=0A+=09=09=09= =09=09=09=09=09=20StrategyNumber=20strategy,=0A+=09=09=09=09=09=09=09=09=20= const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09=20Datum=20query)=0A= +{=0A+=09switch=20(strategy)=0A+=09{=0A+=09=09case=20= RANGESTRAT_CONTAINS_ELEM:=0A+=09=09=09return=20= range_contains_elem_internal(typcache,=20key,=20query);=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20= %d",=20strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20= quiet=20*/=0A+=09}=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20internal=20= consistent=20test=20with=20a=20range=20query.=0A+=20*=0A+=20*=20Like=20= range_gist_consistent_int_range=20but=20relaxes=20CONTAINS=20and=20EQ=20= to=20use=0A+=20*=20overlaps:=20a=20matching=20multirange's=20components=20= may=20be=20spread=20across=20multiple=0A+=20*=20subtrees,=20so=20the=20= union=20key=20need=20not=20fully=20contain=20the=20query.=0A+=20*/=0A= +static=20bool=0A+range_me_consistent_int_range(TypeCacheEntry=20= *typcache,=0A+=09=09=09=09=09=09=09=20=20StrategyNumber=20strategy,=0A+=09= =09=09=09=09=09=09=20=20const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09= =20=20const=20RangeType=20*query)=0A+{=0A+=09switch=20(strategy)=0A+=09{=0A= +=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09=09if=20(RangeIsEmpty(key)=20= ||=20RangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09= return=20(!range_overright_internal(typcache,=20key,=20query));=0A+=09=09= case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= RangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09return=20= (!range_after_internal(typcache,=20key,=20query));=0A+=09=09case=20= RANGESTRAT_OVERLAPS:=0A+=09=09=09return=20= range_overlaps_internal(typcache,=20key,=20query);=0A+=09=09case=20= RANGESTRAT_OVERRIGHT:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= RangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09return=20= (!range_before_internal(typcache,=20key,=20query));=0A+=09=09case=20= RANGESTRAT_AFTER:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= RangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09return=20= (!range_overleft_internal(typcache,=20key,=20query));=0A+=09=09case=20= RANGESTRAT_ADJACENT:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= RangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09if=20= (range_adjacent_internal(typcache,=20key,=20query))=0A+=09=09=09=09= return=20true;=0A+=09=09=09return=20range_overlaps_internal(typcache,=20= key,=20query);=0A+=0A+=09=09=09/*=0A+=09=09=09=20*=20Relaxed:=20overlaps=20= instead=20of=20contains,=20because=20a=20matching=0A+=09=09=09=20*=20= multirange's=20components=20may=20be=20spread=20across=20subtrees.=0A+=09= =09=09=20*=20Empty=20query=20is=20contained=20by=20everything,=20so=20= always=20descend.=0A+=09=09=09=20*/=0A+=09=09case=20RANGESTRAT_CONTAINS:=0A= +=09=09=09if=20(RangeIsEmpty(query))=0A+=09=09=09=09return=20true;=0A+=09= =09=09return=20range_overlaps_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_CONTAINED_BY:=0A+=09=09=09if=20= (RangeIsOrContainsEmpty(key))=0A+=09=09=09=09return=20true;=0A+=09=09=09= return=20range_overlaps_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_EQ:=0A+=09=09=09if=20(RangeIsEmpty(query))=0A+=09=09=09= =09return=20RangeIsOrContainsEmpty(key);=0A+=09=09=09return=20= range_overlaps_internal(typcache,=20key,=20query);=0A+=09=09default:=0A+=09= =09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20%d",=20= strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20quiet=20= */=0A+=09}=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20internal=20consistent=20= test=20with=20a=20multirange=20query.=0A+=20*=0A+=20*=20Like=20= range_gist_consistent_int_multirange=20but=20relaxes=20CONTAINS=20and=20= EQ.=0A+=20*/=0A+static=20bool=0A= +range_me_consistent_int_multirange(TypeCacheEntry=20*typcache,=0A+=09=09= =09=09=09=09=09=09=20=20=20StrategyNumber=20strategy,=0A+=09=09=09=09=09=09= =09=09=20=20=20const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09=20=20= =20const=20MultirangeType=20*query)=0A+{=0A+=09switch=20(strategy)=0A+=09= {=0A+=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09=09if=20(RangeIsEmpty(key)=20= ||=20MultirangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09= return=20(!range_overright_multirange_internal(typcache,=20key,=20= query));=0A+=09=09case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09if=20= (RangeIsEmpty(key)=20||=20MultirangeIsEmpty(query))=0A+=09=09=09=09= return=20false;=0A+=09=09=09return=20= (!range_after_multirange_internal(typcache,=20key,=20query));=0A+=09=09= case=20RANGESTRAT_OVERLAPS:=0A+=09=09=09return=20= range_overlaps_multirange_internal(typcache,=20key,=20query);=0A+=09=09= case=20RANGESTRAT_OVERRIGHT:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= MultirangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09= return=20(!range_before_multirange_internal(typcache,=20key,=20query));=0A= +=09=09case=20RANGESTRAT_AFTER:=0A+=09=09=09if=20(RangeIsEmpty(key)=20||=20= MultirangeIsEmpty(query))=0A+=09=09=09=09return=20false;=0A+=09=09=09= return=20(!range_overleft_multirange_internal(typcache,=20key,=20= query));=0A+=09=09case=20RANGESTRAT_ADJACENT:=0A+=09=09=09if=20= (RangeIsEmpty(key)=20||=20MultirangeIsEmpty(query))=0A+=09=09=09=09= return=20false;=0A+=09=09=09if=20= (range_adjacent_multirange_internal(typcache,=20key,=20query))=0A+=09=09=09= =09return=20true;=0A+=09=09=09return=20= range_overlaps_multirange_internal(typcache,=20key,=20query);=0A+=0A+=09=09= =09/*=0A+=09=09=09=20*=20Relaxed:=20overlaps=20instead=20of=20contains,=20= because=20a=20matching=0A+=09=09=09=20*=20multirange's=20components=20= may=20be=20spread=20across=20subtrees.=0A+=09=09=09=20*=20Empty=20query=20= is=20contained=20by=20everything,=20so=20always=20descend.=0A+=09=09=09=20= */=0A+=09=09case=20RANGESTRAT_CONTAINS:=0A+=09=09=09if=20= (MultirangeIsEmpty(query))=0A+=09=09=09=09return=20true;=0A+=09=09=09= return=20range_overlaps_multirange_internal(typcache,=20key,=20query);=0A= +=09=09case=20RANGESTRAT_CONTAINED_BY:=0A+=09=09=09if=20= (RangeIsOrContainsEmpty(key))=0A+=09=09=09=09return=20true;=0A+=09=09=09= return=20range_overlaps_multirange_internal(typcache,=20key,=20query);=0A= +=09=09case=20RANGESTRAT_EQ:=0A+=09=09=09if=20(MultirangeIsEmpty(query))=0A= +=09=09=09=09return=20RangeIsOrContainsEmpty(key);=0A+=09=09=09return=20= range_overlaps_multirange_internal(typcache,=20key,=20query);=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20= %d",=20strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20= quiet=20*/=0A+=09}=0A+}=0A+=0A+/*=0A+=20*=20Multi-entry=20internal=20= consistent=20test=20with=20an=20element=20query.=0A+=20*=0A+=20*=20Same=20= as=20range_gist_consistent_int_element=20--=20only=20CONTAINS_ELEM=20is=20= used=0A+=20*=20and=20doesn't=20need=20relaxation.=0A+=20*/=0A+static=20= bool=0A+range_me_consistent_int_element(TypeCacheEntry=20*typcache,=0A+=09= =09=09=09=09=09=09=09StrategyNumber=20strategy,=0A+=09=09=09=09=09=09=09=09= const=20RangeType=20*key,=0A+=09=09=09=09=09=09=09=09Datum=20query)=0A+{=0A= +=09switch=20(strategy)=0A+=09{=0A+=09=09case=20= RANGESTRAT_CONTAINS_ELEM:=0A+=09=09=09return=20= range_contains_elem_internal(typcache,=20key,=20query);=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unrecognized=20range=20strategy:=20= %d",=20strategy);=0A+=09=09=09return=20false;=09=09/*=20keep=20compiler=20= quiet=20*/=0A+=09}=0A+}=0Adiff=20--git=20= a/src/include/catalog/pg_amop.dat=20b/src/include/catalog/pg_amop.dat=0A= index=208d5a0004a47..3cc3ba61eeb=20100644=0A---=20= a/src/include/catalog/pg_amop.dat=0A+++=20= b/src/include/catalog/pg_amop.dat=0A@@=20-1477,6=20+1477,62=20@@=0A=20=20= =20amoprighttype=20=3D>=20'anymultirange',=20amopstrategy=20=3D>=20'18',=0A= =20=20=20amopopr=20=3D>=20'=3D(anymultirange,anymultirange)',=20= amopmethod=20=3D>=20'gist'=20},=0A=20=0A+#=20GiST=20multirange_me_ops=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'1',=0A+=20=20amopopr=20=3D>=20= '<<(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'1',=0A+=20=20amopopr=20=3D>=20= '<<(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'2',=0A+=20=20amopopr=20=3D>=20= '&<(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'2',=0A+=20=20amopopr=20=3D>=20= '&<(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'3',=0A+=20=20amopopr=20=3D>=20= '&&(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'3',=0A+=20=20amopopr=20=3D>=20= '&&(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'4',=0A+=20=20amopopr=20=3D>=20= '&>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'4',=0A+=20=20amopopr=20=3D>=20= '&>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'5',=0A+=20=20amopopr=20=3D>=20= '>>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'5',=0A+=20=20amopopr=20=3D>=20= '>>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'6',=0A+=20=20amopopr=20=3D>=20= '-|-(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'6',=0A+=20=20amopopr=20=3D>=20= '-|-(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'7',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'7',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'8',=0A+=20=20amopopr=20=3D>=20= '<@(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +{=20amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'8',=0A+=20=20amopopr=20=3D>=20= '<@(anymultirange,anyrange)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyelement',=20= amopstrategy=20=3D>=20'16',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anyelement)',=20amopmethod=20=3D>=20'gist'=20},=0A+{=20= amopfamily=20=3D>=20'gist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'18',=0A+=20=20amopopr=20=3D>=20= '=3D(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'gist'=20},=0A= +=0A=20#=20btree=20multirange_ops=0A=20{=20amopfamily=20=3D>=20= 'btree/multirange_ops',=20amoplefttype=20=3D>=20'anymultirange',=0A=20=20= =20amoprighttype=20=3D>=20'anymultirange',=20amopstrategy=20=3D>=20'1',=0A= diff=20--git=20a/src/include/catalog/pg_amproc.dat=20= b/src/include/catalog/pg_amproc.dat=0Aindex=204a1efdbc899..0bf9ea1145e=20= 100644=0A---=20a/src/include/catalog/pg_amproc.dat=0A+++=20= b/src/include/catalog/pg_amproc.dat=0A@@=20-689,6=20+689,27=20@@=0A=20{=20= amprocfamily=20=3D>=20'gist/multirange_ops',=20amproclefttype=20=3D>=20= 'any',=0A=20=20=20amprocrighttype=20=3D>=20'any',=20amprocnum=20=3D>=20= '12',=0A=20=20=20amproc=20=3D>=20'gist_translate_cmptype_common'=20},=0A= +{=20amprocfamily=20=3D>=20'gist/multirange_me_ops',=20amproclefttype=20= =3D>=20'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20= 'anymultirange',=20amprocnum=20=3D>=20'1',=0A+=20=20amproc=20=3D>=20= 'multirange_gist_me_consistent'=20},=0A+{=20amprocfamily=20=3D>=20= 'gist/multirange_me_ops',=20amproclefttype=20=3D>=20'anymultirange',=0A+=20= =20amprocrighttype=20=3D>=20'anymultirange',=20amprocnum=20=3D>=20'2',=0A= +=20=20amproc=20=3D>=20'range_gist_union'=20},=0A+{=20amprocfamily=20=3D>=20= 'gist/multirange_me_ops',=20amproclefttype=20=3D>=20'anymultirange',=0A+=20= =20amprocrighttype=20=3D>=20'anymultirange',=20amprocnum=20=3D>=20'5',=0A= +=20=20amproc=20=3D>=20'range_gist_penalty'=20},=0A+{=20amprocfamily=20= =3D>=20'gist/multirange_me_ops',=20amproclefttype=20=3D>=20= 'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20'anymultirange',=20= amprocnum=20=3D>=20'6',=0A+=20=20amproc=20=3D>=20'range_gist_picksplit'=20= },=0A+{=20amprocfamily=20=3D>=20'gist/multirange_me_ops',=20= amproclefttype=20=3D>=20'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20= 'anymultirange',=20amprocnum=20=3D>=20'7',=0A+=20=20amproc=20=3D>=20= 'range_gist_same'=20},=0A+{=20amprocfamily=20=3D>=20= 'gist/multirange_me_ops',=20amproclefttype=20=3D>=20'any',=0A+=20=20= amprocrighttype=20=3D>=20'any',=20amprocnum=20=3D>=20'12',=0A+=20=20= amproc=20=3D>=20'gist_translate_cmptype_common'=20},=0A+{=20amprocfamily=20= =3D>=20'gist/multirange_me_ops',=20amproclefttype=20=3D>=20= 'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20'anymultirange',=20= amprocnum=20=3D>=20'13',=0A+=20=20amproc=20=3D>=20= 'multirange_gist_extractvalue'=20},=0A=20=0A=20#=20gin=0A=20{=20= amprocfamily=20=3D>=20'gin/array_ops',=20amproclefttype=20=3D>=20= 'anyarray',=0Adiff=20--git=20a/src/include/catalog/pg_opclass.dat=20= b/src/include/catalog/pg_opclass.dat=0Aindex=20df170b80840..07920290013=20= 100644=0A---=20a/src/include/catalog/pg_opclass.dat=0A+++=20= b/src/include/catalog/pg_opclass.dat=0A@@=20-246,6=20+246,9=20@@=0A=20{=20= opcmethod=20=3D>=20'gist',=20opcname=20=3D>=20'multirange_ops',=0A=20=20=20= opcfamily=20=3D>=20'gist/multirange_ops',=20opcintype=20=3D>=20= 'anymultirange',=0A=20=20=20opckeytype=20=3D>=20'anyrange'=20},=0A+{=20= opcmethod=20=3D>=20'gist',=20opcname=20=3D>=20'multirange_me_ops',=0A+=20= =20opcfamily=20=3D>=20'gist/multirange_me_ops',=20opcintype=20=3D>=20= 'anymultirange',=0A+=20=20opckeytype=20=3D>=20'anyrange',=20opcdefault=20= =3D>=20'f'=20},=0A=20{=20opcmethod=20=3D>=20'spgist',=20opcname=20=3D>=20= 'box_ops',=20opcfamily=20=3D>=20'spgist/box_ops',=0A=20=20=20opcintype=20= =3D>=20'box'=20},=0A=20{=20opcmethod=20=3D>=20'spgist',=20opcname=20=3D>=20= 'quad_point_ops',=0Adiff=20--git=20a/src/include/catalog/pg_opfamily.dat=20= b/src/include/catalog/pg_opfamily.dat=0Aindex=207a027c4810e..93a80175352=20= 100644=0A---=20a/src/include/catalog/pg_opfamily.dat=0A+++=20= b/src/include/catalog/pg_opfamily.dat=0A@@=20-308,5=20+308,7=20@@=0A=20=20= =20opfmethod=20=3D>=20'hash',=20opfname=20=3D>=20'multirange_ops'=20},=0A= =20{=20oid=20=3D>=20'6158',=0A=20=20=20opfmethod=20=3D>=20'gist',=20= opfname=20=3D>=20'multirange_ops'=20},=0A+{=20oid=20=3D>=20'9319',=0A+=20= =20opfmethod=20=3D>=20'gist',=20opfname=20=3D>=20'multirange_me_ops'=20= },=0A=20=0A=20]=0Adiff=20--git=20a/src/include/catalog/pg_proc.dat=20= b/src/include/catalog/pg_proc.dat=0Aindex=2099fa9a6ede2..699d8416d47=20= 100644=0A---=20a/src/include/catalog/pg_proc.dat=0A+++=20= b/src/include/catalog/pg_proc.dat=0A@@=20-11164,6=20+11164,14=20@@=0A=20= {=20oid=20=3D>=20'6156',=20descr=20=3D>=20'GiST=20support',=0A=20=20=20= proname=20=3D>=20'multirange_gist_compress',=20prorettype=20=3D>=20= 'internal',=0A=20=20=20proargtypes=20=3D>=20'internal',=20prosrc=20=3D>=20= 'multirange_gist_compress'=20},=0A+{=20oid=20=3D>=20'9317',=20descr=20=3D>= =20'GiST=20support',=0A+=20=20proname=20=3D>=20= 'multirange_gist_me_consistent',=20prorettype=20=3D>=20'bool',=0A+=20=20= proargtypes=20=3D>=20'internal=20anymultirange=20int2=20oid=20internal',=0A= +=20=20prosrc=20=3D>=20'multirange_gist_me_consistent'=20},=0A+{=20oid=20= =3D>=20'9318',=20descr=20=3D>=20'GiST=20support',=0A+=20=20proname=20=3D>=20= 'multirange_gist_extractvalue',=20prorettype=20=3D>=20'internal',=0A+=20=20= proargtypes=20=3D>=20'internal=20internal=20internal',=0A+=20=20prosrc=20= =3D>=20'multirange_gist_extractvalue'=20},=0A=20{=20oid=20=3D>=20'3902',=20= descr=20=3D>=20'hash=20a=20range',=0A=20=20=20proname=20=3D>=20= 'hash_range',=20prorettype=20=3D>=20'int4',=20proargtypes=20=3D>=20= 'anyrange',=0A=20=20=20prosrc=20=3D>=20'hash_range'=20},=0Adiff=20--git=20= a/src/test/regress/expected/multirangetypes.out=20= b/src/test/regress/expected/multirangetypes.out=0Aindex=20= f5e7df8df43..4134f1358ed=20100644=0A---=20= a/src/test/regress/expected/multirangetypes.out=0A+++=20= b/src/test/regress/expected/multirangetypes.out=0A@@=20-2874,6=20= +2874,678=20@@=20select=20count(*)=20from=20test_multirange_gist=20where=20= mr=20-|-=20int4multirange(int4range(=0A=20=0A=20drop=20table=20= test_multirange_gist;=0A=20--=0A+--=20Multi-entry=20GiST=20index=20= (multirange_me_ops)=0A+--=20Decomposes=20multiranges=20into=20component=20= ranges=20for=20indexing.=0A+--=0A+create=20table=20= test_multirange_me_gist(mr=20int4multirange);=0A+insert=20into=20= test_multirange_me_gist=20select=20int4multirange(int4range(g,=20= g+10),int4range(g+20,=20g+30),int4range(g+40,=20g+50))=20from=20= generate_series(1,2000)=20g;=0A+insert=20into=20test_multirange_me_gist=20= select=20'{}'::int4multirange=20from=20generate_series(1,500)=20g;=0A= +insert=20into=20test_multirange_me_gist=20select=20= int4multirange(int4range(g,=20g+10000))=20from=20generate_series(1,1000)=20= g;=0A+insert=20into=20test_multirange_me_gist=20select=20= int4multirange(int4range(NULL,=20g*10,=20'(]'),=20int4range(g*10,=20= g*20,=20'(]'))=20from=20generate_series(1,100)=20g;=0A+insert=20into=20= test_multirange_me_gist=20select=20int4multirange(int4range(g*10,=20= g*20,=20'(]'),=20int4range(g*20,=20NULL,=20'(]'))=20from=20= generate_series(1,100)=20g;=0A+create=20index=20= test_multirange_me_gist_idx=20on=20test_multirange_me_gist=20using=20= gist=20(mr=20multirange_me_ops);=0A+--=20first,=20verify=20non-indexed=20= results=0A+SET=20enable_seqscan=20=20=20=20=3D=20t;=0A+SET=20= enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20f;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20=3D=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&&=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20>>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&<=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&&=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20>>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20-|-=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20= =20=20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20now=20check=20same=20= queries=20using=20index=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A= +SET=20enable_indexscan=20=20=3D=20t;=0A+SET=20enable_bitmapscan=20=3D=20= f;=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= =3D=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= 3700=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&&=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<@=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20<<=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20>>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20-|-=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= 3700=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&&=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<@=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20<<=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20= =200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20also=20check=20= bitmap=20scan=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20= enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20t;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20=3D=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&&=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20>>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&<=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20&&=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20>>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20-|-=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20= =20=20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20test=20that=20= multi-column=20indexes=20with=20extractValue=20are=20disallowed=0A= +create=20table=20test_me_multicol(mr=20int4multirange,=20r=20= int4range);=0A+create=20index=20on=20test_me_multicol=20using=20gist=20= (mr=20multirange_me_ops,=20r);=0A+ERROR:=20=20multi-entry=20GiST=20= indexes=20do=20not=20support=20multiple=20key=20columns=0A+--=20test=20= NULL=20handling=0A+create=20table=20test_me_nulls(mr=20int4multirange);=0A= +insert=20into=20test_me_nulls=20values=20(NULL),=20= ('{}'::int4multirange),=20('{[1,3]}');=0A+create=20index=20on=20= test_me_nulls=20using=20gist=20(mr=20multirange_me_ops);=0A+SET=20= enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20enable_indexscan=20=20=3D=20= t;=0A+select=20*=20from=20test_me_nulls=20where=20mr=20@>=201;=0A+=20=20=20= mr=20=20=20=20=0A+---------=0A+=20{[1,4)}=0A+(1=20row)=0A+=0A+drop=20= table=20test_me_nulls;=0A+drop=20table=20test_me_multicol;=0A+drop=20= table=20test_multirange_me_gist;=0A+--=0A=20--=20range_agg=20function=0A=20= --=0A=20create=20table=20reservations=20(=20room_id=20integer=20not=20= null,=20booked_during=20daterange=20);=0Adiff=20--git=20= a/src/test/regress/sql/multirangetypes.sql=20= b/src/test/regress/sql/multirangetypes.sql=0Aindex=20= 112334b03eb..902d719d75c=20100644=0A---=20= a/src/test/regress/sql/multirangetypes.sql=0A+++=20= b/src/test/regress/sql/multirangetypes.sql=0A@@=20-558,6=20+558,160=20@@=20= select=20count(*)=20from=20test_multirange_gist=20where=20mr=20-|-=20= int4multirange(int4range(=0A=20=0A=20drop=20table=20= test_multirange_gist;=0A=20=0A+--=0A+--=20Multi-entry=20GiST=20index=20= (multirange_me_ops)=0A+--=20Decomposes=20multiranges=20into=20component=20= ranges=20for=20indexing.=0A+--=0A+create=20table=20= test_multirange_me_gist(mr=20int4multirange);=0A+insert=20into=20= test_multirange_me_gist=20select=20int4multirange(int4range(g,=20= g+10),int4range(g+20,=20g+30),int4range(g+40,=20g+50))=20from=20= generate_series(1,2000)=20g;=0A+insert=20into=20test_multirange_me_gist=20= select=20'{}'::int4multirange=20from=20generate_series(1,500)=20g;=0A= +insert=20into=20test_multirange_me_gist=20select=20= int4multirange(int4range(g,=20g+10000))=20from=20generate_series(1,1000)=20= g;=0A+insert=20into=20test_multirange_me_gist=20select=20= int4multirange(int4range(NULL,=20g*10,=20'(]'),=20int4range(g*10,=20= g*20,=20'(]'))=20from=20generate_series(1,100)=20g;=0A+insert=20into=20= test_multirange_me_gist=20select=20int4multirange(int4range(g*10,=20= g*20,=20'(]'),=20int4range(g*20,=20NULL,=20'(]'))=20from=20= generate_series(1,100)=20g;=0A+create=20index=20= test_multirange_me_gist_idx=20on=20test_multirange_me_gist=20using=20= gist=20(mr=20multirange_me_ops);=0A+=0A+--=20first,=20verify=20= non-indexed=20results=0A+SET=20enable_seqscan=20=20=20=20=3D=20t;=0A+SET=20= enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20f;=0A+=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20=3D=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= '{}'::int4multirange;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=2010;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20int4range(10,20);=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<@=20int4range(10,50);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= now=20check=20same=20queries=20using=20index=0A+SET=20enable_seqscan=20=20= =20=20=3D=20f;=0A+SET=20enable_indexscan=20=20=3D=20t;=0A+SET=20= enable_bitmapscan=20=3D=20f;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20=3D=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&&=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<@=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&&=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<@=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20'{}'::int4multirange;=0A+=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=2010;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20int4range(10,20);=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<@=20int4range(10,50);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= also=20check=20bitmap=20scan=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A= +SET=20enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20= t;=0A+=0A+select=20count(*)=20from=20test_multirange_me_gist=20where=20= mr=20=3D=20'{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20>>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= '{}'::int4multirange;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20@>=2010;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20@>=20int4range(10,20);=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20test_multirange_me_gist=20= where=20mr=20<@=20int4range(10,50);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20&<=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20-|-=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_gist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_gist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_gist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= test=20that=20multi-column=20indexes=20with=20extractValue=20are=20= disallowed=0A+create=20table=20test_me_multicol(mr=20int4multirange,=20r=20= int4range);=0A+create=20index=20on=20test_me_multicol=20using=20gist=20= (mr=20multirange_me_ops,=20r);=0A+=0A+--=20test=20NULL=20handling=0A= +create=20table=20test_me_nulls(mr=20int4multirange);=0A+insert=20into=20= test_me_nulls=20values=20(NULL),=20('{}'::int4multirange),=20= ('{[1,3]}');=0A+create=20index=20on=20test_me_nulls=20using=20gist=20(mr=20= multirange_me_ops);=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20= enable_indexscan=20=20=3D=20t;=0A+select=20*=20from=20test_me_nulls=20= where=20mr=20@>=201;=0A+=0A+drop=20table=20test_me_nulls;=0A+drop=20= table=20test_me_multicol;=0A+drop=20table=20test_multirange_me_gist;=0A+=0A= =20--=0A=20--=20range_agg=20function=0A=20--=0A--=20=0A2.50.1=20(Apple=20= Git-155)=0A=0A= --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841 Content-Disposition: attachment; filename=v1-0003-Add-multi-entry-support-to-SP-GiST.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0003-Add-multi-entry-support-to-SP-GiST.patch" Content-Transfer-Encoding: quoted-printable =46rom=20f1377d894d5cf9c1feb56ad2e375fb041f6e2e0f=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Maxime=20Schoemans=20= =0ADate:=20Fri,=203=20Apr=202026=20= 18:43:29=20+0200=0ASubject:=20[PATCH=20v1=203/4]=20Add=20multi-entry=20= support=20to=20SP-GiST=0A=0AExtend=20SP-GiST=20to=20support=20an=20= optional=20extractValue=20support=20function=0A= (SPGIST_EXTRACTVALUE_PROC,=20number=208)=20that=20decomposes=20a=20= single=20indexed=0Avalue=20into=20multiple=20sub-entries,=20each=20= stored=20as=20a=20separate=20index=20entry.=0AThis=20mirrors=20the=20= multi-entry=20support=20previously=20added=20to=20GiST.=0A=0A= Infrastructure=20changes:=0A=0A=20=20spgist.h:=20Define=20= SPGIST_EXTRACTVALUE_PROC=20(8),=20bump=20SPGISTNProc=20to=208.=0A=0A=20=20= spgist_private.h:=20Add=20tidHash=20field=20to=20SpGistScanOpaqueData=20= for=20TID=0A=20=20deduplication=20during=20multi-entry=20scans.=0A=0A=20=20= spginsert.c:=20Add=20spgExtractEntries()=20helper.=20Modify=20= spgistBuildCallback=0A=20=20and=20spginsert=20to=20call=20extractValue=20= and=20loop=20over=20the=20returned=20entries.=0A=0A=20=20spgscan.c:=20= Implement=20TID=20deduplication=20via=20simplehash=20to=20ensure=20each=0A= =20=20heap=20TID=20is=20returned=20only=20once=20when=20multiple=20index=20= entries=20match.=0A=20=20Handles=20both=20ordered=20and=20non-ordered=20= scans.=20Bitmap=20scans=20rely=20on=20the=0A=20=20bitmap's=20inherent=20= deduplication.=20Disable=20index-only=20scans=20for=20the=20key=0A=20=20= column=20of=20multi-entry=20indexes=20since=20the=20stored=20entries=20= don't=20represent=0A=20=20the=20original=20datum.=0A=0A=20=20= spgvalidate.c:=20Register=20extractValue=20as=20an=20optional=20support=20= function.=0A=20=20Allow=20compress=20to=20be=20absent=20when=20= extractValue=20is=20present=20(extractValue=0A=20=20handles=20the=20type=20= conversion).=0A=0A=20=20spgutils.c:=20Accept=20extractValue=20as=20an=20= alternative=20to=20compress=20when=0A=20=20the=20leaf=20type=20differs=20= from=20the=20input=20type.=0A---=0A=20= src/backend/access/spgist/spginsert.c=20=20=20|=20=2097=20= +++++++++++++---=0A=20src/backend/access/spgist/spgscan.c=20=20=20=20=20= |=20146=20+++++++++++++++++++++---=0A=20= src/backend/access/spgist/spgutils.c=20=20=20=20|=20=2061=20+++++++++-=0A= =20src/backend/access/spgist/spgvalidate.c=20|=20=2012=20+-=0A=20= src/include/access/spgist.h=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20= =203=20+-=0A=20src/include/access/spgist_private.h=20=20=20=20=20|=20=20=20= 9=20++=0A=206=20files=20changed,=20295=20insertions(+),=2033=20= deletions(-)=0A=0Adiff=20--git=20a/src/backend/access/spgist/spginsert.c=20= b/src/backend/access/spgist/spginsert.c=0Aindex=20= 780ef646a54..0e9e4e845c8=20100644=0A---=20= a/src/backend/access/spgist/spginsert.c=0A+++=20= b/src/backend/access/spgist/spginsert.c=0A@@=20-44,23=20+44,60=20@@=20= spgistBuildCallback(Relation=20index,=20ItemPointer=20tid,=20Datum=20= *values,=0A=20=09SpGistBuildState=20*buildstate=20=3D=20= (SpGistBuildState=20*)=20state;=0A=20=09MemoryContext=20oldCtx;=0A=20=0A= -=09/*=20Work=20in=20temp=20context,=20and=20reset=20it=20after=20each=20= tuple=20*/=0A-=09oldCtx=20=3D=20= MemoryContextSwitchTo(buildstate->tmpCtx);=0A-=0A=20=09/*=0A=20=09=20*=20= Even=20though=20no=20concurrent=20insertions=20can=20be=20happening,=20= we=20still=20might=0A=20=09=20*=20get=20a=20buffer-locking=20failure=20= due=20to=20bgwriter=20or=20checkpointer=20taking=20a=0A=20=09=20*=20lock=20= on=20some=20buffer.=20=20So=20we=20need=20to=20be=20willing=20to=20= retry.=20=20We=20can=20flush=0A=20=09=20*=20any=20temp=20data=20when=20= retrying.=0A+=09=20*=0A+=09=20*=20If=20the=20opclass=20provides=20an=20= extractValue=20function,=20extract=20multiple=0A+=09=20*=20entries=20and=20= insert=20each=20one.=20=20Otherwise,=20insert=20a=20single=20entry.=0A+=09= =20*=0A+=09=20*=20We=20extract=20entries=20in=20the=20caller's=20memory=20= context=20so=20that=20the=20entries=0A+=09=20*=20array=20survives=20= MemoryContextReset(tmpCtx)=20in=20the=20retry=20loop.=0A=20=09=20*/=0A-=09= while=20(!spgdoinsert(index,=20&buildstate->spgstate,=20tid,=0A-=09=09=09= =09=09=09values,=20isnull))=0A+=09if=20= (OidIsValid(index_getprocid(index,=201,=20SPGIST_EXTRACTVALUE_PROC)))=0A=20= =09{=0A-=09=09MemoryContextReset(buildstate->tmpCtx);=0A+=09=09Datum=09=20= =20=20*entries;=0A+=09=09bool=09=20=20=20*nullFlags;=0A+=09=09int32=09=09= nentries;=0A+=09=09int=09=09=09i;=0A+=0A+=09=09entries=20=3D=20= spgExtractEntries(index,=20values[spgKeyColumn],=0A+=09=09=09=09=09=09=09= =09=20=20=20isnull[spgKeyColumn],=0A+=09=09=09=09=09=09=09=09=20=20=20= &nentries,=20&nullFlags);=0A+=0A+=09=09oldCtx=20=3D=20= MemoryContextSwitchTo(buildstate->tmpCtx);=0A+=0A+=09=09for=20(i=20=3D=20= 0;=20i=20<=20nentries;=20i++)=0A+=09=09{=0A+=09=09=09= values[spgKeyColumn]=20=3D=20entries[i];=0A+=09=09=09= isnull[spgKeyColumn]=20=3D=20nullFlags[i];=0A+=0A+=09=09=09while=20= (!spgdoinsert(index,=20&buildstate->spgstate,=20tid,=0A+=09=09=09=09=09=09= =09=09values,=20isnull))=0A+=09=09=09{=0A+=09=09=09=09= MemoryContextReset(buildstate->tmpCtx);=0A+=09=09=09}=0A+=09=09}=0A+=0A+=09= =09/*=20Update=20total=20tuple=20count=20*/=0A+=09=09= buildstate->indtuples=20+=3D=20nentries;=0A=20=09}=0A+=09else=0A+=09{=0A= +=09=09/*=20Work=20in=20temp=20context,=20and=20reset=20it=20after=20= each=20tuple=20*/=0A+=09=09oldCtx=20=3D=20= MemoryContextSwitchTo(buildstate->tmpCtx);=0A+=0A+=09=09while=20= (!spgdoinsert(index,=20&buildstate->spgstate,=20tid,=0A+=09=09=09=09=09=09= =09values,=20isnull))=0A+=09=09{=0A+=09=09=09= MemoryContextReset(buildstate->tmpCtx);=0A+=09=09}=0A=20=0A-=09/*=20= Update=20total=20tuple=20count=20*/=0A-=09buildstate->indtuples=20+=3D=20= 1;=0A+=09=09/*=20Update=20total=20tuple=20count=20*/=0A+=09=09= buildstate->indtuples=20+=3D=201;=0A+=09}=0A=20=0A=20=09= MemoryContextSwitchTo(oldCtx);=0A=20=09= MemoryContextReset(buildstate->tmpCtx);=0A@@=20-193,20=20+230,54=20@@=20= spginsert(Relation=20index,=20Datum=20*values,=20bool=20*isnull,=0A=20=09= insertCtx=20=3D=20AllocSetContextCreate(CurrentMemoryContext,=0A=20=09=09= =09=09=09=09=09=09=09=20=20"SP-GiST=20insert=20temporary=20context",=0A=20= =09=09=09=09=09=09=09=09=09=20=20ALLOCSET_DEFAULT_SIZES);=0A-=09oldCtx=20= =3D=20MemoryContextSwitchTo(insertCtx);=0A-=0A-=09= initSpGistState(&spgstate,=20index);=0A=20=0A=20=09/*=0A=20=09=20*=20We=20= might=20have=20to=20repeat=20spgdoinsert()=20multiple=20times,=20if=20= conflicts=0A=20=09=20*=20occur=20with=20concurrent=20insertions.=20=20If=20= so,=20reset=20the=20insertCtx=20each=20time=0A=20=09=20*=20to=20avoid=20= cumulative=20memory=20consumption.=20=20That=20means=20we=20also=20have=20= to=0A=20=09=20*=20redo=20initSpGistState(),=20but=20it's=20cheap=20= enough=20not=20to=20matter.=0A+=09=20*=0A+=09=20*=20If=20the=20opclass=20= provides=20an=20extractValue=20function,=20extract=20multiple=0A+=09=20*=20= entries=20and=20insert=20each=20one=20separately.=20=20We=20extract=20= entries=20in=20the=0A+=09=20*=20caller's=20memory=20context=20so=20that=20= the=20entries=20array=20survives=0A+=09=20*=20= MemoryContextReset(insertCtx)=20in=20the=20retry=20loop.=0A=20=09=20*/=0A= -=09while=20(!spgdoinsert(index,=20&spgstate,=20ht_ctid,=20values,=20= isnull))=0A+=09if=20(OidIsValid(index_getprocid(index,=201,=20= SPGIST_EXTRACTVALUE_PROC)))=0A+=09{=0A+=09=09Datum=09=20=20=20*entries;=0A= +=09=09bool=09=20=20=20*nullFlags;=0A+=09=09int32=09=09nentries;=0A+=09=09= int=09=09=09i;=0A+=0A+=09=09entries=20=3D=20spgExtractEntries(index,=20= values[spgKeyColumn],=0A+=09=09=09=09=09=09=09=09=20=20=20= isnull[spgKeyColumn],=0A+=09=09=09=09=09=09=09=09=20=20=20&nentries,=20= &nullFlags);=0A+=0A+=09=09oldCtx=20=3D=20= MemoryContextSwitchTo(insertCtx);=0A+=09=09initSpGistState(&spgstate,=20= index);=0A+=0A+=09=09for=20(i=20=3D=200;=20i=20<=20nentries;=20i++)=0A+=09= =09{=0A+=09=09=09values[spgKeyColumn]=20=3D=20entries[i];=0A+=09=09=09= isnull[spgKeyColumn]=20=3D=20nullFlags[i];=0A+=0A+=09=09=09while=20= (!spgdoinsert(index,=20&spgstate,=20ht_ctid,=20values,=20isnull))=0A+=09=09= =09{=0A+=09=09=09=09MemoryContextReset(insertCtx);=0A+=09=09=09=09= initSpGistState(&spgstate,=20index);=0A+=09=09=09}=0A+=09=09}=0A+=09}=0A= +=09else=0A=20=09{=0A-=09=09MemoryContextReset(insertCtx);=0A+=09=09= oldCtx=20=3D=20MemoryContextSwitchTo(insertCtx);=0A=20=09=09= initSpGistState(&spgstate,=20index);=0A+=0A+=09=09while=20= (!spgdoinsert(index,=20&spgstate,=20ht_ctid,=20values,=20isnull))=0A+=09=09= {=0A+=09=09=09MemoryContextReset(insertCtx);=0A+=09=09=09= initSpGistState(&spgstate,=20index);=0A+=09=09}=0A=20=09}=0A=20=0A=20=09= SpGistUpdateMetaPage(index);=0Adiff=20--git=20= a/src/backend/access/spgist/spgscan.c=20= b/src/backend/access/spgist/spgscan.c=0Aindex=202cc5f06f5d7..398a93a7dd9=20= 100644=0A---=20a/src/backend/access/spgist/spgscan.c=0A+++=20= b/src/backend/access/spgist/spgscan.c=0A@@=20-18,6=20+18,7=20@@=0A=20= #include=20"access/genam.h"=0A=20#include=20"access/relscan.h"=0A=20= #include=20"access/spgist_private.h"=0A+#include=20"common/hashfn.h"=0A=20= #include=20"executor/instrument_node.h"=0A=20#include=20"miscadmin.h"=0A=20= #include=20"pgstat.h"=0A@@=20-28,6=20+29,49=20@@=0A=20#include=20= "utils/memutils.h"=0A=20#include=20"utils/rel.h"=0A=20=0A+/*=0A+=20*=20= Simplehash=20implementation=20for=20TID=20deduplication=20in=20= multi-entry=20scans.=0A+=20*=0A+=20*=20When=20an=20opclass=20provides=20= an=20extractValue=20function,=20each=20heap=20tuple=20produces=0A+=20*=20= multiple=20index=20entries.=20=20During=20scans,=20we=20must=20= deduplicate=20results=20so=20that=0A+=20*=20each=20heap=20TID=20is=20= returned=20only=20once.=0A+=20*/=0A+=0A+/*=20Hash=20table=20entry=20for=20= basic=20TID=20dedup=20*/=0A+typedef=20struct=20SPGTIDHashEntry=0A+{=0A+=09= ItemPointerData=20tid;=09=09/*=20TID=20(hashtable=20key)=20*/=0A+=09= uint32=09=09hash;=09=09=09/*=20hash=20value=20(cached)=20*/=0A+=09char=09= =09status;=09=09=09/*=20hash=20status=20*/=0A+}=20SPGTIDHashEntry;=0A+=0A= +static=20inline=20uint32=0A+spg_tid_hash_fn(ItemPointerData=20tid)=0A+{=0A= +=09uint32=09=09h=20=3D=20murmurhash32(ItemPointerGetBlockNumber(&tid));=0A= +=0A+=09return=20murmurhash32(h=20+=20ItemPointerGetOffsetNumber(&tid));=0A= +}=0A+=0A+static=20inline=20bool=0A+spg_tid_match_fn(ItemPointerData=20= a,=20ItemPointerData=20b)=0A+{=0A+=09return=20ItemPointerEquals(&a,=20= &b);=0A+}=0A+=0A+/*=20---=20spgtid=20hash=20table=20(declare=20+=20= define)=20---=20*/=0A+#define=20SH_PREFIX=20spgtid=0A+#define=20= SH_ELEMENT_TYPE=20SPGTIDHashEntry=0A+#define=20SH_KEY_TYPE=20= ItemPointerData=0A+#define=20SH_KEY=20tid=0A+#define=20SH_HASH_KEY(tb,=20= key)=20spg_tid_hash_fn(key)=0A+#define=20SH_EQUAL(tb,=20a,=20b)=20= spg_tid_match_fn(a,=20b)=0A+#define=20SH_SCOPE=20static=20inline=0A= +#define=20SH_DECLARE=0A+#define=20SH_DEFINE=0A+#include=20= "lib/simplehash.h"=0A+=0A+=0A=20typedef=20void=20(*storeRes_func)=20= (SpGistScanOpaque=20so,=20ItemPointer=20heapPtr,=0A=20=09=09=09=09=09=09=09= =20=20=20Datum=20leafValue,=20bool=20isNull,=0A=20=09=09=09=09=09=09=09=20= =20=20SpGistLeafTuple=20leafTuple,=20bool=20recheck,=0A@@=20-158,6=20= +202,14=20@@=20resetSpGistScanOpaque(SpGistScanOpaque=20so)=0A=20=0A=20=09= MemoryContextReset(so->traversalCxt);=0A=20=0A+=09/*=0A+=09=20*=20For=20= multi-entry=20indexes,=20set=20up=20TID=20deduplication=20hash=20table.=20= =20The=20hash=0A+=09=20*=20table=20lives=20in=20traversalCxt=20and=20is=20= destroyed/recreated=20on=20each=20rescan.=0A+=09=20*/=0A+=09if=20= (OidIsValid(index_getprocid(so->state.index,=201,=0A+=09=09=09=09=09=09=09= =09=20=20=20SPGIST_EXTRACTVALUE_PROC)))=0A+=09=09so->tidHash=20=3D=20= spgtid_create(so->traversalCxt,=20256,=20NULL);=0A+=0A=20=09oldCtx=20=3D=20= MemoryContextSwitchTo(so->traversalCxt);=0A=20=0A=20=09/*=20initialize=20= queue=20only=20for=20distance-ordered=20scans=20*/=0A@@=20-364,6=20= +416,9=20@@=20spgbeginscan(Relation=20rel,=20int=20keysz,=20int=20= orderbysz)=0A=20=09=09=09=09=20=20=20index_getprocinfo(rel,=201,=20= SPGIST_LEAF_CONSISTENT_PROC),=0A=20=09=09=09=09=20=20=20= CurrentMemoryContext);=0A=20=0A+=09/*=20tidHash=20will=20be=20set=20up=20= by=20resetSpGistScanOpaque=20if=20needed=20*/=0A+=09so->tidHash=20=3D=20= NULL;=0A+=0A=20=09so->indexCollation=20=3D=20rel->rd_indcollation[0];=0A=20= =0A=20=09scan->opaque=20=3D=20so;=0A@@=20-571,25=20+626,53=20@@=20= spgLeafTest(SpGistScanOpaque=20so,=20SpGistSearchItem=20*item,=0A=20=09=09= {=0A=20=09=09=09/*=20the=20scan=20is=20ordered=20->=20add=20the=20item=20= to=20the=20queue=20*/=0A=20=09=09=09MemoryContext=20oldCxt=20=3D=20= MemoryContextSwitchTo(so->traversalCxt);=0A-=09=09=09SpGistSearchItem=20= *heapItem=20=3D=20spgNewHeapItem(so,=20item->level,=0A-=09=09=09=09=09=09= =09=09=09=09=09=09=09=09leafTuple,=0A-=09=09=09=09=09=09=09=09=09=09=09=09= =09=09leafValue,=0A-=09=09=09=09=09=09=09=09=09=09=09=09=09=09recheck,=0A= -=09=09=09=09=09=09=09=09=09=09=09=09=09=09recheckDistances,=0A-=09=09=09= =09=09=09=09=09=09=09=09=09=09=09isnull,=0A-=09=09=09=09=09=09=09=09=09=09= =09=09=09=09distances);=0A-=0A-=09=09=09spgAddSearchItemToQueue(so,=20= heapItem);=0A=20=0A-=09=09=09MemoryContextSwitchTo(oldCxt);=0A+=09=09=09= /*=0A+=09=09=09=20*=20For=20multi-entry=20ordered=20scans,=20skip=20leaf=20= entries=20whose=20TIDs=0A+=09=09=09=20*=20have=20already=20been=20= returned=20by=20the=20ordered=20dequeue=20path.=20=20We=0A+=09=09=09=20*=20= use=20lookup=20(not=20insert)=20here:=20a=20TID=20must=20remain=20= enqueueable=0A+=09=09=09=20*=20until=20it=20is=20actually=20dequeued,=20= so=20that=20the=20pairing=20heap=20can=0A+=09=09=09=20*=20pick=20the=20= copy=20with=20the=20smallest=20distance.=0A+=09=09=09=20*/=0A+=09=09=09= if=20(so->tidHash=20&&=0A+=09=09=09=09spgtid_lookup(so->tidHash,=20= leafTuple->heapPtr))=0A+=09=09=09{=0A+=09=09=09=09= MemoryContextSwitchTo(oldCxt);=0A+=09=09=09}=0A+=09=09=09else=0A+=09=09=09= {=0A+=09=09=09=09SpGistSearchItem=20*heapItem=20=3D=20spgNewHeapItem(so,=20= item->level,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09leafTuple,=0A= +=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09leafValue,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09recheck,=0A+=09=09=09=09=09=09=09=09=09=09=09= =09=09=09=09recheckDistances,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09= =09isnull,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09distances);=0A= +=0A+=09=09=09=09spgAddSearchItemToQueue(so,=20heapItem);=0A+=09=09=09=09= MemoryContextSwitchTo(oldCxt);=0A+=09=09=09}=0A=20=09=09}=0A=20=09=09= else=0A=20=09=09{=0A-=09=09=09/*=20non-ordered=20scan,=20so=20report=20= the=20item=20right=20away=20*/=0A-=09=09=09Assert(!recheckDistances);=0A= -=09=09=09storeRes(so,=20&leafTuple->heapPtr,=20leafValue,=20isnull,=0A-=09= =09=09=09=09=20leafTuple,=20recheck,=20false,=20NULL);=0A-=09=09=09= *reportedSome=20=3D=20true;=0A+=09=09=09/*=0A+=09=09=09=20*=20= Non-ordered=20scan,=20so=20report=20the=20item=20right=20away.=0A+=09=09=09= =20*=0A+=09=09=09=20*=20For=20multi-entry=20indexes,=20check=20the=20TID=20= hash=20table=20to=20avoid=0A+=09=09=09=20*=20returning=20duplicate=20= heap=20TIDs.=0A+=09=09=09=20*/=0A+=09=09=09bool=09=09found=20=3D=20= false;=0A+=0A+=09=09=09if=20(so->tidHash)=0A+=09=09=09=09= spgtid_insert(so->tidHash,=20leafTuple->heapPtr,=20&found);=0A+=0A+=09=09= =09if=20(!found)=0A+=09=09=09{=0A+=09=09=09=09Assert(!recheckDistances);=0A= +=09=09=09=09storeRes(so,=20&leafTuple->heapPtr,=20leafValue,=20isnull,=0A= +=09=09=09=09=09=09=20leafTuple,=20recheck,=20false,=20NULL);=0A+=09=09=09= =09*reportedSome=20=3D=20true;=0A+=09=09=09}=0A=20=09=09}=0A=20=09}=0A=20= =0A@@=20-830,6=20+913,25=20@@=20redirect:=0A=20=09=09{=0A=20=09=09=09/*=20= We=20store=20heap=20items=20in=20the=20queue=20only=20in=20case=20of=20= ordered=20search=20*/=0A=20=09=09=09Assert(so->numberOfNonNullOrderBys=20= >=200);=0A+=0A+=09=09=09/*=0A+=09=09=09=20*=20For=20multi-entry=20= ordered=20scans,=20deduplicate=20using=20tidHash.=0A+=09=09=09=20*=20The=20= pairing=20heap=20ensures=20we=20see=20the=20smallest=20distance=20first;=0A= +=09=09=09=20*=20tidHash=20skips=20subsequent=20duplicates=20for=20the=20= same=20TID.=0A+=09=09=09=20*/=0A+=09=09=09if=20(so->tidHash)=0A+=09=09=09= {=0A+=09=09=09=09bool=09=09found;=0A+=0A+=09=09=09=09= spgtid_insert(so->tidHash,=20item->heapPtr,=20&found);=0A+=09=09=09=09if=20= (found)=0A+=09=09=09=09{=0A+=09=09=09=09=09spgFreeSearchItem(so,=20= item);=0A+=09=09=09=09=09MemoryContextReset(so->tempCxt);=0A+=09=09=09=09= =09continue;=09/*=20already=20returned=20this=20TID=20*/=0A+=09=09=09=09= }=0A+=09=09=09}=0A+=0A=20=09=09=09storeRes(so,=20&item->heapPtr,=20= item->value,=20item->isNull,=0A=20=09=09=09=09=09=20item->leafTuple,=20= item->recheck,=0A=20=09=09=09=09=09=20item->recheckDistances,=20= item->distances);=0A@@=20-921,7=20+1023,11=20@@=20redirect:=0A=20}=0A=20=0A= =20=0A-/*=20storeRes=20subroutine=20for=20getbitmap=20case=20*/=0A+/*=0A= +=20*=20storeRes=20subroutine=20for=20getbitmap=20case.=0A+=20*=20The=20= bitmap=20itself=20handles=20deduplication,=20so=20no=20extra=20work=20= needed=20for=0A+=20*=20multi-entry.=0A+=20*/=0A=20static=20void=0A=20= storeBitmap(SpGistScanOpaque=20so,=20ItemPointer=20heapPtr,=0A=20=09=09=09= Datum=20leafValue,=20bool=20isnull,=0A@@=20-1083,6=20+1189,14=20@@=20= spgcanreturn(Relation=20index,=20int=20attno)=0A=20=09if=20(attno=20>=20= 1)=0A=20=09=09return=20true;=0A=20=0A+=09/*=0A+=09=20*=20Multi-entry=20= indexes=20store=20decomposed=20sub-entries=20in=20the=20key=20column,=0A= +=09=20*=20not=20the=20original=20datum,=20so=20the=20key=20column=20= cannot=20be=20returned=20in=20an=0A+=09=20*=20index-only=20scan.=0A+=09=20= */=0A+=09if=20(OidIsValid(index_getprocid(index,=201,=20= SPGIST_EXTRACTVALUE_PROC)))=0A+=09=09return=20false;=0A+=0A=20=09/*=20We=20= can=20do=20it=20if=20the=20opclass=20config=20function=20says=20so=20*/=0A= =20=09cache=20=3D=20spgGetCache(index);=0A=20=0Adiff=20--git=20= a/src/backend/access/spgist/spgutils.c=20= b/src/backend/access/spgist/spgutils.c=0Aindex=20= f2ee333f60d..ce30d76e8f5=20100644=0A---=20= a/src/backend/access/spgist/spgutils.c=0A+++=20= b/src/backend/access/spgist/spgutils.c=0A@@=20-246,10=20+246,11=20@@=20= spgGetCache(Relation=20index)=0A=20=0A=20=09=09if=20= (cache->config.leafType=20!=3D=20atttype)=0A=20=09=09{=0A-=09=09=09if=20= (!OidIsValid(index_getprocid(index,=201,=20SPGIST_COMPRESS_PROC)))=0A+=09= =09=09if=20(!OidIsValid(index_getprocid(index,=201,=20= SPGIST_COMPRESS_PROC))=20&&=0A+=09=09=09=09= !OidIsValid(index_getprocid(index,=201,=20SPGIST_EXTRACTVALUE_PROC)))=0A=20= =09=09=09=09ereport(ERROR,=0A=20=09=09=09=09=09=09= (errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A-=09=09=09=09=09=09=20= errmsg("compress=20method=20must=20be=20defined=20when=20leaf=20type=20= is=20different=20from=20input=20type")));=0A+=09=09=09=09=09=09=20= errmsg("compress=20or=20extractValue=20method=20must=20be=20defined=20= when=20leaf=20type=20is=20different=20from=20input=20type")));=0A=20=0A=20= =09=09=09fillTypeDesc(&cache->attLeafType,=20cache->config.leafType);=0A=20= =09=09}=0A@@=20-1365,3=20+1366,59=20@@=20spgproperty(Oid=20index_oid,=20= int=20attno,=0A=20=0A=20=09return=20true;=0A=20}=0A+=0A+/*=0A+=20*=20= spgExtractEntries=20--=20extract=20multiple=20index=20entries=20from=20= one=20heap=20tuple.=0A+=20*=0A+=20*=20Calls=20the=20opclass's=20= extractValue=20function=20to=20decompose=20the=20indexed=20datum=0A+=20*=20= into=20multiple=20sub-entries.=20=20Returns=20an=20array=20of=20Datum=20= values=20and=20sets=0A+=20*=20*nentries=20to=20the=20count.=20=20= *nullFlags=20is=20set=20to=20a=20boolean=20array=20indicating=0A+=20*=20= which=20entries=20are=20NULL=20(or=20NULL=20if=20none=20are).=0A+=20*=0A= +=20*=20If=20the=20datum=20is=20NULL=20or=20extractValue=20returns=20no=20= entries,=20a=20single=20NULL=0A+=20*=20entry=20is=20produced.=0A+=20*/=0A= +Datum=20*=0A+spgExtractEntries(Relation=20index,=20Datum=20value,=20= bool=20isnull,=0A+=09=09=09=09=20=20int32=20*nentries,=20bool=20= **nullFlags)=0A+{=0A+=09Datum=09=20=20=20*entries;=0A+=0A+=09/*=20NULL=20= datum=20produces=20a=20single=20NULL=20entry=20*/=0A+=09if=20(isnull)=0A= +=09{=0A+=09=09*nentries=20=3D=201;=0A+=09=09entries=20=3D=20= palloc(sizeof(Datum));=0A+=09=09entries[0]=20=3D=20(Datum)=200;=0A+=09=09= *nullFlags=20=3D=20palloc(sizeof(bool));=0A+=09=09(*nullFlags)[0]=20=3D=20= true;=0A+=09=09return=20entries;=0A+=09}=0A+=0A+=09/*=20Call=20the=20= opclass's=20extractValue=20function=20*/=0A+=09*nullFlags=20=3D=20NULL;=0A= +=09entries=20=3D=20(Datum=20*)=0A+=09=09= DatumGetPointer(FunctionCall3Coll(index_getprocinfo(index,=201,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=09SPGIST_EXTRACTVALUE_PROC),=0A+=09=09= =09=09=09=09=09=09=09=09=20=20index->rd_indcollation[0],=0A+=09=09=09=09=09= =09=09=09=09=09=20=20value,=0A+=09=09=09=09=09=09=09=09=09=09=20=20= PointerGetDatum(nentries),=0A+=09=09=09=09=09=09=09=09=09=09=20=20= PointerGetDatum(nullFlags)));=0A+=0A+=09/*=20Handle=20empty=20or=20NULL=20= result:=20produce=20a=20single=20NULL=20entry=20*/=0A+=09if=20(entries=20= =3D=3D=20NULL=20||=20*nentries=20<=3D=200)=0A+=09{=0A+=09=09*nentries=20= =3D=201;=0A+=09=09entries=20=3D=20palloc(sizeof(Datum));=0A+=09=09= entries[0]=20=3D=20(Datum)=200;=0A+=09=09*nullFlags=20=3D=20= palloc(sizeof(bool));=0A+=09=09(*nullFlags)[0]=20=3D=20true;=0A+=09=09= return=20entries;=0A+=09}=0A+=0A+=09/*=20Create=20nullFlags=20array=20if=20= the=20function=20didn't=20*/=0A+=09if=20(*nullFlags=20=3D=3D=20NULL)=0A+=09= =09*nullFlags=20=3D=20palloc0_array(bool,=20*nentries);=0A+=0A+=09return=20= entries;=0A+}=0Adiff=20--git=20a/src/backend/access/spgist/spgvalidate.c=20= b/src/backend/access/spgist/spgvalidate.c=0Aindex=20= 27c855921e6..34111058f24=20100644=0A---=20= a/src/backend/access/spgist/spgvalidate.c=0A+++=20= b/src/backend/access/spgist/spgvalidate.c=0A@@=20-175,6=20+175,11=20@@=20= spgvalidate(Oid=20opclassoid)=0A=20=09=09=09case=20SPGIST_OPTIONS_PROC:=0A= =20=09=09=09=09ok=20=3D=20check_amoptsproc_signature(procform->amproc);=0A= =20=09=09=09=09break;=0A+=09=09=09case=20SPGIST_EXTRACTVALUE_PROC:=0A+=09= =09=09=09ok=20=3D=20check_amproc_signature(procform->amproc,=20= INTERNALOID,=20true,=0A+=09=09=09=09=09=09=09=09=09=09=093,=203,=20= INTERNALOID,=20INTERNALOID,=0A+=09=09=09=09=09=09=09=09=09=09=09= INTERNALOID);=0A+=09=09=09=09break;=0A=20=09=09=09default:=0A=20=09=09=09= =09ereport(INFO,=0A=20=09=09=09=09=09=09= (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),=0A@@=20-287,8=20+292,12=20= @@=20spgvalidate(Oid=20opclassoid)=0A=20=09=09{=0A=20=09=09=09if=20= ((thisgroup->functionset=20&=20(((uint64)=201)=20<<=20i))=20!=3D=200)=0A=20= =09=09=09=09continue;=09=09/*=20got=20it=20*/=0A-=09=09=09if=20(i=20=3D=3D= =20SPGIST_OPTIONS_PROC)=0A+=09=09=09if=20(i=20=3D=3D=20= SPGIST_OPTIONS_PROC=20||=0A+=09=09=09=09i=20=3D=3D=20= SPGIST_EXTRACTVALUE_PROC)=0A=20=09=09=09=09continue;=09=09/*=20optional=20= method=20*/=0A+=09=09=09if=20(i=20=3D=3D=20SPGIST_COMPRESS_PROC=20&&=0A+=09= =09=09=09(thisgroup->functionset=20&=20(((uint64)=201)=20<<=20= SPGIST_EXTRACTVALUE_PROC))=20!=3D=200)=0A+=09=09=09=09continue;=09=09/*=20= extractValue=20handles=20type=20conversion=20*/=0A=20=09=09=09= ereport(INFO,=0A=20=09=09=09=09=09= (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),=0A=20=09=09=09=09=09=20= errmsg("operator=20family=20\"%s\"=20of=20access=20method=20%s=20is=20= missing=20support=20function=20%d=20for=20type=20%s",=0A@@=20-367,6=20= +376,7=20@@=20spgadjustmembers(Oid=20opfamilyoid,=0A=20=09=09=09=09= break;=0A=20=09=09=09case=20SPGIST_COMPRESS_PROC:=0A=20=09=09=09case=20= SPGIST_OPTIONS_PROC:=0A+=09=09=09case=20SPGIST_EXTRACTVALUE_PROC:=0A=20=09= =09=09=09/*=20Optional,=20so=20force=20it=20to=20be=20a=20soft=20family=20= dependency=20*/=0A=20=09=09=09=09op->ref_is_hard=20=3D=20false;=0A=20=09=09= =09=09op->ref_is_family=20=3D=20true;=0Adiff=20--git=20= a/src/include/access/spgist.h=20b/src/include/access/spgist.h=0Aindex=20= 083d93f8ffd..efa7aa2d63b=20100644=0A---=20a/src/include/access/spgist.h=0A= +++=20b/src/include/access/spgist.h=0A@@=20-27,8=20+27,9=20@@=0A=20= #define=20SPGIST_LEAF_CONSISTENT_PROC=09=095=0A=20#define=20= SPGIST_COMPRESS_PROC=09=09=096=0A=20#define=20SPGIST_OPTIONS_PROC=09=09=09= =097=0A+#define=20SPGIST_EXTRACTVALUE_PROC=09=098=0A=20#define=20= SPGISTNRequiredProc=09=09=09=095=0A-#define=20SPGISTNProc=09=09=09=09=09=09= 7=0A+#define=20SPGISTNProc=09=09=09=09=09=098=0A=20=0A=20/*=0A=20=20*=20= Argument=20structs=20for=20spg_config=20method=0Adiff=20--git=20= a/src/include/access/spgist_private.h=20= b/src/include/access/spgist_private.h=0Aindex=20ec6d6f5f74d..f6e29acea8a=20= 100644=0A---=20a/src/include/access/spgist_private.h=0A+++=20= b/src/include/access/spgist_private.h=0A@@=20-193,6=20+193,13=20@@=20= typedef=20struct=20SpGistScanOpaqueData=0A=20=09MemoryContext=20tempCxt;=09= =09/*=20short-lived=20memory=20context=20*/=0A=20=09MemoryContext=20= traversalCxt;=20/*=20single=20scan=20lifetime=20memory=20context=20*/=0A=20= =0A+=09/*=0A+=09=20*=20For=20multi-entry=20indexes:=20hash=20table=20for=20= TID=20deduplication.=20=20Each=20heap=0A+=09=20*=20tuple=20produces=20= multiple=20index=20entries,=20so=20we=20track=20which=20TIDs=20have=20= been=0A+=09=20*=20returned.=20=20NULL=20for=20standard=20= (non-multi-entry)=20indexes.=0A+=09=20*/=0A+=09struct=20spgtid_hash=20= *tidHash;=0A+=0A=20=09/*=20Control=20flags=20showing=20whether=20to=20= search=20nulls=20and/or=20non-nulls=20*/=0A=20=09bool=09=09searchNulls;=09= /*=20scan=20matches=20(all)=20null=20entries=20*/=0A=20=09bool=09=09= searchNonNulls;=20/*=20scan=20matches=20(some)=20non-null=20entries=20*/=0A= @@=20-532,6=20+539,8=20@@=20extern=20OffsetNumber=20= SpGistPageAddNewItem(SpGistState=20*state,=20Page=20page,=0A=20extern=20= bool=20spgproperty(Oid=20index_oid,=20int=20attno,=0A=20=09=09=09=09=09=09= IndexAMProperty=20prop,=20const=20char=20*propname,=0A=20=09=09=09=09=09=09= bool=20*res,=20bool=20*isnull);=0A+extern=20Datum=20= *spgExtractEntries(Relation=20index,=20Datum=20value,=20bool=20isnull,=0A= +=09=09=09=09=09=09=09=09int32=20*nentries,=20bool=20**nullFlags);=0A=20=0A= =20/*=20spgdoinsert.c=20*/=0A=20extern=20void=20= spgUpdateNodeLink(SpGistInnerTuple=20tup,=20int=20nodeN,=0A--=20=0A= 2.50.1=20(Apple=20Git-155)=0A=0A= --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841 Content-Disposition: attachment; filename=v1-0004-Add-multirange_me_ops-SP-GiST-opclass-using-multi.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0004-Add-multirange_me_ops-SP-GiST-opclass-using-multi.patch" Content-Transfer-Encoding: quoted-printable =46rom=20d6d2c121554a523b09e9f4698a200a71d934a9c1=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Maxime=20Schoemans=20= =0ADate:=20Fri,=203=20Apr=202026=20= 19:32:01=20+0200=0ASubject:=20[PATCH=20v1=204/4]=20Add=20= multirange_me_ops=20SP-GiST=20opclass=20using=0A=20multi-entry=0A=0AAdd=20= a=20built-in=20SP-GiST=20operator=20class=20for=20multirange=20types=20= that=20uses=0Athe=20multi-entry=20infrastructure=20to=20decompose=20each=20= multirange=20into=20its=0Acomponent=20ranges,=20storing=20each=20as=20a=20= separate=20quad-tree=20entry.=0A=0AThe=20opclass=20is=20marked=20= non-default,=20consistent=20with=20the=20GiST=0Amultirange_me_ops.=0A=0A= The=20opclass=20reuses=20the=20existing=20range=20quad-tree=20structure=20= (choose=20and=0Apicksplit=20from=20range_ops)=20and=20the=20= multirange_gist_extractvalue=20function=0Afrom=20the=20GiST=20= multi-entry=20opclass.=20Three=20new=20SP-GiST-specific=20functions=0A= are=20added:=0A=0A=20=20spg_multirange_me_config:=20Configures=20the=20= quad=20tree=20with=20leafType=20set=0A=20=20to=20the=20corresponding=20= range=20type=20and=20canReturnData=20disabled.=0A=0A=20=20= spg_multirange_me_inner_consistent:=20Handles=20range,=20multirange,=20= and=0A=20=20element=20query=20types.=20Multirange=20queries=20are=20= converted=20to=20bounding=0A=20=20range=20bounds=20for=20quadrant=20= pruning.=20CONTAINS=20and=20EQ=20with=20multirange=0A=20=20queries=20are=20= relaxed=20to=20OVERLAPS=20since=20matching=20components=20may=20span=0A=20= =20multiple=20subtrees.=0A=0A=20=20spg_multirange_me_leaf_consistent:=20= Per-component=20filtering=20with=0A=20=20recheck=20for=20all=20= strategies=20except=20OVERLAPS=20and=20CONTAINS_ELEM,=20which=0A=20=20= are=20exact=20per-component.=20Handles=20empty-range=20sentinels=20for=20= empty=0A=20=20multiranges.=0A=0ACatalog=20entries=20register=20the=20= opclass=20for=20all=20multirange=20types=20with=2019=0Aoperators=20= (range,=20multirange,=20and=20element=20variants)=20and=206=20support=0A= functions=20(config,=20choose,=20picksplit,=20inner=20consistent,=20leaf=20= consistent,=0Aand=20extractValue).=0A=0ARegression=20tests=20verify=20= correctness=20across=20sequential=20scan,=20index=20scan,=0Aand=20bitmap=20= scan=20for=20all=20operators=20with=20range,=20multirange,=20empty,=20= and=0Aelement=20queries.=0A---=0A=20= src/backend/utils/adt/rangetypes_spgist.c=20=20=20=20=20|=20608=20= ++++++++++++++++=0A=20src/include/catalog/pg_amop.dat=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20|=20=2056=20++=0A=20= src/include/catalog/pg_amproc.dat=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=2018=20+=0A=20src/include/catalog/pg_opclass.dat=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=203=20+=0A=20src/include/catalog/pg_opfamily.dat=20= =20=20=20=20=20=20=20=20=20=20|=20=20=202=20+=0A=20= src/include/catalog/pg_proc.dat=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=2011=20+=0A=20src/test/regress/expected/multirangetypes.out=20|=20= 667=20++++++++++++++++++=0A=20src/test/regress/expected/psql.out=20=20=20= =20=20=20=20=20=20=20=20=20|=20=2023=20+-=0A=20= src/test/regress/sql/multirangetypes.sql=20=20=20=20=20=20|=20149=20++++=0A= =209=20files=20changed,=201526=20insertions(+),=2011=20deletions(-)=0A=0A= diff=20--git=20a/src/backend/utils/adt/rangetypes_spgist.c=20= b/src/backend/utils/adt/rangetypes_spgist.c=0Aindex=20= b198375e64d..17da99ff427=20100644=0A---=20= a/src/backend/utils/adt/rangetypes_spgist.c=0A+++=20= b/src/backend/utils/adt/rangetypes_spgist.c=0A@@=20-41,6=20+41,8=20@@=0A=20= #include=20"catalog/pg_type.h"=0A=20#include=20"utils/datum.h"=0A=20= #include=20"utils/fmgrprotos.h"=0A+#include=20"utils/lsyscache.h"=0A= +#include=20"utils/multirangetypes.h"=0A=20#include=20= "utils/rangetypes.h"=0A=20=0A=20static=20int16=20= getQuadrant(TypeCacheEntry=20*typcache,=20const=20RangeType=20*centroid,=0A= @@=20-998,3=20+1000,609=20@@=20= spg_range_quad_leaf_consistent(PG_FUNCTION_ARGS)=0A=20=0A=20=09= PG_RETURN_BOOL(res);=0A=20}=0A+=0A+=0A= +/*----------------------------------------------------------=0A+=20*=20= Multi-entry=20SP-GiST=20support=20for=20multirange=20types.=0A+=20*=0A+=20= *=20When=20an=20extractValue=20support=20function=20is=20registered,=20= SP-GiST=20decomposes=0A+=20*=20each=20multirange=20into=20its=20= component=20ranges=20and=20stores=20each=20as=20a=20separate=0A+=20*=20= index=20entry.=20=20The=20quad=20tree=20structure=20is=20the=20same=20as=20= the=20standard=20range=0A+=20*=20opclass,=20but=20the=20consistent=20= functions=20must=20handle=20multirange,=20range,=20and=0A+=20*=20element=20= query=20types.=0A+=20= *----------------------------------------------------------=0A+=20*/=0A+=0A= +/*=0A+=20*=20SP-GiST=20config=20function=20for=20multirange_me_ops.=0A+=20= *=0A+=20*=20Same=20quad=20tree=20structure=20as=20range_ops,=20but=20= leafType=20is=20the=20corresponding=0A+=20*=20range=20type=20(not=20the=20= multirange=20input=20type),=20and=20canReturnData=20is=20false=0A+=20*=20= because=20multi-entry=20decomposition=20prevents=20reconstructing=20the=20= original.=0A+=20*/=0A+Datum=0A= +spg_multirange_me_config(PG_FUNCTION_ARGS)=0A+{=0A+=09spgConfigIn=20= *cfgin=20=3D=20(spgConfigIn=20*)=20PG_GETARG_POINTER(0);=0A+=09= spgConfigOut=20*cfg=20=3D=20(spgConfigOut=20*)=20PG_GETARG_POINTER(1);=0A= +=0A+=09cfg->prefixType=20=3D=20ANYRANGEOID;=0A+=09cfg->labelType=20=3D=20= VOIDOID;=09/*=20we=20don't=20need=20node=20labels=20*/=0A+=09= cfg->leafType=20=3D=20get_multirange_range(cfgin->attType);=0A+=09= cfg->canReturnData=20=3D=20false;=0A+=09cfg->longValuesOK=20=3D=20false;=0A= +=09PG_RETURN_VOID();=0A+}=0A+=0A+/*=0A+=20*=20SP-GiST=20inner=20= consistent=20function=20for=20multirange_me_ops.=0A+=20*=0A+=20*=20= Handles=20range,=20multirange,=20and=20element=20query=20types.=20=20The=20= tree=20structure=0A+=20*=20is=20the=20standard=20range=20quad=20tree,=20= so=20the=20quadrant=20pruning=20logic=20is=20the=0A+=20*=20same=20as=20= spg_range_quad_inner_consistent.=20=20For=20multirange=20queries,=20the=0A= +=20*=20query=20is=20converted=20to=20its=20bounding=20range=20for=20= pruning=20purposes.=20=20For=0A+=20*=20CONTAINS=20and=20EQ=20with=20= non-empty=20multirange=20queries,=20the=20pruning=20is=0A+=20*=20relaxed=20= to=20OVERLAPS=20because=20a=20matching=20multirange's=20components=20may=20= be=0A+=20*=20spread=20across=20multiple=20subtrees.=0A+=20*/=0A+Datum=0A= +spg_multirange_me_inner_consistent(PG_FUNCTION_ARGS)=0A+{=0A+=09= spgInnerConsistentIn=20*in=20=3D=20(spgInnerConsistentIn=20*)=20= PG_GETARG_POINTER(0);=0A+=09spgInnerConsistentOut=20*out=20=3D=20= (spgInnerConsistentOut=20*)=20PG_GETARG_POINTER(1);=0A+=09int=09=09=09= which;=0A+=09int=09=09=09i;=0A+=09MemoryContext=20oldCtx;=0A+=0A+=09/*=0A= +=09=20*=20For=20adjacent=20search=20we=20need=20also=20previous=20= centroid=20(if=20any)=20to=20improve=0A+=09=20*=20the=20precision=20of=20= the=20consistent=20check.=0A+=09=20*/=0A+=09bool=09=09needPrevious=20=3D=20= false;=0A+=0A+=09if=20(in->allTheSame)=0A+=09{=0A+=09=09/*=20Report=20= that=20all=20nodes=20should=20be=20visited=20*/=0A+=09=09out->nNodes=20=3D= =20in->nNodes;=0A+=09=09out->nodeNumbers=20=3D=20palloc_array(int,=20= in->nNodes);=0A+=09=09for=20(i=20=3D=200;=20i=20<=20in->nNodes;=20i++)=0A= +=09=09=09out->nodeNumbers[i]=20=3D=20i;=0A+=09=09PG_RETURN_VOID();=0A+=09= }=0A+=0A+=09if=20(!in->hasPrefix)=0A+=09{=0A+=09=09/*=0A+=09=09=20*=20No=20= centroid=20on=20this=20inner=20node.=20=20Node=200=20=3D=20empty=20= ranges,=20node=201=20=3D=0A+=09=09=20*=20non-empty=20ranges.=0A+=09=09=20= */=0A+=09=09Assert(in->nNodes=20=3D=3D=202);=0A+=0A+=09=09which=20=3D=20= (1=20<<=201)=20|=20(1=20<<=202);=0A+=09=09for=20(i=20=3D=200;=20i=20<=20= in->nkeys;=20i++)=0A+=09=09{=0A+=09=09=09StrategyNumber=20strategy=20=3D=20= in->scankeys[i].sk_strategy;=0A+=09=09=09Oid=09=09=09subtype=20=3D=20= in->scankeys[i].sk_subtype;=0A+=09=09=09bool=09=09empty;=0A+=0A+=09=09=09= /*=20Determine=20if=20the=20query=20is=20empty=20based=20on=20its=20type=20= */=0A+=09=09=09if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS_ELEM)=0A+=09= =09=09=09empty=20=3D=20false;=0A+=09=09=09else=20if=20(subtype=20=3D=3D=20= ANYMULTIRANGEOID)=0A+=09=09=09=09empty=20=3D=20MultirangeIsEmpty(=0A+=09=09= =09=09=09DatumGetMultirangeTypeP(in->scankeys[i].sk_argument));=0A+=09=09= =09else=0A+=09=09=09=09empty=20=3D=20RangeIsEmpty(=0A+=09=09=09=09=09= DatumGetRangeTypeP(in->scankeys[i].sk_argument));=0A+=0A+=09=09=09switch=20= (strategy)=0A+=09=09=09{=0A+=09=09=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09= =09=09case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09=09case=20= RANGESTRAT_OVERLAPS:=0A+=09=09=09=09case=20RANGESTRAT_OVERRIGHT:=0A+=09=09= =09=09case=20RANGESTRAT_AFTER:=0A+=09=09=09=09case=20= RANGESTRAT_ADJACENT:=0A+=09=09=09=09=09if=20(empty)=0A+=09=09=09=09=09=09= which=20=3D=200;=0A+=09=09=09=09=09else=0A+=09=09=09=09=09=09which=20&=3D=20= (1=20<<=202);=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09case=20= RANGESTRAT_CONTAINS:=0A+=09=09=09=09=09if=20(!empty)=0A+=09=09=09=09=09=09= which=20&=3D=20(1=20<<=202);=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09= case=20RANGESTRAT_CONTAINED_BY:=0A+=09=09=09=09=09if=20(empty)=0A+=09=09=09= =09=09=09which=20&=3D=20(1=20<<=201);=0A+=09=09=09=09=09break;=0A+=0A+=09= =09=09=09case=20RANGESTRAT_CONTAINS_ELEM:=0A+=09=09=09=09=09which=20&=3D=20= (1=20<<=202);=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09case=20= RANGESTRAT_EQ:=0A+=09=09=09=09=09if=20(empty)=0A+=09=09=09=09=09=09which=20= &=3D=20(1=20<<=201);=0A+=09=09=09=09=09else=0A+=09=09=09=09=09=09which=20= &=3D=20(1=20<<=202);=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09= default:=0A+=09=09=09=09=09elog(ERROR,=20"unrecognized=20range=20= strategy:=20%d",=20strategy);=0A+=09=09=09=09=09break;=0A+=09=09=09}=0A+=09= =09=09if=20(which=20=3D=3D=200)=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A= +=09else=0A+=09{=0A+=09=09RangeBound=09centroidLower,=0A+=09=09=09=09=09= centroidUpper;=0A+=09=09bool=09=09centroidEmpty;=0A+=09=09TypeCacheEntry=20= *typcache;=0A+=09=09RangeType=20=20*centroid;=0A+=0A+=09=09centroid=20=3D=20= DatumGetRangeTypeP(in->prefixDatum);=0A+=09=09typcache=20=3D=20= range_get_typcache(fcinfo,=20RangeTypeGetOid(centroid));=0A+=09=09= range_deserialize(typcache,=20centroid,=20¢roidLower,=20= ¢roidUpper,=0A+=09=09=09=09=09=09=20=20¢roidEmpty);=0A+=0A+=09=09= Assert(in->nNodes=20=3D=3D=204=20||=20in->nNodes=20=3D=3D=205);=0A+=0A+=09= =09which=20=3D=20(1=20<<=201)=20|=20(1=20<<=202)=20|=20(1=20<<=203)=20|=20= (1=20<<=204)=20|=20(1=20<<=205);=0A+=0A+=09=09for=20(i=20=3D=200;=20i=20= <=20in->nkeys;=20i++)=0A+=09=09{=0A+=09=09=09StrategyNumber=20strategy;=0A= +=09=09=09RangeBound=09lower,=0A+=09=09=09=09=09=09upper;=0A+=09=09=09= bool=09=09empty;=0A+=09=09=09RangeType=20=20*range=20=3D=20NULL;=0A+=09=09= =09Oid=09=09=09subtype;=0A+=09=09=09bool=09=09is_multirange;=0A+=0A+=09=09= =09RangeType=20=20*prevCentroid=20=3D=20NULL;=0A+=09=09=09RangeBound=09= prevLower,=0A+=09=09=09=09=09=09prevUpper;=0A+=09=09=09bool=09=09= prevEmpty;=0A+=0A+=09=09=09RangeBound=20*minLower=20=3D=20NULL,=0A+=09=09= =09=09=09=20=20=20*maxLower=20=3D=20NULL,=0A+=09=09=09=09=09=20=20=20= *minUpper=20=3D=20NULL,=0A+=09=09=09=09=09=20=20=20*maxUpper=20=3D=20= NULL;=0A+=0A+=09=09=09bool=09=09inclusive=20=3D=20true;=0A+=09=09=09bool=09= =09strictEmpty=20=3D=20true;=0A+=09=09=09int=09=09=09cmp,=0A+=09=09=09=09= =09=09which1,=0A+=09=09=09=09=09=09which2;=0A+=0A+=09=09=09strategy=20=3D=20= in->scankeys[i].sk_strategy;=0A+=09=09=09subtype=20=3D=20= in->scankeys[i].sk_subtype;=0A+=09=09=09is_multirange=20=3D=20subtype=20= =3D=3D=20ANYMULTIRANGEOID;=0A+=0A+=09=09=09/*=0A+=09=09=09=20*=20Extract=20= query=20bounds=20depending=20on=20the=20query=20type.=0A+=09=09=09=20*/=0A= +=09=09=09if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS_ELEM)=0A+=09=09=09= {=0A+=09=09=09=09/*=20Element=20query:=20expand=20to=20point=20range=20= bounds=20*/=0A+=09=09=09=09lower.inclusive=20=3D=20true;=0A+=09=09=09=09= lower.infinite=20=3D=20false;=0A+=09=09=09=09lower.lower=20=3D=20true;=0A= +=09=09=09=09lower.val=20=3D=20in->scankeys[i].sk_argument;=0A+=0A+=09=09= =09=09upper.inclusive=20=3D=20true;=0A+=09=09=09=09upper.infinite=20=3D=20= false;=0A+=09=09=09=09upper.lower=20=3D=20false;=0A+=09=09=09=09= upper.val=20=3D=20in->scankeys[i].sk_argument;=0A+=0A+=09=09=09=09empty=20= =3D=20false;=0A+=0A+=09=09=09=09strategy=20=3D=20RANGESTRAT_CONTAINS;=0A= +=09=09=09}=0A+=09=09=09else=20if=20(is_multirange)=0A+=09=09=09{=0A+=09=09= =09=09/*=20Multirange=20query:=20extract=20bounding=20range=20bounds=20= */=0A+=09=09=09=09MultirangeType=20*mr=20=3D=0A+=09=09=09=09=09= DatumGetMultirangeTypeP(in->scankeys[i].sk_argument);=0A+=0A+=09=09=09=09= if=20(MultirangeIsEmpty(mr))=0A+=09=09=09=09{=0A+=09=09=09=09=09empty=20= =3D=20true;=0A+=09=09=09=09}=0A+=09=09=09=09else=0A+=09=09=09=09{=0A+=09=09= =09=09=09int32=09=09range_count=20=3D=20mr->rangeCount;=0A+=09=09=09=09=09= RangeBound=09tmp;=0A+=0A+=09=09=09=09=09/*=0A+=09=09=09=09=09=20*=20Use=20= the=20range=20typcache=20(from=20the=20centroid)=20to=0A+=09=09=09=09=09=20= *=20extract=20multirange=20bounds.=20=20We=20can't=20use=0A+=09=09=09=09=09= =20*=20multirange_get_typcache=20here=20because=20it=20caches=20in=0A+=09= =09=09=09=09=20*=20fn_extra,=20conflicting=20with=20range_get_typcache.=0A= +=09=09=09=09=09=20*/=0A+=09=09=09=09=09multirange_get_bounds(typcache,=20= mr,=0A+=09=09=09=09=09=09=09=09=09=09=20=200,=20&lower,=20&upper);=0A+=09= =09=09=09=09if=20(range_count=20>=201)=0A+=09=09=09=09=09=09= multirange_get_bounds(typcache,=20mr,=0A+=09=09=09=09=09=09=09=09=09=09=09= =20=20range_count=20-=201,=0A+=09=09=09=09=09=09=09=09=09=09=09=20=20= &tmp,=20&upper);=0A+=09=09=09=09=09empty=20=3D=20false;=0A+=09=09=09=09}=0A= +=0A+=09=09=09=09/*=0A+=09=09=09=09=20*=20For=20CONTAINS/EQ=20with=20= non-empty=20multirange,=20relax=20to=0A+=09=09=09=09=20*=20OVERLAPS:=20= components=20of=20a=20matching=20multirange=20may=20be=0A+=09=09=09=09=20= *=20spread=20across=20multiple=20subtrees.=0A+=09=09=09=09=20*/=0A+=09=09= =09=09if=20(!empty=20&&=0A+=09=09=09=09=09(strategy=20=3D=3D=20= RANGESTRAT_CONTAINS=20||=0A+=09=09=09=09=09=20strategy=20=3D=3D=20= RANGESTRAT_EQ))=0A+=09=09=09=09=09strategy=20=3D=20RANGESTRAT_OVERLAPS;=0A= +=09=09=09}=0A+=09=09=09else=0A+=09=09=09{=0A+=09=09=09=09/*=20Range=20= query=20*/=0A+=09=09=09=09range=20=3D=20= DatumGetRangeTypeP(in->scankeys[i].sk_argument);=0A+=09=09=09=09= range_deserialize(typcache,=20range,=20&lower,=20&upper,=20&empty);=0A+=09= =09=09}=0A+=0A+=09=09=09/*=0A+=09=09=09=20*=20Apply=20the=20same=20= quadrant=20pruning=20logic=20as=20the=20standard=20range=0A+=09=09=09=20= *=20opclass.=20=20See=20spg_range_quad_inner_consistent=20for=20details.=0A= +=09=09=09=20*/=0A+=09=09=09switch=20(strategy)=0A+=09=09=09{=0A+=09=09=09= =09case=20RANGESTRAT_BEFORE:=0A+=09=09=09=09=09maxUpper=20=3D=20&lower;=0A= +=09=09=09=09=09inclusive=20=3D=20false;=0A+=09=09=09=09=09break;=0A+=0A= +=09=09=09=09case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09=09=09maxUpper=20=3D=20= &upper;=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09case=20= RANGESTRAT_OVERLAPS:=0A+=09=09=09=09=09maxLower=20=3D=20&upper;=0A+=09=09= =09=09=09minUpper=20=3D=20&lower;=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09= =09case=20RANGESTRAT_OVERRIGHT:=0A+=09=09=09=09=09minLower=20=3D=20= &lower;=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09case=20= RANGESTRAT_AFTER:=0A+=09=09=09=09=09minLower=20=3D=20&upper;=0A+=09=09=09= =09=09inclusive=20=3D=20false;=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09= case=20RANGESTRAT_ADJACENT:=0A+=09=09=09=09=09if=20(empty)=0A+=09=09=09=09= =09=09break;=09/*=20Skip=20to=20strictEmpty=20check.=20*/=0A+=0A+=09=09=09= =09=09if=20(in->traversalValue)=0A+=09=09=09=09=09{=0A+=09=09=09=09=09=09= prevCentroid=20=3D=20in->traversalValue;=0A+=09=09=09=09=09=09= range_deserialize(typcache,=20prevCentroid,=0A+=09=09=09=09=09=09=09=09=09= =09=20=20&prevLower,=20&prevUpper,=20&prevEmpty);=0A+=09=09=09=09=09}=0A= +=0A+=09=09=09=09=09cmp=20=3D=20adjacent_inner_consistent(typcache,=20= &lower,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09¢roidUpper,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09prevCentroid=20?=20&prevUpper=20:=20= NULL);=0A+=09=09=09=09=09if=20(cmp=20>=200)=0A+=09=09=09=09=09=09which1=20= =3D=20(1=20<<=201)=20|=20(1=20<<=204);=0A+=09=09=09=09=09else=20if=20= (cmp=20<=200)=0A+=09=09=09=09=09=09which1=20=3D=20(1=20<<=202)=20|=20(1=20= <<=203);=0A+=09=09=09=09=09else=0A+=09=09=09=09=09=09which1=20=3D=200;=0A= +=0A+=09=09=09=09=09cmp=20=3D=20adjacent_inner_consistent(typcache,=20= &upper,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09¢roidLower,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09prevCentroid=20?=20&prevLower=20:=20= NULL);=0A+=09=09=09=09=09if=20(cmp=20>=200)=0A+=09=09=09=09=09=09which2=20= =3D=20(1=20<<=201)=20|=20(1=20<<=202);=0A+=09=09=09=09=09else=20if=20= (cmp=20<=200)=0A+=09=09=09=09=09=09which2=20=3D=20(1=20<<=203)=20|=20(1=20= <<=204);=0A+=09=09=09=09=09else=0A+=09=09=09=09=09=09which2=20=3D=200;=0A= +=0A+=09=09=09=09=09which=20&=3D=20which1=20|=20which2;=0A+=09=09=09=09=09= needPrevious=20=3D=20true;=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09= case=20RANGESTRAT_CONTAINS:=0A+=09=09=09=09=09strictEmpty=20=3D=20false;=0A= +=09=09=09=09=09if=20(!empty)=0A+=09=09=09=09=09{=0A+=09=09=09=09=09=09= which=20&=3D=20(1=20<<=201)=20|=20(1=20<<=202)=20|=20(1=20<<=203)=20|=20= (1=20<<=204);=0A+=09=09=09=09=09=09maxLower=20=3D=20&lower;=0A+=09=09=09=09= =09=09minUpper=20=3D=20&upper;=0A+=09=09=09=09=09}=0A+=09=09=09=09=09= break;=0A+=0A+=09=09=09=09case=20RANGESTRAT_CONTAINED_BY:=0A+=09=09=09=09= =09strictEmpty=20=3D=20false;=0A+=09=09=09=09=09if=20(empty)=0A+=09=09=09= =09=09{=0A+=09=09=09=09=09=09which=20&=3D=20(1=20<<=205);=0A+=09=09=09=09= =09}=0A+=09=09=09=09=09else=0A+=09=09=09=09=09{=0A+=09=09=09=09=09=09= minLower=20=3D=20&lower;=0A+=09=09=09=09=09=09maxUpper=20=3D=20&upper;=0A= +=09=09=09=09=09}=0A+=09=09=09=09=09break;=0A+=0A+=09=09=09=09case=20= RANGESTRAT_EQ:=0A+=09=09=09=09=09strictEmpty=20=3D=20false;=0A+=09=09=09=09= =09if=20(empty)=0A+=09=09=09=09=09{=0A+=09=09=09=09=09=09which=20&=3D=20= (1=20<<=205);=0A+=09=09=09=09=09}=0A+=09=09=09=09=09else=0A+=09=09=09=09=09= {=0A+=09=09=09=09=09=09/*=0A+=09=09=09=09=09=09=20*=20For=20range=20= queries,=20restrict=20to=20the=20exact=20quadrant.=0A+=09=09=09=09=09=09=20= *=20For=20multirange=20queries=20(already=20converted=20to=0A+=09=09=09=09= =09=09=20*=20OVERLAPS=20above),=20we=20won't=20reach=20here.=0A+=09=09=09= =09=09=09=20*/=0A+=09=09=09=09=09=09which=20&=3D=20(1=20<<=20= getQuadrant(typcache,=20centroid,=20range));=0A+=09=09=09=09=09}=0A+=09=09= =09=09=09break;=0A+=0A+=09=09=09=09default:=0A+=09=09=09=09=09= elog(ERROR,=20"unrecognized=20range=20strategy:=20%d",=20strategy);=0A+=09= =09=09=09=09break;=0A+=09=09=09}=0A+=0A+=09=09=09if=20(strictEmpty)=0A+=09= =09=09{=0A+=09=09=09=09if=20(empty)=0A+=09=09=09=09{=0A+=09=09=09=09=09= which=20=3D=200;=0A+=09=09=09=09=09break;=0A+=09=09=09=09}=0A+=09=09=09=09= else=0A+=09=09=09=09{=0A+=09=09=09=09=09which=20&=3D=20(1=20<<=201)=20|=20= (1=20<<=202)=20|=20(1=20<<=203)=20|=20(1=20<<=204);=0A+=09=09=09=09}=0A+=09= =09=09}=0A+=0A+=09=09=09if=20(minLower)=0A+=09=09=09{=0A+=09=09=09=09if=20= (range_cmp_bounds(typcache,=20¢roidLower,=20minLower)=20<=3D=200)=0A= +=09=09=09=09=09which=20&=3D=20(1=20<<=201)=20|=20(1=20<<=202)=20|=20(1=20= <<=205);=0A+=09=09=09}=0A+=09=09=09if=20(maxLower)=0A+=09=09=09{=0A+=09=09= =09=09cmp=20=3D=20range_cmp_bounds(typcache,=20¢roidLower,=20= maxLower);=0A+=09=09=09=09if=20(cmp=20>=200=20||=20(!inclusive=20&&=20= cmp=20=3D=3D=200))=0A+=09=09=09=09=09which=20&=3D=20(1=20<<=203)=20|=20= (1=20<<=204)=20|=20(1=20<<=205);=0A+=09=09=09}=0A+=09=09=09if=20= (minUpper)=0A+=09=09=09{=0A+=09=09=09=09if=20(range_cmp_bounds(typcache,=20= ¢roidUpper,=20minUpper)=20<=3D=200)=0A+=09=09=09=09=09which=20&=3D=20= (1=20<<=201)=20|=20(1=20<<=204)=20|=20(1=20<<=205);=0A+=09=09=09}=0A+=09=09= =09if=20(maxUpper)=0A+=09=09=09{=0A+=09=09=09=09cmp=20=3D=20= range_cmp_bounds(typcache,=20¢roidUpper,=20maxUpper);=0A+=09=09=09=09= if=20(cmp=20>=200=20||=20(!inclusive=20&&=20cmp=20=3D=3D=200))=0A+=09=09=09= =09=09which=20&=3D=20(1=20<<=202)=20|=20(1=20<<=203)=20|=20(1=20<<=205);=0A= +=09=09=09}=0A+=0A+=09=09=09if=20(which=20=3D=3D=200)=0A+=09=09=09=09= break;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=20Build=20the=20output=20node=20= list=20*/=0A+=09out->nodeNumbers=20=3D=20palloc_array(int,=20= in->nNodes);=0A+=09if=20(needPrevious)=0A+=09=09out->traversalValues=20=3D= =20palloc_array(void=20*,=20in->nNodes);=0A+=09out->nNodes=20=3D=200;=0A= +=0A+=09oldCtx=20=3D=20= MemoryContextSwitchTo(in->traversalMemoryContext);=0A+=0A+=09for=20(i=20= =3D=201;=20i=20<=3D=20in->nNodes;=20i++)=0A+=09{=0A+=09=09if=20(which=20= &=20(1=20<<=20i))=0A+=09=09{=0A+=09=09=09if=20(needPrevious)=0A+=09=09=09= {=0A+=09=09=09=09Datum=09=09previousCentroid;=0A+=0A+=09=09=09=09= previousCentroid=20=3D=20datumCopy(in->prefixDatum,=20false,=20-1);=0A+=09= =09=09=09out->traversalValues[out->nNodes]=20=3D=20= DatumGetPointer(previousCentroid);=0A+=09=09=09}=0A+=09=09=09= out->nodeNumbers[out->nNodes]=20=3D=20i=20-=201;=0A+=09=09=09= out->nNodes++;=0A+=09=09}=0A+=09}=0A+=0A+=09= MemoryContextSwitchTo(oldCtx);=0A+=0A+=09PG_RETURN_VOID();=0A+}=0A+=0A= +/*=0A+=20*=20SP-GiST=20leaf=20consistent=20function=20for=20= multirange_me_ops.=0A+=20*=0A+=20*=20The=20leaf=20datum=20is=20a=20= single=20component=20range=20from=20the=20indexed=20multirange.=0A+=20*=20= Most=20strategies=20need=20recheck=20because=20a=20single=20component=20= cannot=20fully=0A+=20*=20determine=20the=20multirange's=20relationship=20= with=20the=20query.=20=20OVERLAPS=20and=0A+=20*=20CONTAINS_ELEM=20are=20= exact=20per-component=20and=20skip=20recheck.=0A+=20*/=0A+Datum=0A= +spg_multirange_me_leaf_consistent(PG_FUNCTION_ARGS)=0A+{=0A+=09= spgLeafConsistentIn=20*in=20=3D=20(spgLeafConsistentIn=20*)=20= PG_GETARG_POINTER(0);=0A+=09spgLeafConsistentOut=20*out=20=3D=20= (spgLeafConsistentOut=20*)=20PG_GETARG_POINTER(1);=0A+=09RangeType=20=20= *leafRange=20=3D=20DatumGetRangeTypeP(in->leafDatum);=0A+=09= TypeCacheEntry=20*typcache;=0A+=09bool=09=09res;=0A+=09int=09=09=09i;=0A= +=0A+=09out->recheck=20=3D=20false;=0A+=09out->leafValue=20=3D=20= in->leafDatum;=0A+=0A+=09typcache=20=3D=20range_get_typcache(fcinfo,=20= RangeTypeGetOid(leafRange));=0A+=09res=20=3D=20true;=0A+=09for=20(i=20=3D=20= 0;=20i=20<=20in->nkeys;=20i++)=0A+=09{=0A+=09=09StrategyNumber=20= strategy=20=3D=20in->scankeys[i].sk_strategy;=0A+=09=09Datum=09=09= keyDatum=20=3D=20in->scankeys[i].sk_argument;=0A+=09=09Oid=09=09=09= subtype=20=3D=20in->scankeys[i].sk_subtype;=0A+=0A+=09=09/*=0A+=09=09=20= *=20Set=20recheck=20for=20all=20strategies=20except=20OVERLAPS=20and=20= CONTAINS_ELEM,=0A+=09=09=20*=20which=20are=20exact=20per-component.=0A+=09= =09=20*/=0A+=09=09if=20(strategy=20!=3D=20RANGESTRAT_OVERLAPS=20&&=0A+=09= =09=09strategy=20!=3D=20RANGESTRAT_CONTAINS_ELEM)=0A+=09=09=09= out->recheck=20=3D=20true;=0A+=0A+=09=09if=20(strategy=20=3D=3D=20= RANGESTRAT_CONTAINS_ELEM)=0A+=09=09{=0A+=09=09=09/*=20Element=20query=20= */=0A+=09=09=09res=20=3D=20range_contains_elem_internal(typcache,=20= leafRange,=20keyDatum);=0A+=09=09}=0A+=09=09else=20if=20(subtype=20=3D=3D=20= ANYMULTIRANGEOID)=0A+=09=09{=0A+=09=09=09/*=20Multirange=20query=20*/=0A= +=09=09=09MultirangeType=20*query=20=3D=20= DatumGetMultirangeTypeP(keyDatum);=0A+=0A+=09=09=09/*=20Empty=20key=20is=20= sentinel=20for=20empty=20multirange=20*/=0A+=09=09=09if=20= (RangeIsEmpty(leafRange))=0A+=09=09=09{=0A+=09=09=09=09if=20(strategy=20= =3D=3D=20RANGESTRAT_CONTAINED_BY)=0A+=09=09=09=09=09res=20=3D=20true;=0A= +=09=09=09=09else=20if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS=20||=0A= +=09=09=09=09=09=09=20strategy=20=3D=3D=20RANGESTRAT_EQ)=0A+=09=09=09=09=09= res=20=3D=20MultirangeIsEmpty(query);=0A+=09=09=09=09else=0A+=09=09=09=09= =09res=20=3D=20false;=0A+=09=09=09}=0A+=09=09=09else=20if=20= (MultirangeIsEmpty(query))=0A+=09=09=09{=0A+=09=09=09=09if=20(strategy=20= =3D=3D=20RANGESTRAT_CONTAINS)=0A+=09=09=09=09=09res=20=3D=20true;=0A+=09=09= =09=09else=0A+=09=09=09=09=09res=20=3D=20false;=0A+=09=09=09}=0A+=09=09=09= else=0A+=09=09=09{=0A+=09=09=09=09switch=20(strategy)=0A+=09=09=09=09{=0A= +=09=09=09=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09=09=09=09=09res=20=3D=20= range_before_multirange_internal(typcache,=0A+=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09=20=20leafRange,=20query);=0A+=09=09=09=09=09=09break;=0A= +=09=09=09=09=09case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09=09=09=09res=20=3D= =20range_overleft_multirange_internal(typcache,=0A+=09=09=09=09=09=09=09=09= =09=09=09=09=09=09=09=09leafRange,=20query);=0A+=09=09=09=09=09=09break;=0A= +=09=09=09=09=09case=20RANGESTRAT_OVERRIGHT:=0A+=09=09=09=09=09=09res=20= =3D=20range_overright_multirange_internal(typcache,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=20leafRange,=20query);=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09case=20RANGESTRAT_AFTER:=0A+=09=09=09=09=09=09= res=20=3D=20range_after_multirange_internal(typcache,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=20leafRange,=20query);=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09case=20RANGESTRAT_ADJACENT:=0A+=09=09=09=09=09=09= res=20=3D=20range_adjacent_multirange_internal(typcache,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09leafRange,=20query);=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09case=20RANGESTRAT_OVERLAPS:=0A+=09=09=09=09=09= case=20RANGESTRAT_CONTAINS:=0A+=09=09=09=09=09case=20= RANGESTRAT_CONTAINED_BY:=0A+=09=09=09=09=09case=20RANGESTRAT_EQ:=0A+=09=09= =09=09=09=09/*=20Use=20overlaps=20as=20necessary=20condition=20*/=0A+=09=09= =09=09=09=09res=20=3D=20range_overlaps_multirange_internal(typcache,=0A+=09= =09=09=09=09=09=09=09=09=09=09=09=09=09=09=09leafRange,=20query);=0A+=09=09= =09=09=09=09break;=0A+=09=09=09=09=09default:=0A+=09=09=09=09=09=09= elog(ERROR,=20"unrecognized=20range=20strategy:=20%d",=0A+=09=09=09=09=09= =09=09=20strategy);=0A+=09=09=09=09=09=09res=20=3D=20false;=0A+=09=09=09=09= =09=09break;=0A+=09=09=09=09}=0A+=09=09=09}=0A+=09=09}=0A+=09=09else=0A+=09= =09{=0A+=09=09=09/*=20Range=20query=20*/=0A+=09=09=09RangeType=20=20= *query=20=3D=20DatumGetRangeTypeP(keyDatum);=0A+=0A+=09=09=09/*=20Empty=20= key=20is=20sentinel=20for=20empty=20multirange=20*/=0A+=09=09=09if=20= (RangeIsEmpty(leafRange))=0A+=09=09=09{=0A+=09=09=09=09if=20(strategy=20= =3D=3D=20RANGESTRAT_CONTAINED_BY)=0A+=09=09=09=09=09res=20=3D=20true;=0A= +=09=09=09=09else=20if=20(strategy=20=3D=3D=20RANGESTRAT_CONTAINS)=0A+=09= =09=09=09=09res=20=3D=20RangeIsEmpty(query);=0A+=09=09=09=09else=0A+=09=09= =09=09=09res=20=3D=20false;=0A+=09=09=09}=0A+=09=09=09else=20if=20= (RangeIsEmpty(query))=0A+=09=09=09{=0A+=09=09=09=09if=20(strategy=20=3D=3D= =20RANGESTRAT_CONTAINS)=0A+=09=09=09=09=09res=20=3D=20true;=0A+=09=09=09=09= else=0A+=09=09=09=09=09res=20=3D=20false;=0A+=09=09=09}=0A+=09=09=09else=0A= +=09=09=09{=0A+=09=09=09=09switch=20(strategy)=0A+=09=09=09=09{=0A+=09=09= =09=09=09case=20RANGESTRAT_BEFORE:=0A+=09=09=09=09=09=09res=20=3D=20= range_before_internal(typcache,=20leafRange,=20query);=0A+=09=09=09=09=09= =09break;=0A+=09=09=09=09=09case=20RANGESTRAT_OVERLEFT:=0A+=09=09=09=09=09= =09res=20=3D=20range_overleft_internal(typcache,=20leafRange,=0A+=09=09=09= =09=09=09=09=09=09=09=09=09=09=20=20query);=0A+=09=09=09=09=09=09break;=0A= +=09=09=09=09=09case=20RANGESTRAT_OVERRIGHT:=0A+=09=09=09=09=09=09res=20= =3D=20range_overright_internal(typcache,=20leafRange,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20=20query);=0A+=09=09=09=09=09=09break;=0A+=09=09= =09=09=09case=20RANGESTRAT_AFTER:=0A+=09=09=09=09=09=09res=20=3D=20= range_after_internal(typcache,=20leafRange,=20query);=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09case=20RANGESTRAT_ADJACENT:=0A+=09=09=09=09=09=09= res=20=3D=20range_adjacent_internal(typcache,=20leafRange,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=20=20query);=0A+=09=09=09=09=09=09break;=0A+=09= =09=09=09=09case=20RANGESTRAT_OVERLAPS:=0A+=09=09=09=09=09=09res=20=3D=20= range_overlaps_internal(typcache,=20leafRange,=0A+=09=09=09=09=09=09=09=09= =09=09=09=09=09=20=20query);=0A+=09=09=09=09=09=09break;=0A+=09=09=09=09=09= case=20RANGESTRAT_CONTAINS:=0A+=09=09=09=09=09case=20= RANGESTRAT_CONTAINED_BY:=0A+=09=09=09=09=09case=20RANGESTRAT_EQ:=0A+=09=09= =09=09=09=09/*=20Use=20overlaps=20as=20necessary=20condition=20*/=0A+=09=09= =09=09=09=09res=20=3D=20range_overlaps_internal(typcache,=20leafRange,=0A= +=09=09=09=09=09=09=09=09=09=09=09=09=09=20=20query);=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09default:=0A+=09=09=09=09=09=09elog(ERROR,=20= "unrecognized=20range=20strategy:=20%d",=0A+=09=09=09=09=09=09=09=20= strategy);=0A+=09=09=09=09=09=09res=20=3D=20false;=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09}=0A+=09=09=09}=0A+=09=09}=0A+=0A+=09=09if=20= (!res)=0A+=09=09=09break;=0A+=09}=0A+=0A+=09PG_RETURN_BOOL(res);=0A+}=0A= diff=20--git=20a/src/include/catalog/pg_amop.dat=20= b/src/include/catalog/pg_amop.dat=0Aindex=203cc3ba61eeb..fb427a940fb=20= 100644=0A---=20a/src/include/catalog/pg_amop.dat=0A+++=20= b/src/include/catalog/pg_amop.dat=0A@@=20-1732,6=20+1732,62=20@@=0A=20=20= =20amoprighttype=20=3D>=20'anyrange',=20amopstrategy=20=3D>=20'18',=0A=20= =20=20amopopr=20=3D>=20'=3D(anyrange,anyrange)',=20amopmethod=20=3D>=20= 'spgist'=20},=0A=20=0A+#=20SP-GiST=20multirange_me_ops=0A+{=20amopfamily=20= =3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'1',=0A+=20=20amopopr=20=3D>=20= '<<(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'1',=0A+=20=20amopopr=20=3D>=20= '<<(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'2',=0A+=20=20amopopr=20=3D>=20= '&<(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'2',=0A+=20=20amopopr=20=3D>=20= '&<(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'3',=0A+=20=20amopopr=20=3D>=20= '&&(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'3',=0A+=20=20amopopr=20=3D>=20= '&&(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'4',=0A+=20=20amopopr=20=3D>=20= '&>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'4',=0A+=20=20amopopr=20=3D>=20= '&>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'5',=0A+=20=20amopopr=20=3D>=20= '>>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'5',=0A+=20=20amopopr=20=3D>=20= '>>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'6',=0A+=20=20amopopr=20=3D>=20= '-|-(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'6',=0A+=20=20amopopr=20=3D>=20= '-|-(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'7',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'7',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'8',=0A+=20=20amopopr=20=3D>=20= '<@(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +{=20amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>= =20'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyrange',=20= amopstrategy=20=3D>=20'8',=0A+=20=20amopopr=20=3D>=20= '<@(anymultirange,anyrange)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anyelement',=20= amopstrategy=20=3D>=20'16',=0A+=20=20amopopr=20=3D>=20= '@>(anymultirange,anyelement)',=20amopmethod=20=3D>=20'spgist'=20},=0A+{=20= amopfamily=20=3D>=20'spgist/multirange_me_ops',=20amoplefttype=20=3D>=20= 'anymultirange',=0A+=20=20amoprighttype=20=3D>=20'anymultirange',=20= amopstrategy=20=3D>=20'18',=0A+=20=20amopopr=20=3D>=20= '=3D(anymultirange,anymultirange)',=20amopmethod=20=3D>=20'spgist'=20},=0A= +=0A=20#=20SP-GiST=20box_ops=0A=20{=20amopfamily=20=3D>=20= 'spgist/box_ops',=20amoplefttype=20=3D>=20'box',=20amoprighttype=20=3D>=20= 'box',=0A=20=20=20amopstrategy=20=3D>=20'1',=20amopopr=20=3D>=20= '<<(box,box)',=20amopmethod=20=3D>=20'spgist'=20},=0Adiff=20--git=20= a/src/include/catalog/pg_amproc.dat=20= b/src/include/catalog/pg_amproc.dat=0Aindex=200bf9ea1145e..50013f293f1=20= 100644=0A---=20a/src/include/catalog/pg_amproc.dat=0A+++=20= b/src/include/catalog/pg_amproc.dat=0A@@=20-785,6=20+785,24=20@@=0A=20{=20= amprocfamily=20=3D>=20'spgist/range_ops',=20amproclefttype=20=3D>=20= 'anyrange',=0A=20=20=20amprocrighttype=20=3D>=20'anyrange',=20amprocnum=20= =3D>=20'5',=0A=20=20=20amproc=20=3D>=20'spg_range_quad_leaf_consistent'=20= },=0A+{=20amprocfamily=20=3D>=20'spgist/multirange_me_ops',=20= amproclefttype=20=3D>=20'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20= 'anymultirange',=20amprocnum=20=3D>=20'1',=0A+=20=20amproc=20=3D>=20= 'spg_multirange_me_config'=20},=0A+{=20amprocfamily=20=3D>=20= 'spgist/multirange_me_ops',=20amproclefttype=20=3D>=20'anymultirange',=0A= +=20=20amprocrighttype=20=3D>=20'anymultirange',=20amprocnum=20=3D>=20= '2',=0A+=20=20amproc=20=3D>=20'spg_range_quad_choose'=20},=0A+{=20= amprocfamily=20=3D>=20'spgist/multirange_me_ops',=20amproclefttype=20=3D>=20= 'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20'anymultirange',=20= amprocnum=20=3D>=20'3',=0A+=20=20amproc=20=3D>=20= 'spg_range_quad_picksplit'=20},=0A+{=20amprocfamily=20=3D>=20= 'spgist/multirange_me_ops',=20amproclefttype=20=3D>=20'anymultirange',=0A= +=20=20amprocrighttype=20=3D>=20'anymultirange',=20amprocnum=20=3D>=20= '4',=0A+=20=20amproc=20=3D>=20'spg_multirange_me_inner_consistent'=20},=0A= +{=20amprocfamily=20=3D>=20'spgist/multirange_me_ops',=20amproclefttype=20= =3D>=20'anymultirange',=0A+=20=20amprocrighttype=20=3D>=20= 'anymultirange',=20amprocnum=20=3D>=20'5',=0A+=20=20amproc=20=3D>=20= 'spg_multirange_me_leaf_consistent'=20},=0A+{=20amprocfamily=20=3D>=20= 'spgist/multirange_me_ops',=20amproclefttype=20=3D>=20'anymultirange',=0A= +=20=20amprocrighttype=20=3D>=20'anymultirange',=20amprocnum=20=3D>=20= '8',=0A+=20=20amproc=20=3D>=20'multirange_gist_extractvalue'=20},=0A=20{=20= amprocfamily=20=3D>=20'spgist/network_ops',=20amproclefttype=20=3D>=20= 'inet',=0A=20=20=20amprocrighttype=20=3D>=20'inet',=20amprocnum=20=3D>=20= '1',=20amproc=20=3D>=20'inet_spg_config'=20},=0A=20{=20amprocfamily=20=3D>= =20'spgist/network_ops',=20amproclefttype=20=3D>=20'inet',=0Adiff=20= --git=20a/src/include/catalog/pg_opclass.dat=20= b/src/include/catalog/pg_opclass.dat=0Aindex=2007920290013..1925150374f=20= 100644=0A---=20a/src/include/catalog/pg_opclass.dat=0A+++=20= b/src/include/catalog/pg_opclass.dat=0A@@=20-249,6=20+249,9=20@@=0A=20{=20= opcmethod=20=3D>=20'gist',=20opcname=20=3D>=20'multirange_me_ops',=0A=20=20= =20opcfamily=20=3D>=20'gist/multirange_me_ops',=20opcintype=20=3D>=20= 'anymultirange',=0A=20=20=20opckeytype=20=3D>=20'anyrange',=20opcdefault=20= =3D>=20'f'=20},=0A+{=20opcmethod=20=3D>=20'spgist',=20opcname=20=3D>=20= 'multirange_me_ops',=0A+=20=20opcfamily=20=3D>=20= 'spgist/multirange_me_ops',=20opcintype=20=3D>=20'anymultirange',=0A+=20=20= opckeytype=20=3D>=20'anyrange',=20opcdefault=20=3D>=20'f'=20},=0A=20{=20= opcmethod=20=3D>=20'spgist',=20opcname=20=3D>=20'box_ops',=20opcfamily=20= =3D>=20'spgist/box_ops',=0A=20=20=20opcintype=20=3D>=20'box'=20},=0A=20{=20= opcmethod=20=3D>=20'spgist',=20opcname=20=3D>=20'quad_point_ops',=0Adiff=20= --git=20a/src/include/catalog/pg_opfamily.dat=20= b/src/include/catalog/pg_opfamily.dat=0Aindex=2093a80175352..cc06084004c=20= 100644=0A---=20a/src/include/catalog/pg_opfamily.dat=0A+++=20= b/src/include/catalog/pg_opfamily.dat=0A@@=20-310,5=20+310,7=20@@=0A=20=20= =20opfmethod=20=3D>=20'gist',=20opfname=20=3D>=20'multirange_ops'=20},=0A= =20{=20oid=20=3D>=20'9319',=0A=20=20=20opfmethod=20=3D>=20'gist',=20= opfname=20=3D>=20'multirange_me_ops'=20},=0A+{=20oid=20=3D>=20'9323',=0A= +=20=20opfmethod=20=3D>=20'spgist',=20opfname=20=3D>=20= 'multirange_me_ops'=20},=0A=20=0A=20]=0Adiff=20--git=20= a/src/include/catalog/pg_proc.dat=20b/src/include/catalog/pg_proc.dat=0A= index=20699d8416d47..a9b7f02f5e0=20100644=0A---=20= a/src/include/catalog/pg_proc.dat=0A+++=20= b/src/include/catalog/pg_proc.dat=0A@@=20-11172,6=20+11172,17=20@@=0A=20=20= =20proname=20=3D>=20'multirange_gist_extractvalue',=20prorettype=20=3D>=20= 'internal',=0A=20=20=20proargtypes=20=3D>=20'internal=20internal=20= internal',=0A=20=20=20prosrc=20=3D>=20'multirange_gist_extractvalue'=20= },=0A+{=20oid=20=3D>=20'9320',=20descr=20=3D>=20'SP-GiST=20support=20for=20= multi-entry=20multirange',=0A+=20=20proname=20=3D>=20= 'spg_multirange_me_config',=20prorettype=20=3D>=20'void',=0A+=20=20= proargtypes=20=3D>=20'internal=20internal',=20prosrc=20=3D>=20= 'spg_multirange_me_config'=20},=0A+{=20oid=20=3D>=20'9321',=20descr=20=3D>= =20'SP-GiST=20support=20for=20multi-entry=20multirange',=0A+=20=20= proname=20=3D>=20'spg_multirange_me_inner_consistent',=20prorettype=20=3D>= =20'void',=0A+=20=20proargtypes=20=3D>=20'internal=20internal',=0A+=20=20= prosrc=20=3D>=20'spg_multirange_me_inner_consistent'=20},=0A+{=20oid=20= =3D>=20'9322',=20descr=20=3D>=20'SP-GiST=20support=20for=20multi-entry=20= multirange',=0A+=20=20proname=20=3D>=20= 'spg_multirange_me_leaf_consistent',=20prorettype=20=3D>=20'bool',=0A+=20= =20proargtypes=20=3D>=20'internal=20internal',=0A+=20=20prosrc=20=3D>=20= 'spg_multirange_me_leaf_consistent'=20},=0A=20{=20oid=20=3D>=20'3902',=20= descr=20=3D>=20'hash=20a=20range',=0A=20=20=20proname=20=3D>=20= 'hash_range',=20prorettype=20=3D>=20'int4',=20proargtypes=20=3D>=20= 'anyrange',=0A=20=20=20prosrc=20=3D>=20'hash_range'=20},=0Adiff=20--git=20= a/src/test/regress/expected/multirangetypes.out=20= b/src/test/regress/expected/multirangetypes.out=0Aindex=20= 4134f1358ed..59c843c1a7c=20100644=0A---=20= a/src/test/regress/expected/multirangetypes.out=0A+++=20= b/src/test/regress/expected/multirangetypes.out=0A@@=20-3546,6=20= +3546,673=20@@=20drop=20table=20test_me_nulls;=0A=20drop=20table=20= test_me_multicol;=0A=20drop=20table=20test_multirange_me_gist;=0A=20--=0A= +--=20Multi-entry=20SP-GiST=20index=20(multirange_me_ops)=0A+--=20= Decomposes=20multiranges=20into=20component=20ranges=20for=20quad-tree=20= indexing.=0A+--=0A+create=20table=20test_multirange_me_spgist(mr=20= int4multirange);=0A+insert=20into=20test_multirange_me_spgist=20select=20= int4multirange(int4range(g,=20g+10),int4range(g+20,=20= g+30),int4range(g+40,=20g+50))=20from=20generate_series(1,2000)=20g;=0A= +insert=20into=20test_multirange_me_spgist=20select=20= '{}'::int4multirange=20from=20generate_series(1,500)=20g;=0A+insert=20= into=20test_multirange_me_spgist=20select=20int4multirange(int4range(g,=20= g+10000))=20from=20generate_series(1,1000)=20g;=0A+insert=20into=20= test_multirange_me_spgist=20select=20int4multirange(int4range(NULL,=20= g*10,=20'(]'),=20int4range(g*10,=20g*20,=20'(]'))=20from=20= generate_series(1,100)=20g;=0A+insert=20into=20test_multirange_me_spgist=20= select=20int4multirange(int4range(g*10,=20g*20,=20'(]'),=20= int4range(g*20,=20NULL,=20'(]'))=20from=20generate_series(1,100)=20g;=0A= +create=20index=20test_multirange_me_spgist_idx=20on=20= test_multirange_me_spgist=20using=20spgist=20(mr=20multirange_me_ops);=0A= +--=20first,=20verify=20non-indexed=20results=0A+SET=20enable_seqscan=20=20= =20=20=3D=20t;=0A+SET=20enable_indexscan=20=20=3D=20f;=0A+SET=20= enable_bitmapscan=20=3D=20f;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=203700=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= &&=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20<@=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20&<=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20@>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20&&=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20>>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20-|-=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20= =20=20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20now=20check=20same=20= queries=20using=20index=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A= +SET=20enable_indexscan=20=20=3D=20t;=0A+SET=20enable_bitmapscan=20=3D=20= f;=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= =3D=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20@>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= 3700=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&&=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<@=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20<<=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20&>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=203700=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20&&=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20= =200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20>>=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20-|-=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20= =20=20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20also=20check=20= bitmap=20scan=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20= enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20t;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20=3D=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20500=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20@>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=203700=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20&&=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20500=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20>>=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'empty'::int4range;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= 'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20-|-=20'empty'::int4range;=0A+=20count=20=0A+-------=0A+=20=20=20=20=20= 0=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=203700=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20<@=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20&<=20'{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20= =20=20=200=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20'{}'::int4multirange;=0A+=20= count=20=0A+-------=0A+=20=20=20=20=200=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= '{}'::int4multirange;=0A+=20count=20=0A+-------=0A+=20=20=20=20=200=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20=3D=20int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+=20count=20=0A+-------=0A+=20=20=20=20=201=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20@>=2010;=0A+=20count=20=0A+-------=0A+=20=20=20120=0A+(1=20row)=0A+=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20111=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= &&=20int4range(10,20);=0A+=20count=20=0A+-------=0A+=20=20=20139=0A+(1=20= row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20<@=20int4range(10,50);=0A+=20count=20=0A+-------=0A+=20=20=20500=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20<<=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20= =20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A+=20= count=20=0A+-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20&<=20int4range(100,500);=0A= +=20count=20=0A+-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=202893=0A+(1=20row)=0A= +=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20= -|-=20int4range(100,500);=0A+=20count=20=0A+-------=0A+=20=20=20=20=203=0A= +(1=20row)=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20= where=20mr=20@>=20int4multirange(int4range(10,20),=20int4range(30,40));=0A= +=20count=20=0A+-------=0A+=20=20=20110=0A+(1=20row)=0A+=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20218=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+=20count=20=0A+-------=0A= +=20=20=20500=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=2054=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202053=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20474=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=202893=0A+(1=20row)=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=20count=20=0A= +-------=0A+=20=20=20=20=203=0A+(1=20row)=0A+=0A+--=20test=20NULL=20= handling=0A+create=20table=20test_me_spgist_nulls(mr=20int4multirange);=0A= +insert=20into=20test_me_spgist_nulls=20values=20(NULL),=20= ('{}'::int4multirange),=20('{[1,3]}');=0A+create=20index=20on=20= test_me_spgist_nulls=20using=20spgist=20(mr=20multirange_me_ops);=0A+SET=20= enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20enable_indexscan=20=20=3D=20= t;=0A+select=20*=20from=20test_me_spgist_nulls=20where=20mr=20@>=201;=0A= +=20=20=20mr=20=20=20=20=0A+---------=0A+=20{[1,4)}=0A+(1=20row)=0A+=0A= +drop=20table=20test_me_spgist_nulls;=0A+drop=20table=20= test_multirange_me_spgist;=0A+--=0A=20--=20range_agg=20function=0A=20--=0A= =20create=20table=20reservations=20(=20room_id=20integer=20not=20null,=20= booked_during=20daterange=20);=0Adiff=20--git=20= a/src/test/regress/expected/psql.out=20= b/src/test/regress/expected/psql.out=0Aindex=20c8f3932edf0..3262d7f3b63=20= 100644=0A---=20a/src/test/regress/expected/psql.out=0A+++=20= b/src/test/regress/expected/psql.out=0A@@=20-5262,17=20+5262,18=20@@=20= List=20of=20access=20methods=0A=20(3=20rows)=0A=20=0A=20\dAf=20spgist=0A= -=20=20=20=20=20=20=20=20=20=20List=20of=20operator=20families=0A-=20=20=20= AM=20=20=20|=20Operator=20family=20|=20Applicable=20types=20=0A= ---------+-----------------+------------------=0A-=20spgist=20|=20= box_ops=20=20=20=20=20=20=20=20=20|=20box=0A-=20spgist=20|=20= kd_point_ops=20=20=20=20|=20point=0A-=20spgist=20|=20network_ops=20=20=20= =20=20|=20inet=0A-=20spgist=20|=20poly_ops=20=20=20=20=20=20=20=20|=20= polygon=0A-=20spgist=20|=20quad_point_ops=20=20|=20point=0A-=20spgist=20= |=20range_ops=20=20=20=20=20=20=20|=20anyrange=0A-=20spgist=20|=20= text_ops=20=20=20=20=20=20=20=20|=20text=0A-(7=20rows)=0A+=20=20=20=20=20= =20=20=20=20=20=20List=20of=20operator=20families=0A+=20=20=20AM=20=20=20= |=20=20Operator=20family=20=20|=20Applicable=20types=20=0A= +--------+-------------------+------------------=0A+=20spgist=20|=20= box_ops=20=20=20=20=20=20=20=20=20=20=20|=20box=0A+=20spgist=20|=20= kd_point_ops=20=20=20=20=20=20|=20point=0A+=20spgist=20|=20= multirange_me_ops=20|=20anymultirange=0A+=20spgist=20|=20network_ops=20=20= =20=20=20=20=20|=20inet=0A+=20spgist=20|=20poly_ops=20=20=20=20=20=20=20=20= =20=20|=20polygon=0A+=20spgist=20|=20quad_point_ops=20=20=20=20|=20point=0A= +=20spgist=20|=20range_ops=20=20=20=20=20=20=20=20=20|=20anyrange=0A+=20= spgist=20|=20text_ops=20=20=20=20=20=20=20=20=20=20|=20text=0A+(8=20= rows)=0A=20=0A=20\dAf=20btree=20int4=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20List=20of=20operator=20families=0Adiff=20--git=20= a/src/test/regress/sql/multirangetypes.sql=20= b/src/test/regress/sql/multirangetypes.sql=0Aindex=20= 902d719d75c..10839646983=20100644=0A---=20= a/src/test/regress/sql/multirangetypes.sql=0A+++=20= b/src/test/regress/sql/multirangetypes.sql=0A@@=20-712,6=20+712,155=20@@=20= drop=20table=20test_me_nulls;=0A=20drop=20table=20test_me_multicol;=0A=20= drop=20table=20test_multirange_me_gist;=0A=20=0A+--=0A+--=20Multi-entry=20= SP-GiST=20index=20(multirange_me_ops)=0A+--=20Decomposes=20multiranges=20= into=20component=20ranges=20for=20quad-tree=20indexing.=0A+--=0A+create=20= table=20test_multirange_me_spgist(mr=20int4multirange);=0A+insert=20into=20= test_multirange_me_spgist=20select=20int4multirange(int4range(g,=20= g+10),int4range(g+20,=20g+30),int4range(g+40,=20g+50))=20from=20= generate_series(1,2000)=20g;=0A+insert=20into=20= test_multirange_me_spgist=20select=20'{}'::int4multirange=20from=20= generate_series(1,500)=20g;=0A+insert=20into=20test_multirange_me_spgist=20= select=20int4multirange(int4range(g,=20g+10000))=20from=20= generate_series(1,1000)=20g;=0A+insert=20into=20= test_multirange_me_spgist=20select=20int4multirange(int4range(NULL,=20= g*10,=20'(]'),=20int4range(g*10,=20g*20,=20'(]'))=20from=20= generate_series(1,100)=20g;=0A+insert=20into=20test_multirange_me_spgist=20= select=20int4multirange(int4range(g*10,=20g*20,=20'(]'),=20= int4range(g*20,=20NULL,=20'(]'))=20from=20generate_series(1,100)=20g;=0A= +create=20index=20test_multirange_me_spgist_idx=20on=20= test_multirange_me_spgist=20using=20spgist=20(mr=20multirange_me_ops);=0A= +=0A+--=20first,=20verify=20non-indexed=20results=0A+SET=20= enable_seqscan=20=20=20=20=3D=20t;=0A+SET=20enable_indexscan=20=20=3D=20= f;=0A+SET=20enable_bitmapscan=20=3D=20f;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&&=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<@=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&&=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<@=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20'{}'::int4multirange;=0A+=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=2010;=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20@>=20int4range(10,20);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20int4range(10,50);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= now=20check=20same=20queries=20using=20index=0A+SET=20enable_seqscan=20=20= =20=20=3D=20f;=0A+SET=20enable_indexscan=20=20=3D=20t;=0A+SET=20= enable_bitmapscan=20=3D=20f;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&&=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<@=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20@>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&&=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<@=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&<=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20-|-=20'{}'::int4multirange;=0A+=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=2010;=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20@>=20int4range(10,20);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20int4range(10,50);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= also=20check=20bitmap=20scan=0A+SET=20enable_seqscan=20=20=20=20=3D=20f;=0A= +SET=20enable_indexscan=20=20=3D=20f;=0A+SET=20enable_bitmapscan=20=3D=20= t;=0A+=0A+select=20count(*)=20from=20test_multirange_me_spgist=20where=20= mr=20=3D=20'{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20'empty'::int4range;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= 'empty'::int4range;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= '{}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20'{}'::int4multirange;=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= '{}'::int4multirange;=0A+=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20=3D=20= int4multirange(int4range(10,20),=20int4range(30,40),=20= int4range(50,60));=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=2010;=0A+select=20count(*)=20= from=20test_multirange_me_spgist=20where=20mr=20@>=20int4range(10,20);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= int4range(10,20);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20int4range(10,50);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20<<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20>>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20&>=20int4range(100,500);=0A= +select=20count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4range(100,500);=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20@>=20= int4multirange(int4range(10,20),=20int4range(30,40));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&&=20= '{(10,20),(30,40),(50,60)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<@=20= '{(10,30),(40,60),(70,90)}'::int4multirange;=0A+select=20count(*)=20from=20= test_multirange_me_spgist=20where=20mr=20<<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20>>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&<=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20&>=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+select=20= count(*)=20from=20test_multirange_me_spgist=20where=20mr=20-|-=20= int4multirange(int4range(100,200),=20int4range(400,500));=0A+=0A+--=20= test=20NULL=20handling=0A+create=20table=20test_me_spgist_nulls(mr=20= int4multirange);=0A+insert=20into=20test_me_spgist_nulls=20values=20= (NULL),=20('{}'::int4multirange),=20('{[1,3]}');=0A+create=20index=20on=20= test_me_spgist_nulls=20using=20spgist=20(mr=20multirange_me_ops);=0A+SET=20= enable_seqscan=20=20=20=20=3D=20f;=0A+SET=20enable_indexscan=20=20=3D=20= t;=0A+select=20*=20from=20test_me_spgist_nulls=20where=20mr=20@>=201;=0A= +=0A+drop=20table=20test_me_spgist_nulls;=0A+drop=20table=20= test_multirange_me_spgist;=0A+=0A=20--=0A=20--=20range_agg=20function=0A=20= --=0A--=20=0A2.50.1=20(Apple=20Git-155)=0A=0A= --Apple-Mail=_EA2026AB-E43A-43B7-AB63-CE447CD7F841--