1 /*-------------------------------------------------------------------------
2  *
3  * dict_simple.c
4  *		Simple dictionary: just lowercase and check for stopword
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  *	  src/backend/tsearch/dict_simple.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "commands/defrem.h"
17 #include "tsearch/ts_locale.h"
18 #include "tsearch/ts_utils.h"
19 #include "utils/builtins.h"
20 
21 
22 typedef struct
23 {
24 	StopList	stoplist;
25 	bool		accept;
26 } DictSimple;
27 
28 
29 Datum
dsimple_init(PG_FUNCTION_ARGS)30 dsimple_init(PG_FUNCTION_ARGS)
31 {
32 	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
33 	DictSimple *d = (DictSimple *) palloc0(sizeof(DictSimple));
34 	bool		stoploaded = false,
35 				acceptloaded = false;
36 	ListCell   *l;
37 
38 	d->accept = true;			/* default */
39 
40 	foreach(l, dictoptions)
41 	{
42 		DefElem    *defel = (DefElem *) lfirst(l);
43 
44 		if (strcmp(defel->defname, "stopwords") == 0)
45 		{
46 			if (stoploaded)
47 				ereport(ERROR,
48 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
49 						 errmsg("multiple StopWords parameters")));
50 			readstoplist(defGetString(defel), &d->stoplist, lowerstr);
51 			stoploaded = true;
52 		}
53 		else if (strcmp(defel->defname, "accept") == 0)
54 		{
55 			if (acceptloaded)
56 				ereport(ERROR,
57 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
58 						 errmsg("multiple Accept parameters")));
59 			d->accept = defGetBoolean(defel);
60 			acceptloaded = true;
61 		}
62 		else
63 		{
64 			ereport(ERROR,
65 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
66 					 errmsg("unrecognized simple dictionary parameter: \"%s\"",
67 							defel->defname)));
68 		}
69 	}
70 
71 	PG_RETURN_POINTER(d);
72 }
73 
74 Datum
dsimple_lexize(PG_FUNCTION_ARGS)75 dsimple_lexize(PG_FUNCTION_ARGS)
76 {
77 	DictSimple *d = (DictSimple *) PG_GETARG_POINTER(0);
78 	char	   *in = (char *) PG_GETARG_POINTER(1);
79 	int32		len = PG_GETARG_INT32(2);
80 	char	   *txt;
81 	TSLexeme   *res;
82 
83 	txt = lowerstr_with_len(in, len);
84 
85 	if (*txt == '\0' || searchstoplist(&(d->stoplist), txt))
86 	{
87 		/* reject as stopword */
88 		pfree(txt);
89 		res = palloc0(sizeof(TSLexeme) * 2);
90 		PG_RETURN_POINTER(res);
91 	}
92 	else if (d->accept)
93 	{
94 		/* accept */
95 		res = palloc0(sizeof(TSLexeme) * 2);
96 		res[0].lexeme = txt;
97 		PG_RETURN_POINTER(res);
98 	}
99 	else
100 	{
101 		/* report as unrecognized */
102 		pfree(txt);
103 		PG_RETURN_POINTER(NULL);
104 	}
105 }
106