diff options
Diffstat (limited to 'src/backend/tsearch/to_tsany.c')
-rw-r--r-- | src/backend/tsearch/to_tsany.c | 166 |
1 files changed, 154 insertions, 12 deletions
diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c index 80d80f2451..18368d118e 100644 --- a/src/backend/tsearch/to_tsany.c +++ b/src/backend/tsearch/to_tsany.c @@ -3,7 +3,7 @@ * to_tsany.c * to_ts* function definitions * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -16,6 +16,7 @@ #include "tsearch/ts_cache.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" +#include "utils/jsonapi.h" typedef struct MorphOpaque @@ -24,6 +25,14 @@ typedef struct MorphOpaque int qoperator; /* query operator */ } MorphOpaque; +typedef struct TSVectorBuildState +{ + ParsedText *prs; + TSVector result; + Oid cfgId; +} TSVectorBuildState; + +static void add_to_tsvector(void *state, char *elem_value, int elem_len); Datum get_current_ts_config(PG_FUNCTION_ARGS) @@ -216,19 +225,19 @@ Datum to_tsvector_byid(PG_FUNCTION_ARGS) { Oid cfgId = PG_GETARG_OID(0); - text *in = PG_GETARG_TEXT_P(1); + text *in = PG_GETARG_TEXT_PP(1); ParsedText prs; TSVector out; - prs.lenwords = (VARSIZE(in) - VARHDRSZ) / 6; /* just estimation of - * word's number */ + prs.lenwords = VARSIZE_ANY_EXHDR(in) / 6; /* just estimation of word's + * number */ if (prs.lenwords == 0) prs.lenwords = 2; prs.curwords = 0; prs.pos = 0; prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords); - parsetext(cfgId, &prs, VARDATA(in), VARSIZE(in) - VARHDRSZ); + parsetext(cfgId, &prs, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in)); PG_FREE_IF_COPY(in, 1); if (prs.curwords) @@ -247,7 +256,7 @@ to_tsvector_byid(PG_FUNCTION_ARGS) Datum to_tsvector(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(0); + text *in = PG_GETARG_TEXT_PP(0); Oid cfgId; cfgId = getTSCurrentConfig(true); @@ -256,6 +265,139 @@ to_tsvector(PG_FUNCTION_ARGS) PointerGetDatum(in))); } +Datum +jsonb_to_tsvector_byid(PG_FUNCTION_ARGS) +{ + Oid cfgId = PG_GETARG_OID(0); + Jsonb *jb = PG_GETARG_JSONB(1); + TSVectorBuildState state; + ParsedText *prs = (ParsedText *) palloc(sizeof(ParsedText)); + + prs->words = NULL; + state.result = NULL; + state.cfgId = cfgId; + state.prs = prs; + + iterate_jsonb_string_values(jb, &state, (JsonIterateStringValuesAction) add_to_tsvector); + + PG_FREE_IF_COPY(jb, 1); + + if (state.result == NULL) + { + /* + * There weren't any string elements in jsonb, so wee need to return + * an empty vector + */ + + if (prs->words != NULL) + pfree(prs->words); + + state.result = palloc(CALCDATASIZE(0, 0)); + SET_VARSIZE(state.result, CALCDATASIZE(0, 0)); + state.result->size = 0; + } + + PG_RETURN_TSVECTOR(state.result); +} + +Datum +jsonb_to_tsvector(PG_FUNCTION_ARGS) +{ + Jsonb *jb = PG_GETARG_JSONB(0); + Oid cfgId; + + cfgId = getTSCurrentConfig(true); + PG_RETURN_DATUM(DirectFunctionCall2(jsonb_to_tsvector_byid, + ObjectIdGetDatum(cfgId), + JsonbGetDatum(jb))); +} + +Datum +json_to_tsvector_byid(PG_FUNCTION_ARGS) +{ + Oid cfgId = PG_GETARG_OID(0); + text *json = PG_GETARG_TEXT_P(1); + TSVectorBuildState state; + ParsedText *prs = (ParsedText *) palloc(sizeof(ParsedText)); + + prs->words = NULL; + state.result = NULL; + state.cfgId = cfgId; + state.prs = prs; + + iterate_json_string_values(json, &state, (JsonIterateStringValuesAction) add_to_tsvector); + + PG_FREE_IF_COPY(json, 1); + if (state.result == NULL) + { + /* + * There weren't any string elements in json, so wee need to return an + * empty vector + */ + + if (prs->words != NULL) + pfree(prs->words); + + state.result = palloc(CALCDATASIZE(0, 0)); + SET_VARSIZE(state.result, CALCDATASIZE(0, 0)); + state.result->size = 0; + } + + PG_RETURN_TSVECTOR(state.result); +} + +Datum +json_to_tsvector(PG_FUNCTION_ARGS) +{ + text *json = PG_GETARG_TEXT_P(0); + Oid cfgId; + + cfgId = getTSCurrentConfig(true); + PG_RETURN_DATUM(DirectFunctionCall2(json_to_tsvector_byid, + ObjectIdGetDatum(cfgId), + PointerGetDatum(json))); +} + +/* + * Extend current TSVector from _state with a new one, + * build over a json(b) element. + */ +static void +add_to_tsvector(void *_state, char *elem_value, int elem_len) +{ + TSVectorBuildState *state = (TSVectorBuildState *) _state; + ParsedText *prs = state->prs; + TSVector item_vector; + int i; + + prs->lenwords = elem_len / 6; + if (prs->lenwords == 0) + prs->lenwords = 2; + + prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords); + prs->curwords = 0; + prs->pos = 0; + + parsetext(state->cfgId, prs, elem_value, elem_len); + + if (prs->curwords) + { + if (state->result != NULL) + { + for (i = 0; i < prs->curwords; i++) + prs->words[i].pos.pos = prs->words[i].pos.pos + TS_JUMP; + + item_vector = make_tsvector(prs); + + state->result = (TSVector) DirectFunctionCall2(tsvector_concat, + TSVectorGetDatum(state->result), + PointerGetDatum(item_vector)); + } + else + state->result = make_tsvector(prs); + } +} + /* * to_tsquery */ @@ -362,7 +504,7 @@ pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, Datum to_tsquery_byid(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(1); + text *in = PG_GETARG_TEXT_PP(1); TSQuery query; MorphOpaque data; @@ -380,7 +522,7 @@ to_tsquery_byid(PG_FUNCTION_ARGS) Datum to_tsquery(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(0); + text *in = PG_GETARG_TEXT_PP(0); Oid cfgId; cfgId = getTSCurrentConfig(true); @@ -392,7 +534,7 @@ to_tsquery(PG_FUNCTION_ARGS) Datum plainto_tsquery_byid(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(1); + text *in = PG_GETARG_TEXT_PP(1); TSQuery query; MorphOpaque data; @@ -410,7 +552,7 @@ plainto_tsquery_byid(PG_FUNCTION_ARGS) Datum plainto_tsquery(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(0); + text *in = PG_GETARG_TEXT_PP(0); Oid cfgId; cfgId = getTSCurrentConfig(true); @@ -423,7 +565,7 @@ plainto_tsquery(PG_FUNCTION_ARGS) Datum phraseto_tsquery_byid(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(1); + text *in = PG_GETARG_TEXT_PP(1); TSQuery query; MorphOpaque data; @@ -441,7 +583,7 @@ phraseto_tsquery_byid(PG_FUNCTION_ARGS) Datum phraseto_tsquery(PG_FUNCTION_ARGS) { - text *in = PG_GETARG_TEXT_P(0); + text *in = PG_GETARG_TEXT_PP(0); Oid cfgId; cfgId = getTSCurrentConfig(true); |