2003-08-04 08:43:34 +08:00
/*
* interface functions to parser
2003-07-21 18:27:44 +08:00
* Teodor Sigaev < teodor @ sigaev . ru >
*/
# include <errno.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
# include "postgres.h"
# include "fmgr.h"
# include "utils/array.h"
# include "catalog/pg_type.h"
# include "executor/spi.h"
# include "funcapi.h"
# include "wparser.h"
# include "ts_cfg.h"
# include "snmap.h"
# include "common.h"
/*********top interface**********/
2003-08-04 08:43:34 +08:00
static void * plan_getparser = NULL ;
static Oid current_parser_id = InvalidOid ;
2003-07-21 18:27:44 +08:00
void
2003-08-04 08:43:34 +08:00
init_prs ( Oid id , WParserInfo * prs )
{
2004-04-02 07:44:38 +08:00
Oid arg [ 1 ] ;
2003-08-04 08:43:34 +08:00
bool isnull ;
2004-04-02 07:44:38 +08:00
Datum pars [ 1 ] ;
2003-08-04 08:43:34 +08:00
int stat ;
2004-04-02 07:44:38 +08:00
arg [ 0 ] = OIDOID ;
pars [ 0 ] = ObjectIdGetDatum ( id ) ;
2003-08-04 08:43:34 +08:00
memset ( prs , 0 , sizeof ( WParserInfo ) ) ;
2003-07-21 18:27:44 +08:00
SPI_connect ( ) ;
2003-08-04 08:43:34 +08:00
if ( ! plan_getparser )
{
plan_getparser = SPI_saveplan ( SPI_prepare ( " select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from pg_ts_parser where oid = $1 " , 1 , arg ) ) ;
if ( ! plan_getparser )
2003-07-21 18:27:44 +08:00
ts_error ( ERROR , " SPI_prepare() failed " ) ;
}
stat = SPI_execp ( plan_getparser , pars , " " , 1 ) ;
2003-08-04 08:43:34 +08:00
if ( stat < 0 )
ts_error ( ERROR , " SPI_execp return %d " , stat ) ;
if ( SPI_processed > 0 )
{
Oid oid = InvalidOid ;
oid = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 1 , & isnull ) ) ;
2003-07-21 18:27:44 +08:00
fmgr_info_cxt ( oid , & ( prs - > start_info ) , TopMemoryContext ) ;
2003-08-04 08:43:34 +08:00
oid = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 2 , & isnull ) ) ;
2003-07-21 18:27:44 +08:00
fmgr_info_cxt ( oid , & ( prs - > getlexeme_info ) , TopMemoryContext ) ;
2003-08-04 08:43:34 +08:00
oid = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 3 , & isnull ) ) ;
2003-07-21 18:27:44 +08:00
fmgr_info_cxt ( oid , & ( prs - > end_info ) , TopMemoryContext ) ;
2003-08-04 08:43:34 +08:00
prs - > lextype = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 4 , & isnull ) ) ;
oid = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 5 , & isnull ) ) ;
2003-07-21 18:27:44 +08:00
fmgr_info_cxt ( oid , & ( prs - > headline_info ) , TopMemoryContext ) ;
2003-08-04 08:43:34 +08:00
prs - > prs_id = id ;
}
else
2003-07-21 18:27:44 +08:00
ts_error ( ERROR , " No parser with id %d " , id ) ;
SPI_finish ( ) ;
}
2003-08-04 08:43:34 +08:00
typedef struct
{
WParserInfo * last_prs ;
int len ;
int reallen ;
WParserInfo * list ;
2003-07-21 18:27:44 +08:00
SNMap name2id_map ;
2003-08-04 08:43:34 +08:00
} PrsList ;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
static PrsList PList = { NULL , 0 , 0 , NULL , { 0 , 0 , NULL } } ;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
void
reset_prs ( void )
{
freeSNMap ( & ( PList . name2id_map ) ) ;
if ( PList . list )
2003-07-21 18:27:44 +08:00
free ( PList . list ) ;
2003-08-04 08:43:34 +08:00
memset ( & PList , 0 , sizeof ( PrsList ) ) ;
2003-07-21 18:27:44 +08:00
}
static int
2003-08-04 08:43:34 +08:00
compareprs ( const void * a , const void * b )
{
return ( ( WParserInfo * ) a ) - > prs_id - ( ( WParserInfo * ) b ) - > prs_id ;
2003-07-21 18:27:44 +08:00
}
WParserInfo *
2003-08-04 08:43:34 +08:00
findprs ( Oid id )
{
2003-07-21 18:27:44 +08:00
/* last used prs */
2003-08-04 08:43:34 +08:00
if ( PList . last_prs & & PList . last_prs - > prs_id = = id )
2003-07-21 18:27:44 +08:00
return PList . last_prs ;
/* already used prs */
2003-08-04 08:43:34 +08:00
if ( PList . len ! = 0 )
{
2003-07-21 18:27:44 +08:00
WParserInfo key ;
2003-08-04 08:43:34 +08:00
key . prs_id = id ;
2003-07-21 18:27:44 +08:00
PList . last_prs = bsearch ( & key , PList . list , PList . len , sizeof ( WParserInfo ) , compareprs ) ;
2003-08-04 08:43:34 +08:00
if ( PList . last_prs ! = NULL )
2003-07-21 18:27:44 +08:00
return PList . last_prs ;
}
/* last chance */
2003-08-04 08:43:34 +08:00
if ( PList . len = = PList . reallen )
{
2003-07-21 18:27:44 +08:00
WParserInfo * tmp ;
2003-08-04 08:43:34 +08:00
int reallen = ( PList . reallen ) ? 2 * PList . reallen : 16 ;
tmp = ( WParserInfo * ) realloc ( PList . list , sizeof ( WParserInfo ) * reallen ) ;
if ( ! tmp )
ts_error ( ERROR , " No memory " ) ;
PList . reallen = reallen ;
PList . list = tmp ;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
PList . last_prs = & ( PList . list [ PList . len ] ) ;
2003-07-21 18:27:44 +08:00
init_prs ( id , PList . last_prs ) ;
PList . len + + ;
qsort ( PList . list , PList . len , sizeof ( WParserInfo ) , compareprs ) ;
2003-08-04 08:43:34 +08:00
return findprs ( id ) ; /* qsort changed order!! */ ;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
static void * plan_name2id = NULL ;
2003-07-21 18:27:44 +08:00
Oid
2003-08-04 08:43:34 +08:00
name2id_prs ( text * name )
{
2004-04-02 07:44:38 +08:00
Oid arg [ 1 ] ;
2003-08-04 08:43:34 +08:00
bool isnull ;
2004-04-02 07:44:38 +08:00
Datum pars [ 1 ] ;
2003-08-04 08:43:34 +08:00
int stat ;
Oid id = findSNMap_t ( & ( PList . name2id_map ) , name ) ;
2004-04-02 07:44:38 +08:00
arg [ 0 ] = TEXTOID ;
pars [ 0 ] = PointerGetDatum ( name ) ;
2003-08-04 08:43:34 +08:00
if ( id )
2003-07-21 18:27:44 +08:00
return id ;
2003-08-04 08:43:34 +08:00
2003-07-21 18:27:44 +08:00
SPI_connect ( ) ;
2003-08-04 08:43:34 +08:00
if ( ! plan_name2id )
{
plan_name2id = SPI_saveplan ( SPI_prepare ( " select oid from pg_ts_parser where prs_name = $1 " , 1 , arg ) ) ;
if ( ! plan_name2id )
2003-07-21 18:27:44 +08:00
ts_error ( ERROR , " SPI_prepare() failed " ) ;
}
stat = SPI_execp ( plan_name2id , pars , " " , 1 ) ;
2003-08-04 08:43:34 +08:00
if ( stat < 0 )
ts_error ( ERROR , " SPI_execp return %d " , stat ) ;
if ( SPI_processed > 0 )
id = DatumGetObjectId ( SPI_getbinval ( SPI_tuptable - > vals [ 0 ] , SPI_tuptable - > tupdesc , 1 , & isnull ) ) ;
else
2003-07-21 18:27:44 +08:00
ts_error ( ERROR , " No parser '%s' " , text2char ( name ) ) ;
SPI_finish ( ) ;
2003-08-04 08:43:34 +08:00
addSNMap_t ( & ( PList . name2id_map ) , name , id ) ;
2003-07-21 18:27:44 +08:00
return id ;
}
/******sql-level interface******/
2003-08-04 08:43:34 +08:00
typedef struct
{
int cur ;
LexDescr * list ;
} TypeStorage ;
2003-07-21 18:27:44 +08:00
static void
2003-08-04 08:43:34 +08:00
setup_firstcall ( FuncCallContext * funcctx , Oid prsid )
{
TupleDesc tupdesc ;
MemoryContext oldcontext ;
TypeStorage * st ;
WParserInfo * prs = findprs ( prsid ) ;
2003-07-21 18:27:44 +08:00
oldcontext = MemoryContextSwitchTo ( funcctx - > multi_call_memory_ctx ) ;
2003-08-04 08:43:34 +08:00
st = ( TypeStorage * ) palloc ( sizeof ( TypeStorage ) ) ;
st - > cur = 0 ;
st - > list = ( LexDescr * ) DatumGetPointer (
OidFunctionCall1 ( prs - > lextype , PointerGetDatum ( prs - > prs ) )
) ;
funcctx - > user_fctx = ( void * ) st ;
2003-07-21 18:27:44 +08:00
tupdesc = RelationNameGetTupleDesc ( " tokentype " ) ;
funcctx - > attinmeta = TupleDescGetAttInMetadata ( tupdesc ) ;
MemoryContextSwitchTo ( oldcontext ) ;
}
static Datum
2003-08-04 08:43:34 +08:00
process_call ( FuncCallContext * funcctx )
{
TypeStorage * st ;
st = ( TypeStorage * ) funcctx - > user_fctx ;
if ( st - > list & & st - > list [ st - > cur ] . lexid )
{
Datum result ;
char * values [ 3 ] ;
char txtid [ 16 ] ;
HeapTuple tuple ;
values [ 0 ] = txtid ;
sprintf ( txtid , " %d " , st - > list [ st - > cur ] . lexid ) ;
values [ 1 ] = st - > list [ st - > cur ] . alias ;
values [ 2 ] = st - > list [ st - > cur ] . descr ;
2003-07-21 18:27:44 +08:00
tuple = BuildTupleFromCStrings ( funcctx - > attinmeta , values ) ;
2004-04-02 05:28:47 +08:00
result = HeapTupleGetDatum ( tuple ) ;
2003-07-21 18:27:44 +08:00
pfree ( values [ 1 ] ) ;
pfree ( values [ 2 ] ) ;
st - > cur + + ;
return result ;
2003-08-04 08:43:34 +08:00
}
else
{
if ( st - > list )
pfree ( st - > list ) ;
2003-07-21 18:27:44 +08:00
pfree ( st ) ;
}
2003-08-04 08:43:34 +08:00
return ( Datum ) 0 ;
2003-07-21 18:27:44 +08:00
}
PG_FUNCTION_INFO_V1 ( token_type ) ;
2003-08-04 08:43:34 +08:00
Datum token_type ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
token_type ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
if ( SRF_IS_FIRSTCALL ( ) )
{
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
setup_firstcall ( funcctx , PG_GETARG_OID ( 0 ) ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( token_type_byname ) ;
2003-08-04 08:43:34 +08:00
Datum token_type_byname ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
token_type_byname ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
if ( SRF_IS_FIRSTCALL ( ) )
{
text * name = PG_GETARG_TEXT_P ( 0 ) ;
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
setup_firstcall ( funcctx , name2id_prs ( name ) ) ;
PG_FREE_IF_COPY ( name , 0 ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( token_type_current ) ;
2003-08-04 08:43:34 +08:00
Datum token_type_current ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
token_type_current ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
if ( SRF_IS_FIRSTCALL ( ) )
{
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
if ( current_parser_id = = InvalidOid )
current_parser_id = name2id_prs ( char2text ( " default " ) ) ;
setup_firstcall ( funcctx , current_parser_id ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( set_curprs ) ;
2003-08-04 08:43:34 +08:00
Datum set_curprs ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
set_curprs ( PG_FUNCTION_ARGS )
{
findprs ( PG_GETARG_OID ( 0 ) ) ;
current_parser_id = PG_GETARG_OID ( 0 ) ;
PG_RETURN_VOID ( ) ;
2003-07-21 18:27:44 +08:00
}
PG_FUNCTION_INFO_V1 ( set_curprs_byname ) ;
2003-08-04 08:43:34 +08:00
Datum set_curprs_byname ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
set_curprs_byname ( PG_FUNCTION_ARGS )
{
text * name = PG_GETARG_TEXT_P ( 0 ) ;
DirectFunctionCall1 (
set_curprs ,
ObjectIdGetDatum ( name2id_prs ( name ) )
) ;
PG_FREE_IF_COPY ( name , 0 ) ;
PG_RETURN_VOID ( ) ;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
typedef struct
{
int type ;
char * lexem ;
} LexemEntry ;
typedef struct
{
int cur ;
int len ;
LexemEntry * list ;
} PrsStorage ;
2003-07-21 18:27:44 +08:00
static void
2003-08-04 08:43:34 +08:00
prs_setup_firstcall ( FuncCallContext * funcctx , int prsid , text * txt )
{
TupleDesc tupdesc ;
MemoryContext oldcontext ;
PrsStorage * st ;
WParserInfo * prs = findprs ( prsid ) ;
char * lex = NULL ;
int llen = 0 ,
type = 0 ;
2003-07-21 18:27:44 +08:00
oldcontext = MemoryContextSwitchTo ( funcctx - > multi_call_memory_ctx ) ;
2003-08-04 08:43:34 +08:00
st = ( PrsStorage * ) palloc ( sizeof ( PrsStorage ) ) ;
st - > cur = 0 ;
st - > len = 16 ;
st - > list = ( LexemEntry * ) palloc ( sizeof ( LexemEntry ) * st - > len ) ;
prs - > prs = ( void * ) DatumGetPointer (
FunctionCall2 (
& ( prs - > start_info ) ,
PointerGetDatum ( VARDATA ( txt ) ) ,
Int32GetDatum ( VARSIZE ( txt ) - VARHDRSZ )
)
) ;
while ( ( type = DatumGetInt32 ( FunctionCall3 (
& ( prs - > getlexeme_info ) ,
PointerGetDatum ( prs - > prs ) ,
PointerGetDatum ( & lex ) ,
PointerGetDatum ( & llen ) ) ) ) ! = 0 )
{
if ( st - > cur > = st - > len )
{
st - > len = 2 * st - > len ;
st - > list = ( LexemEntry * ) repalloc ( st - > list , sizeof ( LexemEntry ) * st - > len ) ;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
st - > list [ st - > cur ] . lexem = palloc ( llen + 1 ) ;
memcpy ( st - > list [ st - > cur ] . lexem , lex , llen ) ;
st - > list [ st - > cur ] . lexem [ llen ] = ' \0 ' ;
st - > list [ st - > cur ] . type = type ;
2003-07-21 18:27:44 +08:00
st - > cur + + ;
}
2003-08-04 08:43:34 +08:00
2003-07-21 18:27:44 +08:00
FunctionCall1 (
2003-08-04 08:43:34 +08:00
& ( prs - > end_info ) ,
PointerGetDatum ( prs - > prs )
) ;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
st - > len = st - > cur ;
st - > cur = 0 ;
funcctx - > user_fctx = ( void * ) st ;
2003-07-21 18:27:44 +08:00
tupdesc = RelationNameGetTupleDesc ( " tokenout " ) ;
funcctx - > attinmeta = TupleDescGetAttInMetadata ( tupdesc ) ;
MemoryContextSwitchTo ( oldcontext ) ;
}
static Datum
2003-08-04 08:43:34 +08:00
prs_process_call ( FuncCallContext * funcctx )
{
PrsStorage * st ;
st = ( PrsStorage * ) funcctx - > user_fctx ;
if ( st - > cur < st - > len )
{
Datum result ;
char * values [ 2 ] ;
char tid [ 16 ] ;
HeapTuple tuple ;
values [ 0 ] = tid ;
sprintf ( tid , " %d " , st - > list [ st - > cur ] . type ) ;
values [ 1 ] = st - > list [ st - > cur ] . lexem ;
2003-07-21 18:27:44 +08:00
tuple = BuildTupleFromCStrings ( funcctx - > attinmeta , values ) ;
2004-04-02 05:28:47 +08:00
result = HeapTupleGetDatum ( tuple ) ;
2003-07-21 18:27:44 +08:00
pfree ( values [ 1 ] ) ;
st - > cur + + ;
return result ;
2003-08-04 08:43:34 +08:00
}
else
{
if ( st - > list )
pfree ( st - > list ) ;
2003-07-21 18:27:44 +08:00
pfree ( st ) ;
}
2003-08-04 08:43:34 +08:00
return ( Datum ) 0 ;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
2003-07-21 18:27:44 +08:00
PG_FUNCTION_INFO_V1 ( parse ) ;
2003-08-04 08:43:34 +08:00
Datum parse ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
parse ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
if ( SRF_IS_FIRSTCALL ( ) )
{
text * txt = PG_GETARG_TEXT_P ( 1 ) ;
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
prs_setup_firstcall ( funcctx , PG_GETARG_OID ( 0 ) , txt ) ;
PG_FREE_IF_COPY ( txt , 1 ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = prs_process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( parse_byname ) ;
2003-08-04 08:43:34 +08:00
Datum parse_byname ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
parse_byname ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
if ( SRF_IS_FIRSTCALL ( ) )
{
text * name = PG_GETARG_TEXT_P ( 0 ) ;
text * txt = PG_GETARG_TEXT_P ( 1 ) ;
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
prs_setup_firstcall ( funcctx , name2id_prs ( name ) , txt ) ;
PG_FREE_IF_COPY ( name , 0 ) ;
PG_FREE_IF_COPY ( txt , 1 ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = prs_process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( parse_current ) ;
2003-08-04 08:43:34 +08:00
Datum parse_current ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
parse_current ( PG_FUNCTION_ARGS )
{
FuncCallContext * funcctx ;
Datum result ;
if ( SRF_IS_FIRSTCALL ( ) )
{
text * txt = PG_GETARG_TEXT_P ( 0 ) ;
2003-07-21 18:27:44 +08:00
funcctx = SRF_FIRSTCALL_INIT ( ) ;
2003-08-04 08:43:34 +08:00
if ( current_parser_id = = InvalidOid )
current_parser_id = name2id_prs ( char2text ( " default " ) ) ;
prs_setup_firstcall ( funcctx , current_parser_id , txt ) ;
PG_FREE_IF_COPY ( txt , 0 ) ;
2003-07-21 18:27:44 +08:00
}
funcctx = SRF_PERCALL_SETUP ( ) ;
2003-08-04 08:43:34 +08:00
if ( ( result = prs_process_call ( funcctx ) ) ! = ( Datum ) 0 )
2003-07-21 18:27:44 +08:00
SRF_RETURN_NEXT ( funcctx , result ) ;
SRF_RETURN_DONE ( funcctx ) ;
}
PG_FUNCTION_INFO_V1 ( headline ) ;
2003-08-04 08:43:34 +08:00
Datum headline ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
headline ( PG_FUNCTION_ARGS )
{
TSCfgInfo * cfg = findcfg ( PG_GETARG_OID ( 0 ) ) ;
text * in = PG_GETARG_TEXT_P ( 1 ) ;
2003-07-21 18:27:44 +08:00
QUERYTYPE * query = ( QUERYTYPE * ) DatumGetPointer ( PG_DETOAST_DATUM ( PG_GETARG_DATUM ( 2 ) ) ) ;
2003-08-04 08:43:34 +08:00
text * opt = ( PG_NARGS ( ) > 3 & & PG_GETARG_POINTER ( 3 ) ) ? PG_GETARG_TEXT_P ( 3 ) : NULL ;
2003-07-21 18:27:44 +08:00
HLPRSTEXT prs ;
2003-08-04 08:43:34 +08:00
text * out ;
2003-07-21 18:27:44 +08:00
WParserInfo * prsobj = findprs ( cfg - > prs_id ) ;
2003-08-04 08:43:34 +08:00
memset ( & prs , 0 , sizeof ( HLPRSTEXT ) ) ;
2003-07-21 18:27:44 +08:00
prs . lenwords = 32 ;
prs . words = ( HLWORD * ) palloc ( sizeof ( HLWORD ) * prs . lenwords ) ;
hlparsetext ( cfg , & prs , query , VARDATA ( in ) , VARSIZE ( in ) - VARHDRSZ ) ;
FunctionCall3 (
2003-08-04 08:43:34 +08:00
& ( prsobj - > headline_info ) ,
PointerGetDatum ( & prs ) ,
PointerGetDatum ( opt ) ,
PointerGetDatum ( query )
) ;
2003-07-21 18:27:44 +08:00
out = genhl ( & prs ) ;
2003-08-04 08:43:34 +08:00
PG_FREE_IF_COPY ( in , 1 ) ;
PG_FREE_IF_COPY ( query , 2 ) ;
if ( opt )
PG_FREE_IF_COPY ( opt , 3 ) ;
2003-07-21 18:27:44 +08:00
pfree ( prs . words ) ;
pfree ( prs . startsel ) ;
pfree ( prs . stopsel ) ;
PG_RETURN_POINTER ( out ) ;
}
PG_FUNCTION_INFO_V1 ( headline_byname ) ;
2003-08-04 08:43:34 +08:00
Datum headline_byname ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
headline_byname ( PG_FUNCTION_ARGS )
{
text * cfg = PG_GETARG_TEXT_P ( 0 ) ;
Datum out = DirectFunctionCall4 (
headline ,
ObjectIdGetDatum ( name2id_cfg ( cfg ) ) ,
PG_GETARG_DATUM ( 1 ) ,
PG_GETARG_DATUM ( 2 ) ,
( PG_NARGS ( ) > 3 ) ? PG_GETARG_DATUM ( 3 ) : PointerGetDatum ( NULL )
2003-07-21 18:27:44 +08:00
) ;
2003-08-04 08:43:34 +08:00
PG_FREE_IF_COPY ( cfg , 0 ) ;
PG_RETURN_DATUM ( out ) ;
2003-07-21 18:27:44 +08:00
}
PG_FUNCTION_INFO_V1 ( headline_current ) ;
2003-08-04 08:43:34 +08:00
Datum headline_current ( PG_FUNCTION_ARGS ) ;
2003-07-21 18:27:44 +08:00
Datum
2003-08-04 08:43:34 +08:00
headline_current ( PG_FUNCTION_ARGS )
{
2003-07-21 18:27:44 +08:00
PG_RETURN_DATUM ( DirectFunctionCall4 (
2003-08-04 08:43:34 +08:00
headline ,
ObjectIdGetDatum ( get_currcfg ( ) ) ,
PG_GETARG_DATUM ( 0 ) ,
PG_GETARG_DATUM ( 1 ) ,
( PG_NARGS ( ) > 2 ) ? PG_GETARG_DATUM ( 2 ) : PointerGetDatum ( NULL )
) ) ;
2003-07-21 18:27:44 +08:00
}