View Issue Details

IDProjectCategoryView StatusLast Update
0001659Common[All Projects] Generalpublic2016-08-08 01:32
ReporterXenosAssigned ToXenos 
PrioritynormalSeverityfeatureReproducibilityN/A
Status CloseResolutionfixed 
Product Version1.0.4 
Target VersionFixed in Version2.0.0 
Summary0001659: Gérer les exceptions customs SQL
DescriptionDans mes procédures SQL, je peux lever des exception (SIGNAL). Il faut ensuite que ces exceptions soient récupérées par PDO et puissent être remontées au code PHP.
TagsNo tags attached.
Attach Tags

Activities

Xenos

Xenos

2016-08-07 22:12

administrator   ~0002125

Il me suffit donc d'utiliser la procédure "throw" pour lancer une exception d'une classe donnée (1er paramètre, sans le "Exception" à la fin) avec des paramètres encodés en JSON (second paramètre, souvent vide ou juste '{}').

Cette procédure va renvoyer un resultset et faire un SIGNAL. PHP récupèrera d'abord le resultset (indispensable car sinon, PDO renvoie l'exception quand SIGNAL a lieu avant le premier resultset, et s'il a lieu après, quand PDO rencontre SIGNAL, nextResultset renvoie false et PDO ne lève pas d'exception, donc c'est de la merde) et il le parsera pour générer l'exception correspondante qu'il renverra.

Donc, pour un VRAI driver MySQL, c'est SIGNAL dans THROW qui génère l'exception alors que pour PDO, c'est le RESULTSET dans THROW qui ganère l'exception.

Ensuite, cette exception remonte sous la forme d'un SqlSignalException jusqu'au décorateur du PDOExécutor. Ce décorateur catch l'exception, récupère la classe "réelle" de l'exception que je voulais, et s'il la trouve, il relance l'exception dans cette nouvelle classe. Sinon, il laisse filer le SIGNAL.

Ainsi, dans le code client, l'exception définie par "CALL throw('Gnagna', '{}')" pourra être catchée par "catch (GnagnaException $ex)". Cette exception se trouve dans les sources PHP générées de la procédure.

Le code client n'a pas de raison de catcher "SqlSignalException".
Xenos

Xenos

2016-08-07 22:14

administrator   ~0002126

Last edited: 2016-08-08 01:31

La définition de la procédure "throw" se trouve dans le projet "common" car elle revient dans chaque autre projet. Un lien symbolique est utilisé pour assurer la synchronisation (comme j'ai fait pour "php/framework")
Xenos

Xenos

2016-08-07 23:26

administrator   ~0002128

Last edited: 2016-08-08 01:31

En fait, le problème venait de "PDO emulate prepared statement" qui était défini à "false" sur un projet. Si on laisse ce paramètre en paix, alors PDO renverra correctement les exceptions levées par SIGNAL.

Du coup, la procédure "throw" est simplifiée: elle fait juste le SIGNAL en passant un JSON en guise de message. Ce JSON est parsé coté PHP par le décorateur de PDOExecutor (le catch all exception) qui va alors instancier la bonne classe d'exception avec les bons paramètres.

Ainsi, je gère les exceptions SQL personnalisées de façon parfaitement standard: un vrai IDE affichera l'exception SQL (dont le message est donc un JSON), et PDO renvoie aussi une exception -dont le message est un json- qu'un décorateur convertit alors en exception métier.

En revanche, c'est fusionné au commit du 0001661 (j'ai pas pris le temps de les séparer)

Issue History

Date Modified Username Field Change
2016-08-07 21:47 Xenos New Issue
2016-08-07 21:47 Xenos Status New => Accepted
2016-08-07 22:12 Xenos Note Added: 0002125
2016-08-07 22:12 Xenos Status Accepted => Ready
2016-08-07 22:12 Xenos Resolution open => fixed
2016-08-07 22:12 Xenos Assigned To => Xenos
2016-08-07 22:14 Xenos Note Added: 0002126
2016-08-07 23:26 Xenos Note Added: 0002128
2016-08-08 01:30 AutoUpdater Status Ready => Resolved
2016-08-08 01:31 AutoUpdater Fixed in Version => 2.0.0
2016-08-08 01:32 Xenos Status Resolved => Close