Commit 1c1791e0 authored by Teodor Sigaev's avatar Teodor Sigaev

Add json(b)_to_tsvector function

Jsonb has a complex nature so there isn't best-for-everything way to convert it
to tsvector for full text search. Current to_tsvector(json(b)) suggests to
convert only string values, but it's possible to index keys, numerics and even
booleans value. To solve that json(b)_to_tsvector has a second required
argument contained a list of desired types of json fields. Second argument is
a jsonb scalar or array right now with possibility to add new options in a
future.

Bump catalog version

Author: Dmitry Dolgov with some editorization by me
Reviewed by: Teodor Sigaev
Discussion: https://www.postgresql.org/message-id/CA+q6zcXJQbS1b4kJ_HeAOoOc=unfnOrUEL=KGgE32QKDww7d8g@mail.gmail.com
parent 529ab7bd
...@@ -9727,6 +9727,26 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple ...@@ -9727,6 +9727,26 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
<entry><literal>to_tsvector('english', '{"a": "The Fat Rats"}'::json)</literal></entry> <entry><literal>to_tsvector('english', '{"a": "The Fat Rats"}'::json)</literal></entry>
<entry><literal>'fat':2 'rat':3</literal></entry> <entry><literal>'fat':2 'rat':3</literal></entry>
</row> </row>
<row>
<entry>
<literal><function>json(b)_to_tsvector(<optional> <replaceable class="parameter">config</replaceable> <type>regconfig</type>,
</optional> <replaceable class="parameter">document</replaceable> <type>json(b)</type>,
<replaceable class="parameter">filter</replaceable> <type>json(b)</type>)</function></literal>
</entry>
<entry><type>tsvector</type></entry>
<entry>
reduce each value in the document, specified by <replaceable class="parameter">filter</replaceable> to a <type>tsvector</type>,
and then concatenate those in document order to produce a single <type>tsvector</type>.
<replaceable class="parameter">filter</replaceable> is a jsonb array, that enumerates what kind of elements need to be included
into the resulting <type>tsvector</type>. Possible values for <replaceable class="parameter">filter</replaceable> are
<literal>"string"</literal> (to include all string values), <literal>"numeric"</literal> (to include all numeric values in the string format),
<literal>"boolean"</literal> (to include all boolean values in the string format "true"/"false"),
<literal>"key"</literal> (to include all keys) or <literal>"all"</literal> (to include all above). These values
can be combined together to include, e.g. all string and numeric values.
</entry>
<entry><literal>json_to_tsvector('english', '{"a": "The Fat Rats", "b": 123}'::json, '["string", "numeric"]')</literal></entry>
<entry><literal>'123':5 'fat':2 'rat':3</literal></entry>
</row>
<row> <row>
<entry> <entry>
<indexterm> <indexterm>
......
...@@ -267,12 +267,12 @@ to_tsvector(PG_FUNCTION_ARGS) ...@@ -267,12 +267,12 @@ to_tsvector(PG_FUNCTION_ARGS)
PointerGetDatum(in))); PointerGetDatum(in)));
} }
Datum /*
jsonb_to_tsvector_byid(PG_FUNCTION_ARGS) * Worker function for jsonb(_string)_to_tsvector(_byid)
*/
static TSVector
jsonb_to_tsvector_worker(Oid cfgId, Jsonb *jb, uint32 flags)
{ {
Oid cfgId = PG_GETARG_OID(0);
Jsonb *jb = PG_GETARG_JSONB_P(1);
TSVector result;
TSVectorBuildState state; TSVectorBuildState state;
ParsedText prs; ParsedText prs;
...@@ -281,33 +281,77 @@ jsonb_to_tsvector_byid(PG_FUNCTION_ARGS) ...@@ -281,33 +281,77 @@ jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
state.prs = &prs; state.prs = &prs;
state.cfgId = cfgId; state.cfgId = cfgId;
iterate_jsonb_string_values(jb, &state, add_to_tsvector); iterate_jsonb_values(jb, flags, &state, add_to_tsvector);
PG_FREE_IF_COPY(jb, 1); return make_tsvector(&prs);
}
Datum
jsonb_string_to_tsvector_byid(PG_FUNCTION_ARGS)
{
Oid cfgId = PG_GETARG_OID(0);
Jsonb *jb = PG_GETARG_JSONB_P(1);
TSVector result;
result = make_tsvector(&prs); result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
PG_FREE_IF_COPY(jb, 1);
PG_RETURN_TSVECTOR(result); PG_RETURN_TSVECTOR(result);
} }
Datum Datum
jsonb_to_tsvector(PG_FUNCTION_ARGS) jsonb_string_to_tsvector(PG_FUNCTION_ARGS)
{ {
Jsonb *jb = PG_GETARG_JSONB_P(0); Jsonb *jb = PG_GETARG_JSONB_P(0);
Oid cfgId; Oid cfgId;
TSVector result;
cfgId = getTSCurrentConfig(true); cfgId = getTSCurrentConfig(true);
PG_RETURN_DATUM(DirectFunctionCall2(jsonb_to_tsvector_byid, result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
ObjectIdGetDatum(cfgId), PG_FREE_IF_COPY(jb, 0);
JsonbPGetDatum(jb)));
PG_RETURN_TSVECTOR(result);
} }
Datum Datum
json_to_tsvector_byid(PG_FUNCTION_ARGS) jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
{ {
Oid cfgId = PG_GETARG_OID(0); Oid cfgId = PG_GETARG_OID(0);
text *json = PG_GETARG_TEXT_P(1); Jsonb *jb = PG_GETARG_JSONB_P(1);
Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
TSVector result;
uint32 flags = parse_jsonb_index_flags(jbFlags);
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
PG_FREE_IF_COPY(jb, 1);
PG_FREE_IF_COPY(jbFlags, 2);
PG_RETURN_TSVECTOR(result);
}
Datum
jsonb_to_tsvector(PG_FUNCTION_ARGS)
{
Jsonb *jb = PG_GETARG_JSONB_P(0);
Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
Oid cfgId;
TSVector result; TSVector result;
uint32 flags = parse_jsonb_index_flags(jbFlags);
cfgId = getTSCurrentConfig(true);
result = jsonb_to_tsvector_worker(cfgId, jb, flags);
PG_FREE_IF_COPY(jb, 0);
PG_FREE_IF_COPY(jbFlags, 1);
PG_RETURN_TSVECTOR(result);
}
/*
* Worker function for json(_string)_to_tsvector(_byid)
*/
static TSVector
json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
{
TSVectorBuildState state; TSVectorBuildState state;
ParsedText prs; ParsedText prs;
...@@ -316,11 +360,50 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS) ...@@ -316,11 +360,50 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
state.prs = &prs; state.prs = &prs;
state.cfgId = cfgId; state.cfgId = cfgId;
iterate_json_string_values(json, &state, add_to_tsvector); iterate_json_values(json, flags, &state, add_to_tsvector);
return make_tsvector(&prs);
}
Datum
json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
{
Oid cfgId = PG_GETARG_OID(0);
text *json = PG_GETARG_TEXT_P(1);
TSVector result;
result = json_to_tsvector_worker(cfgId, json, jtiString);
PG_FREE_IF_COPY(json, 1); PG_FREE_IF_COPY(json, 1);
result = make_tsvector(&prs); PG_RETURN_TSVECTOR(result);
}
Datum
json_string_to_tsvector(PG_FUNCTION_ARGS)
{
text *json = PG_GETARG_TEXT_P(0);
Oid cfgId;
TSVector result;
cfgId = getTSCurrentConfig(true);
result = json_to_tsvector_worker(cfgId, json, jtiString);
PG_FREE_IF_COPY(json, 0);
PG_RETURN_TSVECTOR(result);
}
Datum
json_to_tsvector_byid(PG_FUNCTION_ARGS)
{
Oid cfgId = PG_GETARG_OID(0);
text *json = PG_GETARG_TEXT_P(1);
Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
TSVector result;
uint32 flags = parse_jsonb_index_flags(jbFlags);
result = json_to_tsvector_worker(cfgId, json, flags);
PG_FREE_IF_COPY(json, 1);
PG_FREE_IF_COPY(jbFlags, 2);
PG_RETURN_TSVECTOR(result); PG_RETURN_TSVECTOR(result);
} }
...@@ -329,12 +412,17 @@ Datum ...@@ -329,12 +412,17 @@ Datum
json_to_tsvector(PG_FUNCTION_ARGS) json_to_tsvector(PG_FUNCTION_ARGS)
{ {
text *json = PG_GETARG_TEXT_P(0); text *json = PG_GETARG_TEXT_P(0);
Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
Oid cfgId; Oid cfgId;
TSVector result;
uint32 flags = parse_jsonb_index_flags(jbFlags);
cfgId = getTSCurrentConfig(true); cfgId = getTSCurrentConfig(true);
PG_RETURN_DATUM(DirectFunctionCall2(json_to_tsvector_byid, result = json_to_tsvector_worker(cfgId, json, flags);
ObjectIdGetDatum(cfgId), PG_FREE_IF_COPY(json, 0);
PointerGetDatum(json))); PG_FREE_IF_COPY(jbFlags, 1);
PG_RETURN_TSVECTOR(result);
} }
/* /*
...@@ -353,7 +441,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len) ...@@ -353,7 +441,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len)
* First time through: initialize words array to a reasonable size. * First time through: initialize words array to a reasonable size.
* (parsetext() will realloc it bigger as needed.) * (parsetext() will realloc it bigger as needed.)
*/ */
prs->lenwords = Max(elem_len / 6, 64); prs->lenwords = 16;
prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords); prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords);
prs->curwords = 0; prs->curwords = 0;
prs->pos = 0; prs->pos = 0;
......
...@@ -60,6 +60,7 @@ typedef struct IterateJsonStringValuesState ...@@ -60,6 +60,7 @@ typedef struct IterateJsonStringValuesState
JsonIterateStringValuesAction action; /* an action that will be applied JsonIterateStringValuesAction action; /* an action that will be applied
* to each json value */ * to each json value */
void *action_state; /* any necessary context for iteration */ void *action_state; /* any necessary context for iteration */
uint32 flags; /* what kind of elements from a json we want to iterate */
} IterateJsonStringValuesState; } IterateJsonStringValuesState;
/* state for transform_json_string_values function */ /* state for transform_json_string_values function */
...@@ -474,8 +475,9 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems, ...@@ -474,8 +475,9 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems,
int level, Jsonb *newval, uint32 nelems, int op_type); int level, Jsonb *newval, uint32 nelems, int op_type);
static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb); static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
/* function supporting iterate_json_string_values */ /* function supporting iterate_json_values */
static void iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype); static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
static void iterate_values_object_field_start(void *state, char *fname, bool isnull);
/* functions supporting transform_json_string_values */ /* functions supporting transform_json_string_values */
static void transform_string_values_object_start(void *state); static void transform_string_values_object_start(void *state);
...@@ -4939,11 +4941,79 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls, ...@@ -4939,11 +4941,79 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
} }
/* /*
* Iterate over jsonb string values or elements, and pass them together with an * Parse information about what elements of a jsonb document we want to iterate
* iteration state to a specified JsonIterateStringValuesAction. * in functions iterate_json(b)_values. This information is presented in jsonb
* format, so that it can be easily extended in the future.
*/
uint32
parse_jsonb_index_flags(Jsonb *jb)
{
JsonbIterator *it;
JsonbValue v;
JsonbIteratorToken type;
uint32 flags = 0;
it = JsonbIteratorInit(&jb->root);
type = JsonbIteratorNext(&it, &v, false);
/*
* We iterate over array (scalar internally is represented as array, so, we
* will accept it too) to check all its elements. Flag's names are choosen
* the same as jsonb_typeof uses.
*/
if (type != WJB_BEGIN_ARRAY)
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("wrong flag type, only arrays and scalars are allowed")));
while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
{
if (v.type != jbvString)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("flag array element is not a string"),
errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\" and \"all\"")));
if (v.val.string.len == 3 &&
pg_strncasecmp(v.val.string.val, "all", 3) == 0)
flags |= jtiAll;
else if (v.val.string.len == 3 &&
pg_strncasecmp(v.val.string.val, "key", 3) == 0)
flags |= jtiKey;
else if (v.val.string.len == 6 &&
pg_strncasecmp(v.val.string.val, "string", 5) == 0)
flags |= jtiString;
else if (v.val.string.len == 7 &&
pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
flags |= jtiNumeric;
else if (v.val.string.len == 7 &&
pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
flags |= jtiBool;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("wrong flag in flag array: \"%s\"",
pnstrdup(v.val.string.val, v.val.string.len)),
errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\" and \"all\"")));
}
/* user should not get it */
if (type != WJB_END_ARRAY)
elog(ERROR, "unexpected end of flag array");
/* get final WJB_DONE and free iterator */
JsonbIteratorNext(&it, &v, false);
return flags;
}
/*
* Iterate over jsonb values or elements, specified by flags, and pass them
* together with an iteration state to a specified JsonIterateStringValuesAction.
*/ */
void void
iterate_jsonb_string_values(Jsonb *jb, void *state, JsonIterateStringValuesAction action) iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
JsonIterateStringValuesAction action)
{ {
JsonbIterator *it; JsonbIterator *it;
JsonbValue v; JsonbValue v;
...@@ -4951,21 +5021,67 @@ iterate_jsonb_string_values(Jsonb *jb, void *state, JsonIterateStringValuesActio ...@@ -4951,21 +5021,67 @@ iterate_jsonb_string_values(Jsonb *jb, void *state, JsonIterateStringValuesActio
it = JsonbIteratorInit(&jb->root); it = JsonbIteratorInit(&jb->root);
/*
* Just recursively iterating over jsonb and call callback on all
* correspoding elements
*/
while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
{ {
if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString) if (type == WJB_KEY)
{
if (flags & jtiKey)
action(state, v.val.string.val, v.val.string.len);
continue;
}
else if (!(type == WJB_VALUE || type == WJB_ELEM))
{ {
action(state, v.val.string.val, v.val.string.len); /* do not call callback for composite JsonbValue */
continue;
}
/* JsonbValue is a value of object or element of array */
switch(v.type)
{
case jbvString:
if (flags & jtiString)
action(state, v.val.string.val, v.val.string.len);
break;
case jbvNumeric:
if (flags & jtiNumeric)
{
char *val;
val = DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(v.val.numeric)));
action(state, val, strlen(val));
pfree(val);
}
break;
case jbvBool:
if (flags & jtiBool)
{
if (v.val.boolean)
action(state, "true", 4);
else
action(state, "false", 5);
}
break;
default:
/* do not call callback for composite JsonbValue */
break;
} }
} }
} }
/* /*
* Iterate over json string values or elements, and pass them together with an * Iterate over json values and elements, specified by flags, and pass them
* iteration state to a specified JsonIterateStringValuesAction. * together with an iteration state to a specified JsonIterateStringValuesAction.
*/ */
void void
iterate_json_string_values(text *json, void *action_state, JsonIterateStringValuesAction action) iterate_json_values(text *json, uint32 flags, void *action_state,
JsonIterateStringValuesAction action)
{ {
JsonLexContext *lex = makeJsonLexContext(json, true); JsonLexContext *lex = makeJsonLexContext(json, true);
JsonSemAction *sem = palloc0(sizeof(JsonSemAction)); JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
...@@ -4974,24 +5090,55 @@ iterate_json_string_values(text *json, void *action_state, JsonIterateStringValu ...@@ -4974,24 +5090,55 @@ iterate_json_string_values(text *json, void *action_state, JsonIterateStringValu
state->lex = lex; state->lex = lex;
state->action = action; state->action = action;
state->action_state = action_state; state->action_state = action_state;
state->flags = flags;
sem->semstate = (void *) state; sem->semstate = (void *) state;
sem->scalar = iterate_string_values_scalar; sem->scalar = iterate_values_scalar;
sem->object_field_start = iterate_values_object_field_start;
pg_parse_json(lex, sem); pg_parse_json(lex, sem);
} }
/* /*
* An auxiliary function for iterate_json_string_values to invoke a specified * An auxiliary function for iterate_json_values to invoke a specified
* JsonIterateStringValuesAction. * JsonIterateStringValuesAction for specified values.
*/ */
static void static void
iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype) iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
{ {
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state; IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
if (tokentype == JSON_TOKEN_STRING) switch(tokentype)
_state->action(_state->action_state, token, strlen(token)); {
case JSON_TOKEN_STRING:
if (_state->flags & jtiString)
_state->action(_state->action_state, token, strlen(token));
break;
case JSON_TOKEN_NUMBER:
if (_state->flags & jtiNumeric)
_state->action(_state->action_state, token, strlen(token));
break;
case JSON_TOKEN_TRUE:
case JSON_TOKEN_FALSE:
if (_state->flags & jtiBool)
_state->action(_state->action_state, token, strlen(token));
break;
default:
/* do not call callback for any other token */
break;
}
}
static void
iterate_values_object_field_start(void *state, char *fname, bool isnull)
{
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
if (_state->flags & jtiKey)
{
char *val = pstrdup(fname);
_state->action(_state->action_state, val, strlen(val));
}
} }
/* /*
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201804071 #define CATALOG_VERSION_NO 201804072
#endif #endif
...@@ -4987,14 +4987,22 @@ DATA(insert OID = 5001 ( phraseto_tsquery PGNSP PGUID 12 100 0 0 0 f f f t f s ...@@ -4987,14 +4987,22 @@ DATA(insert OID = 5001 ( phraseto_tsquery PGNSP PGUID 12 100 0 0 0 f f f t f s
DESCR("transform to tsquery"); DESCR("transform to tsquery");
DATA(insert OID = 8890 ( websearch_to_tsquery PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3615 "25" _null_ _null_ _null_ _null_ _null_ websearch_to_tsquery _null_ _null_ _null_ )); DATA(insert OID = 8890 ( websearch_to_tsquery PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3615 "25" _null_ _null_ _null_ _null_ _null_ websearch_to_tsquery _null_ _null_ _null_ ));
DESCR("transform to tsquery"); DESCR("transform to tsquery");
DATA(insert OID = 4209 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3614 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector _null_ _null_ _null_ )); DATA(insert OID = 4209 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3614 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_string_to_tsvector _null_ _null_ _null_ ));
DESCR("transform jsonb to tsvector"); DESCR("transform string values from jsonb to tsvector");
DATA(insert OID = 4210 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3614 "114" _null_ _null_ _null_ _null_ _null_ json_to_tsvector _null_ _null_ _null_ )); DATA(insert OID = 4213 ( jsonb_to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 2 0 3614 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector _null_ _null_ _null_ ));
DESCR("transform json to tsvector"); DESCR("transform specified values from jsonb to tsvector");
DATA(insert OID = 4211 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector_byid _null_ _null_ _null_ )); DATA(insert OID = 4210 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 1 0 3614 "114" _null_ _null_ _null_ _null_ _null_ json_string_to_tsvector _null_ _null_ _null_ ));
DESCR("transform jsonb to tsvector"); DESCR("transform string values from json to tsvector");
DATA(insert OID = 4212 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 114" _null_ _null_ _null_ _null_ _null_ json_to_tsvector_byid _null_ _null_ _null_ )); DATA(insert OID = 4215 ( json_to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f s s 2 0 3614 "114 3802" _null_ _null_ _null_ _null_ _null_ json_to_tsvector _null_ _null_ _null_ ));
DESCR("transform json to tsvector"); DESCR("transform specified values from json to tsvector");
DATA(insert OID = 4211 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 3802" _null_ _null_ _null_ _null_ _null_ jsonb_string_to_tsvector_byid _null_ _null_ _null_ ));
DESCR("transform string values from jsonb to tsvector");
DATA(insert OID = 4214 ( jsonb_to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 3 0 3614 "3734 3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector_byid _null_ _null_ _null_ ));
DESCR("transform specified values from jsonb to tsvector");
DATA(insert OID = 4212 ( to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 114" _null_ _null_ _null_ _null_ _null_ json_string_to_tsvector_byid _null_ _null_ _null_ ));
DESCR("transform string values from json to tsvector");
DATA(insert OID = 4216 ( json_to_tsvector PGNSP PGUID 12 100 0 0 0 f f f t f i s 3 0 3614 "3734 114 3802" _null_ _null_ _null_ _null_ _null_ json_to_tsvector_byid _null_ _null_ _null_ ));
DESCR("transform specified values from json to tsvector");
DATA(insert OID = 3752 ( tsvector_update_trigger PGNSP PGUID 12 1 0 0 0 f f f f f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ tsvector_update_trigger_byid _null_ _null_ _null_ )); DATA(insert OID = 3752 ( tsvector_update_trigger PGNSP PGUID 12 1 0 0 0 f f f f f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ tsvector_update_trigger_byid _null_ _null_ _null_ ));
DESCR("trigger for automatic update of tsvector column"); DESCR("trigger for automatic update of tsvector column");
......
...@@ -132,15 +132,28 @@ extern JsonLexContext *makeJsonLexContextCstringLen(char *json, ...@@ -132,15 +132,28 @@ extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
*/ */
extern bool IsValidJsonNumber(const char *str, int len); extern bool IsValidJsonNumber(const char *str, int len);
/* an action that will be applied to each value in iterate_json(b)_string_vaues functions */ /*
* Flag types for iterate_json(b)_values to specify what elements from a
* json(b) document we want to iterate.
*/
typedef enum JsonToIndex {
jtiKey = 0x01,
jtiString = 0x02,
jtiNumeric = 0x04,
jtiBool = 0x08,
jtiAll = jtiKey | jtiString | jtiNumeric | jtiBool
} JsonToIndex;
/* an action that will be applied to each value in iterate_json(b)_vaues functions */
typedef void (*JsonIterateStringValuesAction) (void *state, char *elem_value, int elem_len); typedef void (*JsonIterateStringValuesAction) (void *state, char *elem_value, int elem_len);
/* an action that will be applied to each value in transform_json(b)_string_values functions */ /* an action that will be applied to each value in transform_json(b)_values functions */
typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, int elem_len); typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, int elem_len);
extern void iterate_jsonb_string_values(Jsonb *jb, void *state, extern uint32 parse_jsonb_index_flags(Jsonb *jb);
extern void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
JsonIterateStringValuesAction action); JsonIterateStringValuesAction action);
extern void iterate_json_string_values(text *json, void *action_state, extern void iterate_json_values(text *json, uint32 flags, void *action_state,
JsonIterateStringValuesAction action); JsonIterateStringValuesAction action);
extern Jsonb *transform_jsonb_string_values(Jsonb *jsonb, void *action_state, extern Jsonb *transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
JsonTransformStringValuesAction transform_action); JsonTransformStringValuesAction transform_action);
......
...@@ -2324,6 +2324,86 @@ select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff gg ...@@ -2324,6 +2324,86 @@ select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff gg
'aaa':1 'bbb':3 'ccc':5 'ddd':4 'eee':8 'fff':9 'ggg':10 'hhh':12 'iii':13 'aaa':1 'bbb':3 'ccc':5 'ddd':4 'eee':8 'fff':9 'ggg':10 'hhh':12 'iii':13
(1 row) (1 row)
-- json to tsvector with numeric values
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": 123, "c": 456}'::json);
to_tsvector
---------------------------------
'aaa':1 'bbb':3 'ccc':5 'ddd':4
(1 row)
-- json_to_tsvector
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"all"');
json_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"key"');
json_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"string"');
json_to_tsvector
------------------
'aaa':1 'bbb':3
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"numeric"');
json_to_tsvector
------------------
'123':1 '456':3
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"boolean"');
json_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["string", "numeric"]');
json_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"all"');
json_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"key"');
json_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"string"');
json_to_tsvector
------------------
'aaa':1 'bbb':3
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"numeric"');
json_to_tsvector
------------------
'123':1 '456':3
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"boolean"');
json_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["string", "numeric"]');
json_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
-- ts_vector corner cases -- ts_vector corner cases
select to_tsvector('""'::json); select to_tsvector('""'::json);
to_tsvector to_tsvector
...@@ -2349,6 +2429,48 @@ select to_tsvector('null'::json); ...@@ -2349,6 +2429,48 @@ select to_tsvector('null'::json);
(1 row) (1 row)
-- json_to_tsvector corner cases
select json_to_tsvector('""'::json, '"all"');
json_to_tsvector
------------------
(1 row)
select json_to_tsvector('{}'::json, '"all"');
json_to_tsvector
------------------
(1 row)
select json_to_tsvector('[]'::json, '"all"');
json_to_tsvector
------------------
(1 row)
select json_to_tsvector('null'::json, '"all"');
json_to_tsvector
------------------
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '""');
ERROR: wrong flag in flag array: ""
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '{}');
ERROR: wrong flag type, only arrays and scalars are allowed
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '[]');
json_to_tsvector
------------------
(1 row)
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, 'null');
ERROR: flag array element is not a string
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["all", null]');
ERROR: flag array element is not a string
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
-- ts_headline for json -- ts_headline for json
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh')); select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh'));
ts_headline ts_headline
......
...@@ -4122,6 +4122,86 @@ select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff gg ...@@ -4122,6 +4122,86 @@ select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff gg
'aaa':1 'bbb':3 'ccc':5 'ddd':4 'eee':8 'fff':9 'ggg':10 'hhh':12 'iii':13 'aaa':1 'bbb':3 'ccc':5 'ddd':4 'eee':8 'fff':9 'ggg':10 'hhh':12 'iii':13
(1 row) (1 row)
-- jsonb to tsvector with numeric values
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": 123, "c": 456}'::jsonb);
to_tsvector
---------------------------------
'aaa':1 'bbb':3 'ccc':5 'ddd':4
(1 row)
-- jsonb_to_tsvector
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
jsonb_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
jsonb_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
jsonb_to_tsvector
-------------------
'aaa':1 'bbb':3
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
jsonb_to_tsvector
-------------------
'123':1 '456':3
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
jsonb_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
jsonb_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
jsonb_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
jsonb_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
jsonb_to_tsvector
-------------------
'aaa':1 'bbb':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
jsonb_to_tsvector
-------------------
'123':1 '456':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
jsonb_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
jsonb_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
-- ts_vector corner cases -- ts_vector corner cases
select to_tsvector('""'::jsonb); select to_tsvector('""'::jsonb);
to_tsvector to_tsvector
...@@ -4147,6 +4227,48 @@ select to_tsvector('null'::jsonb); ...@@ -4147,6 +4227,48 @@ select to_tsvector('null'::jsonb);
(1 row) (1 row)
-- jsonb_to_tsvector corner cases
select jsonb_to_tsvector('""'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('{}'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('[]'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('null'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '""');
ERROR: wrong flag in flag array: ""
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '{}');
ERROR: wrong flag type, only arrays and scalars are allowed
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '[]');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, 'null');
ERROR: flag array element is not a string
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["all", null]');
ERROR: flag array element is not a string
HINT: Possible values are: "string", "numeric", "boolean", "key" and "all"
-- ts_headline for jsonb -- ts_headline for jsonb
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh')); select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'));
ts_headline ts_headline
......
...@@ -763,12 +763,42 @@ select to_tsvector('simple', '{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c" ...@@ -763,12 +763,42 @@ select to_tsvector('simple', '{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c"
-- json to tsvector with stop words -- json to tsvector with stop words
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff ggg"], "c": {"d": "hhh. iii"}}'::json); select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff ggg"], "c": {"d": "hhh. iii"}}'::json);
-- json to tsvector with numeric values
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": 123, "c": 456}'::json);
-- json_to_tsvector
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"all"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"key"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"string"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"numeric"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"boolean"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["string", "numeric"]');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"all"');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"key"');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"string"');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"numeric"');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '"boolean"');
select json_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["string", "numeric"]');
-- ts_vector corner cases -- ts_vector corner cases
select to_tsvector('""'::json); select to_tsvector('""'::json);
select to_tsvector('{}'::json); select to_tsvector('{}'::json);
select to_tsvector('[]'::json); select to_tsvector('[]'::json);
select to_tsvector('null'::json); select to_tsvector('null'::json);
-- json_to_tsvector corner cases
select json_to_tsvector('""'::json, '"all"');
select json_to_tsvector('{}'::json, '"all"');
select json_to_tsvector('[]'::json, '"all"');
select json_to_tsvector('null'::json, '"all"');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '""');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '{}');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '[]');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, 'null');
select json_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::json, '["all", null]');
-- ts_headline for json -- ts_headline for json
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh')); select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh'));
select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh')); select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff"}, "d": ["ggg hhh", "iii jjj"]}'::json, tsquery('bbb & ddd & hhh'));
......
...@@ -1089,12 +1089,42 @@ select to_tsvector('simple', '{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c" ...@@ -1089,12 +1089,42 @@ select to_tsvector('simple', '{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c"
-- jsonb to tsvector with stop words -- jsonb to tsvector with stop words
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff ggg"], "c": {"d": "hhh. iii"}}'::jsonb); select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff ggg"], "c": {"d": "hhh. iii"}}'::jsonb);
-- jsonb to tsvector with numeric values
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": 123, "c": 456}'::jsonb);
-- jsonb_to_tsvector
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
-- ts_vector corner cases -- ts_vector corner cases
select to_tsvector('""'::jsonb); select to_tsvector('""'::jsonb);
select to_tsvector('{}'::jsonb); select to_tsvector('{}'::jsonb);
select to_tsvector('[]'::jsonb); select to_tsvector('[]'::jsonb);
select to_tsvector('null'::jsonb); select to_tsvector('null'::jsonb);
-- jsonb_to_tsvector corner cases
select jsonb_to_tsvector('""'::jsonb, '"all"');
select jsonb_to_tsvector('{}'::jsonb, '"all"');
select jsonb_to_tsvector('[]'::jsonb, '"all"');
select jsonb_to_tsvector('null'::jsonb, '"all"');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '""');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '{}');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '[]');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, 'null');
select jsonb_to_tsvector('{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["all", null]');
-- ts_headline for jsonb -- ts_headline for jsonb
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh')); select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'));
select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh')); select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment