

  Le module postgres_fdw fournit le wrapper de données
  distantes postgres_fdw, dont le but est de données accès
  à des données enregistrées dans des serveurs
  PostgreSQL externes.
 
  Les fonctionnalités proposées par ce module sont à peu près les mêmes que
  celles proposées par le module dblink. Mais
  postgres_fdw fournit une syntaxe plus transparente et
  respectant les standards pour l'accès à des tables distantes. Elle peut
  aussi donner de meilleures performances dans beaucoup de cas.
 
  Pour préparer un accès distant en utilisant postgres_fdw :
  
     Installez l'extension  postgres_fdw en utilisant
     CREATE EXTENSION.
    
     Créez un objet serveur distant en utilisant CREATE SERVER,
     pour représenter chaque base distante à laquelle vous souhaitez vous
     connecter. Indiquez les informations de connexions, sauf
     user et password, comme options de
     l'objet serveur.
    
     Créez une correspondance d'utilisateur avec CREATE USER MAPPING pour chaque utilisateur de la base que
     vous voulez autoriser à accéder à un serveur distant. Indiquez le nom
     et le mot de passe de l'utilisateur distant avec les options
     user et password de la correspondance
     d'utilisateur.
    
Créez une table distante avec CREATE FOREIGN TABLE ou IMPORT FOREIGN SCHEMA pour chaque table distante que vous voulez utilisé. Les colonnes de la table distante doit correspondre aux colonnes de la table sur le serveur distant. Néanmoins, vous pouvez utiliser un nom de table et des noms de colonne différents de ceux de la table sur le serveur distant si vous indiquez les bons noms de colonne en options de la table distante.
  Maintenant, vous avez seulement besoin de SELECT sur la
  table distante pour accéder aux données de la table du serveur distant. Vous
  pouvez aussi modifier la table sur le serveur distant en utilisant les
  commandes INSERT, UPDATE,
  DELETE et COPY. (Bien sûr,
  l'utilisateur utilisé pour la connexion au serveur distant doit avoir les
  droits de faire tout cela.)
 
  Notez que postgres_fdw n'a pour l'instant pas de
  support pour les instructions INSERT avec une clause
  ON CONFLICT DO UPDATE. Néanmoins, la clause ON
   CONFLICT DO NOTHING est supporté, si la spécification de l'index
  unique est omise. Notez aussi que postgres_fdw supporte
  le déplacement de ligne demandé par des instructions
  UPDATE exécutées sur des tables partitionnées, mais il ne
  gère pas le cas où une partition distante choisir pour insérer une ligne est
  aussi une partition cible d'UPDATE qui sera mise à jour
  ultérieurement.
 
  Il est généralement recommandé que les colonnes d'une table distante soient
  déclarées avec exactement les mêmes types de données et le même collationnement
  que celles utilisées pour les colonnes référencées dans le table du serveur
  distant. Bien que postgres_fdw est actuellement assez
  lâche sur les conversions de type de données, des anomalies sémantiques
  surprenantes peuvent survenir quand les types ou les collationnements ne
  correspondent pas dans le cas où le serveur distant interprète légèrement
  différemment les conditions de la requête.
 
Notez qu'une table distante peut être déclarée avec moins de colonnes ou avec les colonnes dans un ordre différent. La correspondance des colonnes sur la table du serveur distant se fait par nom, et non pas par position.
    Un serveur distant utilisant le wrapper de données distantes
    postgres_fdw peut avoir les mêmes options que celles
    acceptées par libpq dans les chaînes de connexion
    comme décrit dans Section 34.1.2. Cependant, ces
    options ne sont pas autorisées :
    
       user et password (spécifiez-les au
       niveau de la correspondance d'utilisateur)
      
       client_encoding (ceci est configuré automatiquement à
       partir de l'encodage du serveur local)
      
       fallback_application_name (toujours configuré à
       postgres_fdw)
      
    Seuls les superutilisateurs peuvent se connecter à un serveur distant sans
    authentification par mot de passe. Donc spécifiez toujours l'option
    password pour les correspondances d'utilisateur
    appartenant aux utilisateurs simples.
   
Ces options peuvent être utilisées pour contrôler les noms utilisés dans les requêtes SQL envoyées au serveur PostgreSQL distant. Ces options sont nécessaires lorsqu'une table distante est créée avec des noms différents de ceux de la table du serveur distant.
schema_nameCette option, qui peut être indiquée pour une table distante, donne le nom du schéma à utiliser pour la table du serveur distant. Si cette option est omise, le nom du schéma de la table distante est utilisé.
table_nameCette option, qui peut être indiquée pour une table distante, donne le nom de la table à utiliser pour la table du serveur distant. Si cette option est omise, le nom de la table distante est utilisé.
column_nameCette option, qui peut être indiquée pour une colonne d'une table distante, donne le nom de la colonne à utiliser pour la colonne de la table du serveur distant. Si cette option est omise, le nom de la colonne de la table distante est utilisé.
    postgres_fdw récupère des données distantes en exécutant
    des requêtes sur des serveurs distants. Idéalement, le coût estimé du parcours
    d'une table distante devrait être celui occasionné par le parcours de la
    table sur le serveur distant, et un supplément causé par la communication entre
    le serveur local et le serveur distant. Le moyen le plus fiable d'obtenir
    une telle estimation est de demander au serveur distant, puis d'ajouter
    quelque chose pour le supplément. Pour des requêtes simples, cela ne vaut
    pas le coût d'une requête supplémentaire vers le serveur distant. Donc
    postgres_fdw propose les options suivantes pour
    contrôler la façon dont l'estimation de coût est faite :
   
use_remote_estimate
       Cette option, qui peut être indiquée pour une table distante ou pour
       un serveur distant, contrôle si postgres_fdw
       exécute des commandes EXPLAIN distantes pour obtenir
       les estimations de coût. Une configuration sur la table distante surcharge
       celle sur le serveur, mais seulement pour cette table. La valeur par
       défaut est false.
      
fdw_startup_cost
       Cette option, qui peut être indiquée pour un serveur distant, est une
       valeur numérique qui est ajoutée au coût de démarrage estimé de tout
       parcours de table distante sur ce serveur. Cela représente le coût
       supplémentaire causé par l'établissement d'une connexion, l'analyse et
       la planification de la requête du côté du serveur distant, etc. La valeur
       par défaut est 100.
      
fdw_tuple_cost
       Cette option, qui peut être indiquée pour un serveur distant, est une
       valeur numérique qui est utilisée comme coût supplémentaire par ligne
       pour les parcours de la table distante sur ce serveur. Cela représente
       le coût supplémentaire associé au transfert de données entre les
       serveurs. Vous pouvez augmenter ou réduire ce nombre pour refléter
       les latences réseau vers le serveur distant. La valeur par défaut est
       0.01.
      
    Quand use_remote_estimate est vrai,
    postgres_fdw obtient le nombre de lignes et les
    estimations de coût à partir du serveur distant. Il ajoute
    fdw_startup_cost et fdw_tuple_cost
    aux estimations de coût. Quand use_remote_estimate est
    faux, postgres_fdw réalise le décompte local des lignes
    ainsi que l'estimation de coût, puis ajoute fdw_startup_cost
    et fdw_tuple_cost aux estimations de coût. Cette
    estimation locale a peu de chances d'être précise sauf si des copies locales
    des statistiques de la table distante sont disponibles. Exécuter
    ANALYZE sur la table distante permet de mettre à jour
    les statistiques locales ; cela exécute un parcours sur la table
    distante, puis calcule et enregistre les statistiques comme si la table
    était locale. Garder des statistiques locales peut être utile pour réduire
    la surcharge de planification par requête pour une table distante mais, si
    la table distante est fréquemment mise à jour, les statistiques locales
    seront rapidement obsolètes.
   
    Par défaut, seules les clauses WHERE utilisant des
    opérateurs et des fonctions intégrés sont considérés pour une exécution
    sur le serveur distant. Les clauses impliquant des fonctions non intégrées
    sont vérifiées localement une fois les lignes récupérées. Si ces fonctions
    sont disponibles sur le serveur distant et peuvent produire les mêmes
    résultats que localement, les performances peuvent être améliorées en
    envoyant ces clauses WHERE pour une exécution distante.
    Ce comportement peut être contrôlé en utilisant l'option suivante :
   
extensionsCette option est une liste de noms d'extensions PostgreSQL, séparés par des virgules, installées dans des versions compatibles sur les serveurs local et distant. Les fonctions et opérateurs immutables et appartenant à une extension listée seront considérées pour une exécution sur le serveur distant. Cette option peut seulement être spécifiée sur les serveurs distants, et non pas par table.
       Lors de l'utilisation de l'option extensions,
       il est de la responsabilité de l'utilisateur que
       les extensions listées existent bien et se comportent de façon identique
       sur les serveurs local et distant. Dans le cas contraire, les requêtes
       pourraient échouer ou se comporter de façon inattendue.
      
fetch_size
       Cette option indique le nombre de lignes que
       postgres_fdw doit récupérer à chaque opération
       de lecture. Cette option est disponible au niveau serveur et table.
       Une configuration spécifiée sur une table surcharge celle du serveur.
       La valeur par défaut est 100.
      
    Par défaut, toutes les tables distantes utilisant postgres_fdw
    sont supposées comme étant modifiables. Cela peut se surcharger en utilisant
    l'option suivante :
   
updatable
       Cette option contrôle si postgres_fdw autorise les
       tables distantes à être modifiées en utilisant les commandes
       INSERT, UPDATE et
       DELETE. Cette option est utilisable sur une table
       distante ou sur un serveur distant. La configuration de cette option au
       niveau table surcharge celle au niveau serveur. La valeur par défaut
       est true.
      
       Bien sûr, si la table distante n'est pas modifiable, une erreur surviendra
       malgré tout. L'utilisation de cette option permet principalement que
       l'erreur soit renvoyée localement, sans avoir à tenter l'exécution sur
       le serveur distant. Notez néanmoins que les vues
       information_schema indiqueront que la table distante
       est modifiable ou pas, suivant la configuration de cette option, et donc
       sans vérification du serveur distant.
      
    postgres_fdw est capable d'importer les définitions
    des tables distantes en utilisant IMPORT FOREIGN SCHEMA. Cette commande crée les définitions
    des tables distantes sur le serveur local, correspondant aux tables et
    vues présentes sur le serveur distant. Si les tables distantes à importer
    ont des colonnes de type défini par des utilisateurs, le serveur local
    doit avoir des types compatibles de même nom.
   
    Le comportement de l'import est personnalisable avec les options suivantes
    (à fournir à la commande IMPORT FOREIGN SCHEMA) :
   
import_collate
       Cette option contrôle si les options COLLATE d'une
       colonne sont inclus dans les définitions des tables distantes importées
       à partir d'un serveur distant. La valeur par défaut est
       true. Vous pourriez avoir besoin de la désactiver si
       le serveur distant possède un ensemble de noms de collation différent
       de celui du serveur local, ce qui risque d'être le cas s'il utilise un
       autre système d'exploitation. Néanmoins, si vous le faites, il existe
       un risque sévère que les collations importées des colonnes de la table
       ne correspondent pas aux données, résultant en un comportement
       anormale de la requête.
      
       Même quand ce paramètre est configuré à true,
       importer des colonnes dont la collation est la valeur par défaut du
       serveur distant peut se révéler risqué. Elles seront importées avec
       COLLATE "default", qui sélectionnera la collation
       par défaut du serveur local, qui pourrait bien être différente de
       celle du serveur distant.
      
import_default
       Cette option contrôle si les expressions DEFAULT
       d'une colonne sont incluses dans les définitions des tables distantes
       importées d'un serveur distant. La valeur par défaut est
       false. Si vous activez cette option, faites
       attention au fait que les valeurs par défaut pourraient être calculées
       différemment sur le serveur local et sur le serveur distant ; par
       exemple, nextval() est une source habituelle de
       problèmes. La commande IMPORT échouera si une
       expression par défaut importée utilise une fonction ou un opérateur qui
       n'existe pas localement.
      
import_not_null
       Cette option contrôle si les contraintes NOT NULL
       des colonnes sont incluses dans les définitions des tables distantes
       importées à partir d'un serveur distant. La valeur par défaut est
       true.
      
    Notez que les contraintes autres que NOT NULL ne seront
    jamais importées des tables distantes. Bien que
    PostgreSQL supporte les contraintes
    CHECK sur les tables distantes, rien n'existe pour les
    importer automatiquement à cause du risque qu'une expression de contrainte
    puisse être évaluée différemment entre les serveurs local et distant.
    Toute incohérence du comportement d'une contrainte
    CHECK pourrait amener des erreurs difficile à détecter
    dans l'optimisation des requêtes. Donc, si vous souhaitez importer les
    contraintes CHECK, vous devez le faire manuellement et
    vous devez vérifier la sémantique de chaque contrainte avec attention.
    Pour plus de détails sur le traitement des contraintes
    CHECK sur les tables distantes, voir CREATE FOREIGN TABLE.
   
Les tables ou tables distantes qui sont des partitions d'autres tables sont automatiquement exclues. Les tables partitionnées sont importées, à moins qu'elles soient des partitions d'une autre table. Puisque toutes les données à traver la table partitionnées qui est à la racine de toute la hiérarchie de partitionnement, cette approche devrait autoriser l'accès à toutes les données sans avoir besoin de créer d'objets supplémentaires.
   postgres_fdw établit une connexion au serveur distant
   lors de la première requête qui utilise une table distante associée avec
   le serveur distant. La connexion est conservée et réutilisée pour les
   requêtes suivants de la même session. Néanmoins, si plusieurs identités
   d'utilisateur (correspondances d'utilisateur) sont utilisées pour
   accéder au serveur distant, une connexion est établie pour chaque
   correspondance d'utilisateur.
  
   Lorsqu'une requête référence des tables sur un serveur distant,
   postgres_fdw ouvre une transaction sur le serveur
   distant si une transaction n'est pas déjà ouverte pour la transaction
   locale en cours. La transaction distante est validée ou annulée suivant
   que la transaction locale est validée ou annulée. Les points de
   sauvegardes sont gérés de la même façon en créant les points de
   sauvegarde correspondants.
  
   La transaction distante utilise le niveau d'isolation
   SERIALIZABLE quand la transaction locale a le niveau
   SERIALIZABLE. Dans les cas contraires, elle utilise le
   niveau REPEATABLE READ. Ce choix assure que, si une requête
   réalise plusieurs parcours de table sur le serveur distant, elle obtiendra
   des résultats cohérents pour tous les parcours. Une conséquence est que les
   requêtes successives à l'intérieur d'une seule transaction verront les mêmes
   données provenant du serveur distant, même si des mises à jour sont réalisées
   en même temps avec l'activité standard du serveur. Ce comportement serait
   attendue de toute façon si la transaction locale utilise le niveau d'isolation
   SERIALIZABLE ou REPEATABLE READ mais
   elle pourrait surprendre pour une transaction locale en niveau READ
    COMMITTED. Une prochaine version de
   PostgreSQL pourrait modifier ce comportement.
  
   Notez que postgres_fdw ne supporte pas actuellement de
   préparer la transaction distante pour une validation en deux phases (2PC).
  
   postgres_fdw tente d'optimiser les requêtes distantes
   pour réduire la quantité de données transférées depuis les serveurs distants.
   Cela se fait en envoyant les clauses WHERE au serveur
   distant pour exécution, et en ne récupérant que les colonnes nécessaires
   pour la requête courante. Pour réduire le risque de mauvaise exécution des
   requêtes, les clauses WHERE ne sont pas envoyées au serveur
   distant sauf si elles utilisent seulement des types de données, opérateurs
   et fonctions intégrées ou appartenant à une extension listée dans l'option
   extensions du serveur distant. Les opérateurs et fonctions
   dans ce type de clause doivent aussi être IMMUTABLE. Pour
   une requête UPDATE ou DELETE,
   postgres_fdw tente d'optimiser l'exécution de la requête
   en envoyant la requête complète au serveur distant s'il n'existe pas de
   clauses WHERE pouvant être envoyées au serveur distant, pas
   de jointures locales pour la requête, pas de triggers BEFORE
   ou AFTER au niveau ligne sur la table cible, et pas de
   contraintes CHECK OPTION pour les vues parentes. Dans un
   UPDATE, les expressions à affecter aux colonnes cibles
   doivent seulement utiliser les types de données intégrées, les opérateurs ou les
   fonctions IMMUTABLE pour réduire le risque de mauvaise
   exécution de la requête.
  
   Quand postgres_fdw rencontre une jointure entre des
   tables externes sur le même serveur distant, il envoie la jointure entière
   au serveur distant, sauf s'il pense qu'il sera plus efficace de récupérer
   les lignes de chaque table individuellement ou si les références de table
   sont sujet à des correspondances d'utilisateur différentes. Lors de l'envoi
   des clauses JOIN, il prend les mêmes précautions que
   mentionnées ci-dessus pour les clauses WHERE.
  
   La requête envoyée au serveur distant pour exécution peut être examinée en
   utilisant EXPLAIN VERBOSE.
  
   Dans les sessions distantes ouvertes par postgres_fdw,
   le paramètre search_path est configuré à
   pg_catalog, pour que seuls les objets internes soient
   visibles, sauf utilisant d'un nom de schéma. Ceci n'est pas un problème
   pour les requêtes générées par postgres_fdw lui-même
   car il fournit toujours ce type de qualification. Néanmoins, cela peut se
   révéler problématique pour les fonctions exécutées sur le serveur distant
   via des triggers ou des règles sur les tables distantes. Par exemple, si
   une table distante est en fait une vue, toute fonction utilisée dans cette
   vue sera exécutée avec le chemin de recherche restreint. Il est recommandé
   de qualifier tous les noms dans ce type de fonctions ou de leur attacher
   une option SET search_path (voir CREATE FUNCTION) pour établir le chemin de recherche
   attendu.
  
   De même, postgres_fdw établie une configuration des
   sessions distantes pour différents paramètres :
   
      TimeZone est positionné à UTC
     
      datestyle est positionné à ISO
     
      IntervalStyle est positionné à postgres
     
      extra_float_digits est positionné à
      3 pour les serveurs distants de version 9.0 et après et
      est positionné à 2 pour les versions plus anciennes
     
   Ces paramètres sont moins à même d'être problématique que
   search_path, mais ils peuvent être gérés avec les options
   de fonction SET si le besoin devait se faire sentir.
  
   Il n'est pas recommandé de surcharger ce comportement
   en modifiant la configuration de la session pour ces paramètres. Cela peut
   être la cause d'un mauvais fonctionnement de
   postgres_fdw.
  
   postgres_fdw peut être utilisé avec les serveurs distants
   de version 8.3 et ultérieures. En lecture seule, il est possible d'aller aussi
   loin que la 8.1. Néanmoins, une limitation est que
   postgres_fdw assume généralement que les fonctions et
   opérateurs internes immutables sont sûrs pour être envoyés au serveur distant
   pour exécution s'ils apparaissent dans une clause WHERE de
   la table distante. Du coup, une fonction interne ajoutée depuis la sortie du
   serveur distant pourrait être envoyée pour exécution, résultant en un
   message d'erreur indiquant que la fonction n'existe pas (« function does
    not exist ») ou une erreur similaire. Ce type d'échec peut être
   contourné en réécrivant la requête, par exemple en embarquant la table
   distance dans un sous-SELECT avec OFFSET 0
   comme optimisation, et plaçant la fonction ou l'opérateur problématique
   en dehors du sous-SELECT.
  
   Voici un exemple de création d'une table distante avec
   postgres_fdw. Tout d'abord, il faut installer l'extension :
  
CREATE EXTENSION postgres_fdw;
   Ensuite, il faut créer un serveur distant avec CREATE SERVER.
   Dans cet exemple, nous souhaitons nous connecter à un serveur
   PostgreSQL sur l'hôte 192.83.123.89
   écoutant sur le port 5432.  La base de données sur le
   serveur distant sur laquelle la connexion est faite s'appelle
   foreign_db :
   
CREATE SERVER foreign_server
        FOREIGN DATA WRAPPER postgres_fdw
        OPTIONS (host '192.83.123.89', port '5432', dbname 'foreign_db');
   
Une correspondance d'utilisateur, définie avec CREATE USER MAPPING, est également nécessaire pour identifier le rôle qui sera utilisé sur le serveur distant :
CREATE USER MAPPING FOR local_user
        SERVER foreign_server
        OPTIONS (user 'foreign_user', password 'password');
   
   Il est maintenant possible de créer une table distante avec CREATE FOREIGN TABLE.  Dans cet exemple, nous souhaitons
   accéder à la table nommée some_schema.some_table
   sur le serveur distant. Le nom local pour celle-ci sera
   foreign_table :
   
CREATE FOREIGN TABLE foreign_table (
        id integer NOT NULL,
        data text
)
        SERVER foreign_server
        OPTIONS (schema_name 'some_schema', table_name 'some_table');
   
   Il est essentiel que les types de données et autres propriétés des colonnes
   déclarées dans CREATE FOREIGN TABLE correspondent à la
   vraie table distante. Les noms des colonnes doivent également correspondre,
   à moins que des options column_name soient attachées aux
   colonnes individuelles pour montrer comment elles sont nommées sur la table
   distante.
   Dans de nombreux cas, l'utilisation de IMPORT FOREIGN SCHEMA
   est préférable à la construction manuelle des tables distantes.
  
   Shigeru Hanada <shigeru.hanada@gmail.com>