IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Parser du MS SQL


Sujet :

C#

  1. #1
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut Parser du MS SQL
    Bonjour a tous !
    Voila, je cherche un parser SQL comme le titre l'indique. Si possible gratuit (mais pas GPL, je dois pouvoir l'utiliser dans un produit commercial à source fermé .... c'est la patron qui décide )
    Je suis tout de même preneur des payants, on sait jamais, s'ils sont vraiment mieux...

    Mes contraintes sont les suivantes :
    - La syntaxe parsable doit être celle de Sql Server (version 2005 pour être précis, au cas où il y aurait de grosses différences entres les version, je les connais pas).

    - La syntaxe SQL Ansi 89 n'est pas du tout suffisante (il manque notemment, mais pas seulement, la gestion des schémas (select dbo.ma_table.ma_colonne FROM dbo.ma_table)

    - Le parser comprendre la syntaxe a crochet de MS (select [dbo].[ma_table].[ma_colonne] FROM [dbo].[ma_table] )

    - La problématique premiere que doit résoudre le parser est la suivante :
    Notre soft fait beaucoup mumuse avec la base de donnée, et permet a l'utilisateur final d'ajouter de nouvelles tables et vues. Les tables sont créées via un assistant. Par contre les vues sont trop complexes pour pouvoir être crées de la même manière. En conséquence, l'utilisateur tape sa requête select (avec jointure, union, agrégation et tout les joyeusetés que permettent le SQL). Ensuite, il click sur un bouton, et ca modifie le scripte pour ajouter tout ce qu'il faut (les closes CREATE VIEW, les insertions/mises a jour de nos tables système pour renseigner notre soft de l'apparition de la nouvelle vue, le lancement des procédures, etc, etc, ...).
    Je dois donc pouvoir analyser sa requête et connaitre :
    - Les tables utilisées
    - les jointures faites
    - les noms des champs en entrée et sortie de la requête (champs avec alias, unions et tout le bordel)
    - les champs entièrement calculés
    - les champs utilisés dans le calcule d'autres champs (genre un champs qui serait COALLESCE(col1, col2, col3, 'robert') AS Prenom )
    - ...

    Voila, ca c'est le "minimum vital" dont j'ai besoin. Idéalement, j'aimerai pouvoir parser n'importe quel type de requête (insert, update, scripte multi-requête, ...).

    J'ai évidemment fait quelques recherches avants et je suis tombé sur deux parsers :
    - http://www.sqlparser.com/ (General Sql Parser)
    - http://www.devincook.com/goldparser/

    Le premier, mon patron l'a acheté. Il marche pas trop mal, mais c'est loin d'être la joie. Il ne gère pas les schéma, a tendance a planter sur des requêtes un brin complexes (genre un UNION ALL et pouf le parser meurt).
    J'arrive plus ou moins a combler les défauts mais ca donne un code très bancale et pas propre du tout.

    Le second est un "concepte" plus qu'un parser. On trouve en téléchargement des implémentations diverses et variées dans des langages tout aussi variés.
    C'est un parser encore plus général puisqu'il se base sur un fichier de grammaire pour parser le texte fournis. On peux donc potentiellement obtenir un parser de n'importe quel language. J'ai trouvé la grammaire de la syntaxe Sql Ansi, mais pas celle de SqlServer. J'ai tenté de l'adapté un peu mais je galère grave. En plus, jusqu'ici, j'ai pas été foutu de réussir a parser un pauvre "select * from dbo.matable;". Mais bon ca c'est juste une question de persévérance et de temps pour bien prendre en main le bouzin (sauf que comme d'hab, le temps on l'a pas, ce devra être fini pour hier ...)

    Donc voila, si vous connaissez des parser ou que vous possédez un fichier de grammaire correcte. Ou encore que vous avez des conseils sur comment palier aux différentes problématiques énoncées... D'ailleur je me demandait s'il n'y avait pas moyen de faire parser le scripte à SqlServer, sans qu'il exécute quoi que ce soit, et qu'il me retourne le résultat de manière exploitable (non parce que pour le moment il veux bien parser mes scripts mes il me répond juste "Ok" ou "tu as écris n'importe quoi, recommence ispice de noob"). Je pense notamment a Smo, Nmo et tout la suite.

    Merci de votre aide, de votre temps et de vos conseils

    Edit :
    Petites précisions. Le scripte est entré dans un composant a coloration syntaxique. Ce sera soit ScintillaNet si j'arrive a faire comprendre a mon patron que c'est du LGPL, qu'on a le droit et que le libre n'est pas le mal incarné. Soit ca sera SyntaxEditor d'ActiproSoftware.
    Le premier étant open source, je peux le modifier pour qu'il parse en même temps qu'il fait sa coloration syntaxique.
    Le second est a base de plugin surchargeable pour créer les syntaxes. On pourrait donc imaginer l'étendre pour que lui aussi parse en même temps qu'il fait la coloration.
    Le problème serait alors surtout la masse de boulot. Parce que l'un comme l'autre ne font que catégoriser quelques mots clefs. Autrement dit, ils ne savent absolument pas faire la différence entre "SELECT" et "INSERT", ils savent juste que ces deux mots doivent être coloriés. De plus, ca ne vérifie aucunement la syntaxe. Écrire
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT INSERT; FROM UNION COALLESCE(CREATE, TABLE)
    , ben ca les choques pas du tout.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    je ne comprends pas ce que veux dire parser du sql

    par contre avec les dll d'sql server (smo) tu peux faire pas mal de chose
    et créer son propre éditeur de requete (surtout avec smo) est faisable
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    C'est très simple. Je veux fournit une requête sous la forme d'un string a un parser.
    Admettons :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT
        [dbo].[ma_table].[col_01] AS [Data]
    FROM [dbo].[ma_table]
    UNION ALL
    SELECT
        COALLESCE(datas, 'rien') AS [Data]
    FROM [dbo].[une_autre_table]

    Je passe donc cette requête au parser, qui va me dire :
    - Il y a une union de plusieures requêtes SELECT
    - Dans la premiere requête, la selection se fait sur la table [dbo].[ma_table].
    - Seul la colonne [col_01] de cette table est utilisée, et est aliasée en [Data]
    ...
    etc ...
    je veux donc pouvoir avoir accès a ce genre d'information sur la requête fournie, sans avoir a éxécuter la requête en question.

    Tout ca dans le but d'avoir les informations nécéssaire à la création du scripte final.

    Je me sert déjà pas mal de smo (pour faire un semblant d'intellisense notement, mais également récupérer le scripte ayant servit a la création d'une vue/d'un trigger/...

    J'ai cherché un peu dedans, mais je n'ai rien trouvé qui me permettrait d'analyser une requête. Mais Smo c'est pas petit, je suis peut-être passé a coté. Si tu as des pistes/exemples/nom d'objets/liens de documentations ... je suis prenneur.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    je vais regarder dans smo, parce que ce genre de truc m'intéresserait peut etre aussi

    sinon avec SET FMT_ONLY ON tu peux exécuter la requête instantanément sans retour de données à part la structure des champs (et au passage ca te dis si la requête et exécutable)

    et merci je viens d'apprendre le mot "parser", qui en plus est français ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    Je regarderai de plus près le SET FMT_ONLY, mais si ca ne fait que retourner une table vide pour avoir les colonnes, ca ne sera pas suffisant malheureusement. J'ai besoin de savoir comment est faite la colonne (pour maintenir une table de lien de parenté/héritage).
    Cependant, rien ne m'empêche de me servire de ca pour savoir si ma requête est exécutable et ce qu'elle retourne comme structure, pour macher le boulot du parser et orienter ma recherche d'information complémentaire par la suite.

    Je ne savais pas que le mot "parser" était français. J'ai toujours cru qu'on avait pas vraiment d'équivalent mieux que "analyseur de syntaxe" ou quelque chose comme ca.

    PS: Ah oui, une fonction que j'aimerai bien avoir (présente dans Gold parser) c'est quand il y a une erreure de syntax qu'il te dise ce qui était attendu pour valider la syntaxe.
    Exemple :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * WHERE a = 12;
    Il devrait me dire "erreure près de '*', la clause FROM était attendue.

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    on a fait un éditeur de requete, et on se sert de fmt_only pour savoir si la requete fonctionne
    sachant que si elle fonctionne pas tu as les messages d'erreur comme tu le souhaites, ce qui aide à corriger


    de plus sur l'execute tu peux passer un paramètre (qui vient d'une enum) pour dire que tu veux que ca remonte toutes les infos de structure

    donc sur chaque colonne tu peux savoir si c'est une clé primaire, le nom de la table, le nom du champ, son alias, le type, la taille du champs ...

    m'enfin dans un union t'as pas d'infos ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    sinon tu peux aussi créer la vue avec le code de la requete
    récupérer la vue dans un Microsoft.SqlServer.Management.Smo.View et sur le view tu as .columns pour avoir les infos des colonnes

    mais là aussi je pense qu'en cas d'union ca foire tout


    sinon je pense pas qu'on peut trouver des parser sql facilement, mais ca peut se réécrire avec un peu de temps

    sinon faut voir dans les dll de visual studio
    on avait réussi d'une manière très détournée à utiliser le designer de requete d'sql server, qu'on trouve aussi dans visual studio, mais seulement en mode design
    faudrait voir avec reflector si toute cette fenetre est écrite en .net ou s'il y a une partie en com appelé par du .net
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    En fait, il faut exécuter la requête en ayant activé FMTONLY avant et ca retourne une table vide, comme si la requête n'avait pas fournit de résultat. Ensuite il faut lire les métadatas les la fonction GetSchemaTable présente sur le SqlDataReader. Fonction qui retourne une table contenant pas mal d'info dont le type des données.
    C'est bien ca ?
    En tout cas ca à l'air pas mal du tout. Je pense que je vais m'en servir. Si ca marche pas pour les unions, je peux toujours palier en faisant une première analyse et un découpage. J'enverrai alors chaque requête composante de l'union une à une puis je ferais une fusion des résultats.
    C'est pas parfait, mais c'est la solution la plus propre que j'ai pour le moment.

    Si ca marche comme ca, c'est suffisant pour remplir les conditions demandées. Mais bon, l'idéal serait tout de même un vrai moyen de parser afin de permettre une réaction "intelligente" au moment de la frappe.

    Chez nous on a une sorte de best practice de l'écriture de requête.
    - Pas de SELECT * FROM, on doit noté tous les champs
    - Les noms doivent être au format long (schema.table.colonne, pas juste colonne)
    - les crochets doivent être systématisé (même si personne le fait réellement, [schema].[table].[colonne])

    Un parser me permettrait de parser la requête en tache de fond et "forcer" ces best practices.

    Mais bon, comme je disais, ca serait le top, déjà avec ta solution je pense pouvoir avancer pas mal

  9. #9
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    Oui, écrire mon propre parser j'y ai songé, mais je n'aurais jamais le temps de faire quelque chose de suffisamment avancé

    Le coup de créer la vue et de l'analyser après peux être intéressant aussi, tu as de bonnes idées

    J'étais resté bloqué sur le fait qu'il me fallait un parser...

  10. #10
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    ah oui j'avais pas pensé à découper le union, ca te permet d'analyser les 2 requetes

    et en effet c'est avec getschematable que tu as toutes les infos et faire l'executereader avec CommandBehavior.KeyInfo en paramètre, ca donne plus d'infos
    voir meme CommandBehavior.KeyInfo or CommandBehavior.SchemaOnly
    SchemaOnly ne fait qu'ajouter set fmt_only au début de la requete

    nous on autorise les select * vu qu'on retrouve toutes les infos ca nous dérange pas ...

    et notre éditeur de requete il est pas complet mais il permet de se débrouiller, on gère graphiquement les tables de la requete, les champs, les alias, les jointures et les order by
    à la lecture on récupère en premier tout ce qu'il y après from et avant where, order et/ou group by
    ca nous donne les tables et les jointures
    après on regarde dans le select, ca nous donne les champs, si on voit juste champ1, on recherche sur quelle table il y a champ1, si plusieurs tables ont un champ nommé champ1, c'est qu'il y a forcément un préfixage de table sur les 2
    ensuite tout ce qui est derrière le from on le met dans un textbox modifiable
    le reste se fait donc graphiquement avec des cases à cocher

    la décompilation (ou le parsage donc ^^) de la requete se fait sur une centaine de ligne de code
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    Effectivement, après teste, CommandBehavior.SchemaOnly (qui fait juste le FMTONLY) n'est pas suffisant. Avec KeyInfo y'a plein d'infos complémentaires fort utiles.

    J'ai également tester les union et comme on s'en doutait ca ne marche pas, j'ai plus qu'a faire mon histoire de découpage par union.

    En tout cas, j'aime beaucoup cette solution, c'est foutrement plus simple que d'utiliser un parser

    A terme je devrais également faire un éditeur graphique (un peu a la MS-Access), en utilisant des composants de "chart" (genre Nevron, Mindfusion, ...)
    Mais ce point ne me fait pas vraiment peur. Encore que ... Je sens que quand le patron verra cet éditeur arriver, il me fera encore le coup du "waaawww c'est bien, mais ca serait encore mieux si ...."
    Et qu'il me fera générer le graphique en fonction d'une requête existante (genre, quand tu fait "obtenir le script" sur une vue existante, faudra que je génère le graphique de cette vue...)
    La plupart des vues sont pas trop compliquée, mais on en a quelques unes qui font franchement peur. Enfin, on verra bien ^^

    Edit : Je passe le topic en résolut car ta solution a résolut en très grande partie ma problématique. Cependant, si toi ou d'autres ont d'autres solutions a proposer, faut pas hésiter. Je suis très curieux de voir toutes les possibilités que nous offriraient un parser ou Smo ou autre.

    De plus, il reste tout de même un problème avec cette solution :
    Je ne peux connaitre la structure de la requête QUE si je peux l'exécuter.
    Ce qui signifie qu'il me faut impérativement une connexion (et donc je ne peux pas générer de scripts a exécuter "plus tard") et les objets (tables, vues, colonnes, ...) impliquées dans la requête doivent exister.
    Je ne peux pas obtenir de structure "offline".

  12. #12
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    en effet il faut une connexion ...
    m'enfin si tu es mode execution, tu as à mon avis ta base sous la main
    et si c'est en mode design que tu veux faire des requetes, je peux te trouver le code pour avoir le designer de requete d'sql server

    et si je trouve (ou écrit) un parser je te tiens au courant, c'est vrai que ca permet plus de chose, et entre autre de faire un vrai éditeur de requête
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #13
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    Normalement je devrais avoir toujours la base sous la main. Mais c'est pas absolument certain. Et ca veux dire que je ne peux obtenir aucune infos sur la scripte quand je ne suis pas connecté ou que le scripte n'est pas fait pour la base actuellement connectée.

    Dans mon cas a moi, je pense qu'imposer le mode connecté ne sera pas vraiment un problème. C'est un peu contraignant, mais c'est pas la mort non plus.
    Par contre, comme tu dis, pour faire un vrai éditeur de requête il faut pouvoir analyser la syntaxe de manière déconnecté.

    Un projet de parser j'en ai un en tête qui me démange depuis un moment. Mais je manque vraiment de temps pour m'y mettre. Sans compter que la syntaxe MS-Sql est vraiment conséquente.

    Que le parser ne comprenne pas tout, c'est pas spécialement grave. Mais il faudrait pas qu'il plante ou indique une syntaxe fausse sous prétexte qu'il ne la comprend pas. Et ca, je trouve que c'est foutrement bien complexe

    Edit : Faut que je regarde du coté du combo de Lex + Yacc aussi, y'a ptre moyen de faire quelque chose...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. parser xml pl/sql
    Par eidole62 dans le forum PL/SQL
    Réponses: 1
    Dernier message: 28/12/2007, 10h59
  2. Comment parser une requete sql sans l'executer
    Par FABFAB125 dans le forum SQL
    Réponses: 2
    Dernier message: 30/11/2007, 17h21
  3. Parser une requête SQL pour MySQL
    Par gassla dans le forum SGBD
    Réponses: 3
    Dernier message: 02/08/2006, 15h36
  4. [JDBC][SQL] Parser une requête SQL
    Par tomca dans le forum JDBC
    Réponses: 11
    Dernier message: 24/10/2005, 23h13
  5. Pseudo parser SGML en PL/SQL
    Par j2s dans le forum PL/SQL
    Réponses: 3
    Dernier message: 13/07/2005, 17h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo