PostgreSQL : changer le propriétaire d’une base de données

Une méthode un peu bourrine mais qui marche.

  • Se connecter à la base de données voulue
  • copier/coller les lignes suivantes en changeant newuser et éventuellement public.
\t\a
\o /tmp/hack.sql
select 'ALTER '
||CASE WHEN relkind='r' THEN 'TABLE' WHEN relkind='S' THEN 'SEQUENCE' WHEN relkind='v' THEN 'VIEW' END ||' '||relname||' OWNER TO newuser;'
from pg_class c
join pg_namespace ns ON ns.oid=c.relnamespace
where relkind in ('r','S','v')
and ns.nspname='public'
ORDER BY CASE WHEN relkind='r' THEN 1 ELSE 2 END;
\o
\i /tmp/hack.sql
  • Le ORDER BY est nécessaire pour que les tables soient traitées avant les séquences

Pour remplacer postgres par newuser comme propriétaire de toutes les fonctions “possédées” par postgres :

\t\a
\o /tmp/hack.sql
SELECT 'ALTER FUNCTION '
|| format('%I.%I(%s)', n.nspname, p.proname, oidvectortypes(p.proargtypes))
||' OWNER TO newuser;'
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
AND n.nspname NOT IN ('pg_catalog','information_schema')
AND pg_catalog.pg_get_userbyid(p.proowner)='postgres';
\o
\i /tmp/hack.sql

Enjoy !

UTF8 et Perl

Je ne suis vraiment pas doué avec UTF8 et Perl. Un coup ça marche, un coup non… Des années que je perds des heures à essayer des trucs différents.

Là j’ai un résultat qui a l’air de marcher, jusqu’à la prochaine fois :

#!/usr/bin/perl -w

use DBI;
use Encode;
use utf8;
use open ':utf8'; 
binmode STDOUT, ":utf8"; 

my $dbh = DBI->connect("DBI:Pg:dbname=madb;host=localhost","monuser","motdepasse") ;
$dbh->prepare("SET NAMES 'utf8'")->execute;
$dbh->{pg_enable_utf8}=1;

Sinon, un truc idiot pour être sûr qu’on produit bien de l’UTF8 :

perl monscript.pl >x && file x
x: UTF-8 Unicode text

Un truc à ne pas oublier (issu de la bible) :

When you encode, the resulting UTF8 flag is always off.

When you decode, the resulting UTF8 flag is on–unless you can unambiguously represent data.

Migration de NexusDB à PostgreSQL avec pgDAC

Ce projet est énorme : il vise à remplacer NexusDB par PostgreSQL dans toutes mes applications (déployées en clientèle) en utilisant les composants pgDAC (qui sont fabuleux). Je recense ici toutes les astuces, trucs à ne pas oublier, etc.

TPgConnection

Ne pas oublier de définir :

Options / UseUnicode = True

Conversion des données

Conversion des DDL (définitions des tables)

Je joue la simplicité : j’ai acquis, il y a quelques années, Database Workbench qui permet de faire Extract DDL et récupérer ainsi les définitions de toutes les tables. Reste à convertir certains types de données :

+-------------+--------------------+
| Type Nexus  | Type PostgreSQL    |
+-------------+--------------------+
| AutoInc     | Serial primary key |
| ShortString | VarChar            |
| DWord       | Int                |
+-------------+--------------------+

Conversion des données

J’utilise le composant TCRBatchMove (dans l’onglet Data Access). Je définis 2 tables, nxMigration reliée à la nxDatabase, l’autre pour pgMigration reliée à la PGConnection.

Dans CRBatchMove1, la source est la table NXmigration, la destination est PGmigration. Attention à définir FieldMappingsMode à mmFieldName au cas où l’ordre ne serait pas rigoureusement le même.

Puis le code suivant pour transférer les données :

procedure TFmain.Button1Click(Sender: TObject);
var sl:TStringList;
    i: Integer;
begin
  sl:=TStringList.Create;
  Try
    DM.dbclefs.GetTableNames(sl);
    for i := 0 to sl.Count - 1 do begin
      DM.nxMigration.TableName:=sl[i];
      DM.pgMigration.TableName:=sl[i];
      DM.CRBatchMove1.Execute;
    end;
    ShowMessage('Done !');
  Finally
    sl.free;
  End;
end;

À peaufiner un peu pour mettre à jour les séquences :

alter sequence clilog_id_seq restart with 81;

Accélérer Locate

pgQuery.IndexFieldNames:='champ1;champ2';