Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * dict_ispell.c
4 : : * Ispell dictionary interface
5 : : *
6 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : : *
8 : : *
9 : : * IDENTIFICATION
10 : : * src/backend/tsearch/dict_ispell.c
11 : : *
12 : : *-------------------------------------------------------------------------
13 : : */
14 : : #include "postgres.h"
15 : :
16 : : #include "catalog/pg_collation_d.h"
17 : : #include "commands/defrem.h"
18 : : #include "tsearch/dicts/spell.h"
19 : : #include "tsearch/ts_public.h"
20 : : #include "utils/fmgrprotos.h"
21 : : #include "utils/formatting.h"
22 : :
23 : :
24 : : typedef struct
25 : : {
26 : : StopList stoplist;
27 : : IspellDict obj;
28 : : } DictISpell;
29 : :
30 : : Datum
6591 tgl@sss.pgh.pa.us 31 :CBC 67 : dispell_init(PG_FUNCTION_ARGS)
32 : : {
6590 33 : 67 : List *dictoptions = (List *) PG_GETARG_POINTER(0);
34 : : DictISpell *d;
6591 35 : 67 : bool affloaded = false,
36 : 67 : dictloaded = false,
37 : 67 : stoploaded = false;
38 : : ListCell *l;
39 : :
40 : 67 : d = (DictISpell *) palloc0(sizeof(DictISpell));
41 : :
5449 42 : 67 : NIStartBuild(&(d->obj));
43 : :
6590 44 [ + - + + : 195 : foreach(l, dictoptions)
+ + ]
45 : : {
46 : 131 : DefElem *defel = (DefElem *) lfirst(l);
47 : :
2780 48 [ + + ]: 131 : if (strcmp(defel->defname, "dictfile") == 0)
49 : : {
50 : : char *filename;
51 : :
6591 52 [ - + ]: 64 : if (dictloaded)
6591 tgl@sss.pgh.pa.us 53 [ # # ]:UBC 0 : ereport(ERROR,
54 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
55 : : errmsg("multiple DictFile parameters")));
35 tgl@sss.pgh.pa.us 56 :GNC 64 : filename = get_tsearch_config_filename(defGetString(defel),
57 : : "dict");
58 : 64 : NIImportDictionary(&(d->obj), filename);
59 : 64 : pfree(filename);
6591 tgl@sss.pgh.pa.us 60 :CBC 64 : dictloaded = true;
61 : : }
2780 62 [ + + ]: 67 : else if (strcmp(defel->defname, "afffile") == 0)
63 : : {
64 : : char *filename;
65 : :
6591 66 [ - + ]: 64 : if (affloaded)
6591 tgl@sss.pgh.pa.us 67 [ # # ]:UBC 0 : ereport(ERROR,
68 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
69 : : errmsg("multiple AffFile parameters")));
35 tgl@sss.pgh.pa.us 70 :GNC 64 : filename = get_tsearch_config_filename(defGetString(defel),
71 : : "affix");
72 : 64 : NIImportAffixes(&(d->obj), filename);
73 : 64 : pfree(filename);
6591 tgl@sss.pgh.pa.us 74 :CBC 64 : affloaded = true;
75 : : }
2780 76 [ - + ]: 3 : else if (strcmp(defel->defname, "stopwords") == 0)
77 : : {
6591 tgl@sss.pgh.pa.us 78 [ # # ]:UBC 0 : if (stoploaded)
79 [ # # ]: 0 : ereport(ERROR,
80 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
81 : : errmsg("multiple StopWords parameters")));
263 peter@eisentraut.org 82 : 0 : readstoplist(defGetString(defel), &(d->stoplist), str_tolower);
6591 tgl@sss.pgh.pa.us 83 : 0 : stoploaded = true;
84 : : }
85 : : else
86 : : {
6591 tgl@sss.pgh.pa.us 87 [ + - ]:CBC 3 : ereport(ERROR,
88 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
89 : : errmsg("unrecognized Ispell parameter: \"%s\"",
90 : : defel->defname)));
91 : : }
92 : : }
93 : :
94 [ + - + - ]: 64 : if (affloaded && dictloaded)
95 : : {
96 : 64 : NISortDictionary(&(d->obj));
97 : 55 : NISortAffixes(&(d->obj));
98 : : }
6591 tgl@sss.pgh.pa.us 99 [ # # ]:UBC 0 : else if (!affloaded)
100 : : {
101 [ # # ]: 0 : ereport(ERROR,
102 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
103 : : errmsg("missing AffFile parameter")));
104 : : }
105 : : else
106 : : {
107 [ # # ]: 0 : ereport(ERROR,
108 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
109 : : errmsg("missing DictFile parameter")));
110 : : }
111 : :
5449 tgl@sss.pgh.pa.us 112 :CBC 55 : NIFinishBuild(&(d->obj));
113 : :
6591 114 : 55 : PG_RETURN_POINTER(d);
115 : : }
116 : :
117 : : Datum
118 : 375 : dispell_lexize(PG_FUNCTION_ARGS)
119 : : {
120 : 375 : DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
121 : 375 : char *in = (char *) PG_GETARG_POINTER(1);
6505 bruce@momjian.us 122 : 375 : int32 len = PG_GETARG_INT32(2);
123 : : char *txt;
124 : : TSLexeme *res;
125 : : TSLexeme *ptr,
126 : : *cptr;
127 : :
6591 tgl@sss.pgh.pa.us 128 [ - + ]: 375 : if (len <= 0)
6591 tgl@sss.pgh.pa.us 129 :UBC 0 : PG_RETURN_POINTER(NULL);
130 : :
263 peter@eisentraut.org 131 :CBC 375 : txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
6591 tgl@sss.pgh.pa.us 132 : 375 : res = NINormalizeWord(&(d->obj), txt);
133 : :
134 [ + + ]: 375 : if (res == NULL)
135 : 72 : PG_RETURN_POINTER(NULL);
136 : :
4201 heikki.linnakangas@i 137 : 303 : cptr = res;
138 [ + + ]: 960 : for (ptr = cptr; ptr->lexeme; ptr++)
139 : : {
6591 tgl@sss.pgh.pa.us 140 [ - + ]: 657 : if (searchstoplist(&(d->stoplist), ptr->lexeme))
141 : : {
6591 tgl@sss.pgh.pa.us 142 :UBC 0 : pfree(ptr->lexeme);
143 : 0 : ptr->lexeme = NULL;
144 : : }
145 : : else
146 : : {
4201 heikki.linnakangas@i 147 [ - + ]:CBC 657 : if (cptr != ptr)
4201 heikki.linnakangas@i 148 :UBC 0 : memcpy(cptr, ptr, sizeof(TSLexeme));
6591 tgl@sss.pgh.pa.us 149 :CBC 657 : cptr++;
150 : : }
151 : : }
152 : 303 : cptr->lexeme = NULL;
153 : :
154 : 303 : PG_RETURN_POINTER(res);
155 : : }
|