LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - levenshtein.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: ba12a202ce1b5581dc0ed149cf3f637d7897ad5d vs 2866d8c7dbfc9d882a7d80fef93fbbe763709932 Lines: 95.3 % 107 102 5 1 101 1
Current Date: 2026-08-27 14:31:44 +0300 Functions: 100.0 % 2 2 2
Baseline: lcov-20260827-baseline Branches: 68.6 % 118 81 37 81
Baseline Date: 2026-08-27 14:31:58 +0300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 91.2 % 34 31 3 1 30
(30,360] days: 100.0 % 4 4 4
(360..) days: 97.1 % 69 67 2 67
Function coverage date bins:
(360..) days: 100.0 % 2 2 2
Branch coverage date bins:
(7,30] days: 88.9 % 18 16 2 16
(30,360] days: 75.0 % 4 3 1 3
(360..) days: 64.6 % 96 62 34 62

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * levenshtein.c
                                  4                 :                :  *    Levenshtein distance implementation.
                                  5                 :                :  *
                                  6                 :                :  * Original author:  Joe Conway <mail@joeconway.com>
                                  7                 :                :  *
                                  8                 :                :  * This file is included by varlena.c twice, to provide matching code for (1)
                                  9                 :                :  * Levenshtein distance with custom costings, and (2) Levenshtein distance with
                                 10                 :                :  * custom costings and a "max" value above which exact distances are not
                                 11                 :                :  * interesting.  Before the inclusion, we rely on the presence of the inline
                                 12                 :                :  * functions rest_of_char_same() and levenshtein_result().
                                 13                 :                :  *
                                 14                 :                :  * Written based on a description of the algorithm by Michael Gilleland found
                                 15                 :                :  * at http://www.merriampark.com/ld.htm.  Also looked at levenshtein.c in the
                                 16                 :                :  * PHP 4.0.6 distribution for inspiration.  Configurable penalty costs
                                 17                 :                :  * extension is introduced by Volkan YAZICI <volkan.yazici@gmail.com.
                                 18                 :                :  *
                                 19                 :                :  * Copyright (c) 2001-2026, PostgreSQL Global Development Group
                                 20                 :                :  *
                                 21                 :                :  * IDENTIFICATION
                                 22                 :                :  *  src/backend/utils/adt/levenshtein.c
                                 23                 :                :  *
                                 24                 :                :  *-------------------------------------------------------------------------
                                 25                 :                :  */
                                 26                 :                : #define MAX_LEVENSHTEIN_STRLEN      255
                                 27                 :                : 
                                 28                 :                : /*
                                 29                 :                :  * Calculates Levenshtein distance metric between supplied strings, which are
                                 30                 :                :  * not necessarily null-terminated.
                                 31                 :                :  *
                                 32                 :                :  * source: source string, of length slen bytes.
                                 33                 :                :  * target: target string, of length tlen bytes.
                                 34                 :                :  * ins_c, del_c, sub_c: costs to charge for character insertion, deletion,
                                 35                 :                :  *      and substitution respectively; (1, 1, 1) costs suffice for common
                                 36                 :                :  *      cases, but your mileage may vary.
                                 37                 :                :  * max_d: if provided and >= 0, maximum distance we care about; see below.
                                 38                 :                :  * trusted: caller is trusted and need not obey MAX_LEVENSHTEIN_STRLEN.
                                 39                 :                :  *
                                 40                 :                :  * One way to compute Levenshtein distance is to incrementally construct
                                 41                 :                :  * an (m+1)x(n+1) matrix where cell (i, j) represents the minimum number
                                 42                 :                :  * of operations required to transform the first i characters of s into
                                 43                 :                :  * the first j characters of t.  The last column of the final row is the
                                 44                 :                :  * answer.
                                 45                 :                :  *
                                 46                 :                :  * We use that algorithm here with some modification.  In lieu of holding
                                 47                 :                :  * the entire array in memory at once, we'll just use two arrays of size
                                 48                 :                :  * m+1 for storing accumulated values. At each step one array represents
                                 49                 :                :  * the "previous" row and one is the "current" row of the notional large
                                 50                 :                :  * array.
                                 51                 :                :  *
                                 52                 :                :  * If max_d >= 0, we only need to provide an accurate answer when that answer
                                 53                 :                :  * is less than or equal to max_d.  From any cell in the matrix, there is
                                 54                 :                :  * theoretical "minimum residual distance" from that cell to the last column
                                 55                 :                :  * of the final row.  This minimum residual distance is zero when the
                                 56                 :                :  * untransformed portions of the strings are of equal length (because we might
                                 57                 :                :  * get lucky and find all the remaining characters matching) and is otherwise
                                 58                 :                :  * based on the minimum number of insertions or deletions needed to make them
                                 59                 :                :  * equal length.  The residual distance grows as we move toward the upper
                                 60                 :                :  * right or lower left corners of the matrix.  When the max_d bound is
                                 61                 :                :  * usefully tight, we can use this property to avoid computing the entirety
                                 62                 :                :  * of each row; instead, we maintain a start_column and stop_column that
                                 63                 :                :  * identify the portion of the matrix close to the diagonal which can still
                                 64                 :                :  * affect the final answer.
                                 65                 :                :  */
                                 66                 :                : int
                                 67                 :                : #ifdef LEVENSHTEIN_LESS_EQUAL
 3870 tgl@sss.pgh.pa.us          68                 :CBC        1934 : varstr_levenshtein_less_equal(const char *source, int slen,
                                 69                 :                :                               const char *target, int tlen,
                                 70                 :                :                               int ins_c, int del_c, int sub_c,
                                 71                 :                :                               int max_d, bool trusted)
                                 72                 :                : #else
                                 73                 :              4 : varstr_levenshtein(const char *source, int slen,
                                 74                 :                :                    const char *target, int tlen,
                                 75                 :                :                    int ins_c, int del_c, int sub_c,
                                 76                 :                :                    bool trusted)
                                 77                 :                : #endif
                                 78                 :                : {
                                 79                 :                :     int         m,
                                 80                 :                :                 n;
                                 81                 :                :     int64      *prev;
                                 82                 :                :     int64      *curr;
 5791 rhaas@postgresql.org       83                 :           1938 :     int        *s_char_len = NULL;
                                 84                 :                :     int         j;
                                 85                 :                :     const char *y;
  232 tmunro@postgresql.or       86                 :           1938 :     const char *send = source + slen;
                                 87                 :           1938 :     const char *tend = target + tlen;
   17 nathan@postgresql.or       88                 :           1938 :     int64       ins_c_64 = ins_c;
                                 89                 :           1938 :     int64       del_c_64 = del_c;
                                 90                 :           1938 :     int64       sub_c_64 = sub_c;
                                 91                 :                : 
                                 92                 :                :     /*
                                 93                 :                :      * For varstr_levenshtein_less_equal, we have real variables called
                                 94                 :                :      * start_column and stop_column; otherwise it's just short-hand for 0 and
                                 95                 :                :      * m.
                                 96                 :                :      */
                                 97                 :                : #ifdef LEVENSHTEIN_LESS_EQUAL
                                 98                 :                :     int         start_column,
                                 99                 :                :                 stop_column;
                                100                 :                : 
                                101                 :                : #undef START_COLUMN
                                102                 :                : #undef STOP_COLUMN
                                103                 :                : #define START_COLUMN start_column
                                104                 :                : #define STOP_COLUMN stop_column
                                105                 :                : #else
                                106                 :                : #undef START_COLUMN
                                107                 :                : #undef STOP_COLUMN
                                108                 :                : #define START_COLUMN 0
                                109                 :                : #define STOP_COLUMN m
                                110                 :                : #endif
                                111                 :                : 
                                112                 :                :     /* Convert string lengths (in bytes) to lengths in characters */
 4305 rhaas@postgresql.org      113                 :           1938 :     m = pg_mbstrlen_with_len(source, slen);
                                114                 :           1938 :     n = pg_mbstrlen_with_len(target, tlen);
                                115                 :                : 
                                116                 :                :     /*
                                117                 :                :      * We can transform an empty s into t with n insertions, or a non-empty t
                                118                 :                :      * into an empty s with m deletions.
                                119                 :                :      */
 5791                           120   [ -  +  -  + ]:           1938 :     if (!m)
   17 nathan@postgresql.or      121                 :UBC           0 :         return levenshtein_result(n * ins_c_64);
 5791 rhaas@postgresql.org      122   [ -  +  -  + ]:CBC        1938 :     if (!n)
   17 nathan@postgresql.or      123                 :UBC           0 :         return levenshtein_result(m * del_c_64);
                                124                 :                : 
                                125                 :                :     /*
                                126                 :                :      * For security concerns, restrict excessive CPU+RAM usage. (This
                                127                 :                :      * implementation uses O(m) memory and has O(mn) complexity.)  If
                                128                 :                :      * "trusted" is true, caller is responsible for not making excessive
                                129                 :                :      * requests, typically by using a small max_d along with strings that are
                                130                 :                :      * bounded, though not necessarily to MAX_LEVENSHTEIN_STRLEN exactly.
                                131                 :                :      */
 3870 tgl@sss.pgh.pa.us         132   [ +  +  +  -  :CBC        1938 :     if (!trusted &&
                                        +  -  +  - ]
                                133   [ -  +  -  + ]:              7 :         (m > MAX_LEVENSHTEIN_STRLEN ||
                                134                 :                :          n > MAX_LEVENSHTEIN_STRLEN))
 5791 rhaas@postgresql.org      135   [ #  #  #  # ]:UBC           0 :         ereport(ERROR,
                                136                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                137                 :                :                  errmsg("levenshtein argument exceeds maximum length of %d characters",
                                138                 :                :                         MAX_LEVENSHTEIN_STRLEN)));
                                139                 :                : 
                                140                 :                : #ifdef LEVENSHTEIN_LESS_EQUAL
                                141                 :                :     /* Initialize start and stop columns. */
 5791 rhaas@postgresql.org      142                 :CBC        1934 :     start_column = 0;
                                143                 :           1934 :     stop_column = m + 1;
                                144                 :                : 
                                145                 :                :     /*
                                146                 :                :      * If max_d >= 0, determine whether the bound is impossibly tight.  If so,
                                147                 :                :      * return max_d + 1 immediately.  Otherwise, determine whether it's tight
                                148                 :                :      * enough to limit the computation we must perform.  If so, figure out
                                149                 :                :      * initial stop column.
                                150                 :                :      */
                                151         [ +  - ]:           1934 :     if (max_d >= 0)
                                152                 :                :     {
                                153                 :                :         int64       min_theo_d; /* Theoretical minimum distance. */
                                154                 :                :         int64       max_theo_d; /* Theoretical maximum distance. */
 5618 bruce@momjian.us          155                 :           1934 :         int         net_inserts = n - m;
                                156                 :                : 
 5791 rhaas@postgresql.org      157                 :           1934 :         min_theo_d = net_inserts < 0 ?
   17 nathan@postgresql.or      158         [ +  + ]:           1934 :             -net_inserts * del_c_64 : net_inserts * ins_c_64;
 5791 rhaas@postgresql.org      159         [ +  + ]:           1934 :         if (min_theo_d > max_d)
   17 nathan@postgresql.or      160                 :            693 :             return levenshtein_result((int64) max_d + 1);
                                161         [ -  + ]:           1241 :         if (ins_c_64 + del_c_64 < sub_c_64)
   17 nathan@postgresql.or      162                 :UBC           0 :             sub_c_64 = ins_c_64 + del_c_64;
   17 nathan@postgresql.or      163                 :CBC        1241 :         max_theo_d = min_theo_d + sub_c_64 * Min(m, n);
 5791 rhaas@postgresql.org      164         [ +  + ]:           1241 :         if (max_d >= max_theo_d)
                                165                 :            381 :             max_d = -1;
   17 nathan@postgresql.or      166         [ +  - ]:            860 :         else if (ins_c_64 + del_c_64 > 0)
                                167                 :                :         {
                                168                 :                :             /*
                                169                 :                :              * Figure out how much of the first row of the notional matrix we
                                170                 :                :              * need to fill in.  If the string is growing, the theoretical
                                171                 :                :              * minimum distance already incorporates the cost of deleting the
                                172                 :                :              * number of characters necessary to make the two strings equal in
                                173                 :                :              * length.  Each additional deletion forces another insertion, so
                                174                 :                :              * the best-case total cost increases by ins_c + del_c. If the
                                175                 :                :              * string is shrinking, the minimum theoretical cost assumes no
                                176                 :                :              * excess deletions; that is, we're starting no further right than
                                177                 :                :              * column n - m.  If we do start further right, the best-case
                                178                 :                :              * total cost increases by ins_c + del_c for each move right.
                                179                 :                :              */
                                180                 :            860 :             int64       slack_d = max_d - min_theo_d;
 5618 bruce@momjian.us          181         [ +  + ]:            860 :             int         best_column = net_inserts < 0 ? -net_inserts : 0;
                                182                 :                :             int64       tmp;
                                183                 :                : 
   17 nathan@postgresql.or      184                 :            860 :             tmp = best_column + (slack_d / (ins_c_64 + del_c_64)) + 1;
                                185                 :            860 :             stop_column = Min(tmp, m + 1);
                                186                 :                :         }
                                187                 :                :     }
                                188                 :                : #endif
                                189                 :                : 
                                190                 :                :     /*
                                191                 :                :      * In order to avoid calling pg_mblen_range() repeatedly on each character
                                192                 :                :      * in s, we cache all the lengths before starting the main loop -- but if
                                193                 :                :      * all the characters in both strings are single byte, then we skip this
                                194                 :                :      * and use a fast-path in the main loop.  If only one string contains
                                195                 :                :      * multi-byte characters, we still build the array, so that the fast-path
                                196                 :                :      * needn't deal with the case where the array hasn't been initialized.
                                197                 :                :      */
 4305 rhaas@postgresql.org      198   [ +  -  +  +  :           1245 :     if (m != slen || n != tlen)
                                        +  -  -  + ]
                                199                 :                :     {
                                200                 :                :         int         i;
                                201                 :              4 :         const char *cp = source;
                                202                 :                : 
   10 michael@paquier.xyz       203                 :GNC           4 :         s_char_len = palloc_array(int, m + 1);
 5791 rhaas@postgresql.org      204   [ +  +  -  - ]:CBC          40 :         for (i = 0; i < m; ++i)
                                205                 :                :         {
  232 tmunro@postgresql.or      206                 :             36 :             s_char_len[i] = pg_mblen_range(cp, send);
 5791 rhaas@postgresql.org      207                 :             36 :             cp += s_char_len[i];
                                208                 :                :         }
                                209                 :              4 :         s_char_len[i] = 0;
                                210                 :                :     }
                                211                 :                : 
                                212                 :                :     /* One more cell for initialization column and row. */
                                213                 :           1245 :     ++m;
                                214                 :           1245 :     ++n;
                                215                 :                : 
                                216                 :                :     /* Previous and current rows of notional array. */
   17 nathan@postgresql.or      217                 :           1245 :     prev = (int64 *) palloc(2 * m * sizeof(int64));
 5791 rhaas@postgresql.org      218                 :           1245 :     curr = prev + m;
                                219                 :                : 
                                220                 :                :     /*
                                221                 :                :      * To transform the first i characters of s into the first 0 characters of
                                222                 :                :      * t, we must perform i deletions.
                                223                 :                :      */
 1464 drowley@postgresql.o      224   [ +  +  +  + ]:           4844 :     for (int i = START_COLUMN; i < STOP_COLUMN; i++)
   17 nathan@postgresql.or      225                 :           3599 :         prev[i] = i * del_c_64;
                                226                 :                : 
                                227                 :                :     /* Loop through rows of the notional array */
 4305 rhaas@postgresql.org      228   [ +  +  +  + ]:           4848 :     for (y = target, j = 1; j < n; j++)
                                229                 :                :     {
                                230                 :                :         int64      *temp;
                                231                 :           4332 :         const char *x = source;
  232 tmunro@postgresql.or      232   [ +  +  -  + ]:           4332 :         int         y_char_len = n != tlen + 1 ? pg_mblen_range(y, tend) : 1;
                                233                 :                :         int         i;
                                234                 :                : 
                                235                 :                : #ifdef LEVENSHTEIN_LESS_EQUAL
                                236                 :                : 
                                237                 :                :         /*
                                238                 :                :          * In the best case, values percolate down the diagonal unchanged, so
                                239                 :                :          * we must increment stop_column unless it's already on the right end
                                240                 :                :          * of the array.  The inner loop will read prev[stop_column], so we
                                241                 :                :          * have to initialize it even though it shouldn't affect the result.
                                242                 :                :          */
 5791 rhaas@postgresql.org      243         [ +  + ]:           4308 :         if (stop_column < m)
                                244                 :                :         {
   17 nathan@postgresql.or      245                 :           3446 :             prev[stop_column] = (int64) max_d + 1;
 5791 rhaas@postgresql.org      246                 :           3446 :             ++stop_column;
                                247                 :                :         }
                                248                 :                : 
                                249                 :                :         /*
                                250                 :                :          * The main loop fills in curr, but curr[0] needs a special case: to
                                251                 :                :          * transform the first 0 characters of s into the first j characters
                                252                 :                :          * of t, we must perform j insertions.  However, if start_column > 0,
                                253                 :                :          * this special case does not apply.
                                254                 :                :          */
                                255         [ +  + ]:           4308 :         if (start_column == 0)
                                256                 :                :         {
   17 nathan@postgresql.or      257                 :           2762 :             curr[0] = j * ins_c_64;
 5791 rhaas@postgresql.org      258                 :           2762 :             i = 1;
                                259                 :                :         }
                                260                 :                :         else
                                261                 :           1546 :             i = start_column;
                                262                 :                : #else
   17 nathan@postgresql.or      263                 :             24 :         curr[0] = j * ins_c_64;
 5791 rhaas@postgresql.org      264                 :             24 :         i = 1;
                                265                 :                : #endif
                                266                 :                : 
                                267                 :                :         /*
                                268                 :                :          * This inner loop is critical to performance, so we include a
                                269                 :                :          * fast-path to handle the (fairly common) case where no multibyte
                                270                 :                :          * characters are in the mix.  The fast-path is entitled to assume
                                271                 :                :          * that if s_char_len is not initialized then BOTH strings contain
                                272                 :                :          * only single-byte characters.
                                273                 :                :          */
                                274   [ +  +  -  + ]:           4332 :         if (s_char_len != NULL)
                                275                 :                :         {
                                276   [ +  +  -  - ]:            248 :             for (; i < STOP_COLUMN; i++)
                                277                 :                :             {
                                278                 :                :                 int64       ins;
                                279                 :                :                 int64       del;
                                280                 :                :                 int64       sub;
                                281                 :            208 :                 int         x_char_len = s_char_len[i - 1];
                                282                 :                : 
                                283                 :                :                 /*
                                284                 :                :                  * Calculate costs for insertion, deletion, and substitution.
                                285                 :                :                  *
                                286                 :                :                  * When calculating cost for substitution, we compare the last
                                287                 :                :                  * character of each possibly-multibyte character first,
                                288                 :                :                  * because that's enough to rule out most mis-matches.  If we
                                289                 :                :                  * get past that test, then we compare the lengths and the
                                290                 :                :                  * remaining bytes.
                                291                 :                :                  */
   17 nathan@postgresql.or      292                 :            208 :                 ins = prev[i] + ins_c_64;
                                293                 :            208 :                 del = curr[i - 1] + del_c_64;
 5618 bruce@momjian.us          294   [ +  +  -  - ]:            208 :                 if (x[x_char_len - 1] == y[y_char_len - 1]
 5791 rhaas@postgresql.org      295   [ +  -  -  +  :             36 :                     && x_char_len == y_char_len &&
                                        -  -  -  - ]
 5791 rhaas@postgresql.org      296   [ #  #  #  # ]:UBC           0 :                     (x_char_len == 1 || rest_of_char_same(x, y, x_char_len)))
 5791 rhaas@postgresql.org      297                 :CBC          36 :                     sub = prev[i - 1];
                                298                 :                :                 else
   17 nathan@postgresql.or      299                 :            172 :                     sub = prev[i - 1] + sub_c_64;
                                300                 :                : 
                                301                 :                :                 /* Take the one with minimum cost. */
 5791 rhaas@postgresql.org      302                 :            208 :                 curr[i] = Min(ins, del);
                                303                 :            208 :                 curr[i] = Min(curr[i], sub);
                                304                 :                : 
                                305                 :                :                 /* Point to next character. */
                                306                 :            208 :                 x += x_char_len;
                                307                 :                :             }
                                308                 :                :         }
                                309                 :                :         else
                                310                 :                :         {
                                311   [ +  +  +  + ]:          17372 :             for (; i < STOP_COLUMN; i++)
                                312                 :                :             {
                                313                 :                :                 int64       ins;
                                314                 :                :                 int64       del;
                                315                 :                :                 int64       sub;
                                316                 :                : 
                                317                 :                :                 /* Calculate costs for insertion, deletion, and substitution. */
   17 nathan@postgresql.or      318                 :          13080 :                 ins = prev[i] + ins_c_64;
                                319                 :          13080 :                 del = curr[i - 1] + del_c_64;
                                320   [ +  +  +  + ]:          13080 :                 sub = prev[i - 1] + ((*x == *y) ? 0 : sub_c_64);
                                321                 :                : 
                                322                 :                :                 /* Take the one with minimum cost. */
 5791 rhaas@postgresql.org      323                 :          13080 :                 curr[i] = Min(ins, del);
                                324                 :          13080 :                 curr[i] = Min(curr[i], sub);
                                325                 :                : 
                                326                 :                :                 /* Point to next character. */
                                327                 :          13080 :                 x++;
                                328                 :                :             }
                                329                 :                :         }
                                330                 :                : 
                                331                 :                :         /* Swap current row with previous row. */
                                332                 :           4332 :         temp = curr;
                                333                 :           4332 :         curr = prev;
                                334                 :           4332 :         prev = temp;
                                335                 :                : 
                                336                 :                :         /* Point to next character. */
                                337                 :             24 :         y += y_char_len;
                                338                 :                : 
                                339                 :                : #ifdef LEVENSHTEIN_LESS_EQUAL
                                340                 :                : 
                                341                 :                :         /*
                                342                 :                :          * This chunk of code represents a significant performance hit if used
                                343                 :                :          * in the case where there is no max_d bound.  This is probably not
                                344                 :                :          * because the max_d >= 0 test itself is expensive, but rather because
                                345                 :                :          * the possibility of needing to execute this code prevents tight
                                346                 :                :          * optimization of the loop as a whole.
                                347                 :                :          */
                                348         [ +  + ]:           4308 :         if (max_d >= 0)
                                349                 :                :         {
                                350                 :                :             /*
                                351                 :                :              * The "zero point" is the column of the current row where the
                                352                 :                :              * remaining portions of the strings are of equal length.  There
                                353                 :                :              * are (n - 1) characters in the target string, of which j have
                                354                 :                :              * been transformed.  There are (m - 1) characters in the source
                                355                 :                :              * string, so we want to find the value for zp where (n - 1) - j =
                                356                 :                :              * (m - 1) - zp.
                                357                 :                :              */
 5618 bruce@momjian.us          358                 :           3552 :             int         zp = j - (n - m);
                                359                 :                : 
                                360                 :                :             /* Check whether the stop column can slide left. */
 5791 rhaas@postgresql.org      361         [ +  + ]:           8523 :             while (stop_column > 0)
                                362                 :                :             {
 5618 bruce@momjian.us          363                 :           7794 :                 int         ii = stop_column - 1;
                                364                 :           7794 :                 int         net_inserts = ii - zp;
                                365                 :                : 
   17 nathan@postgresql.or      366         [ +  + ]:           7794 :                 if (prev[ii] + (net_inserts > 0 ? net_inserts * ins_c_64 :
                                367         [ +  + ]:           7794 :                                 -net_inserts * del_c_64) <= max_d)
 5791 rhaas@postgresql.org      368                 :           2823 :                     break;
                                369                 :           4971 :                 stop_column--;
                                370                 :                :             }
                                371                 :                : 
                                372                 :                :             /* Check whether the start column can slide right. */
                                373         [ +  + ]:           5857 :             while (start_column < stop_column)
                                374                 :                :             {
 5618 bruce@momjian.us          375                 :           5128 :                 int         net_inserts = start_column - zp;
                                376                 :                : 
 5791 rhaas@postgresql.org      377                 :          10256 :                 if (prev[start_column] +
   17 nathan@postgresql.or      378         [ +  + ]:           5128 :                     (net_inserts > 0 ? net_inserts * ins_c_64 :
                                379         [ +  + ]:           5128 :                      -net_inserts * del_c_64) <= max_d)
 5791 rhaas@postgresql.org      380                 :           2823 :                     break;
                                381                 :                : 
                                382                 :                :                 /*
                                383                 :                :                  * We'll never again update these values, so we must make sure
                                384                 :                :                  * there's nothing here that could confuse any future
                                385                 :                :                  * iteration of the outer loop.
                                386                 :                :                  */
   17 nathan@postgresql.or      387                 :           2305 :                 prev[start_column] = (int64) max_d + 1;
                                388                 :           2305 :                 curr[start_column] = (int64) max_d + 1;
 5791 rhaas@postgresql.org      389         [ +  + ]:           2305 :                 if (start_column != 0)
 4305                           390         [ +  + ]:           1579 :                     source += (s_char_len != NULL) ? s_char_len[start_column - 1] : 1;
 5791                           391                 :           2305 :                 start_column++;
                                392                 :                :             }
                                393                 :                : 
                                394                 :                :             /* If they cross, we're going to exceed the bound. */
                                395         [ +  + ]:           3552 :             if (start_column >= stop_column)
   17 nathan@postgresql.or      396                 :            729 :                 return levenshtein_result((int64) max_d + 1);
                                397                 :                :         }
                                398                 :                : #endif
                                399                 :                :     }
                                400                 :                : 
                                401                 :                :     /*
                                402                 :                :      * Because the final value was swapped from the previous row to the
                                403                 :                :      * current row, that's where we'll find it.
                                404                 :                :      */
                                405                 :            516 :     return levenshtein_result(prev[m - 1]);
                                406                 :                : }
        

Generated by: LCOV version 2.0-1