LCOV - code coverage report
Current view: top level - src/backend/tsearch - dict_ispell.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 77.2 % 57 44
Test Date: 2026-03-01 22:14:38 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * dict_ispell.c
       4              :  *      Ispell dictionary interface
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, 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
      31           67 : dispell_init(PG_FUNCTION_ARGS)
      32              : {
      33           67 :     List       *dictoptions = (List *) PG_GETARG_POINTER(0);
      34              :     DictISpell *d;
      35           67 :     bool        affloaded = false,
      36           67 :                 dictloaded = false,
      37           67 :                 stoploaded = false;
      38              :     ListCell   *l;
      39              : 
      40           67 :     d = palloc0_object(DictISpell);
      41              : 
      42           67 :     NIStartBuild(&(d->obj));
      43              : 
      44          195 :     foreach(l, dictoptions)
      45              :     {
      46          131 :         DefElem    *defel = (DefElem *) lfirst(l);
      47              : 
      48          131 :         if (strcmp(defel->defname, "dictfile") == 0)
      49              :         {
      50              :             char       *filename;
      51              : 
      52           64 :             if (dictloaded)
      53            0 :                 ereport(ERROR,
      54              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      55              :                          errmsg("multiple DictFile parameters")));
      56           64 :             filename = get_tsearch_config_filename(defGetString(defel),
      57              :                                                    "dict");
      58           64 :             NIImportDictionary(&(d->obj), filename);
      59           64 :             pfree(filename);
      60           64 :             dictloaded = true;
      61              :         }
      62           67 :         else if (strcmp(defel->defname, "afffile") == 0)
      63              :         {
      64              :             char       *filename;
      65              : 
      66           64 :             if (affloaded)
      67            0 :                 ereport(ERROR,
      68              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      69              :                          errmsg("multiple AffFile parameters")));
      70           64 :             filename = get_tsearch_config_filename(defGetString(defel),
      71              :                                                    "affix");
      72           64 :             NIImportAffixes(&(d->obj), filename);
      73           64 :             pfree(filename);
      74           64 :             affloaded = true;
      75              :         }
      76            3 :         else if (strcmp(defel->defname, "stopwords") == 0)
      77              :         {
      78            0 :             if (stoploaded)
      79            0 :                 ereport(ERROR,
      80              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      81              :                          errmsg("multiple StopWords parameters")));
      82            0 :             readstoplist(defGetString(defel), &(d->stoplist), str_tolower);
      83            0 :             stoploaded = true;
      84              :         }
      85              :         else
      86              :         {
      87            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              :     }
      99            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              : 
     112           55 :     NIFinishBuild(&(d->obj));
     113              : 
     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);
     122          375 :     int32       len = PG_GETARG_INT32(2);
     123              :     char       *txt;
     124              :     TSLexeme   *res;
     125              :     TSLexeme   *ptr,
     126              :                *cptr;
     127              : 
     128          375 :     if (len <= 0)
     129            0 :         PG_RETURN_POINTER(NULL);
     130              : 
     131          375 :     txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
     132          375 :     res = NINormalizeWord(&(d->obj), txt);
     133              : 
     134          375 :     if (res == NULL)
     135           72 :         PG_RETURN_POINTER(NULL);
     136              : 
     137          303 :     cptr = res;
     138          960 :     for (ptr = cptr; ptr->lexeme; ptr++)
     139              :     {
     140          657 :         if (searchstoplist(&(d->stoplist), ptr->lexeme))
     141              :         {
     142            0 :             pfree(ptr->lexeme);
     143            0 :             ptr->lexeme = NULL;
     144              :         }
     145              :         else
     146              :         {
     147          657 :             if (cptr != ptr)
     148            0 :                 memcpy(cptr, ptr, sizeof(TSLexeme));
     149          657 :             cptr++;
     150              :         }
     151              :     }
     152          303 :     cptr->lexeme = NULL;
     153              : 
     154          303 :     PG_RETURN_POINTER(res);
     155              : }
        

Generated by: LCOV version 2.0-1