dict_ispell.c 3.21 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*-------------------------------------------------------------------------
 *
 * dict_ispell.c
 *		Ispell dictionary interface
 *
 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
10
 *	  $PostgreSQL: pgsql/src/backend/tsearch/dict_ispell.c,v 1.6 2007/11/28 15:42:46 petere Exp $
11 12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

16
#include "commands/defrem.h"
17 18 19 20 21 22 23 24 25 26 27 28
#include "tsearch/dicts/spell.h"
#include "tsearch/ts_locale.h"
#include "tsearch/ts_public.h"
#include "tsearch/ts_utils.h"
#include "utils/builtins.h"
#include "utils/memutils.h"


typedef struct
{
	StopList	stoplist;
	IspellDict	obj;
29
} DictISpell;
30 31 32 33

Datum
dispell_init(PG_FUNCTION_ARGS)
{
34
	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
35 36 37 38
	DictISpell *d;
	bool		affloaded = false,
				dictloaded = false,
				stoploaded = false;
39
	ListCell   *l;
40 41 42

	d = (DictISpell *) palloc0(sizeof(DictISpell));

43
	foreach(l, dictoptions)
44
	{
45 46 47
		DefElem    *defel = (DefElem *) lfirst(l);

		if (pg_strcasecmp(defel->defname, "DictFile") == 0)
48 49 50 51 52 53
		{
			if (dictloaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple DictFile parameters")));
			NIImportDictionary(&(d->obj),
Bruce Momjian's avatar
Bruce Momjian committed
54 55
							 get_tsearch_config_filename(defGetString(defel),
														 "dict"));
56 57
			dictloaded = true;
		}
58
		else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
59 60 61 62 63 64
		{
			if (affloaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple AffFile parameters")));
			NIImportAffixes(&(d->obj),
65
							get_tsearch_config_filename(defGetString(defel),
66 67 68
														"affix"));
			affloaded = true;
		}
69
		else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
70 71 72 73 74
		{
			if (stoploaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple StopWords parameters")));
75
			readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
76 77 78 79 80 81
			stoploaded = true;
		}
		else
		{
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82
					 errmsg("unrecognized Ispell parameter: \"%s\"",
83
							defel->defname)));
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
		}
	}

	if (affloaded && dictloaded)
	{
		NISortDictionary(&(d->obj));
		NISortAffixes(&(d->obj));
	}
	else if (!affloaded)
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("missing AffFile parameter")));
	}
	else
	{
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("missing DictFile parameter")));
	}

	MemoryContextDeleteChildren(CurrentMemoryContext);

	PG_RETURN_POINTER(d);
}

Datum
dispell_lexize(PG_FUNCTION_ARGS)
{
	DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
	char	   *in = (char *) PG_GETARG_POINTER(1);
Bruce Momjian's avatar
Bruce Momjian committed
115
	int32		len = PG_GETARG_INT32(2);
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	char	   *txt;
	TSLexeme   *res;
	TSLexeme   *ptr,
			   *cptr;

	if (len <= 0)
		PG_RETURN_POINTER(NULL);

	txt = lowerstr_with_len(in, len);
	res = NINormalizeWord(&(d->obj), txt);

	if (res == NULL)
		PG_RETURN_POINTER(NULL);

	ptr = cptr = res;
	while (ptr->lexeme)
	{
		if (searchstoplist(&(d->stoplist), ptr->lexeme))
		{
			pfree(ptr->lexeme);
			ptr->lexeme = NULL;
			ptr++;
		}
		else
		{
			memcpy(cptr, ptr, sizeof(TSLexeme));
			cptr++;
			ptr++;
		}
	}
	cptr->lexeme = NULL;

	PG_RETURN_POINTER(res);
}