java/sql-vyuka/src/java/cz/frantovo/sql/vyuka/dao/PiskovisteDAO.java
author František Kučera <franta-hg@frantovo.cz>
Sat Jul 18 17:16:41 2009 +0200 (2009-07-18)
changeset 51 bc821c6d090c
parent 44 8ce7c1ad5fde
child 52 0eeae8c247cc
permissions -rw-r--r--
Oprava #3 – uživatel může zadat příkaz, který nevrací výsledkovou sadu (typicky nastavení „search_path“), dříve se nezobrazovaly následné výsledky (tabulky) a proces procházení skončil.
Teď může uživatel zadar jeden příkaz, který nevrací výsledek a výsledky (tabulky) následujících dotazů se mu zobrazí správně.
     1 package cz.frantovo.sql.vyuka.dao;
     2 
     3 import cz.frantovo.sql.vyuka.dao.VyukaSuperDAO.DATABAZE;
     4 import cz.frantovo.sql.vyuka.dto.Hlaska;
     5 import cz.frantovo.sql.vyuka.dto.Hlaska.Typ;
     6 import cz.frantovo.sql.vyuka.dto.Tabulka;
     7 import cz.frantovo.sql.vyuka.dto.Uzivatel;
     8 import cz.frantovo.sql.vyuka.dto.VysledekSQL;
     9 import java.sql.Connection;
    10 import java.sql.PreparedStatement;
    11 import java.sql.ResultSet;
    12 import java.sql.SQLException;
    13 import java.util.logging.Level;
    14 
    15 /**
    16  * Pro spouštění uživatelových příkazů.
    17  * @author fiki
    18  */
    19 public class PiskovisteDAO extends VyukaSuperDAO {
    20 
    21     private enum VLASTNOSTI {
    22 
    23         VYCHOZI_CESTA
    24     }
    25     TipyDAO tipy = new TipyDAO();
    26     HistorieDAO historie = new HistorieDAO();
    27 
    28     public VysledekSQL vykonejSQL(String sql, Uzivatel uzivatel) {
    29         VysledekSQL v = new VysledekSQL();
    30         if (historie.ulozPrikaz(sql, uzivatel)) {
    31 
    32             Connection db = getSpojeni(DATABAZE.PISKOVISTE);
    33             if (db == null) {
    34                 v.getHlasky().add(new Hlaska("Došlo k chybě spojení.", Typ.Chyba));
    35             } else {
    36                 PreparedStatement ps = null;
    37                 ResultSet rs = null;
    38                 try {
    39                     /**
    40                      * Uživatelskému SQL příkazu předřadíme výchozí cestu (search_path).
    41                      * Protože uživatelé si ji mohou měnit a kvůli recyklaci databázových zdrojů
    42                      * by jeden uživatel mohl ovlivnit jiného.
    43                      */
    44                     if (getVlastnost(VLASTNOSTI.VYCHOZI_CESTA) != null) {
    45                         sql = orizni(getVlastnost(VLASTNOSTI.VYCHOZI_CESTA)) + sql;
    46                     }
    47 
    48                     long casPred = System.currentTimeMillis();
    49                     ps = db.prepareStatement(sql);
    50                     boolean isRS = ps.execute();
    51 
    52                     if (isRS) {
    53                         rs = ps.getResultSet();
    54                         v.getTabulky().add(zpracujVysledek(rs));
    55                     }
    56 
    57                     /**
    58                      * Ošetříme případ, kdy uživatel zadá SQL příkaz, který nevrací výsledkovou sadu.
    59                      * Typicky nastavení výchozího schématu: SET search_path = '…';
    60                      * pokud bude pocetPokusu = 0 a první dotaz nevrátí výsledkovou sadu,
    61                      * procházení se ukončí a uživatel neuvidí žádnou tabulku (i když další příkazy už výsledkové sady vracely).
    62                      * Poznámka: jeden „SET search_path = '…'“ se obvykle předřazuje uživatelskému SQL (viz PiskovisteDAO.xml).
    63                      */
    64                     int pocetPokusuBezRS = 1;
    65                     while (ps.getMoreResults() || pocetPokusuBezRS > 0) {
    66                         pocetPokusuBezRS--;
    67                         rs = ps.getResultSet();
    68                         if (rs == null) {
    69                             /** Jedná se buď o „update count“ nebo tu už žádná další výsledková sada není. */
    70                         } else {
    71                             v.getTabulky().add(zpracujVysledek(rs));
    72                         }
    73                     }
    74                     long dobaProvadeni = System.currentTimeMillis() - casPred;
    75 
    76                     /** Varování */
    77                     if (v.getHlasky().size() < 1 && v.getTabulky().size() < 1) {
    78                         v.getHlasky().add(new Hlaska("SQL příkaz proběhl, ale nevrátil žádná data.", Typ.Varovani));
    79                     }
    80 
    81                     /** Varování */
    82                     int pocitadloTabulek = 1;
    83                     for (Tabulka t : v.getTabulky()) {
    84                         if (t.getHodnoty().size() < 1) {
    85                             v.getHlasky().add(new Hlaska("Tabulka " + pocitadloTabulek + "  je prázdná.", Typ.Varovani));
    86                         }
    87                         pocitadloTabulek++;
    88                     }
    89 
    90                     v.getHlasky().add(new Hlaska("SQL příkaz byl proveden úspěšně, během " + dobaProvadeni + " ms.", Typ.OK));
    91 
    92                 } catch (SQLException e) {
    93                     log.log(Level.SEVERE, "SQL chyba při vykonávání uživatelského dotazu.", e);
    94                     v.getHlasky().add(new Hlaska("Chybné SQL: " + e.getMessage(), Typ.Chyba));
    95                 } catch (Exception e) {
    96                     log.log(Level.SEVERE, "Chyba při vykonávání uživatelského dotazu.", e);
    97                     v.getHlasky().add(new Hlaska("Došlo k chybě dotazu.", Typ.Chyba));
    98                 } finally {
    99                     zavri(db, ps, rs);
   100                 }
   101             }
   102 
   103             /** Tip pro uživatele */
   104             String tip = tipy.getTip();
   105             if (tip != null) {
   106                 v.getHlasky().add(new Hlaska(tip, Typ.Tip, false));
   107             }
   108 
   109         } else {
   110             v.getHlasky().add(new Hlaska("Došlo k chybě historie.", Typ.Chyba));
   111         }
   112         return v;
   113     }
   114 
   115     private Tabulka zpracujVysledek(ResultSet rs) throws SQLException {
   116         Tabulka t = new Tabulka();
   117 
   118         int pocetSloupecku = rs.getMetaData().getColumnCount();
   119         String[] zahlavi = new String[pocetSloupecku];
   120         t.setZahlavi(zahlavi);
   121         for (int i = 0; i < pocetSloupecku; i++) {
   122             zahlavi[i] = rs.getMetaData().getColumnName(i + 1);
   123         }
   124 
   125         while (rs.next()) {
   126             Object[] hodnoty = new Object[pocetSloupecku];
   127             for (int i = 0; i < pocetSloupecku; i++) {
   128                 hodnoty[i] = rs.getObject(i + 1);
   129             }
   130             t.getHodnoty().add(hodnoty);
   131         }
   132 
   133         return t;
   134     }
   135 }