package cz.frantovo.sql.vyuka.dao; import cz.frantovo.sql.vyuka.dao.VyukaSuperDAO.DATABAZE; import cz.frantovo.sql.vyuka.dto.Hlaska; import cz.frantovo.sql.vyuka.dto.Hlaska.Typ; import cz.frantovo.sql.vyuka.dto.Tabulka; import cz.frantovo.sql.vyuka.dto.Uzivatel; import cz.frantovo.sql.vyuka.dto.VysledekSQL; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; /** * Pro spouštění uživatelových příkazů. * @author fiki */ public class PiskovisteDAO extends VyukaSuperDAO { private enum VLASTNOSTI { VYCHOZI_CESTA } TipyDAO tipy = new TipyDAO(); HistorieDAO historie = new HistorieDAO(); public VysledekSQL vykonejSQL(String sql, Uzivatel uzivatel) { VysledekSQL v = new VysledekSQL(); if (historie.ulozPrikaz(sql, uzivatel)) { Connection db = getSpojeni(DATABAZE.PISKOVISTE); if (db == null) { v.getHlasky().add(new Hlaska("Došlo k chybě spojení.", Typ.Chyba)); } else { PreparedStatement ps = null; ResultSet rs = null; try { /** * Uživatelskému SQL příkazu předřadíme výchozí cestu (search_path). * Protože uživatelé si ji mohou měnit a kvůli recyklaci databázových zdrojů * by jeden uživatel mohl ovlivnit jiného. */ if (getVlastnost(VLASTNOSTI.VYCHOZI_CESTA) != null) { sql = orizni(getVlastnost(VLASTNOSTI.VYCHOZI_CESTA)) + sql; } long casPred = System.currentTimeMillis(); ps = db.prepareStatement(sql); boolean isRS = ps.execute(); if (isRS) { rs = ps.getResultSet(); v.getTabulky().add(zpracujVysledek(rs)); } /** * Ošetříme případ, kdy uživatel zadá SQL příkaz, který nevrací výsledkovou sadu. * Typicky nastavení výchozího schématu: SET search_path = '…'; * Poznámka: jeden „SET search_path TO "…"“ se obvykle předřazuje uživatelskému SQL (viz PiskovisteDAO.xml). */ while (ps.getMoreResults() || ps.getUpdateCount() > -1) { rs = ps.getResultSet(); if (rs == null) { /** Jedná se o „update count“. */ } else { v.getTabulky().add(zpracujVysledek(rs)); } } long dobaProvadeni = System.currentTimeMillis() - casPred; /** Varování */ if (v.getHlasky().size() < 1 && v.getTabulky().size() < 1) { v.getHlasky().add(new Hlaska("SQL příkaz proběhl, ale nevrátil žádná data.", Typ.Varovani)); } /** Varování */ int pocitadloTabulek = 1; for (Tabulka t : v.getTabulky()) { if (t.getHodnoty().size() < 1) { v.getHlasky().add(new Hlaska("Tabulka " + pocitadloTabulek + " je prázdná.", Typ.Varovani)); } pocitadloTabulek++; } v.getHlasky().add(new Hlaska("SQL příkaz byl proveden úspěšně, během " + dobaProvadeni + " ms.", Typ.OK)); } catch (SQLException e) { log.log(Level.SEVERE, "SQL chyba při vykonávání uživatelského dotazu.", e); v.getHlasky().add(new Hlaska("Chybné SQL: " + e.getMessage(), Typ.Chyba)); } catch (Exception e) { log.log(Level.SEVERE, "Chyba při vykonávání uživatelského dotazu.", e); v.getHlasky().add(new Hlaska("Došlo k chybě dotazu.", Typ.Chyba)); } finally { zavri(db, ps, rs); } } /** Tip pro uživatele */ String tip = tipy.getTip(); if (tip != null) { v.getHlasky().add(new Hlaska(tip, Typ.Tip, false)); } } else { v.getHlasky().add(new Hlaska("Došlo k chybě historie.", Typ.Chyba)); } return v; } private Tabulka zpracujVysledek(ResultSet rs) throws SQLException { Tabulka t = new Tabulka(); int pocetSloupecku = rs.getMetaData().getColumnCount(); String[] zahlavi = new String[pocetSloupecku]; t.setZahlavi(zahlavi); for (int i = 0; i < pocetSloupecku; i++) { zahlavi[i] = rs.getMetaData().getColumnName(i + 1); } while (rs.next()) { Object[] hodnoty = new Object[pocetSloupecku]; for (int i = 0; i < pocetSloupecku; i++) { hodnoty[i] = rs.getObject(i + 1); } t.getHodnoty().add(hodnoty); } return t; } }