Vous n'êtes pas identifié(e).
Bonjour,
Je suis novice sur Postgres et je voudrais savoir les differences entre PQexec et psql, car j'ai fait un dump du schema de ma DB de base via PgAdmin3 que je veux réutiliser dans mon appli C++ pour recréer mes DBs sur cette base et lorsque je rétablis ce dump via psql ça marche nickel mais via PQexec j'ai tout plein d'erreurs de syntax ou directives inconnues, pourquoi ne sont-ils pas compatibles pour executer les mêmes commandes SQL? Je voudrais absolument pouvoir rétablir mon dump via PQexec et non psql car ça ne me plait pas de passer le dump via une commande de script etc... et en plus c'est une usine à gaz voir presque impossible de gérer les exceptions et erreurs via psql.
Alors y aurait-il un moyen de rendre mon dump compatible avec PQexec? Merci d'avance pour votre aide.
Dernière modification par Mudr0x (20/04/2022 15:06:10)
Hors ligne
Bonjour,
Comment avez-vous effectué le dump exactement, si possible la ligne de commande générée. Avez-vous des exemples de commandes en erreur avec le retour côté client ainsi que les logs associés ?
Julien.
https://rjuju.github.io/
Hors ligne
Bonjour,
J'ai effectué le dump directement via PgAdmin3 (qui utilise pg_dump normalement), mais je crois que j'ai compris en fait il n'y a pas de differences en fait entre PQexec et psql dans l'execution de commande SQL si ce n'est que comme je réutilise le meme schema et qu'il existe déjà lors de la création de ma DB de base avec psql toutes les créations d'entités (fonctions, relations etc...) qui existent déjà sont automatiquement abandonnées sans emettre d'erreurs et avec PQexec une erreur est émise comme quoi l'entité existent déjà... Je sais que j'ai peut-être du mal à me faire comprendre alors avec un exemple de mon dump peut-être que ce sera plus clair:
-- Database: "OT DB"
--
-- PostgreSQL database dump
--
-- Dumped from database version 9.3.25
-- Dumped by pg_dump version 9.3.25
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
--
-- TOC entry 1 (class 3079 OID 11750)
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- TOC entry 2954 (class 0 OID 0)
-- Dependencies: 1
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--
-- TOC entry 209 (class 1255 OID 17388)
-- Name: update_cash_cache(); Type: FUNCTION; Schema: public; Owner: %USERNAME%
--
CREATE FUNCTION public.update_cash_cache() RETURNS void
LANGUAGE plpgsql
AS $$
...
Au niveau de CREATE FUNCTION public.update_cash_cache() j'ai une erreur avec PQexec (alors que non avec psql): "Error FUNCTION public.update_cash_cache() already exists".
Pour que ça passe je dois à chaque fois faire (pour toutes les entités me donnant cette erreur):
DROP FUNCTION IF EXISTS public.update_cash_cache();
CREATE FUNCTION public.update_cash_cache() RETURNS void
LANGUAGE plpgsql
AS $$
...
Et c'est un peu laborieux de le faire, y aurait-il pas un moyen avec PQexec de skipper toutes les requêtes où les entités existent déjà comme le fait psql? Merci.
Hors ligne
psql n'a pas cette fonctionnalité, et je ne vois pas comment il pourrait l'avoir vu qu'il n'est pas capable de parser les requêtes pour détecter la création d'un object.
En général on résoud ce problème en utilisant un dump au format custom et en le restaurant avec pg_restore, qui lui dispose d'une option --clean permettant de supprimer les objects avant création. Mais cela n'est possible que grace à la liste des objects contenu dans le format custom. Avec psql la seule chose possible à faire est d'utiliser ON_ERROR_ROLLBACK probablement, mais les erreurs surviennent toujours, elles sont juste ignorées à coup de SAVEPOINT / ROLLBACK TO.
Julien.
https://rjuju.github.io/
Hors ligne
Très bien, y'a-t-il un équivalent de pg_restore dans libpq C++?
Hors ligne
Non, c'est un programme et non pas une partie du protocole.
Vous pouvez toujours regarder le code source (https://github.com/postgres/postgres/blob/master/src/bin/pg_dump/pg_restore.c ) et réutiliser une partie de l'API (https://github.com/postgres/postgres/blob/master/src/bin/pg_dump/pg_backup.h et autres) si vous voulez l'intégrer dans votre outil.
Julien.
https://rjuju.github.io/
Hors ligne
Merci de votre aide je vais effectivement reprendre sur le source de pg_restore.c
Mais c'est juste cette erreur qui m'étonne... pourquoi cette erreur qui m'est retournée ""ERROR: function "update_cash_cache" already exists with same argument types" alors qu'elle n'existe pas sur ma nouvelle DB vierge à laquelle je veux restaurer le schéma de ma DB de base? C'est comme si PQexec exécute les requêtes de mon dump sur ma DB de base alors qu'en argument je lui précise la connexion (PGconn) sur ma DB vierge...
Hors ligne
erreur de duplication...
Dernière modification par Mudr0x (20/04/2022 19:41:47)
Hors ligne
Si vous avez l'erreur, c'est que la fonction existe bel et bien. Soit votre outil ne se connecte pas à une base de données vierge, soit votre outil exécute deux fois l'ordre de création de la fonction, soit autre chose.
Guillaume.
Hors ligne
psql utilise PQexec pour lancer les commandes, mais il analyse le script de commandes pour trouver le début et la fin de chaque requête et les envoie une par une après découpage.
J'ai l'impression que c'est l'étape que vous n'avez pas dans votre programme.
Ce découpage est fait dans psql avec un analyseur lexical dédié fait avec lex, qui lui même est une copie de l'analyseur lexical du moteur SQL. Voir https://git.postgresql.org/gitweb/?p=po … psqlscan.l
* This code is mainly concerned with determining where the end of a SQL
* statement is: we are looking for semicolons that are not within quotes,
* comments, or parentheses. The most reliable way to handle this is to
* borrow the backend's flex lexer rules, lock, stock, and barrel. The rules
* below are (except for a few) the same as the backend's, but their actions
* are just ECHO whereas the backend's actions generally do other things.
On peut toujours envoyer un énorme bloc plein de requêtes SQL accolées à PQexec en espérant que ça va passer, mais à titre d'exemple si on envoie ça à PQexec:
CREATE DATABASE dbtest; select 1;
ça échouera avec une erreur disant que CREATE DATABASE ne marche pas dans une transaction, alors qu'avec psql ça passerait sans erreur, parce qu'il aura découpé ça en 2 requêtes à envoyer séparément.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne