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