lundi, septembre 22 2008, 23:48
Développons une nouvelle fonctionnalité pour PostgreSQL (4/13)
Par Guillaume Lelarge - PostgreSQL - Lien permanent
un peu de code
Encore une fois, commençons par mettre à jour les sources :
guillaume@laptop$ cd postgresql_src/pgsql/ guillaume@laptop$ cvs -q update -d [... coupé parce que trop long ...] P src/interfaces/libpq/fe-exec.c P src/interfaces/libpq/libpq-events.c P src/interfaces/libpq/libpq-events.h P src/interfaces/libpq/libpq-fe.h P src/interfaces/libpq/libpq-int.h
Et on compile rapidement :
guillaume@laptop$ make && make install [... coupé parce que trop long ...] PostgreSQL installation complete.
Lançons PostgreSQL :
guillaume@laptop$ export PGDIR=/home/guillaume/postgresql_devel guillaume@laptop$ export PGDATA=$PGDIR/data guillaume@laptop$ export PATH=$PGDIR/bin:$PATH guillaume@laptop$ pg_ctl start server starting FATAL: database files are incompatible with server DETAIL: The database cluster was initialized with CATALOG_VERSION_NO 200809151, but the server was compiled with CATALOG_VERSION_NO 200809191. HINT: It looks like you need to initdb.
Oups. Tiens, la version du catalogue a changé. Il faut de nouveau exécuter initdb... c'est parti :
guillaume@laptop$ rm -rf $PGDATA/* /home/guillaume/postgresql_tblspc/*
guillaume@laptop$ initdb
The files belonging to this database system will be owned by user "guillaume".
This user must also own the server process.
[... coupé ...]
Success. You can now start the database server using:
postgres -D /home/guillaume/postgresql_devel/data
or
pg_ctl -D /home/guillaume/postgresql_devel/data -l logfile start
guillaume@laptop$ pg_ctl start
server starting
LOG: database system was shut down at 2008-09-22 19:48:45 CEST
LOG: autovacuum launcher started
LOG: database system is ready to accept connections
C'est bon ! On doit recréer la base de données, la table et le tablespace :
guillaume@laptop$ createdb guillaume guillaume@laptop$ psql guillaume psql (8.4devel) Type "help" for help. guillaume=# CREATE TABLE t1 (id integer); CREATE TABLE guillaume=# CREATE TABLESPACE mon_espace_de_stockage LOCATION '/home/guillaume/postgresql_tblspc'; CREATE TABLESPACE
Voilà. On est prêt à plonger dans le code.
La première chose à faire est de modifier la syntaxe. On a vu la dernière fois que cela se passe dans le fichier src/backend/parser/gram.y (gram pour grammaire). En regardant la syntaxe déjà proposée par ALTER DATABASE, on voit qu'il est déjà possible d'ajouter une option, l'option « connection limit ». On va donc chercher cette syntaxe dans le fichier gram.y. Cherchons l'instruction ALTER DATABASE. Première occurence, le ALTER DATABASE pour le renommage d'une base de données. En fait ce code est intégré aux autres instructions de renommage des objets. Ça ne nous intéresse pas. Occurence suivante, le ALTER DATABASE pour changer le propriétaire. Là aussi, ce code est intégré aux autres instructions de changement de propriétaire. Ça ne nous intéresse toujours pas. Occurence suivante. Ah, une partie complète sur ALTER DATABASE. Le jeton AlterDatabaseStmt est celui qui nous intéresse. « ALTER DATABASE database_name opt_with alterdb_opt_list » correspond au « ALTER DATABASE database_name WITH CONNECTION LIMIT x ». « alterdb_opt_list » correspond à la liste des options, pour l'instant qui se limite à une, mais nous devons en ajouter une deuxième. Cherchons donc maintenant « alterdb_opt_list ». Nous trouvons ce code :
alterdb_opt_list:
alterdb_opt_list alterdb_opt_item { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
Cela déclare « tout simplement » une liste. Nous devons maintenant chercher « alterdb_opt_item », et nous trouvons ceci :
alterdb_opt_item:
CONNECTION LIMIT opt_equal SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
}
;
Si on essaie d'analyser cela, on comprend que la chaîne précise les mots fixes (« CONNECTION LIMIT »), un jeton pour le symbole d'égalité et un SignedIconst qui est un jeton correspondant à une constante entière signée (Signed Integer Constant). Il nous faut ajouter la syntaxe pour le tablespace :
alterdb_opt_item:
CONNECTION LIMIT opt_equal SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
}
| TABLESPACE name
{
$$ = makeDefElem("tablespace", (Node *)makeString($2));
}
;
C'est-à-dire le mot fixe TABLESPACE suivi du nom du tablespace. « name » n'est pas juste la traduction bête, mais un jeton représentant le nom d'un objet PostgreSQL.
Et maintenant que doit faire cette nouvelle syntaxe ? Nous avons vu la dernière fois que le fichier backend/commands/tablecmds.c gérait tout ce qui concernait les commandes relatives aux tables. Peut-être existe-il la même chose pour les bases. Cherchons ça :
guillaume@laptop$ ll src/backend/commands/ | grep base guillaume@laptop$ ll src/backend/commands/ | grep db -rw-rr1 guillaume guillaume 46550 2008-09-22 22:37 dbcommands.c -rw-rr1 guillaume guillaume 22084 2008-09-22 22:37 dbcommands.o
backend/commands/dbcommands.c semble être le bon fichier. Ouvrons le fichier et cherchons le texte « ALTER DATABASE ». On arrive directement sur une fonction qui prend en argument une structure AlterDatabaseStmt. Hmmm, mais c'est le jeton que nous avons modifié... excellent, ça. En lisant le code de la fonction, on voit cette partie :
if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
dconnlimit = defel;
}
C'est le code qui s'occupe de l'option CONNECTION LIMIT. Il nous reste à ajouter le code pour l'option TABLESPACE. Nous allons seulement ajouter un code qui envoie un message dans les journaux applicatifs pour savoir si nous avons bien réussi à intégrer une nouvelle syntaxe. Cela donne ce code :
else if (strcmp(defel->defname, "tablespace") == 0)
{
elog(NOTICE, "set tablespace !");
}
Simple, non ?
Voyons déjà ce que donne ces modifications. On compile, installe et redémarre PostgreSQL :
guillaume@laptop$ make && make install [... coupé de nouveau ...] make1: quittant le répertoire « /home/guillaume/postgresql_src/pgsql/config » PostgreSQL installation complete. guillaume@laptop$ pg_ctl restart waiting for server to shut down.... LOG: received smart shutdown request LOG: autovacuum launcher shutting down LOG: shutting down LOG: database system is shut down done server stopped server starting LOG: database system was shut down at 2008-09-22 22:36:28 CEST LOG: autovacuum launcher started LOG: database system is ready to accept connections
Lançons psql :
guillaume@laptop$ psql postgres psql (8.4devel) Type "help" for help. postgres=# alter database guillaume with tablespace mon_espace_de_stockage ; NOTICE: set tablespace ! ALTER DATABASE
L'ajout de la syntaxe a fonctionné \o/
Maintenant, il va falloir ajouter un code plus intéressant dans cette fonction.
aucun commentaire