]> granicus.if.org Git - postgresql/commitdiff
Fix contrib/pg_trgm's similarity() function for trigram-free strings.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 13 Feb 2013 19:07:22 +0000 (14:07 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 13 Feb 2013 19:07:22 +0000 (14:07 -0500)
Cases such as similarity('', '') produced a NaN result due to computing
0/0.  Per discussion, make it return zero instead.

This appears to be the basic cause of bug #7867 from Michele Baravalle,
although it remains unclear why her installation doesn't think Cyrillic
letters are letters.

Back-patch to all active branches.

contrib/pg_trgm/expected/pg_trgm.out
contrib/pg_trgm/sql/pg_trgm.sql
contrib/pg_trgm/trgm_op.c

index 98385347295d70f6b618d6ff40f0af733d54c17c..641e8cecf6b2f192f1067dffc4220a31cee957b6 100644 (file)
@@ -59,6 +59,12 @@ select similarity('wow',' WOW ');
           1
 (1 row)
 
+select similarity('---', '####---');
+ similarity 
+------------
+          0
+(1 row)
+
 CREATE TABLE test_trgm(t text);
 \copy test_trgm from 'data/trgm.data
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
index 13045827ac7734e09baa0e9c92aca9546022c61e..1bcf2c9146c8aff682d82667a60d94b121d52672 100644 (file)
@@ -19,6 +19,8 @@ select show_trgm('a b C0*%^');
 select similarity('wow','WOWa ');
 select similarity('wow',' WOW ');
 
+select similarity('---', '####---');
+
 CREATE TABLE test_trgm(t text);
 
 \copy test_trgm from 'data/trgm.data
index 19b6747d68b7d0b7b5ea172df6ef26540caf9b5c..30965f818cbcb77bc4cd792ad6a7750efb02025b 100644 (file)
@@ -311,6 +311,10 @@ cnt_sml(TRGM *trg1, TRGM *trg2)
        len1 = ARRNELEM(trg1);
        len2 = ARRNELEM(trg2);
 
+       /* explicit test is needed to avoid 0/0 division when both lengths are 0 */
+       if (len1 <= 0 || len2 <= 0)
+               return (float4) 0.0;
+
        while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2)
        {
                int                     res = CMPTRGM(ptr1, ptr2);
@@ -328,9 +332,9 @@ cnt_sml(TRGM *trg1, TRGM *trg2)
        }
 
 #ifdef DIVUNION
-       return ((((float4) count) / ((float4) (len1 + len2 - count))));
+       return ((float4) count) / ((float4) (len1 + len2 - count));
 #else
-       return (((float) count) / ((float) ((len1 > len2) ? len1 : len2)));
+       return ((float4) count) / ((float4) ((len1 > len2) ? len1 : len2));
 #endif
 
 }