jeudi 11 juin 2009

Functions, requêtes préparées, ou les deux?

Comme souvent, mes choix technologiques correspondent souvent à de grands coups de volant d'un extrême l'autre. Découvrant les fonctions postgresql, je me suis précipité dessus en voulant les utiliser partout. Un peu plus tard, je découvre qu'elles ne sont pas la panacée:

- Pas de protection particulière contre l'injection, puisque l'appel à la fonction est fait d'un appel SQL normal
- Le plan est compilé une fois pour toutes. Si l'on créé une fonction alors que la table est vide, le planificateur peut choisir d'ignorer les index, ce qui provoquera des performances épouvantables si la table devient tout d'un coup énorme
- Enfin, la modification de la signature d'une fonction entraîne un changement dans la base, ainsi qu'un changement dans le code.

Utilisons les requêtes préparées, donc! Compilées au démarrage de l'appli, lors de leur enregistrement, elles permettent un plan plus optimal, protègent de l'injection, et un changement de requête se fait dans le code, au plus près de leur utilisation.

C'était sans compter les requêtes complexes que nécessitent mon système d'authentification... Les requêtes préparées devenaient alors trop compliquées, forçant beaucoup d'allers-retours entre l'application et la base de données. Et libpqxx, pour être une bibliothèque très bien conçue, nécessite beaucoup de code pour faire tenir une requête dans une transaction et pour en récupérer les résultats.

Je me suis donc remis à écrire des fonctions, au moins pour le système de gestion de compte (création et vérification d'un utilisateur, création et vérification d'un avatar). J'appellerai les fonctions via des requêtes préparées, histoire d'améliorer la sécurité. J'espère ne pas trop avoir à modifier mes fonctions, et je les recompilerai autant de fois qu'il le faudra pour que le planificateur prenne des décisions qui montent en charge!

Ma règle devient donc d'utiliser les requêtes préparées quand je le peux, et des fonctions quand je le dois! Certes, avec du recul, c'est évident, mais ça va mieux en le disant.

D'ailleurs, en parlant de choses qui vont mieux en le disant, il est maintenant beaucoup plus facile de rajouter le support du langage pl/pgsql dans sa base (au moins à partir de Postgresql 8.3). Alors que jusqu'à présent j'indiquais systématiquement le chemin vers la bibliothèque, il suffit en fait de faire:


create language plpgsql

C'est quand même plus simple et mnémotechnique, non?

Aucun commentaire: