summaryrefslogtreecommitdiff
path: root/src/backend/tsearch/dict_ispell.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tsearch/dict_ispell.c')
-rw-r--r--src/backend/tsearch/dict_ispell.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c
new file mode 100644
index 0000000000..f7cee10730
--- /dev/null
+++ b/src/backend/tsearch/dict_ispell.c
@@ -0,0 +1,164 @@
+/*-------------------------------------------------------------------------
+ *
+ * dict_ispell.c
+ * Ispell dictionary interface
+ *
+ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/tsearch/dict_ispell.c,v 1.1 2007/08/21 01:11:18 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#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;
+} DictISpell;
+
+Datum
+dispell_init(PG_FUNCTION_ARGS)
+{
+ DictISpell *d;
+ Map *cfg,
+ *pcfg;
+ bool affloaded = false,
+ dictloaded = false,
+ stoploaded = false;
+ text *in;
+
+ /* init functions must defend against NULLs for themselves */
+ if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("NULL config not allowed for ISpell")));
+ in = PG_GETARG_TEXT_P(0);
+
+ parse_keyvalpairs(in, &cfg);
+ PG_FREE_IF_COPY(in, 0);
+
+ d = (DictISpell *) palloc0(sizeof(DictISpell));
+ d->stoplist.wordop = recode_and_lowerstr;
+
+ pcfg = cfg;
+ while (pcfg->key)
+ {
+ if (pg_strcasecmp("DictFile", pcfg->key) == 0)
+ {
+ if (dictloaded)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("multiple DictFile parameters")));
+ NIImportDictionary(&(d->obj),
+ get_tsearch_config_filename(pcfg->value,
+ "dict"));
+ dictloaded = true;
+ }
+ else if (pg_strcasecmp("AffFile", pcfg->key) == 0)
+ {
+ if (affloaded)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("multiple AffFile parameters")));
+ NIImportAffixes(&(d->obj),
+ get_tsearch_config_filename(pcfg->value,
+ "affix"));
+ affloaded = true;
+ }
+ else if (pg_strcasecmp("StopWords", pcfg->key) == 0)
+ {
+ if (stoploaded)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("multiple StopWords parameters")));
+ readstoplist(pcfg->value, &(d->stoplist));
+ sortstoplist(&(d->stoplist));
+ stoploaded = true;
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized ISpell parameter: \"%s\"",
+ pcfg->key)));
+ }
+ pfree(pcfg->key);
+ pfree(pcfg->value);
+ pcfg++;
+ }
+ pfree(cfg);
+
+ 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);
+ int32 len = PG_GETARG_INT32(2);
+ 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);
+}