LCOV - differential code coverage report
Current view: top level - contrib/postgres_fdw - shippable.c (source / functions) Coverage Total Hit UBC GIC GNC CBC ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 97.4 % 38 37 1 3 3 31 2 4
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 5 5 2 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 3 3 3
Legend: Lines: hit not hit (240..) days: 97.1 % 35 34 1 3 31 2
Function coverage date bins:
(240..) days: 100.0 % 5 5 2 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * shippable.c
                                  4                 :  *    Determine which database objects are shippable to a remote server.
                                  5                 :  *
                                  6                 :  * We need to determine whether particular functions, operators, and indeed
                                  7                 :  * data types are shippable to a remote server for execution --- that is,
                                  8                 :  * do they exist and have the same behavior remotely as they do locally?
                                  9                 :  * Built-in objects are generally considered shippable.  Other objects can
                                 10                 :  * be shipped if they are declared as such by the user.
                                 11                 :  *
                                 12                 :  * Note: there are additional filter rules that prevent shipping mutable
                                 13                 :  * functions or functions using nonportable collations.  Those considerations
                                 14                 :  * need not be accounted for here.
                                 15                 :  *
                                 16                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 17                 :  *
                                 18                 :  * IDENTIFICATION
                                 19                 :  *    contrib/postgres_fdw/shippable.c
                                 20                 :  *
                                 21                 :  *-------------------------------------------------------------------------
                                 22                 :  */
                                 23                 : 
                                 24                 : #include "postgres.h"
                                 25                 : 
                                 26                 : #include "access/transam.h"
                                 27                 : #include "catalog/dependency.h"
                                 28                 : #include "postgres_fdw.h"
                                 29                 : #include "utils/hsearch.h"
                                 30                 : #include "utils/inval.h"
                                 31                 : #include "utils/syscache.h"
                                 32                 : 
                                 33                 : /* Hash table for caching the results of shippability lookups */
                                 34                 : static HTAB *ShippableCacheHash = NULL;
                                 35                 : 
                                 36                 : /*
                                 37                 :  * Hash key for shippability lookups.  We include the FDW server OID because
                                 38                 :  * decisions may differ per-server.  Otherwise, objects are identified by
                                 39                 :  * their (local!) OID and catalog OID.
                                 40                 :  */
                                 41                 : typedef struct
                                 42                 : {
                                 43                 :     /* XXX we assume this struct contains no padding bytes */
                                 44                 :     Oid         objid;          /* function/operator/type OID */
                                 45                 :     Oid         classid;        /* OID of its catalog (pg_proc, etc) */
                                 46                 :     Oid         serverid;       /* FDW server we are concerned with */
                                 47                 : } ShippableCacheKey;
                                 48                 : 
                                 49                 : typedef struct
                                 50                 : {
                                 51                 :     ShippableCacheKey key;      /* hash key - must be first */
                                 52                 :     bool        shippable;
                                 53                 : } ShippableCacheEntry;
                                 54                 : 
                                 55                 : 
                                 56                 : /*
                                 57                 :  * Flush cache entries when pg_foreign_server is updated.
                                 58                 :  *
                                 59                 :  * We do this because of the possibility of ALTER SERVER being used to change
                                 60                 :  * a server's extensions option.  We do not currently bother to check whether
                                 61                 :  * objects' extension membership changes once a shippability decision has been
                                 62                 :  * made for them, however.
                                 63                 :  */
                                 64                 : static void
 2714 tgl                        65 CBC         124 : InvalidateShippableCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
                                 66                 : {
                                 67                 :     HASH_SEQ_STATUS status;
                                 68                 :     ShippableCacheEntry *entry;
                                 69                 : 
                                 70                 :     /*
                                 71                 :      * In principle we could flush only cache entries relating to the
                                 72                 :      * pg_foreign_server entry being outdated; but that would be more
                                 73                 :      * complicated, and it's probably not worth the trouble.  So for now, just
                                 74                 :      * flush all entries.
                                 75                 :      */
                                 76             124 :     hash_seq_init(&status, ShippableCacheHash);
                                 77             139 :     while ((entry = (ShippableCacheEntry *) hash_seq_search(&status)) != NULL)
                                 78                 :     {
                                 79              15 :         if (hash_search(ShippableCacheHash,
   62 peter                      80 GNC          15 :                         &entry->key,
                                 81                 :                         HASH_REMOVE,
                                 82                 :                         NULL) == NULL)
 2714 tgl                        83 UBC           0 :             elog(ERROR, "hash table corrupted");
                                 84                 :     }
 2714 tgl                        85 CBC         124 : }
                                 86                 : 
                                 87                 : /*
                                 88                 :  * Initialize the backend-lifespan cache of shippability decisions.
                                 89                 :  */
                                 90                 : static void
                                 91               2 : InitializeShippableCache(void)
                                 92                 : {
                                 93                 :     HASHCTL     ctl;
                                 94                 : 
                                 95                 :     /* Create the hash table. */
                                 96               2 :     ctl.keysize = sizeof(ShippableCacheKey);
                                 97               2 :     ctl.entrysize = sizeof(ShippableCacheEntry);
                                 98               2 :     ShippableCacheHash =
                                 99               2 :         hash_create("Shippability cache", 256, &ctl, HASH_ELEM | HASH_BLOBS);
                                100                 : 
                                101                 :     /* Set up invalidation callback on pg_foreign_server. */
                                102               2 :     CacheRegisterSyscacheCallback(FOREIGNSERVEROID,
                                103                 :                                   InvalidateShippableCacheCallback,
                                104                 :                                   (Datum) 0);
                                105               2 : }
                                106                 : 
                                107                 : /*
                                108                 :  * Returns true if given object (operator/function/type) is shippable
                                109                 :  * according to the server options.
                                110                 :  *
                                111                 :  * Right now "shippability" is exclusively a function of whether the object
                                112                 :  * belongs to an extension declared by the user.  In the future we could
                                113                 :  * additionally have a list of functions/operators declared one at a time.
                                114                 :  */
                                115                 : static bool
                                116              18 : lookup_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
                                117                 : {
                                118                 :     Oid         extensionOid;
                                119                 : 
                                120                 :     /*
                                121                 :      * Is object a member of some extension?  (Note: this is a fairly
                                122                 :      * expensive lookup, which is why we try to cache the results.)
                                123                 :      */
                                124              18 :     extensionOid = getExtensionOfObject(classId, objectId);
                                125                 : 
                                126                 :     /* If so, is that extension in fpinfo->shippable_extensions? */
                                127              27 :     if (OidIsValid(extensionOid) &&
                                128               9 :         list_member_oid(fpinfo->shippable_extensions, extensionOid))
                                129               9 :         return true;
                                130                 : 
                                131               9 :     return false;
                                132                 : }
                                133                 : 
                                134                 : /*
                                135                 :  * Return true if given object is one of PostgreSQL's built-in objects.
                                136                 :  *
                                137                 :  * We use FirstGenbkiObjectId as the cutoff, so that we only consider
                                138                 :  * objects with hand-assigned OIDs to be "built in", not for instance any
                                139                 :  * function or type defined in the information_schema.
                                140                 :  *
                                141                 :  * Our constraints for dealing with types are tighter than they are for
                                142                 :  * functions or operators: we want to accept only types that are in pg_catalog,
                                143                 :  * else deparse_type_name might incorrectly fail to schema-qualify their names.
                                144                 :  * Thus we must exclude information_schema types.
                                145                 :  *
                                146                 :  * XXX there is a problem with this, which is that the set of built-in
                                147                 :  * objects expands over time.  Something that is built-in to us might not
                                148                 :  * be known to the remote server, if it's of an older version.  But keeping
                                149                 :  * track of that would be a huge exercise.
                                150                 :  */
                                151                 : bool
                                152            9133 : is_builtin(Oid objectId)
                                153                 : {
 1578 andres                    154            9133 :     return (objectId < FirstGenbkiObjectId);
                                155                 : }
                                156                 : 
                                157                 : /*
                                158                 :  * is_shippable
                                159                 :  *     Is this object (function/operator/type) shippable to foreign server?
                                160                 :  */
                                161                 : bool
 2714 tgl                       162            8687 : is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
                                163                 : {
                                164                 :     ShippableCacheKey key;
                                165                 :     ShippableCacheEntry *entry;
                                166                 : 
                                167                 :     /* Built-in objects are presumed shippable. */
                                168            8687 :     if (is_builtin(objectId))
                                169            8577 :         return true;
                                170                 : 
                                171                 :     /* Otherwise, give up if user hasn't specified any shippable extensions. */
                                172             110 :     if (fpinfo->shippable_extensions == NIL)
                                173              58 :         return false;
                                174                 : 
                                175                 :     /* Initialize cache if first time through. */
                                176              52 :     if (!ShippableCacheHash)
                                177               2 :         InitializeShippableCache();
                                178                 : 
                                179                 :     /* Set up cache hash key */
                                180              52 :     key.objid = objectId;
                                181              52 :     key.classid = classId;
                                182              52 :     key.serverid = fpinfo->server->serverid;
                                183                 : 
                                184                 :     /* See if we already cached the result. */
                                185                 :     entry = (ShippableCacheEntry *)
   62 peter                     186 GNC          52 :         hash_search(ShippableCacheHash, &key, HASH_FIND, NULL);
                                187                 : 
 2714 tgl                       188 CBC          52 :     if (!entry)
                                189                 :     {
                                190                 :         /* Not found in cache, so perform shippability lookup. */
 2714 tgl                       191 GIC          18 :         bool        shippable = lookup_shippable(objectId, classId, fpinfo);
                                192                 : 
                                193                 :         /*
                                194                 :          * Don't create a new hash entry until *after* we have the shippable
                                195                 :          * result in hand, as the underlying catalog lookups might trigger a
 2714 tgl                       196 ECB             :          * cache invalidation.
                                197                 :          */
                                198                 :         entry = (ShippableCacheEntry *)
   62 peter                     199 GNC          18 :             hash_search(ShippableCacheHash, &key, HASH_ENTER, NULL);
                                200                 : 
 2714 tgl                       201 GIC          18 :         entry->shippable = shippable;
                                202                 :     }
                                203                 : 
                                204              52 :     return entry->shippable;
                                205                 : }
        

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