Vous n'êtes pas identifié(e).

#1 25/04/2019 23:06:44

rvs75
Membre

Envoyer fin de fichier dans le STDIN

Bonjour,

Dans le cadre d'une migration Oracle vers PostgreSQL, je réécrit des outils d'insertion. Les outils sont écrit en C# et sont lancés sur un serveur Windows (pour des raisons historiques). La base de données est sur un serveur Linux. Cette application (scripts, outils, base de données) reçoit et envoie des données plusieurs fois par jour, les contraintes de performance sont assez importantes (certains flux font plusieurs millions de lignes).
-
Le but est de faire un commande COPY dans PSQL.

Les arguments pour  sont construit comme cela :

 
string debutPsqlArg = "-d " + o.Dbname + " -c \"";
string copyCommand = "copy " + PGSchema + "." + o.Table + "(" + string.Join(", ", CorrespondanceColonneCsvChampsTable.Select(kvp => kvp.Value.NomColonne)) + ") from stdin delimiter '" + o.Separator +  "' csv escape '/' quote '~';";
string finPsqlArg = "\"";

psqlArg = debutPsqlArg + copyCommand + finPsqlArg;

PSQL est lancé comme ceci :

ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false; //obligatoire pour utliser le stdin
psi.RedirectStandardError = true;//a voir si utilisable
psi.RedirectStandardInput = true;//obligatoire pour utliser le stdin
psi.RedirectStandardOutput = true;//a voir si utilisable
psi.FileName = @"C:\Program Files\PostgreSQL\11\bin\psql.exe";
psi.Arguments = psqlArg; 

Process proc = new Process();
proc.StartInfo = psi;
proc.Start();
proc.StandardInput.NewLine = "\n";

Apres je créé les ligne et je les envoie sur le STDIN par des :

proc.StandardInput.WriteLine(string.Join("|", champsTable));

Et normalement, j'envoie quelque chose pour dire à PSQL que c'est la fin des données.
J'ai essayé d'envoyer Ctrl-D, Ctrl-Z, "/." et d'autre variante trouvé sur Internet. Au mieux, rien ne se passe, au pire, j'ai une erreur séquence inattendu, erreur d'encoding UTF8.

Réellement, qu'est-ce que je dois envoyer ?


Pour info, si au lieu d'envoyer les données dans le STDIN, je les enregistre dans un fichier et que je lance  à la main PSQL avec la ligne de commande généré par l'outil mais en changeant STDIN par le chemin du fichier généré, ça marche, donc OK pour la ligne de commande et OK pour les données

Hors ligne

#2 26/04/2019 08:55:40

rjuju
Administrateur

Re : Envoyer fin de fichier dans le STDIN

Vous pouvez faire un dump au format texte pour voir le format des données.  La fin de l'entrée est normalement signifiée par une ligne ne contentant que

\.

Hors ligne

#3 26/04/2019 10:30:27

rvs75
Membre

Re : Envoyer fin de fichier dans le STDIN

proc.StandardInput.Write("\\."); => PSQL toujours en attente
proc.StandardInput.Write("\\.\n");  => ERREUR:  séquence d'octets invalide pour l'encodage « UTF8 » : 0x82
proc.StandardInput.WriteLine("\\.");   => ERREUR:  séquence d'octets invalide pour l'encodage « UTF8 » : 0x82

Hors ligne

#4 26/04/2019 13:14:40

rvs75
Membre

Re : Envoyer fin de fichier dans le STDIN

Test directement avec les octets (méthode C# et méthode PSQL).
-
byte[] bytes = new byte[] { 0x5c, 0x2e,0x2a };
proc.StandardInput.BaseStream.Write(bytes, 0, bytes.Length); => PSQL toujours en attente
-
proc.StandardInput.Write("\\x5c\\x2e\\x2a"); => PSQL toujours en attente
-
Bug PSQL ?

Hors ligne

#5 26/04/2019 14:58:06

rjuju
Administrateur

Re : Envoyer fin de fichier dans le STDIN

Bug PQSL

Si un cycle pg_dump / psql montre le même problème oui, sinon non.  Je ne suis pas sur de comprendre votre 0x2A non plus cela dit.

Hors ligne

#6 27/04/2019 23:20:10

rvs75
Membre

Re : Envoyer fin de fichier dans le STDIN

Finalement, j'ai utilisé la fonction copy de Npgsql (https://www.npgsql.org/doc/copy.html).
Ça fonctionne très bien, mais ça m'a couté un samedi de dev !

Hors ligne

Pied de page des forums