Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * dict_ispell.c
4 : * Ispell dictionary interface
5 : *
6 : * Portions Copyright (c) 1996-2023, 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 "commands/defrem.h"
17 : #include "tsearch/dicts/spell.h"
18 : #include "tsearch/ts_locale.h"
19 : #include "tsearch/ts_utils.h"
20 : #include "utils/builtins.h"
21 :
22 :
23 : typedef struct
24 : {
25 : StopList stoplist;
26 : IspellDict obj;
27 : } DictISpell;
28 :
29 : Datum
5710 tgl 30 CBC 67 : dispell_init(PG_FUNCTION_ARGS)
31 : {
5709 32 67 : List *dictoptions = (List *) PG_GETARG_POINTER(0);
33 : DictISpell *d;
5710 34 67 : bool affloaded = false,
35 67 : dictloaded = false,
36 67 : stoploaded = false;
37 : ListCell *l;
38 :
39 67 : d = (DictISpell *) palloc0(sizeof(DictISpell));
40 :
4568 41 67 : NIStartBuild(&(d->obj));
42 :
5709 43 195 : foreach(l, dictoptions)
44 : {
45 131 : DefElem *defel = (DefElem *) lfirst(l);
46 :
1899 47 131 : if (strcmp(defel->defname, "dictfile") == 0)
48 : {
5710 49 64 : if (dictloaded)
5710 tgl 50 UBC 0 : ereport(ERROR,
51 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
52 : errmsg("multiple DictFile parameters")));
5710 tgl 53 CBC 64 : NIImportDictionary(&(d->obj),
2118 54 64 : get_tsearch_config_filename(defGetString(defel),
55 : "dict"));
5710 56 64 : dictloaded = true;
57 : }
1899 58 67 : else if (strcmp(defel->defname, "afffile") == 0)
59 : {
5710 60 64 : if (affloaded)
5710 tgl 61 UBC 0 : ereport(ERROR,
62 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
63 : errmsg("multiple AffFile parameters")));
5710 tgl 64 CBC 64 : NIImportAffixes(&(d->obj),
5709 65 64 : get_tsearch_config_filename(defGetString(defel),
66 : "affix"));
5710 67 64 : affloaded = true;
68 : }
1899 69 3 : else if (strcmp(defel->defname, "stopwords") == 0)
70 : {
5710 tgl 71 UBC 0 : if (stoploaded)
72 0 : ereport(ERROR,
73 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
74 : errmsg("multiple StopWords parameters")));
5706 75 0 : readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
5710 76 0 : stoploaded = true;
77 : }
78 : else
79 : {
5710 tgl 80 CBC 3 : ereport(ERROR,
81 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82 : errmsg("unrecognized Ispell parameter: \"%s\"",
83 : defel->defname)));
84 : }
85 : }
86 :
87 64 : if (affloaded && dictloaded)
88 : {
89 64 : NISortDictionary(&(d->obj));
90 55 : NISortAffixes(&(d->obj));
91 : }
5710 tgl 92 UBC 0 : else if (!affloaded)
93 : {
94 0 : ereport(ERROR,
95 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
96 : errmsg("missing AffFile parameter")));
97 : }
98 : else
99 : {
100 0 : ereport(ERROR,
101 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
102 : errmsg("missing DictFile parameter")));
103 : }
104 :
4568 tgl 105 CBC 55 : NIFinishBuild(&(d->obj));
106 :
5710 107 55 : PG_RETURN_POINTER(d);
108 : }
109 :
110 : Datum
111 375 : dispell_lexize(PG_FUNCTION_ARGS)
112 : {
113 375 : DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
114 375 : char *in = (char *) PG_GETARG_POINTER(1);
5624 bruce 115 375 : int32 len = PG_GETARG_INT32(2);
116 : char *txt;
117 : TSLexeme *res;
118 : TSLexeme *ptr,
119 : *cptr;
120 :
5710 tgl 121 375 : if (len <= 0)
5710 tgl 122 UBC 0 : PG_RETURN_POINTER(NULL);
123 :
5710 tgl 124 CBC 375 : txt = lowerstr_with_len(in, len);
125 375 : res = NINormalizeWord(&(d->obj), txt);
126 :
127 375 : if (res == NULL)
128 72 : PG_RETURN_POINTER(NULL);
129 :
3320 heikki.linnakangas 130 303 : cptr = res;
131 960 : for (ptr = cptr; ptr->lexeme; ptr++)
132 : {
5710 tgl 133 657 : if (searchstoplist(&(d->stoplist), ptr->lexeme))
134 : {
5710 tgl 135 UBC 0 : pfree(ptr->lexeme);
136 0 : ptr->lexeme = NULL;
137 : }
138 : else
139 : {
3320 heikki.linnakangas 140 CBC 657 : if (cptr != ptr)
3320 heikki.linnakangas 141 UBC 0 : memcpy(cptr, ptr, sizeof(TSLexeme));
5710 tgl 142 CBC 657 : cptr++;
143 : }
144 : }
145 303 : cptr->lexeme = NULL;
146 :
147 303 : PG_RETURN_POINTER(res);
148 : }
|