LCOV - differential code coverage report
Current view: top level - contrib/citext - citext.c (source / functions) Coverage Total Hit GIC GNC CBC ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 100.0 % 156 156 106 1 49 107
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 35 35 35 35
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  * contrib/citext/citext.c
       3                 :  */
       4                 : #include "postgres.h"
       5                 : 
       6                 : #include "catalog/pg_collation.h"
       7                 : #include "common/hashfn.h"
       8                 : #include "utils/builtins.h"
       9                 : #include "utils/formatting.h"
      10                 : #include "utils/varlena.h"
      11                 : #include "varatt.h"
      12                 : 
      13 GIC           2 : PG_MODULE_MAGIC;
      14 ECB             : 
      15                 : /*
      16                 :  *      ====================
      17                 :  *      FORWARD DECLARATIONS
      18                 :  *      ====================
      19                 :  */
      20                 : 
      21                 : static int32 citextcmp(text *left, text *right, Oid collid);
      22                 : static int32 internal_citext_pattern_cmp(text *left, text *right, Oid collid);
      23                 : 
      24                 : /*
      25                 :  *      =================
      26                 :  *      UTILITY FUNCTIONS
      27                 :  *      =================
      28                 :  */
      29                 : 
      30                 : /*
      31                 :  * citextcmp()
      32                 :  * Internal comparison function for citext strings.
      33                 :  * Returns int32 negative, zero, or positive.
      34                 :  */
      35                 : static int32
      36 GIC         159 : citextcmp(text *left, text *right, Oid collid)
      37 ECB             : {
      38                 :     char       *lcstr,
      39                 :                *rcstr;
      40                 :     int32       result;
      41                 : 
      42                 :     /*
      43                 :      * We must do our str_tolower calls with DEFAULT_COLLATION_OID, not the
      44                 :      * input collation as you might expect.  This is so that the behavior of
      45                 :      * citext's equality and hashing functions is not collation-dependent.  We
      46                 :      * should change this once the core infrastructure is able to cope with
      47                 :      * collation-dependent equality and hashing functions.
      48                 :      */
      49                 : 
      50 GIC         159 :     lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
      51 CBC         159 :     rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
      52 ECB             : 
      53 GIC         159 :     result = varstr_cmp(lcstr, strlen(lcstr),
      54 CBC         159 :                         rcstr, strlen(rcstr),
      55 ECB             :                         collid);
      56                 : 
      57 GIC         159 :     pfree(lcstr);
      58 CBC         159 :     pfree(rcstr);
      59 ECB             : 
      60 GIC         159 :     return result;
      61 ECB             : }
      62                 : 
      63                 : /*
      64                 :  * citext_pattern_cmp()
      65                 :  * Internal character-by-character comparison function for citext strings.
      66                 :  * Returns int32 negative, zero, or positive.
      67                 :  */
      68                 : static int32
      69 GIC          51 : internal_citext_pattern_cmp(text *left, text *right, Oid collid)
      70 ECB             : {
      71                 :     char       *lcstr,
      72                 :                *rcstr;
      73                 :     int         llen,
      74                 :                 rlen;
      75                 :     int32       result;
      76                 : 
      77 GIC          51 :     lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
      78 CBC          51 :     rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
      79 ECB             : 
      80 GIC          51 :     llen = strlen(lcstr);
      81 CBC          51 :     rlen = strlen(rcstr);
      82 ECB             : 
      83 GNC          51 :     result = memcmp(lcstr, rcstr, Min(llen, rlen));
      84 CBC          51 :     if (result == 0)
      85 ECB             :     {
      86 GIC          16 :         if (llen < rlen)
      87 CBC           1 :             result = -1;
      88              15 :         else if (llen > rlen)
      89               1 :             result = 1;
      90 ECB             :     }
      91                 : 
      92 GIC          51 :     pfree(lcstr);
      93 CBC          51 :     pfree(rcstr);
      94 ECB             : 
      95 GIC          51 :     return result;
      96 ECB             : }
      97                 : 
      98                 : /*
      99                 :  *      ==================
     100                 :  *      INDEXING FUNCTIONS
     101                 :  *      ==================
     102                 :  */
     103                 : 
     104 GIC           4 : PG_FUNCTION_INFO_V1(citext_cmp);
     105 ECB             : 
     106                 : Datum
     107 GIC         140 : citext_cmp(PG_FUNCTION_ARGS)
     108 ECB             : {
     109 GIC         140 :     text       *left = PG_GETARG_TEXT_PP(0);
     110 CBC         140 :     text       *right = PG_GETARG_TEXT_PP(1);
     111 ECB             :     int32       result;
     112                 : 
     113 GIC         140 :     result = citextcmp(left, right, PG_GET_COLLATION());
     114 ECB             : 
     115 GIC         140 :     PG_FREE_IF_COPY(left, 0);
     116 CBC         140 :     PG_FREE_IF_COPY(right, 1);
     117 ECB             : 
     118 GIC         140 :     PG_RETURN_INT32(result);
     119 ECB             : }
     120                 : 
     121 GIC           4 : PG_FUNCTION_INFO_V1(citext_pattern_cmp);
     122 ECB             : 
     123                 : Datum
     124 GIC          11 : citext_pattern_cmp(PG_FUNCTION_ARGS)
     125 ECB             : {
     126 GIC          11 :     text       *left = PG_GETARG_TEXT_PP(0);
     127 CBC          11 :     text       *right = PG_GETARG_TEXT_PP(1);
     128 ECB             :     int32       result;
     129                 : 
     130 GIC          11 :     result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION());
     131 ECB             : 
     132 GIC          11 :     PG_FREE_IF_COPY(left, 0);
     133 CBC          11 :     PG_FREE_IF_COPY(right, 1);
     134 ECB             : 
     135 GIC          11 :     PG_RETURN_INT32(result);
     136 ECB             : }
     137                 : 
     138 GIC           3 : PG_FUNCTION_INFO_V1(citext_hash);
     139 ECB             : 
     140                 : Datum
     141 GIC          10 : citext_hash(PG_FUNCTION_ARGS)
     142 ECB             : {
     143 GIC          10 :     text       *txt = PG_GETARG_TEXT_PP(0);
     144 ECB             :     char       *str;
     145                 :     Datum       result;
     146                 : 
     147 GIC          10 :     str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
     148 CBC          10 :     result = hash_any((unsigned char *) str, strlen(str));
     149              10 :     pfree(str);
     150 ECB             : 
     151                 :     /* Avoid leaking memory for toasted inputs */
     152 GIC          10 :     PG_FREE_IF_COPY(txt, 0);
     153 ECB             : 
     154 GIC          10 :     PG_RETURN_DATUM(result);
     155 ECB             : }
     156                 : 
     157 GIC           3 : PG_FUNCTION_INFO_V1(citext_hash_extended);
     158 ECB             : 
     159                 : Datum
     160 GIC          10 : citext_hash_extended(PG_FUNCTION_ARGS)
     161 ECB             : {
     162 GIC          10 :     text       *txt = PG_GETARG_TEXT_PP(0);
     163 CBC          10 :     uint64      seed = PG_GETARG_INT64(1);
     164 ECB             :     char       *str;
     165                 :     Datum       result;
     166                 : 
     167 GIC          10 :     str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
     168 CBC          10 :     result = hash_any_extended((unsigned char *) str, strlen(str), seed);
     169              10 :     pfree(str);
     170 ECB             : 
     171                 :     /* Avoid leaking memory for toasted inputs */
     172 GIC          10 :     PG_FREE_IF_COPY(txt, 0);
     173 ECB             : 
     174 GIC          10 :     PG_RETURN_DATUM(result);
     175 ECB             : }
     176                 : 
     177                 : /*
     178                 :  *      ==================
     179                 :  *      OPERATOR FUNCTIONS
     180                 :  *      ==================
     181                 :  */
     182                 : 
     183 GIC           4 : PG_FUNCTION_INFO_V1(citext_eq);
     184 ECB             : 
     185                 : Datum
     186 GIC          80 : citext_eq(PG_FUNCTION_ARGS)
     187 ECB             : {
     188 GIC          80 :     text       *left = PG_GETARG_TEXT_PP(0);
     189 CBC          80 :     text       *right = PG_GETARG_TEXT_PP(1);
     190 ECB             :     char       *lcstr,
     191                 :                *rcstr;
     192                 :     bool        result;
     193                 : 
     194                 :     /* We can't compare lengths in advance of downcasing ... */
     195                 : 
     196 GIC          80 :     lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
     197 CBC          80 :     rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
     198 ECB             : 
     199                 :     /*
     200                 :      * Since we only care about equality or not-equality, we can avoid all the
     201                 :      * expense of strcoll() here, and just do bitwise comparison.
     202                 :      */
     203 GIC          80 :     result = (strcmp(lcstr, rcstr) == 0);
     204 ECB             : 
     205 GIC          80 :     pfree(lcstr);
     206 CBC          80 :     pfree(rcstr);
     207              80 :     PG_FREE_IF_COPY(left, 0);
     208              80 :     PG_FREE_IF_COPY(right, 1);
     209 ECB             : 
     210 GIC          80 :     PG_RETURN_BOOL(result);
     211 ECB             : }
     212                 : 
     213 GIC           3 : PG_FUNCTION_INFO_V1(citext_ne);
     214 ECB             : 
     215                 : Datum
     216 GIC          17 : citext_ne(PG_FUNCTION_ARGS)
     217 ECB             : {
     218 GIC          17 :     text       *left = PG_GETARG_TEXT_PP(0);
     219 CBC          17 :     text       *right = PG_GETARG_TEXT_PP(1);
     220 ECB             :     char       *lcstr,
     221                 :                *rcstr;
     222                 :     bool        result;
     223                 : 
     224                 :     /* We can't compare lengths in advance of downcasing ... */
     225                 : 
     226 GIC          17 :     lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
     227 CBC          17 :     rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
     228 ECB             : 
     229                 :     /*
     230                 :      * Since we only care about equality or not-equality, we can avoid all the
     231                 :      * expense of strcoll() here, and just do bitwise comparison.
     232                 :      */
     233 GIC          17 :     result = (strcmp(lcstr, rcstr) != 0);
     234 ECB             : 
     235 GIC          17 :     pfree(lcstr);
     236 CBC          17 :     pfree(rcstr);
     237              17 :     PG_FREE_IF_COPY(left, 0);
     238              17 :     PG_FREE_IF_COPY(right, 1);
     239 ECB             : 
     240 GIC          17 :     PG_RETURN_BOOL(result);
     241 ECB             : }
     242                 : 
     243 GIC           3 : PG_FUNCTION_INFO_V1(citext_lt);
     244 ECB             : 
     245                 : Datum
     246 GIC           1 : citext_lt(PG_FUNCTION_ARGS)
     247 ECB             : {
     248 GIC           1 :     text       *left = PG_GETARG_TEXT_PP(0);
     249 CBC           1 :     text       *right = PG_GETARG_TEXT_PP(1);
     250 ECB             :     bool        result;
     251                 : 
     252 GIC           1 :     result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
     253 ECB             : 
     254 GIC           1 :     PG_FREE_IF_COPY(left, 0);
     255 CBC           1 :     PG_FREE_IF_COPY(right, 1);
     256 ECB             : 
     257 GIC           1 :     PG_RETURN_BOOL(result);
     258 ECB             : }
     259                 : 
     260 GIC           3 : PG_FUNCTION_INFO_V1(citext_le);
     261 ECB             : 
     262                 : Datum
     263 GIC           1 : citext_le(PG_FUNCTION_ARGS)
     264 ECB             : {
     265 GIC           1 :     text       *left = PG_GETARG_TEXT_PP(0);
     266 CBC           1 :     text       *right = PG_GETARG_TEXT_PP(1);
     267 ECB             :     bool        result;
     268                 : 
     269 GIC           1 :     result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
     270 ECB             : 
     271 GIC           1 :     PG_FREE_IF_COPY(left, 0);
     272 CBC           1 :     PG_FREE_IF_COPY(right, 1);
     273 ECB             : 
     274 GIC           1 :     PG_RETURN_BOOL(result);
     275 ECB             : }
     276                 : 
     277 GIC           3 : PG_FUNCTION_INFO_V1(citext_gt);
     278 ECB             : 
     279                 : Datum
     280 GIC           3 : citext_gt(PG_FUNCTION_ARGS)
     281 ECB             : {
     282 GIC           3 :     text       *left = PG_GETARG_TEXT_PP(0);
     283 CBC           3 :     text       *right = PG_GETARG_TEXT_PP(1);
     284 ECB             :     bool        result;
     285                 : 
     286 GIC           3 :     result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
     287 ECB             : 
     288 GIC           3 :     PG_FREE_IF_COPY(left, 0);
     289 CBC           3 :     PG_FREE_IF_COPY(right, 1);
     290 ECB             : 
     291 GIC           3 :     PG_RETURN_BOOL(result);
     292 ECB             : }
     293                 : 
     294 GIC           3 : PG_FUNCTION_INFO_V1(citext_ge);
     295 ECB             : 
     296                 : Datum
     297 GIC           1 : citext_ge(PG_FUNCTION_ARGS)
     298 ECB             : {
     299 GIC           1 :     text       *left = PG_GETARG_TEXT_PP(0);
     300 CBC           1 :     text       *right = PG_GETARG_TEXT_PP(1);
     301 ECB             :     bool        result;
     302                 : 
     303 GIC           1 :     result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
     304 ECB             : 
     305 GIC           1 :     PG_FREE_IF_COPY(left, 0);
     306 CBC           1 :     PG_FREE_IF_COPY(right, 1);
     307 ECB             : 
     308 GIC           1 :     PG_RETURN_BOOL(result);
     309 ECB             : }
     310                 : 
     311 GIC           3 : PG_FUNCTION_INFO_V1(citext_pattern_lt);
     312 ECB             : 
     313                 : Datum
     314 GIC           8 : citext_pattern_lt(PG_FUNCTION_ARGS)
     315 ECB             : {
     316 GIC           8 :     text       *left = PG_GETARG_TEXT_PP(0);
     317 CBC           8 :     text       *right = PG_GETARG_TEXT_PP(1);
     318 ECB             :     bool        result;
     319                 : 
     320 GIC           8 :     result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) < 0;
     321 ECB             : 
     322 GIC           8 :     PG_FREE_IF_COPY(left, 0);
     323 CBC           8 :     PG_FREE_IF_COPY(right, 1);
     324 ECB             : 
     325 GIC           8 :     PG_RETURN_BOOL(result);
     326 ECB             : }
     327                 : 
     328 GIC           3 : PG_FUNCTION_INFO_V1(citext_pattern_le);
     329 ECB             : 
     330                 : Datum
     331 GIC          12 : citext_pattern_le(PG_FUNCTION_ARGS)
     332 ECB             : {
     333 GIC          12 :     text       *left = PG_GETARG_TEXT_PP(0);
     334 CBC          12 :     text       *right = PG_GETARG_TEXT_PP(1);
     335 ECB             :     bool        result;
     336                 : 
     337 GIC          12 :     result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) <= 0;
     338 ECB             : 
     339 GIC          12 :     PG_FREE_IF_COPY(left, 0);
     340 CBC          12 :     PG_FREE_IF_COPY(right, 1);
     341 ECB             : 
     342 GIC          12 :     PG_RETURN_BOOL(result);
     343 ECB             : }
     344                 : 
     345 GIC           3 : PG_FUNCTION_INFO_V1(citext_pattern_gt);
     346 ECB             : 
     347                 : Datum
     348 GIC           9 : citext_pattern_gt(PG_FUNCTION_ARGS)
     349 ECB             : {
     350 GIC           9 :     text       *left = PG_GETARG_TEXT_PP(0);
     351 CBC           9 :     text       *right = PG_GETARG_TEXT_PP(1);
     352 ECB             :     bool        result;
     353                 : 
     354 GIC           9 :     result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) > 0;
     355 ECB             : 
     356 GIC           9 :     PG_FREE_IF_COPY(left, 0);
     357 CBC           9 :     PG_FREE_IF_COPY(right, 1);
     358 ECB             : 
     359 GIC           9 :     PG_RETURN_BOOL(result);
     360 ECB             : }
     361                 : 
     362 GIC           3 : PG_FUNCTION_INFO_V1(citext_pattern_ge);
     363 ECB             : 
     364                 : Datum
     365 GIC          11 : citext_pattern_ge(PG_FUNCTION_ARGS)
     366 ECB             : {
     367 GIC          11 :     text       *left = PG_GETARG_TEXT_PP(0);
     368 CBC          11 :     text       *right = PG_GETARG_TEXT_PP(1);
     369 ECB             :     bool        result;
     370                 : 
     371 GIC          11 :     result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) >= 0;
     372 ECB             : 
     373 GIC          11 :     PG_FREE_IF_COPY(left, 0);
     374 CBC          11 :     PG_FREE_IF_COPY(right, 1);
     375 ECB             : 
     376 GIC          11 :     PG_RETURN_BOOL(result);
     377 ECB             : }
     378                 : 
     379                 : /*
     380                 :  *      ===================
     381                 :  *      AGGREGATE FUNCTIONS
     382                 :  *      ===================
     383                 :  */
     384                 : 
     385 GIC           3 : PG_FUNCTION_INFO_V1(citext_smaller);
     386 ECB             : 
     387                 : Datum
     388 GIC           7 : citext_smaller(PG_FUNCTION_ARGS)
     389 ECB             : {
     390 GIC           7 :     text       *left = PG_GETARG_TEXT_PP(0);
     391 CBC           7 :     text       *right = PG_GETARG_TEXT_PP(1);
     392 ECB             :     text       *result;
     393                 : 
     394 GIC           7 :     result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
     395 CBC           7 :     PG_RETURN_TEXT_P(result);
     396 ECB             : }
     397                 : 
     398 GIC           3 : PG_FUNCTION_INFO_V1(citext_larger);
     399 ECB             : 
     400                 : Datum
     401 GIC           6 : citext_larger(PG_FUNCTION_ARGS)
     402 ECB             : {
     403 GIC           6 :     text       *left = PG_GETARG_TEXT_PP(0);
     404 CBC           6 :     text       *right = PG_GETARG_TEXT_PP(1);
     405 ECB             :     text       *result;
     406                 : 
     407 GIC           6 :     result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
     408 CBC           6 :     PG_RETURN_TEXT_P(result);
     409 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a