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;
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;
16 * Pro spouštění uživatelových příkazů.
19 public class PiskovisteDAO extends VyukaSuperDAO {
21 private enum VLASTNOSTI {
25 TipyDAO tipy = new TipyDAO();
26 HistorieDAO historie = new HistorieDAO();
28 public VysledekSQL vykonejSQL(String sql, Uzivatel uzivatel) {
29 VysledekSQL v = new VysledekSQL();
30 if (historie.ulozPrikaz(sql, uzivatel)) {
32 Connection db = getSpojeni(DATABAZE.PISKOVISTE);
34 v.getHlasky().add(new Hlaska("Došlo k chybě spojení.", Typ.Chyba));
36 PreparedStatement ps = null;
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.
44 if (getVlastnost(VLASTNOSTI.VYCHOZI_CESTA) != null) {
45 sql = orizni(getVlastnost(VLASTNOSTI.VYCHOZI_CESTA)) + sql;
48 long casPred = System.currentTimeMillis();
49 ps = db.prepareStatement(sql);
50 boolean isRS = ps.execute();
53 rs = ps.getResultSet();
54 v.getTabulky().add(zpracujVysledek(rs));
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).
64 int pocetPokusuBezRS = 1;
65 while (ps.getMoreResults() || pocetPokusuBezRS > 0) {
67 rs = ps.getResultSet();
69 /** Jedná se buď o „update count“ nebo tu už žádná další výsledková sada není. */
71 v.getTabulky().add(zpracujVysledek(rs));
74 long dobaProvadeni = System.currentTimeMillis() - casPred;
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));
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));
90 v.getHlasky().add(new Hlaska("SQL příkaz byl proveden úspěšně, během " + dobaProvadeni + " ms.", Typ.OK));
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));
103 /** Tip pro uživatele */
104 String tip = tipy.getTip();
106 v.getHlasky().add(new Hlaska(tip, Typ.Tip, false));
110 v.getHlasky().add(new Hlaska("Došlo k chybě historie.", Typ.Chyba));
115 private Tabulka zpracujVysledek(ResultSet rs) throws SQLException {
116 Tabulka t = new Tabulka();
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);
126 Object[] hodnoty = new Object[pocetSloupecku];
127 for (int i = 0; i < pocetSloupecku; i++) {
128 hodnoty[i] = rs.getObject(i + 1);
130 t.getHodnoty().add(hodnoty);