Header And Logo

PostgreSQL
| The world's most advanced open source database.

dict_ispell.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * dict_ispell.c
00004  *      Ispell dictionary interface
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  *
00008  *
00009  * IDENTIFICATION
00010  *    src/backend/tsearch/dict_ispell.c
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #include "postgres.h"
00015 
00016 #include "commands/defrem.h"
00017 #include "tsearch/dicts/spell.h"
00018 #include "tsearch/ts_locale.h"
00019 #include "tsearch/ts_utils.h"
00020 
00021 
00022 typedef struct
00023 {
00024     StopList    stoplist;
00025     IspellDict  obj;
00026 } DictISpell;
00027 
00028 Datum
00029 dispell_init(PG_FUNCTION_ARGS)
00030 {
00031     List       *dictoptions = (List *) PG_GETARG_POINTER(0);
00032     DictISpell *d;
00033     bool        affloaded = false,
00034                 dictloaded = false,
00035                 stoploaded = false;
00036     ListCell   *l;
00037 
00038     d = (DictISpell *) palloc0(sizeof(DictISpell));
00039 
00040     NIStartBuild(&(d->obj));
00041 
00042     foreach(l, dictoptions)
00043     {
00044         DefElem    *defel = (DefElem *) lfirst(l);
00045 
00046         if (pg_strcasecmp(defel->defname, "DictFile") == 0)
00047         {
00048             if (dictloaded)
00049                 ereport(ERROR,
00050                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00051                          errmsg("multiple DictFile parameters")));
00052             NIImportDictionary(&(d->obj),
00053                              get_tsearch_config_filename(defGetString(defel),
00054                                                          "dict"));
00055             dictloaded = true;
00056         }
00057         else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
00058         {
00059             if (affloaded)
00060                 ereport(ERROR,
00061                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00062                          errmsg("multiple AffFile parameters")));
00063             NIImportAffixes(&(d->obj),
00064                             get_tsearch_config_filename(defGetString(defel),
00065                                                         "affix"));
00066             affloaded = true;
00067         }
00068         else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
00069         {
00070             if (stoploaded)
00071                 ereport(ERROR,
00072                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00073                          errmsg("multiple StopWords parameters")));
00074             readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
00075             stoploaded = true;
00076         }
00077         else
00078         {
00079             ereport(ERROR,
00080                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00081                      errmsg("unrecognized Ispell parameter: \"%s\"",
00082                             defel->defname)));
00083         }
00084     }
00085 
00086     if (affloaded && dictloaded)
00087     {
00088         NISortDictionary(&(d->obj));
00089         NISortAffixes(&(d->obj));
00090     }
00091     else if (!affloaded)
00092     {
00093         ereport(ERROR,
00094                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00095                  errmsg("missing AffFile parameter")));
00096     }
00097     else
00098     {
00099         ereport(ERROR,
00100                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00101                  errmsg("missing DictFile parameter")));
00102     }
00103 
00104     NIFinishBuild(&(d->obj));
00105 
00106     PG_RETURN_POINTER(d);
00107 }
00108 
00109 Datum
00110 dispell_lexize(PG_FUNCTION_ARGS)
00111 {
00112     DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
00113     char       *in = (char *) PG_GETARG_POINTER(1);
00114     int32       len = PG_GETARG_INT32(2);
00115     char       *txt;
00116     TSLexeme   *res;
00117     TSLexeme   *ptr,
00118                *cptr;
00119 
00120     if (len <= 0)
00121         PG_RETURN_POINTER(NULL);
00122 
00123     txt = lowerstr_with_len(in, len);
00124     res = NINormalizeWord(&(d->obj), txt);
00125 
00126     if (res == NULL)
00127         PG_RETURN_POINTER(NULL);
00128 
00129     ptr = cptr = res;
00130     while (ptr->lexeme)
00131     {
00132         if (searchstoplist(&(d->stoplist), ptr->lexeme))
00133         {
00134             pfree(ptr->lexeme);
00135             ptr->lexeme = NULL;
00136             ptr++;
00137         }
00138         else
00139         {
00140             memcpy(cptr, ptr, sizeof(TSLexeme));
00141             cptr++;
00142             ptr++;
00143         }
00144     }
00145     cptr->lexeme = NULL;
00146 
00147     PG_RETURN_POINTER(res);
00148 }