2020#include "tsearch/ts_cache.h"
2121#include "tsearch/ts_utils.h"
2222#include "utils/builtins.h"
23+ #include "utils/jsonapi.h"
2324#include "utils/varlena.h"
2425
2526
@@ -31,6 +32,19 @@ typedef struct
3132 LexDescr * list ;
3233} TSTokenTypeStorage ;
3334
35+ /* state for ts_headline_json_* */
36+ typedef struct HeadlineJsonState
37+ {
38+ HeadlineParsedText * prs ;
39+ TSConfigCacheEntry * cfg ;
40+ TSParserCacheEntry * prsobj ;
41+ TSQuery query ;
42+ List * prsoptions ;
43+ bool transformed ;
44+ } HeadlineJsonState ;
45+
46+ static text * headline_json_value (void * _state , char * elem_value , int elem_len );
47+
3448static void
3549tt_setup_firstcall (FuncCallContext * funcctx , Oid prsid )
3650{
@@ -363,3 +377,179 @@ ts_headline_opt(PG_FUNCTION_ARGS)
363377 PG_GETARG_DATUM (1 ),
364378 PG_GETARG_DATUM (2 )));
365379}
380+
381+ Datum
382+ ts_headline_jsonb_byid_opt (PG_FUNCTION_ARGS )
383+ {
384+ Jsonb * out , * jb = PG_GETARG_JSONB (1 );
385+ TSQuery query = PG_GETARG_TSQUERY (2 );
386+ text * opt = (PG_NARGS () > 3 && PG_GETARG_POINTER (3 )) ? PG_GETARG_TEXT_P (3 ) : NULL ;
387+ JsonTransformStringValuesAction action = (JsonTransformStringValuesAction ) headline_json_value ;
388+
389+ HeadlineParsedText prs ;
390+ HeadlineJsonState * state = palloc0 (sizeof (HeadlineJsonState ));
391+
392+ memset (& prs , 0 , sizeof (HeadlineParsedText ));
393+ prs .lenwords = 32 ;
394+ prs .words = (HeadlineWordEntry * ) palloc (sizeof (HeadlineWordEntry ) * prs .lenwords );
395+
396+ state -> prs = & prs ;
397+ state -> cfg = lookup_ts_config_cache (PG_GETARG_OID (0 ));
398+ state -> prsobj = lookup_ts_parser_cache (state -> cfg -> prsId );
399+ state -> query = query ;
400+ if (opt )
401+ state -> prsoptions = deserialize_deflist (PointerGetDatum (opt ));
402+ else
403+ state -> prsoptions = NIL ;
404+
405+ if (!OidIsValid (state -> prsobj -> headlineOid ))
406+ ereport (ERROR ,
407+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
408+ errmsg ("text search parser does not support headline creation" )));
409+
410+ out = transform_jsonb_string_values (jb , state , action );
411+
412+ PG_FREE_IF_COPY (jb , 1 );
413+ PG_FREE_IF_COPY (query , 2 );
414+ if (opt )
415+ PG_FREE_IF_COPY (opt , 3 );
416+
417+ pfree (prs .words );
418+
419+ if (state -> transformed )
420+ {
421+ pfree (prs .startsel );
422+ pfree (prs .stopsel );
423+ }
424+
425+ PG_RETURN_JSONB (out );
426+ }
427+
428+ Datum
429+ ts_headline_jsonb (PG_FUNCTION_ARGS )
430+ {
431+ PG_RETURN_DATUM (DirectFunctionCall3 (ts_headline_jsonb_byid_opt ,
432+ ObjectIdGetDatum (getTSCurrentConfig (true)),
433+ PG_GETARG_DATUM (0 ),
434+ PG_GETARG_DATUM (1 )));
435+ }
436+
437+ Datum
438+ ts_headline_jsonb_byid (PG_FUNCTION_ARGS )
439+ {
440+ PG_RETURN_DATUM (DirectFunctionCall3 (ts_headline_jsonb_byid_opt ,
441+ PG_GETARG_DATUM (0 ),
442+ PG_GETARG_DATUM (1 ),
443+ PG_GETARG_DATUM (2 )));
444+ }
445+
446+ Datum
447+ ts_headline_jsonb_opt (PG_FUNCTION_ARGS )
448+ {
449+ PG_RETURN_DATUM (DirectFunctionCall4 (ts_headline_jsonb_byid_opt ,
450+ ObjectIdGetDatum (getTSCurrentConfig (true)),
451+ PG_GETARG_DATUM (0 ),
452+ PG_GETARG_DATUM (1 ),
453+ PG_GETARG_DATUM (2 )));
454+ }
455+
456+ Datum
457+ ts_headline_json_byid_opt (PG_FUNCTION_ARGS )
458+ {
459+ text * json = PG_GETARG_TEXT_P (1 );
460+ TSQuery query = PG_GETARG_TSQUERY (2 );
461+ text * opt = (PG_NARGS () > 3 && PG_GETARG_POINTER (3 )) ? PG_GETARG_TEXT_P (3 ) : NULL ;
462+ text * out ;
463+ JsonTransformStringValuesAction action = (JsonTransformStringValuesAction ) headline_json_value ;
464+
465+ HeadlineParsedText prs ;
466+ HeadlineJsonState * state = palloc0 (sizeof (HeadlineJsonState ));
467+
468+ memset (& prs , 0 , sizeof (HeadlineParsedText ));
469+ prs .lenwords = 32 ;
470+ prs .words = (HeadlineWordEntry * ) palloc (sizeof (HeadlineWordEntry ) * prs .lenwords );
471+
472+ state -> prs = & prs ;
473+ state -> cfg = lookup_ts_config_cache (PG_GETARG_OID (0 ));
474+ state -> prsobj = lookup_ts_parser_cache (state -> cfg -> prsId );
475+ state -> query = query ;
476+ if (opt )
477+ state -> prsoptions = deserialize_deflist (PointerGetDatum (opt ));
478+ else
479+ state -> prsoptions = NIL ;
480+
481+ if (!OidIsValid (state -> prsobj -> headlineOid ))
482+ ereport (ERROR ,
483+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
484+ errmsg ("text search parser does not support headline creation" )));
485+
486+ out = transform_json_string_values (json , state , action );
487+
488+ PG_FREE_IF_COPY (json , 1 );
489+ PG_FREE_IF_COPY (query , 2 );
490+ if (opt )
491+ PG_FREE_IF_COPY (opt , 3 );
492+ pfree (prs .words );
493+
494+ if (state -> transformed )
495+ {
496+ pfree (prs .startsel );
497+ pfree (prs .stopsel );
498+ }
499+
500+ PG_RETURN_TEXT_P (out );
501+ }
502+
503+ Datum
504+ ts_headline_json (PG_FUNCTION_ARGS )
505+ {
506+ PG_RETURN_DATUM (DirectFunctionCall3 (ts_headline_json_byid_opt ,
507+ ObjectIdGetDatum (getTSCurrentConfig (true)),
508+ PG_GETARG_DATUM (0 ),
509+ PG_GETARG_DATUM (1 )));
510+ }
511+
512+ Datum
513+ ts_headline_json_byid (PG_FUNCTION_ARGS )
514+ {
515+ PG_RETURN_DATUM (DirectFunctionCall3 (ts_headline_json_byid_opt ,
516+ PG_GETARG_DATUM (0 ),
517+ PG_GETARG_DATUM (1 ),
518+ PG_GETARG_DATUM (2 )));
519+ }
520+
521+ Datum
522+ ts_headline_json_opt (PG_FUNCTION_ARGS )
523+ {
524+ PG_RETURN_DATUM (DirectFunctionCall4 (ts_headline_json_byid_opt ,
525+ ObjectIdGetDatum (getTSCurrentConfig (true)),
526+ PG_GETARG_DATUM (0 ),
527+ PG_GETARG_DATUM (1 ),
528+ PG_GETARG_DATUM (2 )));
529+ }
530+
531+
532+ /*
533+ * Return headline in text from, generated from a json(b) element
534+ */
535+ static text *
536+ headline_json_value (void * _state , char * elem_value , int elem_len )
537+ {
538+ HeadlineJsonState * state = (HeadlineJsonState * ) _state ;
539+
540+ HeadlineParsedText * prs = state -> prs ;
541+ TSConfigCacheEntry * cfg = state -> cfg ;
542+ TSParserCacheEntry * prsobj = state -> prsobj ;
543+ TSQuery query = state -> query ;
544+ List * prsoptions = state -> prsoptions ;
545+
546+ prs -> curwords = 0 ;
547+ hlparsetext (cfg -> cfgId , prs , query , elem_value , elem_len );
548+ FunctionCall3 (& (prsobj -> prsheadline ),
549+ PointerGetDatum (prs ),
550+ PointerGetDatum (prsoptions ),
551+ PointerGetDatum (query ));
552+
553+ state -> transformed = true;
554+ return generateHeadline (prs );
555+ }
0 commit comments