Implementation of gin triconsistent functions.
authorAlexander Korotkov <[email protected]>
Tue, 18 Mar 2014 09:44:38 +0000 (13:44 +0400)
committerAlexander Korotkov <[email protected]>
Tue, 18 Mar 2014 09:44:38 +0000 (13:44 +0400)
src/backend/utils/adt/jsonb_gin.c
src/include/catalog/pg_amproc.h
src/include/catalog/pg_proc.h

index 77f7b77b1ce7f534b83b3dd0eece9645f1572759..45796a4cafd1e0729692b8996780c6f5c99fca18 100644 (file)
@@ -255,6 +255,91 @@ gin_consistent_jsonb(PG_FUNCTION_ARGS)
    PG_RETURN_BOOL(res);
 }
 
+Datum
+gin_triconsistent_jsonb(PG_FUNCTION_ARGS)
+{
+   GinLogicValue   *check = (GinLogicValue *) PG_GETARG_POINTER(0);
+   StrategyNumber strategy = PG_GETARG_UINT16(1);
+
+   /* Jsonb       *query = PG_GETARG_JSONB(2); */
+   int32       nkeys = PG_GETARG_INT32(3);
+
+   /* Pointer     *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+   GinLogicValue   res = GIN_TRUE;
+
+   int32       i;
+
+   if (strategy == JsonbContainsStrategyNumber)
+   {
+       bool    has_maybe = false;
+
+       /*
+        * All extracted keys must be present. Combination of GIN_MAYBE and
+        * GIN_TRUE gives GIN_MAYBE result because all keys may be present in
+        * this situation.
+        */
+       for (i = 0; i < nkeys; i++)
+       {
+           if (check[i] == GIN_FALSE)
+           {
+               res = GIN_FALSE;
+               break;
+           }
+           if (check[i] == GIN_MAYBE)
+           {
+               res = GIN_MAYBE;
+               has_maybe = true;
+           }
+       }
+       /*
+        * Index doesn't have information about correspondence of Jsonb keys
+        * and values (as distinct from GIN keys, which both are stored as). So
+        * invariably we recheck. In thiconsistent function we reflect it as
+        * GIN_MAYBE in response to no GIN_MAYBE at input.
+        */
+       if (!has_maybe && res == GIN_TRUE)
+           res = GIN_MAYBE;
+   }
+   else if (strategy == JsonbExistsStrategyNumber ||
+            strategy == JsonbExistsAnyStrategyNumber)
+   {
+       /* Existence of key guaranteed in default search mode */
+       res = GIN_FALSE;
+       for (i = 0; i < nkeys; i++)
+       {
+           if (check[i] == GIN_TRUE)
+           {
+               res = GIN_TRUE;
+               break;
+           }
+           if (check[i] == GIN_MAYBE)
+           {
+               res = GIN_MAYBE;
+           }
+       }
+   }
+   else if (strategy == JsonbExistsAllStrategyNumber)
+   {
+       /* Testing for the presence of all keys gives an exact result */
+       for (i = 0; i < nkeys; i++)
+       {
+           if (check[i] == GIN_FALSE)
+           {
+               res = GIN_FALSE;
+               break;
+           }
+           if (check[i] == GIN_MAYBE)
+           {
+               res = GIN_MAYBE;
+           }
+       }
+   }
+   else
+       elog(ERROR, "unrecognized strategy number: %d", strategy);
+
+   PG_RETURN_BOOL(res);
+}
+
 /*
  *
  * jsonb_hash_ops GIN opclass support functions
@@ -296,7 +381,58 @@ gin_consistent_jsonb_hash(PG_FUNCTION_ARGS)
    else
        elog(ERROR, "unrecognized strategy number: %d", strategy);
 
-   PG_RETURN_BOOL(res);
+   PG_RETURN_GIN_LOGIC_VALUE(res);
+}
+
+Datum
+gin_triconsistent_jsonb_hash(PG_FUNCTION_ARGS)
+{
+   GinLogicValue   *check = (GinLogicValue *) PG_GETARG_POINTER(0);
+   StrategyNumber strategy = PG_GETARG_UINT16(1);
+
+   /* Jsonb       *query = PG_GETARG_JSONB(2); */
+   int32       nkeys = PG_GETARG_INT32(3);
+
+   /* Pointer     *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+   GinLogicValue   res = GIN_TRUE;
+
+   int32       i;
+
+   if (strategy == JsonbContainsStrategyNumber)
+   {
+       bool    has_maybe = false;
+
+       /*
+        * All extracted keys must be present. Combination of GIN_MAYBE and
+        * GIN_TRUE gives GIN_MAYBE result because all keys may be present in
+        * this situation.
+        */
+       for (i = 0; i < nkeys; i++)
+       {
+           if (check[i] == GIN_FALSE)
+           {
+               res = GIN_FALSE;
+               break;
+           }
+           if (check[i] == GIN_MAYBE)
+           {
+               res = GIN_MAYBE;
+               has_maybe = true;
+           }
+       }
+       /*
+        * Index doesn't have information about correspondence of Jsonb keys
+        * and values (as distinct from GIN keys, which both are stored as). So
+        * invariably we recheck. In thiconsistent function we reflect it as
+        * GIN_MAYBE in response to no GIN_MAYBE at input.
+        */
+       if (!has_maybe && res == GIN_TRUE)
+           res = GIN_MAYBE;
+   }
+   else
+       elog(ERROR, "unrecognized strategy number: %d", strategy);
+
+   PG_RETURN_GIN_LOGIC_VALUE(res);
 }
 
 Datum
index 04edd985ebda7a07c9b1ec5a2b1b8e8baa0a2842..b28dd563a8c9f0de05a309621f41adb583551c42 100644 (file)
@@ -393,10 +393,12 @@ DATA(insert ( 4036   3802 3802 1 3480 ));
 DATA(insert (  4036   3802 3802 2 3482 ));
 DATA(insert (  4036   3802 3802 3 3483 ));
 DATA(insert (  4036   3802 3802 4 3484 ));
+DATA(insert (  4036   3802 3802 6 3488 ));
 DATA(insert (  4037   3802 3802 1 351 ));
 DATA(insert (  4037   3802 3802 2 3485 ));
 DATA(insert (  4037   3802 3802 3 3486 ));
 DATA(insert (  4037   3802 3802 4 3487 ));
+DATA(insert (  4037   3802 3802 6 3489 ));
 
 /* sp-gist */
 DATA(insert (  3474   3831 3831 1 3469 ));
index 610f0a141ed1238086c256aedced7de90a6da59a..56f0f11ebe27d1826b0db6c518e789c37fa85ac9 100644 (file)
@@ -4576,12 +4576,16 @@ DATA(insert OID = 3483 (  gin_extract_jsonb_query  PGNSP PGUID 12 1 0 0 0 f f f
 DESCR("GIN support");
 DATA(insert OID = 3484 (  gin_consistent_jsonb PGNSP PGUID 12 1 0 0 0 f f f f t f i 8 0 16 "2281 21 2277 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ gin_consistent_jsonb _null_ _null_ _null_ ));
 DESCR("GIN support");
+DATA(insert OID = 3488 (  gin_triconsistent_jsonb  PGNSP PGUID 12 1 0 0 0 f f f f t f i 7 0 16 "2281 21 2277 23 2281 2281 2281" _null_ _null_ _null_ _null_ gin_triconsistent_jsonb _null_ _null_ _null_ ));
+DESCR("GIN support");
 DATA(insert OID = 3485 (  gin_extract_jsonb_hash  PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ gin_extract_jsonb_hash _null_ _null_ _null_ ));
 DESCR("GIN support");
 DATA(insert OID = 3486 (  gin_extract_jsonb_query_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i 7 0 2281 "2277 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ gin_extract_jsonb_query_hash _null_ _null_ _null_ ));
 DESCR("GIN support");
 DATA(insert OID = 3487 (  gin_consistent_jsonb_hash  PGNSP PGUID 12 1 0 0 0 f f f f t f i 8 0 16 "2281 21 2277 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ gin_consistent_jsonb_hash _null_ _null_ _null_ ));
 DESCR("GIN support");
+DATA(insert OID = 3489 (  gin_triconsistent_jsonb_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i 7 0 16 "2281 21 2277 23 2281 2281 2281" _null_ _null_ _null_ _null_ gin_triconsistent_jsonb_hash _null_ _null_ _null_ ));
+DESCR("GIN support");
 
 /* txid */
 DATA(insert OID = 2939 (  txid_snapshot_in         PGNSP PGUID 12 1  0 0 0 f f f f t f i 1 0 2970 "2275" _null_ _null_ _null_ _null_ txid_snapshot_in _null_ _null_ _null_ ));