Skip to content

Commit dc3e823

Browse files
committed
Push simple ORDER clauses into the SQL
1 parent bd09dcf commit dc3e823

File tree

9 files changed

+127
-8
lines changed

9 files changed

+127
-8
lines changed

jena-sdb/src/main/java/org/apache/jena/sdb/SDB.java

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class SDB
7070
public static final Symbol annotateGeneratedSQL = SDBConstants.allocSymbol("annotateGeneratedSQL") ;
7171

7272
public static final Symbol optimizeSubqueryFragments = SDBConstants.allocSymbol("optimizeSubqueryFragments") ;
73+
74+
public static final Symbol optimizeOrderClause = SDBConstants.allocSymbol("optimizeOrderClause") ;
7375
// ----------------------------------
7476

7577
// Global context is the ARQ context.

jena-sdb/src/main/java/org/apache/jena/sdb/compiler/OpSQL.java

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.jena.sdb.compiler;
2020

2121
import org.apache.jena.atlas.io.IndentedWriter ;
22+
import org.apache.jena.query.SortCondition;
2223
import org.apache.jena.sdb.core.SDBRequest ;
2324
import org.apache.jena.sdb.core.sqlnode.SqlNode ;
2425
import org.apache.jena.sdb.store.SQLBridge ;
@@ -32,12 +33,15 @@
3233
import org.apache.jena.sparql.serializer.SerializationContext ;
3334
import org.apache.jena.sparql.util.NodeIsomorphismMap ;
3435

36+
import java.util.List;
37+
3538
public class OpSQL extends OpExt
3639
{
3740
private SqlNode sqlNode ;
3841
private Op originalOp ;
3942
private SQLBridge bridge = null ;
4043
private SDBRequest request ;
44+
private List<SortCondition> sortConditions;
4145

4246
public OpSQL(SqlNode sqlNode, Op original, SDBRequest request)
4347
{
@@ -121,6 +125,9 @@ public void resetSqlNode(SqlNode sqlNode2)
121125

122126
public void setBridge(SQLBridge bridge) { this.bridge = bridge ; }
123127

128+
public List<SortCondition> getSortConditions() { return this.sortConditions; }
129+
public void setSortConditions(List<SortCondition> sortConditions) { this.sortConditions = sortConditions; }
130+
124131
@Override
125132
public void outputArgs(IndentedWriter out, SerializationContext sCxt)
126133
{

jena-sdb/src/main/java/org/apache/jena/sdb/compiler/QueryCompilerMain.java

+2
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ public Op transformSliceProject(OpSlice opSlice, OpProject opProject)
227227
// Put back project - as an OpProject to leave for the bridge.
228228
OpSQL x = new OpSQL(n, opProject, request) ;
229229
x.setBridge(opSQL.getBridge()) ;
230+
// Ensure any sort conditions are copied to the new OpSQL
231+
x.setSortConditions(opSQL.getSortConditions());
230232
// Bridge will be set later.
231233
// Is OpProject needed?
232234
return new OpProject(x, pv) ;

jena-sdb/src/main/java/org/apache/jena/sdb/compiler/SDBCompile.java

+9
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ public static Op compile(Store store, Op op, Binding binding, Context context, S
124124
request.LimitOffsetTranslation = true ;
125125
request.DistinctTranslation = true ;
126126
}
127+
128+
if (context.isTrueOrUndef(SDB.optimizeOrderClause))
129+
{
130+
request.OrderTranslation = true;
131+
}
132+
else
133+
{
134+
request.OrderTranslation = false;
135+
}
127136

128137
QueryCompiler queryCompiler = store.getQueryCompilerFactory().createQueryCompiler(request) ;
129138
Op op2 = queryCompiler.compile(op) ;

jena-sdb/src/main/java/org/apache/jena/sdb/compiler/SDB_QC.java

+13
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.sql.SQLException;
2424
import java.util.List;
2525
import java.util.Set;
26+
27+
import org.apache.jena.sdb.core.sqlnode.SqlSelectBlock;
2628
import org.slf4j.Logger;
2729
import org.slf4j.LoggerFactory;
2830
import org.apache.jena.query.Query ;
@@ -87,6 +89,17 @@ public static String toSqlString(OpSQL opSQL,
8789
SDBRequest request)
8890
{
8991
SqlNode sqlNode = opSQL.getSqlNode() ;
92+
93+
// If any sort conditions have been set, pass them on to the SQL Node - ensuring the SQL Node is a select block
94+
List<SortCondition> sortConditions = opSQL.getSortConditions();
95+
if (sortConditions != null && sortConditions.size() > 0) {
96+
if ( ! sqlNode.isSelectBlock() ) {
97+
sqlNode = SqlSelectBlock.project(request, sqlNode) ;
98+
}
99+
100+
sqlNode.asSelectBlock().setSortConditions(sortConditions);
101+
}
102+
90103
String sqlStmt = request.getStore().getSQLGenerator().generateSQL(request, sqlNode) ;
91104
return sqlStmt ;
92105
}

jena-sdb/src/main/java/org/apache/jena/sdb/compiler/TransformSDB.java

+41-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import org.apache.jena.atlas.iterator.Iter ;
3030
import org.apache.jena.graph.Node ;
31+
import org.apache.jena.query.SortCondition;
3132
import org.apache.jena.sdb.core.AliasesSql ;
3233
import org.apache.jena.sdb.core.SDBRequest ;
3334
import org.apache.jena.sdb.core.ScopeEntry ;
@@ -43,6 +44,8 @@
4344
import org.apache.jena.sparql.algebra.TransformCopy ;
4445
import org.apache.jena.sparql.algebra.op.* ;
4546
import org.apache.jena.sparql.core.Var ;
47+
import org.apache.jena.sparql.expr.ExprAggregator;
48+
import org.apache.jena.sparql.expr.ExprVar;
4649
import org.slf4j.Logger ;
4750
import org.slf4j.LoggerFactory ;
4851

@@ -190,24 +193,56 @@ public Op transform(OpDistinct opDistinct, Op subOp)
190193

191194
@Override
192195
public Op transform(OpProject opProject, Op subOp)
193-
{
196+
{
197+
// If the an OpOrder has been pushed onto an SQL Op
198+
if (opProject.getSubOp() instanceof OpOrder && SDB_QC.isOpSQL(subOp) ) {
199+
// Just return an update Project, without a bridge
200+
return opProject.copy(subOp);
201+
}
202+
194203
//request.getStore().getSQLBridgeFactory().create(request, null, null)
195204
if ( ! SDB_QC.isOpSQL(subOp) )
196205
return super.transform(opProject, subOp) ;
197-
206+
198207
// Need to not do bridge elsewhere.
199-
List<Var> vars = opProject.getVars() ;
200-
return doBridge(request, (OpSQL)subOp, vars, opProject) ;
208+
List<Var> vars = opProject.getVars();
209+
return doBridge(request, (OpSQL) subOp, vars, opProject);
201210
}
202-
211+
212+
@Override
213+
public Op transform(OpOrder opOrder, Op subOp) {
214+
if (request.OrderTranslation) {
215+
// If this Order has an OpSQL child
216+
if (SDB_QC.isOpSQL(subOp)) {
217+
// Check that all of the SortConditions are simple variable expressions
218+
boolean orderInSQL = true;
219+
for (SortCondition sc : opOrder.getConditions()) {
220+
if (!(sc.getExpression() instanceof ExprVar)) {
221+
orderInSQL = false;
222+
}
223+
}
224+
225+
// Simple sorts, so copy them on to the OpSQL and drop the OpOrder
226+
// (Ordering is then applied in the database, not in memory
227+
if (orderInSQL) {
228+
OpSQL opSQL = (OpSQL) subOp;
229+
opSQL.setSortConditions(opOrder.getConditions());
230+
return opSQL;
231+
}
232+
}
233+
}
234+
235+
return super.transform(opOrder, subOp);
236+
}
237+
203238
@Override
204239
public Op transform(OpService opService, Op subOp)
205240
{
206241
// Do not walk in any further.
207242
// See ARQ Optimize class for a better way to do this.
208243
return opService ;
209244
}
210-
245+
211246
// See QueryCompilerMain.SqlNodesFinisher.visit(OpExt op)
212247
// Be careful about being done twice.
213248
// XXX SHARE CODE!

jena-sdb/src/main/java/org/apache/jena/sdb/core/SDBRequest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public class SDBRequest extends StoreHolder
4747
public boolean LeftJoinTranslation = true ; // Does the DB support general join expressions?
4848
public boolean LimitOffsetTranslation = false ; // Does the DB grok the Limit/Offset SQL?
4949
public boolean DistinctTranslation = true ; // Some DBs can't do DISTINCT on CLOBS.
50-
50+
public boolean OrderTranslation = true ; // Allow translation of ORDER to SQL to be configurable
51+
5152
private Context context ;
5253

5354
public SDBRequest(Store store, Query query, Context context)

jena-sdb/src/main/java/org/apache/jena/sdb/core/sqlnode/GenerateSQLVisitor.java

+45
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
import org.apache.jena.atlas.io.IndentedWriter ;
2424
import org.apache.jena.atlas.iterator.Iter ;
2525
import org.apache.jena.atlas.lib.Lib ;
26+
import org.apache.jena.query.Query;
27+
import org.apache.jena.query.SortCondition;
2628
import org.apache.jena.sdb.SDB ;
2729
import org.apache.jena.sdb.core.Annotations ;
30+
import org.apache.jena.sdb.core.ScopeEntry;
2831
import org.apache.jena.sdb.core.sqlexpr.S_Equal ;
2932
import org.apache.jena.sdb.core.sqlexpr.SqlColumn ;
3033
import org.apache.jena.sdb.core.sqlexpr.SqlExpr ;
@@ -115,6 +118,10 @@ public void visit(SqlSelectBlock sqlSelectBlock)
115118
if ( sqlSelectBlock.getConditions().size() > 0 )
116119
genWHERE(sqlSelectBlock.getConditions()) ;
117120

121+
// ORDDER
122+
out.ensureStartOfLine() ;
123+
genOrder(sqlSelectBlock) ;
124+
118125
// LIMIT/OFFSET
119126
out.ensureStartOfLine() ;
120127
genLimitOffset(sqlSelectBlock) ;
@@ -147,6 +154,44 @@ protected void genSuffix(SqlSelectBlock sqlSelectBlock)
147154
// By default, NOP.
148155
}
149156

157+
protected void genOrder(SqlSelectBlock sqlSelectBlock) {
158+
StringBuilder orderBuilder = new StringBuilder();
159+
160+
List<SortCondition> sortConditions = sqlSelectBlock.getSortConditions();
161+
if (sortConditions != null && sortConditions.size() > 0) {
162+
for (SortCondition sc : sortConditions) {
163+
if (orderBuilder.length() > 0) {
164+
orderBuilder.append(", ");
165+
}
166+
167+
// Find the correct column for this condition
168+
for (ColAlias ca : sqlSelectBlock.getCols()) {
169+
if ("lex".equals(ca.getColumn().getColumnName())) {
170+
ScopeEntry se = ca.getColumn().getTable().getNodeScope().findScopeForVar(sc.getExpression().asVar());
171+
if (se != null) {
172+
orderBuilder.append(ca.getColumn().getFullColumnName());
173+
switch (sc.getDirection()) {
174+
case Query.ORDER_DESCENDING:
175+
orderBuilder.append(" DESC");
176+
break;
177+
178+
case Query.ORDER_ASCENDING:
179+
orderBuilder.append(" ASC");
180+
break;
181+
}
182+
break;
183+
}
184+
}
185+
}
186+
}
187+
}
188+
189+
if (orderBuilder.length() > 0) {
190+
out.println("ORDER BY " + orderBuilder.toString());
191+
}
192+
}
193+
194+
150195
protected void genLimitOffset(SqlSelectBlock sqlSelectBlock)
151196
{
152197
if ( sqlSelectBlock.getLength() >= 0 )

jena-sdb/src/main/java/org/apache/jena/sdb/core/sqlnode/SqlSelectBlock.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Collection;
2323
import java.util.List;
2424

25+
import org.apache.jena.query.SortCondition;
2526
import org.apache.jena.sdb.core.* ;
2627
import org.apache.jena.sdb.core.sqlexpr.SqlColumn ;
2728
import org.apache.jena.sdb.core.sqlexpr.SqlExpr ;
@@ -62,7 +63,8 @@ public class SqlSelectBlock extends SqlNodeBase1
6263
private SqlTable vTable ; // Naming base for renamed columns
6364
private Scope idScope = null ; // Scopes are as the wrapped SqlNode unless explicitly changed.
6465
private Scope nodeScope = null ;
65-
66+
67+
private List<SortCondition> sortConditions = null;
6668

6769
static public SqlNode distinct(SDBRequest request, SqlNode sqlNode)
6870
{
@@ -223,6 +225,9 @@ public boolean getDistinct()
223225
return distinct ;
224226
}
225227

228+
public List<SortCondition> getSortConditions() { return this.sortConditions; }
229+
public void setSortConditions(List<SortCondition> sortConditions) { this.sortConditions = sortConditions; }
230+
226231
private void setDistinct(boolean isDistinct)
227232
{
228233
this.distinct = isDistinct ;

0 commit comments

Comments
 (0)