Question

Voici mon cas d'utilisation: Input est une chaîne représentant une instruction Oracle PL / SQL de complexité arbitray. Nous pouvons supposer que c'est une seule déclaration (pas un script). Maintenant, plusieurs bits de cette chaîne d'entrée doivent être réécrits .

E.g. les noms de table doivent être préfixés, les fonctions agrégées de la liste de sélection qui n'utilisent pas d'alias de colonne doivent être affectées d'un nom par défaut:

SELECT SUM(ABS(x.value)), 
TO_CHAR(y.ID,'111,111'),
y.some_col
FROM
tableX x,
(SELECT DISTINCT ID
FROM tableZ z
WHERE ID > 10) y
WHERE
...

devient

SELECT SUM(ABS(x.value)) COL1, 
TO_CHAR(y.ID,'111,111') COL2,
y.some_col
FROM
pref.tableX x,
(SELECT DISTINCT ID, some_col
FROM pref.tableZ z
WHERE ID > 10) y
WHERE
...

(Avertissement: juste pour illustrer le problème, la déclaration n'a aucun sens)

Etant donné que les fonctions d'agrégation peuvent être imbriquées et que subSELECT est un b_tch, je n'ose pas utiliser d'expressions régulières. Eh bien, en fait, j’ai réussi et obtenu 80% du succès, mais j’ai besoin des 20% restants.

La bonne approche, je suppose, consiste à utiliser des grammaires et des analyseurs syntaxiques. Je me suis amusé avec c ++ ANTLR2 (bien que je ne sache pas grand chose des grammaires et de l'analyse syntaxique à l'aide de tels outils). Je ne vois pas de moyen facile d’obtenir les bits SQL:

list<string> *ssel = theAST.getSubSelectList(); // fantasy land

Quelqu'un pourrait-il donner des indications sur la manière dont "analyser les professionnels"? poursuivrait cette question? EDIT: j'utilise Oracle 9i .

Était-ce utile?

La solution

Peut-être que vous pouvez utiliser ceci, cela change une instruction select en un bloc xml:

declare
    cl clob;
begin
    dbms_lob.createtemporary (
        cl,
        true
    );
    sys.utl_xml.parsequery (
        user,
        'select e.deptno from emp e where deptno = 10',
        cl
    );
    dbms_output.put_line (cl);
    dbms_lob.freetemporary (cl);
end;
/ 

<QUERY>
  <SELECT>
    <SELECT_LIST>
      <SELECT_LIST_ITEM>
        <COLUMN_REF>
          <SCHEMA>MICHAEL</SCHEMA>
          <TABLE>EMP</TABLE>
          <TABLE_ALIAS>E</TABLE_ALIAS>
          <COLUMN_ALIAS>DEPTNO</COLUMN_ALIAS>
          <COLUMN>DEPTNO</COLUMN>
        </COLUMN_REF>
        ....
        ....
        ....
</QUERY>

Voir ici: http://forums.oracle.com/ forums / thread.jspa? messageID = 3693276 & amp; # 3693276

Il ne vous reste plus qu’à analyser ce bloc xml.

Modifier1:

Malheureusement, je ne comprends pas tout à fait les besoins de l'OP mais j'espère que cela pourra vous aider (c'est une autre façon de demander les "noms" des colonnes de la requête , par exemple, sélectionnez le nombre mannequin) de double ):

set serveroutput on

DECLARE
 c       NUMBER;
 d       NUMBER;
 col_cnt PLS_INTEGER;
 f       BOOLEAN;
 rec_tab dbms_sql.desc_tab;
 col_num NUMBER;

PROCEDURE print_rec(rec in dbms_sql.desc_rec) IS
BEGIN
  dbms_output.new_line;
  dbms_output.put_line('col_type = ' || rec.col_type);
  dbms_output.put_line('col_maxlen = ' || rec.col_max_len);
  dbms_output.put_line('col_name = ' || rec.col_name);
  dbms_output.put_line('col_name_len = ' || rec.col_name_len);
  dbms_output.put_line('col_schema_name= ' || rec.col_schema_name);
  dbms_output.put_line('col_schema_name_len= ' || rec.col_schema_name_len);
  dbms_output.put_line('col_precision = ' || rec.col_precision);
  dbms_output.put_line('col_scale = ' || rec.col_scale);
  dbms_output.put('col_null_ok = ');

  IF (rec.col_null_ok) THEN
    dbms_output.put_line('True');
  ELSE
    dbms_output.put_line('False');
  END IF;
END;

BEGIN
  c := dbms_sql.open_cursor; 
  dbms_sql.parse(c,'select count(*),max(dummy) from dual ',dbms_sql.NATIVE); 
  dbms_sql.describe_columns(c, col_cnt, rec_tab);

  for i in rec_tab.first..rec_tab.last loop
    print_rec(rec_tab(i));
  end loop;

  dbms_sql.close_cursor(c);
END;
/

(Voir ici pour plus d'informations: http://www.psoug.org/reference/ dbms_sql.html )

L’opérateur souhaite également pouvoir modifier le nom de schéma de la table dans une requête. Je pense que le moyen le plus simple d'y parvenir est d'interroger les noms de table à partir de user_tables et de rechercher ces noms de table dans l'instruction SQL et de les préfixer ou de faire un 'alter session set current_schema = .. .. '.

Autres conseils

Si les chaînes d'instruction SQL proviennent d'autres codeurs, vous pouvez simplement insister sur le fait que les parties devant être modifiées sont simplement marquées par des conventions d'échappement spéciales, par exemple, écrivez $ TABLE au lieu du nom de la table, ou $ TABLEPREFIX, où l'une est nécessaire. Il est ensuite possible de rechercher les endroits nécessitant une correction en effectuant une recherche et un remplacement de sous-chaîne.

Si vous avez réellement des chaînes SQL arbitraires et que vous ne parvenez pas à les marquer correctement, vous devez en quelque sorte analyser la chaîne SQL comme vous l'avez observé. La solution XML est certainement un moyen possible.

Vous pouvez également utiliser un système de transformation de programme . Un tel outil peut analyser une chaîne pour une instance de langage, créer des AST, effectuer une analyse et une transformation sur des AST, puis cracher une chaîne révisée.

Le DMS Software Reengineering Toolkit est un tel système. Il a un analyseur frontal PLSQL. Et il peut utiliser des transformations dirigées par des motifs pour effectuer les réécritures dont vous semblez avoir besoin. Pour votre exemple impliquant des éléments sélectionnés:

domain PLSQL.
rule use_explicit_column(e: expression):select_item -> select_item
   "\e" -> "\e \column\(\e\)".

Pour lire la règle, vous devez comprendre que les éléments entre guillemets représentent des arbres abstraits dans certaines langues informatiques que nous souhaitons manipuler. Qu'est-ce que le " domaine PLSQL " la phrase dit est, "utilisez l’analyseur PLSQL" pour traiter le contenu de chaîne cité, c'est comment il sait. (DMS propose de nombreux analyseurs de langage). Les termes " expression " et " select_item " sont des constructions grammaticales du langage d'intérêt, par exemple PLSQL dans ce cas. Consultez les schémas de chemin de fer dans votre manuel de référence PLSQL. La barre oblique inverse représente les informations méta et d'échappement plutôt que la syntaxe de la langue cible.

La règle dit, transformez ces éléments analysés qui sont select_item s composées uniquement d'une expression \ e , en les convertissant en un select_item consistant en la même expression \ e et la colonne correspondante ( \ column (\ e) ) probablement basée sur la position dans la liste des éléments sélectionnés pour la table spécifique. Vous devez implémenter une fonction colonne permettant de déterminer le nom correspondant à partir de la position de l'élément sélectionné. Dans cet exemple, j'ai choisi de définir la fonction de colonne pour accepter l'expression d'intérêt comme argument. l'expression est effectivement transmise sous forme d'arborescence correspondante. La fonction de colonne peut ainsi déterminer où elle se trouve dans la liste select_items en affichant l'arborescence de la syntaxe abstraite.

Cette règle gère uniquement les éléments sélectionnés. Vous ajouteriez plus de règles pour traiter les autres cas d’intérêt qui vous intéressent.

Ce que le système de transformation fait pour vous est le suivant:

  • analyser le fragment de langue d'intérêt
  • construire un AST
  • vous permet de rechercher les correspondances de motifs pour les lieux d'intérêt (en effectuant une correspondance de motifs AST) mais en utilisant la syntaxe de surface de la langue cible
  • remplacer les modèles correspondants par d'autres modèles
  • calculez les remplacements arbitraires (en tant que AST)
  • régénérer le texte source à partir des AST modifiés.

Bien que l’écriture des règles ne soit pas toujours anodine, c’est ce qui est nécessaire si votre problème est indiqué comme posé.

La solution XML suggérée est un autre moyen de créer de tels AST. Il ne possède pas les propriétés de correspondance de modèle intéressantes, bien que vous puissiez peut-être tirer beaucoup de choses de XSLT. Ce que je ne sais pas, c'est si le fichier XML contient l'arborescence d'analyse en détail; L’analyseur DMS fournit cela par conception, car il est nécessaire si vous souhaitez effectuer une analyse et une transformation arbitraires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top