From: Alexander Korotkov Date: Tue, 18 Mar 2014 09:44:38 +0000 (+0400) Subject: Implementation of gin triconsistent functions. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=a0d889152880e7160cd85d2eca6a2fd8bd0cb0a8;p=users%2Fandresfreund%2Fpostgres.git Implementation of gin triconsistent functions. --- diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c index 77f7b77b1c..45796a4caf 100644 --- a/src/backend/utils/adt/jsonb_gin.c +++ b/src/backend/utils/adt/jsonb_gin.c @@ -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 diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index 04edd985eb..b28dd563a8 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -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 )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 610f0a141e..56f0f11ebe 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -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_ ));