@@ -6281,14 +6281,14 @@ gincostestimate(PG_FUNCTION_ARGS)
62816281Selectivity * indexSelectivity = (Selectivity * )PG_GETARG_POINTER (7 );
62826282double * indexCorrelation = (double * )PG_GETARG_POINTER (8 );
62836283ListCell * l ;
6284- int32 nfullscan = 0 ;
62856284List * selectivityQuals ;
62866285double numPages = index -> pages ,
62876286numTuples = index -> tuples ;
62886287double numEntryPages ,
62896288numDataPages ,
62906289numPendingPages ,
62916290numEntries ;
6291+ bool haveFullScan = false;
62926292double partialEntriesInQuals = 0.0 ;
62936293double searchEntriesInQuals = 0.0 ;
62946294double exactEntriesInQuals = 0.0 ;
@@ -6394,6 +6394,8 @@ gincostestimate(PG_FUNCTION_ARGS)
63946394int32 nentries = 0 ;
63956395bool * partial_matches = NULL ;
63966396Pointer * extra_data = NULL ;
6397+ bool * nullFlags = NULL ;
6398+ int32 searchMode = GIN_SEARCH_MODE_DEFAULT ;
63976399int indexcol ;
63986400
63996401Assert (IsA (rinfo ,RestrictInfo ));
@@ -6414,7 +6416,7 @@ gincostestimate(PG_FUNCTION_ARGS)
64146416}
64156417else
64166418{
6417- elog (ERROR ,"Could not match index to operand" );
6419+ elog (ERROR ,"could not match index to operand" );
64186420operand = NULL ;/* keep compiler quiet */
64196421}
64206422
@@ -6443,50 +6445,51 @@ gincostestimate(PG_FUNCTION_ARGS)
64436445
64446446/*
64456447 * Get the operator's strategy number and declared input data types
6446- * within the index opfamily.
6448+ * within the index opfamily. (We don't need the latter, but we
6449+ * use get_op_opfamily_properties because it will throw error if
6450+ * it fails to find a matching pg_amop entry.)
64476451 */
64486452get_op_opfamily_properties (clause_op ,index -> opfamily [indexcol ], false,
64496453& strategy_op ,& lefttype ,& righttype );
64506454
64516455/*
6452- * GIN (like GiST) always has lefttype == righttype in pg_amproc
6453- * and they are equal to type Oid on which index was created/designed
6456+ * GIN always uses the "default" support functions, which are those
6457+ * with lefttype == righttype == the opclass' opcintype (see
6458+ * IndexSupportInitialize in relcache.c).
64546459 */
64556460extractProcOid = get_opfamily_proc (index -> opfamily [indexcol ],
6456- lefttype ,lefttype ,
6461+ index -> opcintype [indexcol ],
6462+ index -> opcintype [indexcol ],
64576463GIN_EXTRACTQUERY_PROC );
64586464
64596465if (!OidIsValid (extractProcOid ))
64606466{
6461- /* probably shouldn't happen, but cope sanely if so */
6462- searchEntriesInQuals ++ ;
6463- continue ;
6467+ /* should not happen; throw same error as index_getprocinfo */
6468+ elog (ERROR ,"missing support function %d for attribute %d of index \"%s\"" ,
6469+ GIN_EXTRACTQUERY_PROC ,indexcol + 1 ,
6470+ get_rel_name (index -> indexoid ));
64646471}
64656472
6466- OidFunctionCall5 (extractProcOid ,
6467- ((Const * )operand )-> constvalue ,
6473+ OidFunctionCall7 (extractProcOid ,
6474+ ((Const * )operand )-> constvalue ,
64686475PointerGetDatum (& nentries ),
64696476UInt16GetDatum (strategy_op ),
64706477PointerGetDatum (& partial_matches ),
6471- PointerGetDatum (& extra_data ));
6478+ PointerGetDatum (& extra_data ),
6479+ PointerGetDatum (& nullFlags ),
6480+ PointerGetDatum (& searchMode ));
64726481
6473- if (nentries == 0 )
6474- {
6475- nfullscan ++ ;
6476- }
6477- else if (nentries < 0 )
6482+ if (nentries <=0 && searchMode == GIN_SEARCH_MODE_DEFAULT )
64786483{
6479- /*
6480- * GIN_EXTRACTQUERY_PROC guarantees that nothing will be found
6481- */
6484+ /* No match is possible */
64826485* indexStartupCost = 0 ;
64836486* indexTotalCost = 0 ;
64846487* indexSelectivity = 0 ;
64856488PG_RETURN_VOID ();
64866489}
64876490else
64886491{
6489- int i ;
6492+ int32 i ;
64906493
64916494for (i = 0 ;i < nentries ;i ++ )
64926495{
@@ -6503,10 +6506,28 @@ gincostestimate(PG_FUNCTION_ARGS)
65036506searchEntriesInQuals ++ ;
65046507}
65056508}
6509+
6510+ if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY )
6511+ {
6512+ /* Treat "include empty" like an exact-match item */
6513+ exactEntriesInQuals ++ ;
6514+ searchEntriesInQuals ++ ;
6515+ }
6516+ else if (searchMode != GIN_SEARCH_MODE_DEFAULT )
6517+ {
6518+ /* It's GIN_SEARCH_MODE_ALL */
6519+ haveFullScan = true;
6520+ }
65066521}
65076522
6508- if (nfullscan == list_length (indexQuals ))
6523+ if (haveFullScan || indexQuals == NIL )
6524+ {
6525+ /*
6526+ * Full index scan will be required. We treat this as if every key in
6527+ * the index had been listed in the query; is that reasonable?
6528+ */
65096529searchEntriesInQuals = numEntries ;
6530+ }
65106531
65116532/* Will we have more than one iteration of a nestloop scan? */
65126533if (outer_rel != NULL && outer_rel -> rows > 1 )