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