LCOV - code coverage report
Current view: top level - src/backend/catalog - pg_conversion.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 98.6 % 72 71
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 66.7 % 30 20

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * pg_conversion.c
       4                 :             :  *        routines to support manipulation of the pg_conversion relation
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/backend/catalog/pg_conversion.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "access/htup_details.h"
      18                 :             : #include "access/table.h"
      19                 :             : #include "catalog/catalog.h"
      20                 :             : #include "catalog/dependency.h"
      21                 :             : #include "catalog/indexing.h"
      22                 :             : #include "catalog/objectaccess.h"
      23                 :             : #include "catalog/pg_conversion.h"
      24                 :             : #include "catalog/pg_namespace.h"
      25                 :             : #include "catalog/pg_proc.h"
      26                 :             : #include "mb/pg_wchar.h"
      27                 :             : #include "utils/builtins.h"
      28                 :             : #include "utils/catcache.h"
      29                 :             : #include "utils/rel.h"
      30                 :             : #include "utils/syscache.h"
      31                 :             : 
      32                 :             : /*
      33                 :             :  * ConversionCreate
      34                 :             :  *
      35                 :             :  * Add a new tuple to pg_conversion.
      36                 :             :  */
      37                 :             : ObjectAddress
      38                 :          10 : ConversionCreate(const char *conname, Oid connamespace,
      39                 :             :                                  Oid conowner,
      40                 :             :                                  int32 conforencoding, int32 contoencoding,
      41                 :             :                                  Oid conproc, bool def)
      42                 :             : {
      43                 :          10 :         int                     i;
      44                 :          10 :         Relation        rel;
      45                 :          10 :         TupleDesc       tupDesc;
      46                 :          10 :         HeapTuple       tup;
      47                 :          10 :         Oid                     oid;
      48                 :          10 :         bool            nulls[Natts_pg_conversion];
      49                 :          10 :         Datum           values[Natts_pg_conversion];
      50                 :          10 :         NameData        cname;
      51                 :          10 :         ObjectAddress myself,
      52                 :             :                                 referenced;
      53                 :             : 
      54                 :             :         /* sanity checks */
      55         [ +  - ]:          10 :         if (!conname)
      56   [ #  #  #  # ]:           0 :                 elog(ERROR, "no conversion name supplied");
      57                 :             : 
      58                 :             :         /* make sure there is no existing conversion of same name */
      59         [ +  + ]:          10 :         if (SearchSysCacheExists2(CONNAMENSP,
      60                 :             :                                                           PointerGetDatum(conname),
      61                 :             :                                                           ObjectIdGetDatum(connamespace)))
      62   [ +  -  +  - ]:           1 :                 ereport(ERROR,
      63                 :             :                                 (errcode(ERRCODE_DUPLICATE_OBJECT),
      64                 :             :                                  errmsg("conversion \"%s\" already exists", conname)));
      65                 :             : 
      66         [ +  + ]:           9 :         if (def)
      67                 :             :         {
      68                 :             :                 /*
      69                 :             :                  * make sure there is no existing default <for encoding><to encoding>
      70                 :             :                  * pair in this name space
      71                 :             :                  */
      72   [ +  +  +  + ]:           4 :                 if (FindDefaultConversion(connamespace,
      73                 :           2 :                                                                   conforencoding,
      74                 :           2 :                                                                   contoencoding))
      75   [ +  -  +  - ]:           1 :                         ereport(ERROR,
      76                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
      77                 :             :                                          errmsg("default conversion for %s to %s already exists",
      78                 :             :                                                         pg_encoding_to_char(conforencoding),
      79                 :             :                                                         pg_encoding_to_char(contoencoding))));
      80                 :           1 :         }
      81                 :             : 
      82                 :             :         /* open pg_conversion */
      83                 :           8 :         rel = table_open(ConversionRelationId, RowExclusiveLock);
      84                 :           8 :         tupDesc = rel->rd_att;
      85                 :             : 
      86                 :             :         /* initialize nulls and values */
      87         [ +  + ]:          72 :         for (i = 0; i < Natts_pg_conversion; i++)
      88                 :             :         {
      89                 :          64 :                 nulls[i] = false;
      90                 :          64 :                 values[i] = (Datum) 0;
      91                 :          64 :         }
      92                 :             : 
      93                 :             :         /* form a tuple */
      94                 :           8 :         namestrcpy(&cname, conname);
      95                 :           8 :         oid = GetNewOidWithIndex(rel, ConversionOidIndexId,
      96                 :             :                                                          Anum_pg_conversion_oid);
      97                 :           8 :         values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid);
      98                 :           8 :         values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
      99                 :           8 :         values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
     100                 :           8 :         values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
     101                 :           8 :         values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
     102                 :           8 :         values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
     103                 :           8 :         values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
     104                 :           8 :         values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
     105                 :             : 
     106                 :           8 :         tup = heap_form_tuple(tupDesc, values, nulls);
     107                 :             : 
     108                 :             :         /* insert a new tuple */
     109                 :           8 :         CatalogTupleInsert(rel, tup);
     110                 :             : 
     111                 :           8 :         myself.classId = ConversionRelationId;
     112                 :           8 :         myself.objectId = oid;
     113                 :           8 :         myself.objectSubId = 0;
     114                 :             : 
     115                 :             :         /* create dependency on conversion procedure */
     116                 :           8 :         referenced.classId = ProcedureRelationId;
     117                 :           8 :         referenced.objectId = conproc;
     118                 :           8 :         referenced.objectSubId = 0;
     119                 :           8 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
     120                 :             : 
     121                 :             :         /* create dependency on namespace */
     122                 :           8 :         referenced.classId = NamespaceRelationId;
     123                 :           8 :         referenced.objectId = connamespace;
     124                 :           8 :         referenced.objectSubId = 0;
     125                 :           8 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
     126                 :             : 
     127                 :             :         /* create dependency on owner */
     128                 :           8 :         recordDependencyOnOwner(ConversionRelationId, oid, conowner);
     129                 :             : 
     130                 :             :         /* dependency on extension */
     131                 :           8 :         recordDependencyOnCurrentExtension(&myself, false);
     132                 :             : 
     133                 :             :         /* Post creation hook for new conversion */
     134         [ +  - ]:           8 :         InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
     135                 :             : 
     136                 :           8 :         heap_freetuple(tup);
     137                 :           8 :         table_close(rel, RowExclusiveLock);
     138                 :             : 
     139                 :             :         return myself;
     140                 :           8 : }
     141                 :             : 
     142                 :             : /*
     143                 :             :  * FindDefaultConversion
     144                 :             :  *
     145                 :             :  * Find "default" conversion proc by for_encoding and to_encoding in the
     146                 :             :  * given namespace.
     147                 :             :  *
     148                 :             :  * If found, returns the procedure's oid, otherwise InvalidOid.  Note that
     149                 :             :  * you get the procedure's OID not the conversion's OID!
     150                 :             :  */
     151                 :             : Oid
     152                 :        1098 : FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
     153                 :             : {
     154                 :        1098 :         CatCList   *catlist;
     155                 :        1098 :         HeapTuple       tuple;
     156                 :        1098 :         Form_pg_conversion body;
     157                 :        1098 :         Oid                     proc = InvalidOid;
     158                 :        1098 :         int                     i;
     159                 :             : 
     160                 :        1098 :         catlist = SearchSysCacheList3(CONDEFAULT,
     161                 :             :                                                                   ObjectIdGetDatum(name_space),
     162                 :             :                                                                   Int32GetDatum(for_encoding),
     163                 :             :                                                                   Int32GetDatum(to_encoding));
     164                 :             : 
     165         [ +  + ]:        1100 :         for (i = 0; i < catlist->n_members; i++)
     166                 :             :         {
     167                 :        1099 :                 tuple = &catlist->members[i]->tuple;
     168                 :        1099 :                 body = (Form_pg_conversion) GETSTRUCT(tuple);
     169         [ +  + ]:        1099 :                 if (body->condefault)
     170                 :             :                 {
     171                 :        1097 :                         proc = body->conproc;
     172                 :        1097 :                         break;
     173                 :             :                 }
     174                 :           2 :         }
     175                 :        1098 :         ReleaseSysCacheList(catlist);
     176                 :        2196 :         return proc;
     177                 :        1098 : }
        

Generated by: LCOV version 2.3.2-1