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