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

Generated by: LCOV version 1.14