Make `wildspeed` a modern Postgres extension.
[wildspeed.git] / wildspeed.c
index 389dff8..2090e04 100644 (file)
@@ -133,14 +133,9 @@ gin_extract_permuted(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(entries);
 }
 
-PG_FUNCTION_INFO_V1(wildcmp);
-Datum       wildcmp(PG_FUNCTION_ARGS);
-Datum
-wildcmp(PG_FUNCTION_ARGS)
+static int 
+wildcmp_internal(text *a, text *b, bool partialMatch)
 {
-       text    *a = PG_GETARG_TEXT_P(0);
-       text    *b = PG_GETARG_TEXT_P(1);
-       bool    partialMatch = PG_GETARG_BOOL(2);
        int32   cmp;
        int             lena,
                        lenb;
@@ -244,6 +239,39 @@ wildcmp(PG_FUNCTION_ARGS)
                }
        }
 
+       return cmp;
+}
+
+PG_FUNCTION_INFO_V1(wildcmp);
+Datum       wildcmp(PG_FUNCTION_ARGS);
+Datum
+wildcmp(PG_FUNCTION_ARGS)
+{
+       text    *a = PG_GETARG_TEXT_P(0);
+       text    *b = PG_GETARG_TEXT_P(1);
+       int32   cmp;
+
+       cmp = wildcmp_internal(a, b, false);
+
+       PG_FREE_IF_COPY(a,0);
+       PG_FREE_IF_COPY(b,1);
+       PG_RETURN_INT32( cmp ); 
+}
+
+PG_FUNCTION_INFO_V1(wildcmp_prefix);
+Datum       wildcmp_prefix(PG_FUNCTION_ARGS);
+Datum
+wildcmp_prefix(PG_FUNCTION_ARGS)
+{
+       text    *a = PG_GETARG_TEXT_P(0);
+       text    *b = PG_GETARG_TEXT_P(1);
+#ifdef NOT_USED
+       StrategyNumber  strategy = PG_GETARG_UINT16(2);
+#endif
+       int32   cmp;
+
+       cmp = wildcmp_internal(a, b, true);
+
        PG_FREE_IF_COPY(a,0);
        PG_FREE_IF_COPY(b,1);
        PG_RETURN_INT32( cmp ); 
@@ -356,6 +384,7 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
 #endif
        bool                    *partialmatch, 
                                        **ptr_partialmatch = (bool**) PG_GETARG_POINTER(3);
+       Pointer                 **extra = (Pointer**)PG_GETARG_POINTER(4);
        Datum                   *entries = NULL;
        char                    *qptr = VARDATA(q);
        int                             clen,
@@ -363,6 +392,7 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
                                        i;
        WildItem                *items;
        text                    *entry;
+       bool                    needRecheck = false;
 
        *nentries = 0;
 
@@ -454,6 +484,9 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
                                entries[ *nentries ] =  PointerGetDatum( entry );
                                (*nentries)++;
                        }
+
+                       if ( splitqlen > 3 /* X1 may be inside X OR Y */ )
+                               needRecheck = true;
                }
                else
                {
@@ -476,6 +509,8 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
                                entries[ *nentries ] =  PointerGetDatum( entry );
                                (*nentries)++;
                        }
+                       if ( splitqlen > 2 /* we don't remeber an order of Xn */ )
+                               needRecheck = true;
                }
        } 
        else
@@ -510,6 +545,8 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
                                entries[ *nentries ] =  PointerGetDatum( entry );
                                (*nentries)++;
                        }
+                       if ( splitqlen > 2 /* X1 may be inside X */ )
+                               needRecheck = true;
                }
                else
                {
@@ -534,6 +571,9 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
                                partialmatch[ *nentries ] = true;
                                entries[ *nentries ] =  PointerGetDatum( entry );
                                (*nentries)++;
+
+                       if ( splitqlen > 3 /* we don't remeber an order of Xn */ )
+                               needRecheck = true;
                        }
                }
        }
@@ -542,9 +582,25 @@ gin_extract_wildcard(PG_FUNCTION_ARGS)
 
 #ifdef OPTIMIZE_WILDCARD_QUERY
        if ( *nentries > 1 )
+       {
+               int saven = *nentries;
+
                optimize_wildcard_search( entries, nentries );
+
+               if ( saven != *nentries )
+                       needRecheck = true;
+       }
 #endif
 
+       if (needRecheck)
+       {
+               /*
+                * Non empty extra signals to consistentFn about
+                * rechecking of result
+                */
+               *extra = palloc0(sizeof(Pointer) * *nentries);
+       }
+
        PG_RETURN_POINTER(entries);
 }
 
@@ -555,37 +611,22 @@ Datum
 gin_consistent_wildcard(PG_FUNCTION_ARGS)
 {
        bool            *check = (bool *) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       StrategyNumber strategy = PG_GETARG_UINT16(1);
+       text            *query = PG_GETARG_TEXT_P(2);
+#endif
+       int                     nentries = PG_GETARG_INT32(3);
+       Pointer         *extra = (Pointer *) PG_GETARG_POINTER(4);
+       bool        *recheck = (bool *) PG_GETARG_POINTER(5);
        bool        res = true;
        int         i;
-       int32           nentries;
-
-       if ( fcinfo->flinfo->fn_extra == NULL )
-       {
-               bool    *pmatch;
-
-               /*
-                * we need to get nentries, we'll get it by regular way
-                * and store it in function context
-                */
-
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                               sizeof(int32));
-
-               DirectFunctionCall4(
-                                       gin_extract_wildcard,
-                                       PG_GETARG_DATUM(2),  /* query */
-                                       PointerGetDatum( fcinfo->flinfo->fn_extra ), /* &nentries */
-                                       PG_GETARG_DATUM(1),  /* strategy */
-                                       PointerGetDatum( &pmatch )
-               );
-       }
-
-       nentries = *(int32*) fcinfo->flinfo->fn_extra;
 
        for (i = 0; res && i < nentries; i++)
                if (check[i] == false)
                        res = false;
 
+       *recheck = (extra == NULL) ? false : true;
+
        PG_RETURN_BOOL(res);
 }