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ů.
20 public class PiskovisteDAO extends VyukaSuperDAO {
22 /** maximální doba trvání SQL dotazu – vteřiny */
23 private static final int LIMIT_ČASU = 3;
24 /** maximální počet řádků */
25 private static final int LIMIT_POČTU = 10000;
27 private enum VLASTNOSTI {
32 TipyDAO tipy = new TipyDAO();
33 HistorieDAO historie = new HistorieDAO();
35 public VysledekSQL vykonejSQL(String sql, Uzivatel uzivatel) {
36 VysledekSQL v = new VysledekSQL();
37 if (historie.ulozPrikaz(sql, uzivatel)) {
39 Connection db = getSpojeni(DATABAZE.PISKOVISTE);
41 v.getHlasky().add(new Hlaska("Došlo k chybě spojení.", Typ.Chyba));
43 PreparedStatement ps = null;
47 * Uživatelskému SQL příkazu předřadíme výchozí cestu (search_path).
48 * Protože uživatelé si ji mohou měnit a kvůli recyklaci databázových zdrojů
49 * by jeden uživatel mohl ovlivnit jiného.
51 if (getVlastnost(VLASTNOSTI.VYCHOZI_CESTA) != null) {
52 sql = orizni(getVlastnost(VLASTNOSTI.VYCHOZI_CESTA)) + sql;
57 * použít ps.setQueryTimeout(LIMIT_ČASU);
58 * až ho bude podporovat JDBC ovladač,
60 * Uživatel ale stejně může zadat:
61 * SET statement_timeout 0;
62 * do svého SQL dotazu.
64 if (getVlastnost(VLASTNOSTI.LIMIT_ČASU) != null) {
65 sql = orizni(getVlastnost(VLASTNOSTI.LIMIT_ČASU)) + sql;
68 long casPred = System.currentTimeMillis();
69 ps = db.prepareStatement(sql);
71 * Limit času bohužel není podporován JDBC ovladačem.
72 * Alespoň ne v postgresql-9.1-901.jdbc4.jar
73 * http://jdbc.postgresql.org/todo.html
76 * ps.setQueryTimeout(LIMIT_ČASU);
78 ps.setMaxRows(LIMIT_POČTU);
79 boolean isRS = ps.execute();
82 rs = ps.getResultSet();
83 v.getTabulky().add(zpracujVysledek(rs));
87 * Ošetříme případ, kdy uživatel zadá SQL příkaz, který nevrací výsledkovou
89 * Typicky nastavení výchozího schématu: SET search_path = '…';
90 * Poznámka: jeden „SET search_path TO "…"“ se obvykle předřazuje uživatelskému
91 * SQL (viz PiskovisteDAO.xml).
93 while (ps.getMoreResults() || ps.getUpdateCount() > -1) {
94 rs = ps.getResultSet();
96 /** Jedná se o „update count“. */
98 v.getTabulky().add(zpracujVysledek(rs));
101 long dobaProvadeni = System.currentTimeMillis() - casPred;
104 if (v.getHlasky().size() < 1 && v.getTabulky().size() < 1) {
105 v.getHlasky().add(new Hlaska("SQL příkaz proběhl, ale nevrátil žádná data.", Typ.Varovani));
109 int pocitadloTabulek = 1;
110 for (Tabulka t : v.getTabulky()) {
111 if (t.getHodnoty().size() < 1) {
112 v.getHlasky().add(new Hlaska("Tabulka " + pocitadloTabulek + " je prázdná.", Typ.Varovani));
117 v.getHlasky().add(new Hlaska("SQL příkaz byl proveden úspěšně, během " + dobaProvadeni + " ms.", Typ.OK));
119 } catch (SQLException e) {
120 log.log(Level.SEVERE, "SQL chyba při vykonávání uživatelského dotazu.", e);
121 v.getHlasky().add(new Hlaska("Chybné SQL: " + e.getMessage(), Typ.Chyba));
122 } catch (Exception e) {
123 log.log(Level.SEVERE, "Chyba při vykonávání uživatelského dotazu.", e);
124 v.getHlasky().add(new Hlaska("Došlo k chybě dotazu.", Typ.Chyba));
130 /** Tip pro uživatele */
131 String tip = tipy.getTip();
133 v.getHlasky().add(new Hlaska(tip, Typ.Tip, false));
137 v.getHlasky().add(new Hlaska("Došlo k chybě historie.", Typ.Chyba));
142 private Tabulka zpracujVysledek(ResultSet rs) throws SQLException {
143 Tabulka t = new Tabulka();
145 int pocetSloupecku = rs.getMetaData().getColumnCount();
146 String[] zahlavi = new String[pocetSloupecku];
147 t.setZahlavi(zahlavi);
148 for (int i = 0; i < pocetSloupecku; i++) {
149 zahlavi[i] = rs.getMetaData().getColumnName(i + 1);
153 Object[] hodnoty = new Object[pocetSloupecku];
154 for (int i = 0; i < pocetSloupecku; i++) {
155 hodnoty[i] = rs.getObject(i + 1);
157 t.getHodnoty().add(hodnoty);