[#1024] Add Factory.resultQuery(String, Object...) to allow for arbitrary execution modes of plain SQL queries
This commit is contained in:
parent
b7a7442e9e
commit
d1660ea0ec
@ -63,6 +63,7 @@ import org.jooq.Query;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.ResultQuery;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.SchemaMapping;
|
||||
@ -380,6 +381,16 @@ public class FactoryProxy implements FactoryOperations, MethodInterceptor {
|
||||
return getDelegate().fetchOne(sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record> resultQuery(String sql) throws DataAccessException {
|
||||
return getDelegate().resultQuery(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record> resultQuery(String sql, Object... bindings) throws DataAccessException {
|
||||
return getDelegate().resultQuery(sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BigInteger lastID() {
|
||||
return getDelegate().lastID();
|
||||
|
||||
@ -126,6 +126,7 @@ import org.jooq.Record;
|
||||
import org.jooq.RecordHandler;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.ResultQuery;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.SchemaMapping;
|
||||
@ -1721,6 +1722,64 @@ public abstract class jOOQAbstractTest<
|
||||
.fetchOne(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlainSQLResultQuery() throws Exception {
|
||||
String sql = create().select(param("p", Integer.class).as("p")).getSQL();
|
||||
ResultQuery<Record> q = create().resultQuery(sql, 10);
|
||||
|
||||
Result<Record> fetch1 = q.fetch();
|
||||
assertEquals(1, fetch1.size());
|
||||
assertEquals(1, fetch1.getFields().size());
|
||||
assertEquals("p", fetch1.getField(0).getName());
|
||||
assertEquals("p", fetch1.getField("p").getName());
|
||||
assertEquals(10, fetch1.getValue(0, 0));
|
||||
assertEquals(10, fetch1.getValue(0, "p"));
|
||||
assertEquals(10, fetch1.getValue(0, fetch1.getField("p")));
|
||||
|
||||
List<?> fetch2 = q.fetch("p");
|
||||
assertEquals(1, fetch2.size());
|
||||
assertEquals(10, fetch2.get(0));
|
||||
|
||||
List<Long> fetch3 = q.fetch(0, Long.class);
|
||||
assertEquals(1, fetch3.size());
|
||||
assertEquals(10L, (long) fetch3.get(0));
|
||||
|
||||
Record fetch4 = q.fetchAny();
|
||||
assertEquals(1, fetch4.getFields().size());
|
||||
assertEquals("p", fetch4.getField(0).getName());
|
||||
assertEquals("p", fetch4.getField("p").getName());
|
||||
assertEquals(10, fetch4.getValue(0));
|
||||
assertEquals(10, fetch4.getValue("p"));
|
||||
assertEquals(10, fetch4.getValue(fetch4.getField("p")));
|
||||
|
||||
Object[] fetch5 = q.fetchArray("p");
|
||||
assertEquals(1, fetch5.length);
|
||||
assertEquals(10, fetch5[0]);
|
||||
|
||||
Object[] fetch6 = q.fetchArray(0);
|
||||
assertEquals(1, fetch6.length);
|
||||
assertEquals(10, fetch6[0]);
|
||||
|
||||
Long[] fetch7 = q.fetchArray(0, Long.class);
|
||||
assertEquals(1, fetch7.length);
|
||||
assertEquals(10L, (long) fetch7[0]);
|
||||
|
||||
List<TestPlainSQLResultQuery> fetch8 = q.fetchInto(TestPlainSQLResultQuery.class);
|
||||
assertEquals(1, fetch8.size());
|
||||
assertEquals(10, fetch8.get(0).p);
|
||||
|
||||
q.fetchInto(new RecordHandler<Record>() {
|
||||
@Override
|
||||
public void next(Record record) {
|
||||
assertEquals(1, record.getFields().size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class TestPlainSQLResultQuery {
|
||||
public int p;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomSQL() throws Exception {
|
||||
final Field<Integer> IDx2 = new CustomField<Integer>(TBook_ID().getName(), TBook_ID().getDataType()) {
|
||||
|
||||
@ -1033,4 +1033,101 @@ public interface FactoryOperations extends Configuration {
|
||||
*/
|
||||
@Support
|
||||
Record fetchOne(String sql, Object... bindings) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Create a new query holding plain SQL. There must not be any binding
|
||||
* variables contained in the SQL
|
||||
* <p>
|
||||
* Use this method, when you want to take advantage of the many ways to
|
||||
* fetch results in jOOQ, using {@link ResultQuery}. Some examples:
|
||||
* <p>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchLazy()}</td>
|
||||
* <td>Open a cursor and fetch records one by one</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchInto(Class)}</td>
|
||||
* <td>Fetch records into a custom POJO (optionally annotated with JPA
|
||||
* annotations)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchInto(RecordHandler)}</td>
|
||||
* <td>Fetch records into a custom callback (similar to Spring's RowMapper)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchLater()}</td>
|
||||
* <td>Fetch records of a long-running query asynchronously</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <p>
|
||||
* Example (Postgres):
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* String sql = "FETCH ALL IN \"<unnamed cursor 1>\"";</pre></code> Example
|
||||
* (SQLite):
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* String sql = "pragma table_info('my_table')";</pre></code>
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @param sql The SQL
|
||||
* @return An executable query
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
*/
|
||||
@Support
|
||||
ResultQuery<Record> resultQuery(String sql) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Create a new query holding plain SQL. There must be as many binding
|
||||
* variables contained in the SQL, as passed in the bindings parameter
|
||||
* <p>
|
||||
* Use this method, when you want to take advantage of the many ways to
|
||||
* fetch results in jOOQ, using {@link ResultQuery}. Some examples:
|
||||
* <p>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchLazy()}</td>
|
||||
* <td>Open a cursor and fetch records one by one</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchInto(Class)}</td>
|
||||
* <td>Fetch records into a custom POJO (optionally annotated with JPA
|
||||
* annotations)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchInto(RecordHandler)}</td>
|
||||
* <td>Fetch records into a custom callback (similar to Spring's RowMapper)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link ResultQuery#fetchLater()}</td>
|
||||
* <td>Fetch records of a long-running query asynchronously</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <p>
|
||||
* Example (Postgres):
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* String sql = "FETCH ALL IN \"<unnamed cursor 1>\"";</pre></code> Example
|
||||
* (SQLite):
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* String sql = "pragma table_info('my_table')";</pre></code>
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @param sql The SQL
|
||||
* @param bindings The bindings
|
||||
* @return An executable query
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
*/
|
||||
@Support
|
||||
ResultQuery<Record> resultQuery(String sql, Object... bindings) throws DataAccessException;
|
||||
}
|
||||
|
||||
@ -97,6 +97,7 @@ import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.ResultQuery;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.SchemaMapping;
|
||||
@ -117,6 +118,7 @@ import org.jooq.UpdateQuery;
|
||||
import org.jooq.UpdateSetStep;
|
||||
import org.jooq.WindowIgnoreNullsStep;
|
||||
import org.jooq.WindowOverStep;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.InvalidResultException;
|
||||
import org.jooq.exception.SQLDialectNotSupportedException;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
@ -820,6 +822,22 @@ public class Factory implements FactoryOperations {
|
||||
return new SQLResultQuery(this, sql, bindings).fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final ResultQuery<Record> resultQuery(String sql) throws DataAccessException {
|
||||
return resultQuery(sql, new Object[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final ResultQuery<Record> resultQuery(String sql, Object... bindings) throws DataAccessException {
|
||||
return new SQLResultQuery(this, sql, bindings);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// JDBC convenience methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Loading…
Reference in New Issue
Block a user