Implement limit/offset support for oracle and use the occasion to refactor and simplify Relation.buildQuery() a bit.

This commit is contained in:
hns 2009-04-01 15:49:59 +00:00
parent 196bf97053
commit d6a51d3fc9
2 changed files with 35 additions and 54 deletions

View file

@ -918,11 +918,8 @@ public final class NodeManager {
query = b.append(" ").append(home.getSubnodeRelation()).toString(); query = b.append(" ").append(home.getSubnodeRelation()).toString();
} else { } else {
// let relation object build the query // let relation object build the query
query = b.append(rel.buildQuery(home, rel.buildQuery(b, home, null, " WHERE ", true);
home.getNonVirtualParent(), query = b.toString();
null,
" WHERE ",
true)).toString();
} }
stmt = con.createStatement(); stmt = con.createStatement();
@ -1014,11 +1011,7 @@ public final class NodeManager {
b.append(home.getSubnodeRelation()); b.append(home.getSubnodeRelation());
} else { } else {
// let relation object build the query // let relation object build the query
b.append(rel.buildQuery(home, rel.buildQuery(b, home, null, " WHERE ", true);
home.getNonVirtualParent(),
null,
" WHERE ",
true));
} }
query = b.toString(); query = b.toString();
@ -1132,17 +1125,9 @@ public final class NodeManager {
if (updateCriteria != null) { if (updateCriteria != null) {
b.append (" WHERE "); b.append (" WHERE ");
b.append (updateCriteria); b.append (updateCriteria);
b.append (rel.buildQuery(home, rel.buildQuery(b, home, null, " AND ", true);
home.getNonVirtualParent(),
null,
" AND ",
true));
} else { } else {
b.append (rel.buildQuery(home, rel.buildQuery(b, home, null, " WHERE ", true);
home.getNonVirtualParent(),
null,
" WHERE ",
true));
} }
q = b.toString(); q = b.toString();
} }
@ -1253,7 +1238,7 @@ public final class NodeManager {
dbm.addJoinConstraints(b, " AND "); dbm.addJoinConstraints(b, " AND ");
if (rel.groupby != null) { if (rel.groupby != null) {
rel.renderConstraints(b, home, home.getNonVirtualParent(), " AND "); rel.renderConstraints(b, home, " AND ");
if (rel.order != null) { if (rel.order != null) {
b.append(" ORDER BY "); b.append(" ORDER BY ");
@ -1398,11 +1383,8 @@ public final class NodeManager {
query = b.append(" ").append(home.getSubnodeRelation()).toString(); query = b.append(" ").append(home.getSubnodeRelation()).toString();
} else { } else {
// let relation object build the query // let relation object build the query
query = b.append(rel.buildQuery(home, rel.buildQuery(b, home, null, " WHERE ", false);
home.getNonVirtualParent(), query = b.toString();
null,
" WHERE ",
false)).toString();
} }
stmt = con.createStatement(); stmt = con.createStatement();
@ -1472,11 +1454,7 @@ public final class NodeManager {
b.append(" ").append(home.getSubnodeRelation()); b.append(" ").append(home.getSubnodeRelation());
} else { } else {
// let relation object build the query // let relation object build the query
b.append(rel.buildQuery(home, rel.buildQuery(b, home, null, " WHERE ", true);
home.getNonVirtualParent(),
null,
" WHERE ",
true));
} }
stmt = con.createStatement(); stmt = con.createStatement();
@ -1637,12 +1615,7 @@ public final class NodeManager {
b.append(")"); b.append(")");
} }
} else { } else {
b.append(rel.buildQuery(home, rel.buildQuery(b, home, dbm, kstr, " WHERE ", false);
home.getNonVirtualParent(),
dbm,
kstr,
" WHERE ",
false));
} }
stmt = con.createStatement(); stmt = con.createStatement();

View file

@ -876,21 +876,20 @@ public final class Relation {
* Build the second half of an SQL select statement according to this relation * Build the second half of an SQL select statement according to this relation
* and a local object. * and a local object.
*/ */
public String buildQuery(INode home, INode nonvirtual, public void buildQuery(StringBuffer q, Node home, String kstr, String pre, boolean useOrder)
String kstr, String pre, boolean useOrder)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {
return buildQuery(home, nonvirtual, otherType, kstr, pre, useOrder); buildQuery(q, home, otherType, kstr, pre, useOrder);
} }
/** /**
* Build the second half of an SQL select statement according to this relation * Build the second half of an SQL select statement according to this relation
* and a local object. * and a local object.
*/ */
public String buildQuery(INode home, INode nonvirtual, DbMapping otherDbm, public void buildQuery(StringBuffer q, Node home, DbMapping otherDbm, String kstr,
String kstr, String pre, boolean useOrder) String pre, boolean useOrder)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {
StringBuffer q = new StringBuffer();
String prefix = pre; String prefix = pre;
Node nonvirtual = home.getNonVirtualParent();
if (kstr != null && !isComplexReference()) { if (kstr != null && !isComplexReference()) {
q.append(prefix); q.append(prefix);
@ -919,14 +918,25 @@ public final class Relation {
q.append(" ORDER BY ").append(order); q.append(" ORDER BY ").append(order);
} }
if (maxSize > 0 && !ownType.isOracle()) { if (maxSize > 0) {
q.append(" LIMIT ").append(maxSize); if (otherType.isOracle()) {
if (offset > 0) { // see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
q.append(" OFFSET ").append(offset); int minRow = offset;
int maxRow = minRow + maxSize;
if (minRow > 0) {
q.insert(0, "SELECT * FROM ( SELECT /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum FROM (");
q.append(") a WHERE ROWNUM <= ").append(maxRow).append(") WHERE rnum > ").append(minRow);
} else {
q.insert(0, "SELECT /*+ FIRST_ROWS(n) */ * FROM (");
q.append(") WHERE ROWNUM <= ").append(maxRow);
}
} else {
q.append(" LIMIT ").append(maxSize);
if (offset > 0) {
q.append(" OFFSET ").append(offset);
}
} }
} }
return q.toString();
} }
protected void appendAdditionalTables(StringBuffer q) { protected void appendAdditionalTables(StringBuffer q) {
@ -991,16 +1001,14 @@ public final class Relation {
* *
* @param q the query string * @param q the query string
* @param home our home node * @param home our home node
* @param nonvirtual our non-virtual home node
* @param prefix the prefix to use to append to the existing query (e.g. " AND ") * @param prefix the prefix to use to append to the existing query (e.g. " AND ")
* *
* @throws SQLException sql related exception * @throws SQLException sql related exception
* @throws ClassNotFoundException driver class not found * @throws ClassNotFoundException driver class not found
*/ */
public void renderConstraints(StringBuffer q, INode home, INode nonvirtual, public void renderConstraints(StringBuffer q, Node home, String prefix)
String prefix)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {
renderConstraints(q, home, nonvirtual, otherType, prefix); renderConstraints(q, home, home.getNonVirtualParent(), otherType, prefix);
} }
/** /**
@ -1015,7 +1023,7 @@ public final class Relation {
* @throws SQLException sql related exception * @throws SQLException sql related exception
* @throws ClassNotFoundException driver class not found * @throws ClassNotFoundException driver class not found
*/ */
public void renderConstraints(StringBuffer q, INode home, INode nonvirtual, public void renderConstraints(StringBuffer q, Node home, Node nonvirtual,
DbMapping otherDbm, String prefix) DbMapping otherDbm, String prefix)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {