From cdd02cdf00f020292cdcc8dafa5475e0149c34a6 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 7 Aug 2001 18:16:01 +0000 Subject: [PATCH] Sorry - I should have gotten to this sooner. Here's a patch which you should be able to apply against what you just committed. It rolls soundex into fuzzystrmatch. Remove soundex/metaphone and merge into fuzzystrmatch. Joe Conway --- contrib/README | 6 +- contrib/fuzzystrmatch/README.fuzzystrmatch | 10 +- contrib/fuzzystrmatch/README.soundex | 62 ++++ contrib/fuzzystrmatch/fuzzystrmatch.c | 68 +++++ contrib/fuzzystrmatch/fuzzystrmatch.h | 31 +- contrib/fuzzystrmatch/fuzzystrmatch.sql.in | 6 + contrib/metaphone/Makefile | 40 --- contrib/metaphone/README.metaphone | 79 ----- contrib/metaphone/metaphone.c | 321 --------------------- contrib/metaphone/metaphone.sql.in | 3 - contrib/soundex/Makefile | 40 --- contrib/soundex/README.soundex | 66 ----- contrib/soundex/soundex.c | 119 -------- contrib/soundex/soundex.sql.in | 5 - 14 files changed, 167 insertions(+), 689 deletions(-) create mode 100644 contrib/fuzzystrmatch/README.soundex delete mode 100644 contrib/metaphone/Makefile delete mode 100755 contrib/metaphone/README.metaphone delete mode 100755 contrib/metaphone/metaphone.c delete mode 100755 contrib/metaphone/metaphone.sql.in delete mode 100644 contrib/soundex/Makefile delete mode 100644 contrib/soundex/README.soundex delete mode 100644 contrib/soundex/soundex.c delete mode 100644 contrib/soundex/soundex.sql.in diff --git a/contrib/README b/contrib/README index 5823520c0f..7197d38abc 100644 --- a/contrib/README +++ b/contrib/README @@ -57,7 +57,7 @@ fulltextindex - fuzzystrmatch - Levenshtein and Metaphone fuzzy string matching - by Joe Conway + by Joe Conway , Joel Burton intarray - Index support for arrays of int4, using GiST @@ -86,7 +86,6 @@ mac - metaphone - Improved Soundex function - by Joel Burton miscutil - PostgreSQL assert checking and various utility functions @@ -149,9 +148,6 @@ seg - Confidence-interval datatype (GiST indexing example) by Gene Selkov, Jr. -soundex - - Soundex function - spi - Various trigger functions, examples for using SPI. diff --git a/contrib/fuzzystrmatch/README.fuzzystrmatch b/contrib/fuzzystrmatch/README.fuzzystrmatch index 9109ea7e06..8d310b4ade 100644 --- a/contrib/fuzzystrmatch/README.fuzzystrmatch +++ b/contrib/fuzzystrmatch/README.fuzzystrmatch @@ -20,6 +20,11 @@ * Metaphone was originally created by Lawrence Philips and presented in article * in "Computer Language" December 1990 issue. * + * soundex() + * ----------- + * Folded existing soundex contrib into this one. Renamed text_soundex() (C function) + * to soundex() for consistency. + * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without a written agreement * is hereby granted, provided that the above copyright notice and this @@ -40,12 +45,15 @@ */ -Version 0.1 (3 August, 2001): +Version 0.2 (7 August, 2001): Functions to calculate the degree to which two strings match in a "fuzzy" way Tested under Linux (Red Hat 6.2 and 7.0) and PostgreSQL 7.2devel Release Notes: + Version 0.2 + - folded soundex contrib into this one + Version 0.1 - initial release diff --git a/contrib/fuzzystrmatch/README.soundex b/contrib/fuzzystrmatch/README.soundex new file mode 100644 index 0000000000..b9a6149542 --- /dev/null +++ b/contrib/fuzzystrmatch/README.soundex @@ -0,0 +1,62 @@ +NOTE: Modified August 07, 2001 by Joe Conway. Updated for accuracy + after combining soundex code into the fuzzystrmatch contrib +--------------------------------------------------------------------- +The Soundex system is a method of matching similar sounding names +(or any words) to the same code. It was initially used by the +United States Census in 1880, 1900, and 1910, but it has little use +beyond English names (or the English pronunciation of names), and +it is not a linguistic tool. + +The following are some usage examples: + +SELECT soundex('hello world!'); + +CREATE TABLE s (nm text)\g + +insert into s values ('john')\g +insert into s values ('joan')\g +insert into s values ('wobbly')\g + +select * from s +where soundex(nm) = soundex('john')\g + +select nm from s a, s b +where soundex(a.nm) = soundex(b.nm) +and a.oid <> b.oid\g + +CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS +'select soundex($1) = soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS +'select soundex($1) < soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS +'select soundex($1) > soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS +'select soundex($1) <= soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS +'select soundex($1) >= soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS +'select soundex($1) <> soundex($2)' +LANGUAGE 'sql'; + +DROP OPERATOR #= (text,text)\g + +CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, +commutator=text_sx_eq)\g + +SELECT * +FROM s +WHERE text_sx_eq(nm,'john')\g + +SELECT * +from s +where s.nm #= 'john'; diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c index 80e9e69cfa..4a2d3f932e 100644 --- a/contrib/fuzzystrmatch/fuzzystrmatch.c +++ b/contrib/fuzzystrmatch/fuzzystrmatch.c @@ -629,3 +629,71 @@ int _metaphone ( return(META_SUCCESS); } /* END metaphone */ + + +/* + * SQL function: soundex(text) returns text + */ +PG_FUNCTION_INFO_V1(soundex); + +Datum +soundex(PG_FUNCTION_ARGS) +{ + char outstr[SOUNDEX_LEN + 1]; + char *arg; + + arg = _textout(PG_GETARG_TEXT_P(0)); + + _soundex(arg, outstr); + + PG_RETURN_TEXT_P(_textin(outstr)); +} + +static void +_soundex(const char *instr, char *outstr) +{ + int count; + + AssertArg(instr); + AssertArg(outstr); + + outstr[SOUNDEX_LEN] = '\0'; + + /* Skip leading non-alphabetic characters */ + while (!isalpha((unsigned char) instr[0]) && instr[0]) + ++instr; + + /* No string left */ + if (!instr[0]) + { + outstr[0] = (char) 0; + return; + } + + /* Take the first letter as is */ + *outstr++ = (char) toupper((unsigned char) *instr++); + + count = 1; + while (*instr && count < SOUNDEX_LEN) + { + if (isalpha((unsigned char) *instr) && + soundex_code(*instr) != soundex_code(*(instr - 1))) + { + *outstr = soundex_code(instr[0]); + if (*outstr != '0') + { + ++outstr; + ++count; + } + } + ++instr; + } + + /* Fill with 0's */ + while (count < SOUNDEX_LEN) + { + *outstr = '0'; + ++outstr; + ++count; + } +} diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.h b/contrib/fuzzystrmatch/fuzzystrmatch.h index 5ed9c3746e..9a9be1e9a0 100644 --- a/contrib/fuzzystrmatch/fuzzystrmatch.h +++ b/contrib/fuzzystrmatch/fuzzystrmatch.h @@ -51,32 +51,43 @@ #include "utils/builtins.h" -#define MAX_LEVENSHTEIN_STRLEN 255 -#define MAX_METAPHONE_STRLEN 255 - -typedef struct dynmatrix -{ - int value; -} dynmat; - /* * External declarations */ extern Datum levenshtein(PG_FUNCTION_ARGS); extern Datum metaphone(PG_FUNCTION_ARGS); +extern Datum soundex(PG_FUNCTION_ARGS); /* - * Internal declarations + * Soundex */ +static void _soundex(const char *instr, char *outstr); + +#define SOUNDEX_LEN 4 +#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) +#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str))) + +/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ +static const char *soundex_table = "01230120022455012623010202"; + +#define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A'] - +/* + * Levenshtein + */ #define STRLEN(p) strlen(p) #define CHAREQ(p1, p2) (*(p1) == *(p2)) #define NextChar(p) ((p)++) +#define MAX_LEVENSHTEIN_STRLEN 255 +/* + * Metaphone + */ +#define MAX_METAPHONE_STRLEN 255 + /* * Original code by Michael G Schwern starts here. * Code slightly modified for use as PostgreSQL diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.sql.in b/contrib/fuzzystrmatch/fuzzystrmatch.sql.in index 4125b75d14..b02f1b28eb 100644 --- a/contrib/fuzzystrmatch/fuzzystrmatch.sql.in +++ b/contrib/fuzzystrmatch/fuzzystrmatch.sql.in @@ -3,3 +3,9 @@ CREATE FUNCTION levenshtein (text,text) RETURNS int CREATE FUNCTION metaphone (text,int) RETURNS text AS 'MODULE_PATHNAME','metaphone' LANGUAGE 'c' with (iscachable, isstrict); + +CREATE FUNCTION soundex(text) RETURNS text + AS 'MODULE_PATHNAME', 'soundex' LANGUAGE 'c' with (iscachable, isstrict); + +CREATE FUNCTION text_soundex(text) RETURNS text + AS 'MODULE_PATHNAME', 'soundex' LANGUAGE 'c'; diff --git a/contrib/metaphone/Makefile b/contrib/metaphone/Makefile deleted file mode 100644 index cc1696ae01..0000000000 --- a/contrib/metaphone/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# -# $Header: /cvsroot/pgsql/contrib/metaphone/Attic/Makefile,v 1.2 2001/06/20 00:04:44 momjian Exp $ -# - -subdir = contrib/metaphone -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global - -NAME := metaphone -SONAME := $(NAME)$(DLSUFFIX) - -override CPPFLAGS += -I$(srcdir) -override CFLAGS += $(CFLAGS_SL) -override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS) - -all: $(SONAME) $(NAME).sql - -$(NAME).sql: $(NAME).sql.in - sed 's,@MODULE_FILENAME@,$(libdir)/contrib/$(SONAME),g' $< >$@ - -install: all installdirs - $(INSTALL_SHLIB) $(SONAME) $(libdir)/contrib - $(INSTALL_DATA) $(NAME).sql $(datadir)/contrib - $(INSTALL_DATA) README.$(NAME) $(docdir)/contrib - -installdirs: - $(mkinstalldirs) $(libdir)/contrib $(datadir)/contrib $(docdir)/contrib - -uninstall: - rm -f $(libdir)/contrib/$(SONAME) $(datadir)/contrib/$(NAME).sql $(docdir)/contrib/README.$(NAME) - -clean distclean maintainer-clean: - rm -f $(SONAME) $(NAME).o $(NAME).sql - -depend dep: - $(CC) -MM -MG $(CFLAGS) *.c > depend - -ifeq (depend,$(wildcard depend)) -include depend -endif diff --git a/contrib/metaphone/README.metaphone b/contrib/metaphone/README.metaphone deleted file mode 100755 index 2a517c16d3..0000000000 --- a/contrib/metaphone/README.metaphone +++ /dev/null @@ -1,79 +0,0 @@ -This directory contains a module that implements the "Metaphone" code as -a PostgreSQL user-defined function. The Metaphone system is a method of -matching similar sounding names (or any words) to the same code. - -Metaphone was invented by Lawrence Philips as an improvement to the popular -name-hashing routine, Soundex. - -This metaphone code is from Michael Kuhn, and is detailed at - http://aspell.sourceforge.net/metaphone/metaphone-kuhn.txt - -Code for this (including this help file!) was liberally borrowed from -the soundex() module for PostgreSQL. - -There are two functions: - metaphone(text) : returns hash of a name - metaphone(text,int) : returns hash (maximum length of int) of name - ---- - -To install it, first configure the main source tree, then run make; -make install in this directory. Finally, load the function definition -with psql: - - psql -f PREFIX/share/contrib/metaphone.sql - -The following are some usage examples: - -SELECT text_metaphone('hello world!'); -SELECT text_metaphone('hello world!', 4); - -CREATE TABLE s (nm text)\g - -insert into s values ('john')\g -insert into s values ('joan')\g -insert into s values ('wobbly')\g - -select * from s -where text_metaphone(nm) = text_metaphone('john')\g - -select nm from s a, s b -where text_metaphone(a.nm) = text_metaphone(b.nm) -and a.oid <> b.oid\g - -CREATE FUNCTION text_mp_eq(text, text) RETURNS bool AS -'select text_metaphone($1) = text_metaphone($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_mp_lt(text,text) RETURNS bool AS -'select text_metaphone($1) < text_metaphone($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_mp_gt(text,text) RETURNS bool AS -'select text_metaphone($1) > text_metaphone($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_mp_le(text,text) RETURNS bool AS -'select text_metaphone($1) <= text_metaphone($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_mp_ge(text,text) RETURNS bool AS -'select text_metaphone($1) >= text_metaphone($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_mp_ne(text,text) RETURNS bool AS -'select text_metaphone($1) <> text_metaphone($2)' -LANGUAGE 'sql'; - -DROP OPERATOR #= (text,text)\g - -CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_mp_eq, -commutator=text_mp_eq)\g - -SELECT * -FROM s -WHERE text_mp_eq(nm,'pillsbury')\g - -SELECT * -from s -where s.nm #= 'pillsbury'; diff --git a/contrib/metaphone/metaphone.c b/contrib/metaphone/metaphone.c deleted file mode 100755 index 0306f9af82..0000000000 --- a/contrib/metaphone/metaphone.c +++ /dev/null @@ -1,321 +0,0 @@ - -#include "postgres.h" -#include "fmgr.h" -#include "utils/builtins.h" - -#include -#include -#include - -Datum text_metaphone(PG_FUNCTION_ARGS); -Datum text_metaphone_length(PG_FUNCTION_ARGS); - -void phonetic(char *name, char *metaph, int metalen); - -#define METAPHONE_LEN 50 -#undef METAPHONE_TEST - -#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) -#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str))) - -#define NULLCHAR (char *) 0 - -char *VOWELS="AEIOU", - *FRONTV="EIY", /* special cases for letters in FRONT of these */ - *VARSON="CSPTG", /* variable sound--those modified by adding an "h" */ - *DOUBLE="."; /* let these double letters through */ - -char *excpPAIR="AGKPW", /* exceptions "ae-", "gn-", "kn-", "pn-", "wr-" */ - *nextLTR ="ENNNR"; -char *chrptr, *chrptr1; - -void phonetic(name,metaph,metalen) -char *name, *metaph; -int metalen; -{ - -int ii, jj, silent, hard, Lng, lastChr; - -char curLtr, prevLtr, nextLtr, nextLtr2, nextLtr3; - -int vowelAfter, vowelBefore, frontvAfter; - -char wname[60]; -char *ename=wname; - - jj = 0; - for (ii=0; name[ii] != '\0'; ii++) { - if ( isalpha(name[ii]) ) { - ename[jj] = toupper(name[ii]); - jj++; - } - } - ename[jj] = '\0'; - - if (strlen(ename) == 0) return; - - /* if ae, gn, kn, pn, wr then drop the first letter */ - if ( (chrptr=strchr(excpPAIR,ename[0]) ) != NULLCHAR ) { - chrptr1 = nextLTR + (chrptr-excpPAIR); - if ( *chrptr1 == ename[1] ) strcpy(ename,&ename[1]); - } - /* change x to s */ - if (ename[0] == 'X') ename[0] = 'S'; - /* get rid of the "h" in "wh" */ - if ( strncmp(ename,"WH",2) == 0 ) strcpy(&ename[1], &ename[2]); - - Lng = strlen(ename); - lastChr = Lng -1; /* index to last character in string makes code easier*/ - - /* Remove an S from the end of the string */ - if ( ename[lastChr] == 'S' ) { - ename[lastChr] = '\0'; - Lng = strlen(ename); - lastChr = Lng -1; - } - - for (ii=0; ( (strlen(metaph) < metalen) && (ii < Lng) ); ii++) { - - curLtr = ename[ii]; - - vowelBefore = FALSE; prevLtr = ' '; - if (ii > 0) { - prevLtr = ename[ii-1]; - if ( strchr(VOWELS,prevLtr) != NULLCHAR ) vowelBefore = TRUE; - } - /* if first letter is a vowel KEEP it */ - if (ii == 0 && (strchr(VOWELS,curLtr) != NULLCHAR) ) { - strncat(metaph,&curLtr,1); - continue; - } - - vowelAfter = FALSE; frontvAfter = FALSE; nextLtr = ' '; - if ( ii < lastChr ) { - nextLtr = ename[ii+1]; - if ( strchr(VOWELS,nextLtr) != NULLCHAR ) vowelAfter = TRUE; - if ( strchr(FRONTV,nextLtr) != NULLCHAR ) frontvAfter = TRUE; - } - /* skip double letters except ones in list */ - if (curLtr == nextLtr && (strchr(DOUBLE,nextLtr) == NULLCHAR) ) continue; - - nextLtr2 = ' '; - if (ii < (lastChr-1) ) nextLtr2 = ename[ii+2]; - - nextLtr3 = ' '; - if (ii < (lastChr-2) ) nextLtr3 = ename[ii+3]; - - switch (curLtr) { - - case 'B': silent = FALSE; - if (ii == lastChr && prevLtr == 'M') silent = TRUE; - if (! silent) strncat(metaph,&curLtr,1); - break; - - /*silent -sci-,-sce-,-scy-; sci-, etc OK*/ - case 'C': if (! (ii > 1 && prevLtr == 'S' && frontvAfter) ) { - - if ( ii > 0 && nextLtr == 'I' && nextLtr2 == 'A' ) - strncat(metaph,"X",1); - else - if (frontvAfter) - strncat(metaph,"S",1); - else - if (ii > 1 && prevLtr == 'S' && nextLtr == 'H') - strncat(metaph,"K",1); - else - if (nextLtr == 'H') - if (ii == 0 && (strchr(VOWELS,nextLtr2) == NULLCHAR) ) - strncat(metaph,"K",1); - else - strncat(metaph,"X",1); - else - if (prevLtr == 'C') - strncat(metaph,"C",1); - else - strncat(metaph,"K",1); - } - break; - - case 'D': if (nextLtr == 'G' && (strchr(FRONTV,nextLtr2) != NULLCHAR)) - strncat(metaph,"J",1); - else - strncat(metaph,"T",1); - break; - - case 'G': silent=FALSE; - /* SILENT -gh- except for -gh and no vowel after h */ - if ( (ii < (lastChr-1) && nextLtr == 'H') - && (strchr(VOWELS,nextLtr2) == NULLCHAR) ) - silent=TRUE; - - if ( (ii == (lastChr-3) ) - && nextLtr == 'N' && nextLtr2 == 'E' && nextLtr3 == 'D') - silent=TRUE; - else - if ( (ii == (lastChr-1)) && nextLtr == 'N') silent=TRUE; - - if (prevLtr == 'D' && frontvAfter) silent=TRUE; - - if (prevLtr == 'G') - hard=TRUE; - else - hard=FALSE; - - if (!silent) { - if (frontvAfter && (! hard) ) - strncat(metaph,"J",1); - else - strncat(metaph,"K",1); - } - break; - - case 'H': silent = FALSE; - if ( strchr(VARSON,prevLtr) != NULLCHAR ) silent = TRUE; - - if ( vowelBefore && !vowelAfter) silent = TRUE; - - if (!silent) strncat(metaph,&curLtr,1); - break; - - case 'F': - case 'J': - case 'L': - case 'M': - case 'N': - case 'R': strncat(metaph,&curLtr,1); - break; - - case 'K': if (prevLtr != 'C') strncat(metaph,&curLtr,1); - break; - - case 'P': if (nextLtr == 'H') - strncat(metaph,"F",1); - else - strncat(metaph,"P",1); - break; - - case 'Q': strncat(metaph,"K",1); - break; - - case 'S': if (ii > 1 && nextLtr == 'I' - && ( nextLtr2 == 'O' || nextLtr2 == 'A') ) - strncat(metaph,"X",1); - else - if (nextLtr == 'H') - strncat(metaph,"X",1); - else - strncat(metaph,"S",1); - break; - - case 'T': if (ii > 1 && nextLtr == 'I' - && ( nextLtr2 == 'O' || nextLtr2 == 'A') ) - strncat(metaph,"X",1); - else - if (nextLtr == 'H') /* The=0, Tho=T, Withrow=0 */ - if (ii > 0 || (strchr(VOWELS,nextLtr2) != NULLCHAR) ) - strncat(metaph,"0",1); - else - strncat(metaph,"T",1); - else - if (! (ii < (lastChr-2) && nextLtr == 'C' && nextLtr2 == 'H')) - strncat(metaph,"T",1); - break; - - case 'V': strncat(metaph,"F",1); - break; - - case 'W': - case 'Y': if (ii < lastChr && vowelAfter) strncat(metaph,&curLtr,1); - break; - - case 'X': strncat(metaph,"KS",2); - break; - - case 'Z': strncat(metaph,"S",1); - break; - } - - } - -/* DON'T DO THIS NOW, REMOVING "S" IN BEGINNING HAS the same effect - with plurals, in addition imbedded S's in the Metaphone are included - Lng = strlen(metaph); - lastChr = Lng -1; - if ( metaph[lastChr] == 'S' && Lng >= 3 ) metaph[lastChr] = '\0'; -*/ - - return; -} - - -#ifdef METAPHONE_TEST -int -main(int argc, char *argv[]) -{ - if (argc < 2) - { - fprintf(stderr, "usage: %s string\n", argv[0]); - return 1; - } - else - { - char output[51]=""; - - phonetic(argv[1], output, 50); - printf("metaphone(%s) = %s\n", argv[1], output); - return 0; - } -} - -#endif /* METAPHONE_TEST */ - -#ifndef METAPHONE_TEST -/* - * SQL function: text_metaphone(text) returns text - */ -PG_FUNCTION_INFO_V1(text_metaphone); - -Datum -text_metaphone(PG_FUNCTION_ARGS) -{ - char outstr[51]=""; - char *arg; - - arg = _textout(PG_GETARG_TEXT_P(0)); - - phonetic(arg, outstr, 50); - - PG_RETURN_TEXT_P(_textin(outstr)); -} - -/* - char outstr[51]=""; - char *arg; - int32 metalen; - - arg = _textout(PG_GETARG_TEXT_P(0)); - metalen = PG_GETARG_INT32(1); - - - phonetic(arg, outstr, metalen); -*/ - -PG_FUNCTION_INFO_V1(text_metaphone_length); - -Datum -text_metaphone_length(PG_FUNCTION_ARGS) -{ - char outstr[51]=""; - char *arg; - int32 metalen; - - arg = _textout(PG_GETARG_TEXT_P(0)); - metalen = PG_GETARG_INT32(1); - - phonetic(arg, outstr, metalen); - - PG_RETURN_TEXT_P(_textin(outstr)); -} - - -#endif /* not METAPHONE_TEST */ diff --git a/contrib/metaphone/metaphone.sql.in b/contrib/metaphone/metaphone.sql.in deleted file mode 100755 index 65f680b2d5..0000000000 --- a/contrib/metaphone/metaphone.sql.in +++ /dev/null @@ -1,3 +0,0 @@ -CREATE FUNCTION text_soundex(text) RETURNS text - AS '@MODULE_FILENAME@', 'text_metaphone' LANGUAGE 'C'; - diff --git a/contrib/soundex/Makefile b/contrib/soundex/Makefile deleted file mode 100644 index 76538e052b..0000000000 --- a/contrib/soundex/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# -# $Header: /cvsroot/pgsql/contrib/soundex/Attic/Makefile,v 1.10 2001/06/18 21:38:02 momjian Exp $ -# - -subdir = contrib/soundex -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global - -NAME := soundex -SONAME := $(NAME)$(DLSUFFIX) - -override CPPFLAGS += -I$(srcdir) -override CFLAGS += $(CFLAGS_SL) -override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS) - -all: $(SONAME) $(NAME).sql - -$(NAME).sql: $(NAME).sql.in - sed 's,@MODULE_FILENAME@,$(libdir)/contrib/$(SONAME),g' $< >$@ - -install: all installdirs - $(INSTALL_SHLIB) $(SONAME) $(libdir)/contrib - $(INSTALL_DATA) $(NAME).sql $(datadir)/contrib - $(INSTALL_DATA) README.$(NAME) $(docdir)/contrib - -installdirs: - $(mkinstalldirs) $(libdir)/contrib $(datadir)/contrib $(docdir)/contrib - -uninstall: - rm -f $(libdir)/contrib/$(SONAME) $(datadir)/contrib/$(NAME).sql $(docdir)/contrib/README.$(NAME) - -clean distclean maintainer-clean: - rm -f $(SONAME) $(NAME).o $(NAME).sql - -depend dep: - $(CC) -MM -MG $(CFLAGS) *.c > depend - -ifeq (depend,$(wildcard depend)) -include depend -endif diff --git a/contrib/soundex/README.soundex b/contrib/soundex/README.soundex deleted file mode 100644 index a5b1fb3c44..0000000000 --- a/contrib/soundex/README.soundex +++ /dev/null @@ -1,66 +0,0 @@ -This directory contains a module that implements the "Soundex" code as -a PostgreSQL user-defined function. The Soundex system is a method of -matching similar sounding names (or any words) to the same code. It -was initially used by the United States Census in 1880, 1900, and -1910, but it has little use beyond English names (or the English -pronunciation of names), and it is not a linguistic tool. - -To install it, first configure the main source tree, then run make; -make install in this directory. Finally, load the function definition -with psql: - - psql -f PREFIX/share/contrib/soundex.sql - -The following are some usage examples: - -SELECT text_soundex('hello world!'); - -CREATE TABLE s (nm text)\g - -insert into s values ('john')\g -insert into s values ('joan')\g -insert into s values ('wobbly')\g - -select * from s -where text_soundex(nm) = text_soundex('john')\g - -select nm from s a, s b -where text_soundex(a.nm) = text_soundex(b.nm) -and a.oid <> b.oid\g - -CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS -'select text_soundex($1) = text_soundex($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS -'select text_soundex($1) < text_soundex($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS -'select text_soundex($1) > text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS -'select text_soundex($1) <= text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS -'select text_soundex($1) >= text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS -'select text_soundex($1) <> text_soundex($2)' -LANGUAGE 'sql'; - -DROP OPERATOR #= (text,text)\g - -CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, -commutator=text_sx_eq)\g - -SELECT * -FROM s -WHERE text_sx_eq(nm,'john')\g - -SELECT * -from s -where s.nm #= 'john'; diff --git a/contrib/soundex/soundex.c b/contrib/soundex/soundex.c deleted file mode 100644 index ff1b0f7aec..0000000000 --- a/contrib/soundex/soundex.c +++ /dev/null @@ -1,119 +0,0 @@ -/* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.11 2001/03/22 03:59:10 momjian Exp $ */ -#include "postgres.h" - -#include - -#include "fmgr.h" -#include "utils/builtins.h" - - -Datum text_soundex(PG_FUNCTION_ARGS); - -static void soundex(const char *instr, char *outstr); - -#define SOUNDEX_LEN 4 - - -#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) -#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str))) - - -#ifndef SOUNDEX_TEST -/* - * SQL function: text_soundex(text) returns text - */ -PG_FUNCTION_INFO_V1(text_soundex); - -Datum -text_soundex(PG_FUNCTION_ARGS) -{ - char outstr[SOUNDEX_LEN + 1]; - char *arg; - - arg = _textout(PG_GETARG_TEXT_P(0)); - - soundex(arg, outstr); - - PG_RETURN_TEXT_P(_textin(outstr)); -} - -#endif /* not SOUNDEX_TEST */ - - -/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ -static const char *soundex_table = "01230120022455012623010202"; - -#define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A'] - - -static void -soundex(const char *instr, char *outstr) -{ - int count; - - AssertArg(instr); - AssertArg(outstr); - - outstr[SOUNDEX_LEN] = '\0'; - - /* Skip leading non-alphabetic characters */ - while (!isalpha((unsigned char) instr[0]) && instr[0]) - ++instr; - - /* No string left */ - if (!instr[0]) - { - outstr[0] = (char) 0; - return; - } - - /* Take the first letter as is */ - *outstr++ = (char) toupper((unsigned char) *instr++); - - count = 1; - while (*instr && count < SOUNDEX_LEN) - { - if (isalpha((unsigned char) *instr) && - soundex_code(*instr) != soundex_code(*(instr - 1))) - { - *outstr = soundex_code(instr[0]); - if (*outstr != '0') - { - ++outstr; - ++count; - } - } - ++instr; - } - - /* Fill with 0's */ - while (count < SOUNDEX_LEN) - { - *outstr = '0'; - ++outstr; - ++count; - } -} - - - -#ifdef SOUNDEX_TEST -int -main(int argc, char *argv[]) -{ - if (argc < 2) - { - fprintf(stderr, "usage: %s string\n", argv[0]); - return 1; - } - else - { - char output[SOUNDEX_LEN + 1]; - - soundex(argv[1], output); - printf("soundex(%s) = %s\n", argv[1], output); - return 0; - } -} - -#endif /* SOUNDEX_TEST */ diff --git a/contrib/soundex/soundex.sql.in b/contrib/soundex/soundex.sql.in deleted file mode 100644 index 4805694f9a..0000000000 --- a/contrib/soundex/soundex.sql.in +++ /dev/null @@ -1,5 +0,0 @@ -CREATE FUNCTION text_soundex(text) RETURNS text - AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'C'; - -CREATE FUNCTION soundex(text) RETURNS text - AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'C';