package io.trygvis.persistence.sql; import javax.persistence.FlushModeType; import javax.persistence.LockModeType; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import javax.persistence.Parameter; import javax.persistence.PersistenceException; import javax.persistence.TemporalType; import javax.persistence.TypedQuery; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.Collections.emptyMap; public class SqlQuery implements TypedQuery { private final FromResultSet fromResultSet; private final SqlExecutor executor; private final String sql; private final boolean isSqlFinal; private int maxResults = -1; private int firstResult = -1; public SqlQuery(FromResultSet fromResultSet, SqlExecutor executor, String sql, boolean sqlFinal) { this.fromResultSet = fromResultSet; this.executor = executor; this.sql = sql; this.isSqlFinal = sqlFinal; } @Override public List getResultList() { return getResultList(firstResult, maxResults); } @Override public T getSingleResult() { List list = getResultList(0, 2); if (list.size() == 1) { return list.get(0); } if (list.size() == 0) { throw new NoResultException(); } throw new NonUniqueResultException(); } public List getResultList(int offset, int limit) { final String sql = generateSql(this.sql, offset, limit); return executor.executeQuery(new SqlExecutor.QueryCommand() { @Override public List run(Connection c) throws SQLException { List list = new ArrayList<>(); try (Statement stmt = c.createStatement()) { ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { T t = fromResultSet.fromResultSet(rs); list.add(t); } } return list; } }); } private static String generateSql(String sql, int offset, int limit) { if (offset > 0) { sql += " OFFSET " + offset; } if (limit > 0) { sql += " LIMIT " + limit; } return sql; } @Override public int executeUpdate() { return executor.executeUpdate(new SqlExecutor.UpdateCommand() { @Override public int run(Connection c) throws SQLException { try (Statement stmt = c.createStatement()) { return stmt.executeUpdate(sql); } } }); } @Override public SqlQuery setMaxResults(int maxResult) { if (maxResult <= 0) { throw new IllegalArgumentException("maxResult has to be positive: " + maxResult); } this.maxResults = maxResult; return this; } @Override public int getMaxResults() { return maxResults; } @Override public SqlQuery setFirstResult(int startPosition) { this.firstResult = startPosition; return this; } @Override public int getFirstResult() { return firstResult; } @Override public SqlQuery setHint(String hintName, Object value) { return null; } @Override public Map getHints() { return emptyMap(); } @Override public SqlQuery setParameter(Parameter param, A value) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(Parameter param, Calendar value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(Parameter param, Date value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(String name, Object value) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(String name, Calendar value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(String name, Date value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(int position, Object value) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(int position, Calendar value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public SqlQuery setParameter(int position, Date value, TemporalType temporalType) { throw new UnsupportedOperationException(); } @Override public Set> getParameters() { throw new UnsupportedOperationException(); } @Override public Parameter getParameter(String name) { throw new UnsupportedOperationException(); } @Override public Parameter getParameter(String name, Class type) { throw new UnsupportedOperationException(); } @Override public Parameter getParameter(int position) { throw new UnsupportedOperationException(); } @Override public Parameter getParameter(int position, Class type) { throw new UnsupportedOperationException(); } @Override public boolean isBound(Parameter param) { throw new UnsupportedOperationException(); } @Override public T getParameterValue(Parameter param) { throw new UnsupportedOperationException(); } @Override public Object getParameterValue(String name) { throw new UnsupportedOperationException(); } @Override public Object getParameterValue(int position) { throw new UnsupportedOperationException(); } @Override public SqlQuery setFlushMode(FlushModeType flushMode) { throw new UnsupportedOperationException(); } @Override public FlushModeType getFlushMode() { throw new UnsupportedOperationException(); } @Override public SqlQuery setLockMode(LockModeType lockMode) { throw new UnsupportedOperationException(); } @Override public LockModeType getLockMode() { throw new UnsupportedOperationException(); } @Override public T unwrap(Class klass) { throw new PersistenceException("Unsupported class: " + klass); } }