Author: andy
Date: Tue Apr 16 20:17:00 2013
New Revision: 1468596
URL: http://svn.apache.org/r1468596
Log:
dev sync
Added:
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
Removed:
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena247_XSDDatimeTzBoundary.java
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/xsddt_247/
Modified:
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java
Modified: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java?rev=1468596&r1=1468595&r2=1468596&view=diff
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java
(original)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java Tue Apr
16 20:17:00 2013
@@ -69,7 +69,16 @@ public class JenaNNN_FilterEquality
, "}"
) ;
- String[] x = { qs1 , qs2 } ;
+ // Scoping issues : unsafe works
+ String qs3 = StrUtils.strjoinNL
+ ( "PREFIX : <http://example/> SELECT * {"
+ , " ?z :p ?o2"
+ , " OPTIONAL { ?x :q ?o }" // ?x is optional.
+ , " FILTER(?x = :x)"
+ , "}"
+ ) ;
+
+ String[] x = { qs1 } ;
for ( String qs : x )
{
Query query = QueryFactory.create(qs) ;
@@ -84,8 +93,9 @@ public class JenaNNN_FilterEquality
// Op op1 = TransformScopeRename.transform(op) ;
// Op op1 = Transformer.transform(new
TransformJoinStrategy(), op) ;
// Op op1 = Transformer.transform(new
TransformFilterDisjunction(), op) ;
- System.out.println("- - - - - TransformFilterEquality") ;
- Op op1 = Transformer.transform(new TransformFilterEquality(), op) ;
+ System.out.println("- - - - - Single Transform") ;
+ Op op1 = Transformer.transform(new TransformFilterEquality2(), op)
;
+
System.out.print(op1) ;
System.out.println("- - - - - Optimize") ;
Op op2 = Algebra.optimize(op) ;
@@ -111,6 +121,7 @@ public class JenaNNN_FilterEquality
, " ?x :p ?o2"
, "}"
) ;
+ // Possible transformation:
// Safe to transform: This (sequence) always defined ?x
String ops = StrUtils.strjoinNL
("(assign ((?x <http://example/x>))"
@@ -120,7 +131,17 @@ public class JenaNNN_FilterEquality
, " (bgp (triple <http://example/x> <http://example/q>
?o)))"
, " (bgp (triple <http://example/x> <http://example/p>
?o2))))"
) ;
- check(qs, ops) ;
+ // Currently :
+ String ops1 = StrUtils.strjoinNL
+ ("(filter (= ?x <http://example/x>)"
+ ," (sequence"
+ ," (conditional"
+ ," (table unit)"
+ ," (bgp (triple ?x <http://example/q> ?o)) )"
+ ," (bgp (triple ?x <http://example/p> ?o2)) ))"
+ ) ;
+
+ check(qs, ops1) ;
}
// JENA-294 part II
@@ -143,15 +164,36 @@ public class JenaNNN_FilterEquality
check(qs, ops) ;
}
- // Scope of variable (optional, defined) cases
+ // JENA-294 part II
@Test public void test_OptEqualityScope_03() {
String qs = StrUtils.strjoinNL
( "PREFIX : <http://example/> SELECT * {"
+ , " ?z :p ?o2"
, " OPTIONAL { ?x :q ?o }"
, " FILTER(?x = :x)"
, "}"
) ;
- // Unsafe to transform: This may not defined ?x, then FILTER ->
unbound -> error -> false
+ // Unsafe to transform: ?x is optional.
+ String ops = StrUtils.strjoinNL
+ ( "(filter (= ?x <http://example/x>)"
+ , " (conditional"
+ , " (bgp (triple ?z <http://example/p> ?o2))"
+ , " (bgp (triple ?x <http://example/q> ?o))"
+ , "))"
+ ) ;
+ check(qs, ops) ;
+ }
+
+ // Scope of variable (optional, defined) cases
+ @Test public void test_OptEqualityScope_04() {
+ String qs = StrUtils.strjoinNL
+ ( "PREFIX : <http://example/> SELECT * {"
+ , " OPTIONAL { ?x :q ?o }"
+ , " FILTER(?x = :x)"
+ , "}"
+ ) ;
+ // Unsafe to transform: This may not defined ?x, then FILTER ->
unbound -> error -> false
+ // But push down possible.
String ops = StrUtils.strjoinNL
("(assign ((?x <http://example/x>))"
, " (sequence"
@@ -160,20 +202,43 @@ public class JenaNNN_FilterEquality
, " (bgp (triple <http://example/x> <http://example/q>
?o)))"
, " (bgp (triple <http://example/x> <http://example/p>
?o2))))"
) ;
- check(qs, ops) ;
+ String ops1 = StrUtils.strjoinNL
+ ("(filter (= ?x <http://example/x>)"
+ ," (conditional"
+ ," (table unit)"
+ ," (assign ((?x <http://example/x>))"
+ ," (bgp (triple <http://example/x> <http://example/q>
?o)))))"
+ ) ;
+
+ check(qs, ops1) ;
}
-
+ // JENA-383
+ @Test public void test_OptEqualityScopingNested() {
+ // Can't transform: ?var not used in middle OPTIONAL.
+ String qs = StrUtils.strjoinNL
+ ( "PREFIX ex: <http://example.org/test#>"
+ , "SELECT * {"
+ , " ?var ex:p1 ?x."
+ , " OPTIONAL {"
+ , " ?x ex:p2 ?y."
+ , " OPTIONAL { ?y ex:p3 ?z }"
+ , " }"
+ , " FILTER (?var = ex:i)"
+ , " }"
+ ) ;
+ String ops = StrUtils.strjoinNL
+ ( "(filter (= ?var <http://example.org/test#i>)"
+ , " (conditional"
+ , " (bgp (triple ?var <http://example.org/test#p1> ?x))"
+ , " (conditional"
+ , " (bgp (triple ?x <http://example.org/test#p2> ?y))"
+ , " (bgp (triple ?y <http://example.org/test#p3> ?z)))"
+ , " ))"
+ ) ;
+ check(qs, ops) ;
+ }
- //JENA-294 part II
- /*
-SELECT *
-{
-?x :p ?o2
-OPTIONAL { ?x :q ?o }
-FILTER(?x = :x)
-}
- */
// JENA-432
@Test public void test_OptEqualitySubQuery_01() {
@@ -199,34 +264,54 @@ FILTER(?x = :x)
, " (project (?s1)"
, " (bgp (triple ?s1 ?/p2 ?/o2))))))"
) ;
- check(qs, ops) ;
- }
-
- // JENA-432
- @Test public void test_OptEqualitySubQuery_02() {
- String qs = StrUtils.strjoinNL
- ( "SELECT *",
- "WHERE {",
- " ?test ?p1 ?o1.",
- " OPTIONAL {",
- " SELECT ?test",
- " { ?s1 ?p2 ?o2 }", //" GROUP BY ?s1",
- " }" ,
- "}" ) ;
- String ops = StrUtils.strjoinNL
+ String ops1 = StrUtils.strjoinNL
( "(disjunction"
, " (assign ((?test <http://localhost/t1>))"
- , " (conditional"
+ , " (leftjoin"
, " (bgp (triple <http://localhost/t1> ?p1 ?o1))"
, " (project (?s1)"
, " (bgp (triple ?s1 ?/p2 ?/o2)))))"
, " (assign ((?test <http://localhost/t2>))"
- , " (conditional"
+ , " (leftjoin"
, " (bgp (triple <http://localhost/t2> ?p1 ?o1))"
, " (project (?s1)"
, " (bgp (triple ?s1 ?/p2 ?/o2))))))"
) ;
+
+ check(qs, ops1) ;
+ }
+
+ @Test public void test_OptSubQuery_01() {
+ String qs = StrUtils.strjoinNL
+ ( "SELECT *"
+ , "WHERE {"
+ , " ?test ?p1 ?X."
+ , " { SELECT ?s1 ?test { ?test ?p2 ?o2 } }"
+ , "}") ;
+ String ops = StrUtils.strjoinNL
+ ("(sequence"
+ ," (bgp (triple ?test ?p1 ?X))"
+ ," (project (?s1 ?test)"
+ ," (bgp (triple ?test ?/p2 ?/o2))))"
+ ) ;
+ check(qs, ops) ;
+ }
+
+ @Test public void test_OptSubQuery_02() {
+ String qs = StrUtils.strjoinNL
+ ( "SELECT *"
+ , "WHERE {"
+ , " ?test ?p1 ?X."
+ , " { SELECT ?s1 { ?test ?p2 ?o2 } }"
+ , "}") ;
+
+ String ops = StrUtils.strjoinNL
+ ("(sequence"
+ ," (bgp (triple ?test ?p1 ?X))"
+ ," (project (?s1)"
+ ," (bgp (triple ?test ?/p2 ?/o2))))"
+ ) ;
check(qs, ops) ;
}
@@ -241,17 +326,11 @@ FILTER(?x = :x)
, "}") ;
String ops = StrUtils.strjoinNL
- ( "(disjunction"
- , " (assign ((?test <http://localhost/t1>))"
- , " (conditional"
- , " (bgp (triple <http://localhost/t1> ?p1 ?o1))"
- , " (project (?s1)"
- , " (bgp (triple ?s1 ?/p2 ?/o2)))))"
- , " (assign ((?test <http://localhost/t2>))"
- , " (conditional"
- , " (bgp (triple <http://localhost/t2> ?p1 ?o1))"
- , " (project (?s1)"
- , " (bgp (triple ?s1 ?/p2 ?/o2))))))"
+ ("(filter (= ?test <http://localhost/t1>)"
+ ," (join"
+ ," (bgp (triple ?test ?p1 ?X))"
+ ," (project (?s1 ?test)"
+ ," (bgp (triple ?test ?/p2 ?/o2)))))"
) ;
check(qs, ops) ;
}
@@ -266,17 +345,11 @@ FILTER(?x = :x)
, " { SELECT ?s1 { ?test ?p2 ?o2 } }"
, "}") ;
String ops = StrUtils.strjoinNL
- ( "(disjunction"
- , " (assign ((?test <http://localhost/t1>))"
- , " (conditional"
- , " (bgp (triple <http://localhost/t1> ?p1 ?o1))"
- , " (project (?s1)"
- , " (bgp (triple ?s1 ?/p2 ?/o2)))))"
- , " (assign ((?test <http://localhost/t2>))"
- , " (conditional"
- , " (bgp (triple <http://localhost/t2> ?p1 ?o1))"
- , " (project (?s1)"
- , " (bgp (triple ?s1 ?/p2 ?/o2))))))"
+ ( " (assign ((?test <http://localhost/t1>))"
+ , " (join"
+ , " (bgp (triple <http://localhost/t1> ?p1 ?X))"
+ , " (project (?s1)"
+ , " (bgp (triple ?/test ?/p2 ?/o2))) ))"
) ;
check(qs, ops) ;
@@ -294,44 +367,18 @@ FILTER(?x = :x)
, "}"
) ;
String ops = StrUtils.strjoinNL
- ( "(filter (= ?var <http://example.org/test#i>)"
- , " (conditional"
- , " (bgp (triple ?var <http://example.org/test#p1> ?x))"
- , " (conditional"
- , " (bgp (triple ?x <http://example.org/test#p2> ?y))"
- , " (bgp (triple ?y <http://example.org/test#p3> ?z)))"
+ ( "(filter (= ?x <http://example/x>)"
+ , " (sequence"
+ , " (conditional"
+ , " (table unit)"
+ , " (bgp (triple ?x <http://example/q> ?o)))"
+ , " (bgp (triple ?x <http://example/p> ?o2))"
, " ))"
) ;
check(qs, ops) ;
}
-
- // JENA-383
- @Test public void test_OptEqualityScopingNested() {
- // Can't transform: ?var not used in middle OPTIONAL.
- String qs = StrUtils.strjoinNL
- ( "PREFIX ex: <http://example.org/test#>"
- , "SELECT * {"
- , " ?var ex:p1 ?x."
- , " OPTIONAL {"
- , " ?x ex:p2 ?y."
- , " OPTIONAL { ?y ex:p3 ?z }"
- , " }"
- , " FILTER (?var = ex:i)"
- , " }"
- ) ;
- String ops = StrUtils.strjoinNL
- ( "(filter (= ?var <http://example.org/test#i>)"
- , " (conditional"
- , " (bgp (triple ?var <http://example.org/test#p1> ?x))"
- , " (conditional"
- , " (bgp (triple ?x <http://example.org/test#p2> ?y))"
- , " (bgp (triple ?y <http://example.org/test#p3> ?z)))"
- , " ))"
- ) ;
- check(qs, ops) ;
- }
@@ -352,6 +399,7 @@ FILTER(?x = :x)
System.out.print(opExpected) ;
System.out.println("*** Actual") ;
System.out.print(opOptimize) ;
+ System.out.println() ;
}
Assert.assertEquals(opExpected, opOptimize) ;
Added: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java?rev=1468596&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java
(added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java Tue
Apr 16 20:17:00 2013
@@ -0,0 +1,405 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dev;
+
+import static org.apache.jena.atlas.lib.CollectionUtils.disjoint ;
+
+import java.util.ArrayList ;
+import java.util.Collection ;
+import java.util.List ;
+import java.util.Set ;
+
+import org.apache.jena.atlas.lib.Pair ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.algebra.OpVars ;
+import com.hp.hpl.jena.sparql.algebra.TransformCopy ;
+import com.hp.hpl.jena.sparql.algebra.op.* ;
+import com.hp.hpl.jena.sparql.core.Substitute ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.core.VarExprList ;
+import com.hp.hpl.jena.sparql.engine.main.VarFinder ;
+import com.hp.hpl.jena.sparql.expr.* ;
+
+public class TransformFilterEquality2 extends TransformCopy
+{
+ // The approach taken for { OPTIONAL{} OPTIONAL{} } is more general ...
and better?
+ // Still need to be careful of double-nested OPTIONALS as intermedates of
a different
+ // value can block overall results so don't mask immediately.
+ public TransformFilterEquality2()
+ { }
+
+ @Override
+ public Op transform(OpFilter opFilter, Op subOp)
+ {
+ Op op = apply(opFilter.getExprs(), subOp) ;
+ if ( op == null )
+ return super.transform(opFilter, subOp) ;
+ return op ;
+ }
+
+ private static Op apply(ExprList exprs, Op subOp)
+ {
+ // ---- Find and extract any equality filters.
+ Pair<List<Pair<Var, NodeValue>>, ExprList> p =
preprocessFilterEquality(exprs) ;
+ if ( p == null || p.getLeft().size() == 0 )
+ return null ;
+
+ List<Pair<Var, NodeValue>> equalities = p.getLeft() ;
+ Collection<Var> varsMentioned =
varsMentionedInEqualityFilters(equalities) ;
+ ExprList remaining = p.getRight() ;
+
+ // ---- Check if the subOp is the right shape to transform.
+ Op op = subOp ;
+
+ // Special case : deduce that the filter will always "eval unbound"
+ // hence elimate all rows. Return the empty table.
+
+ if ( testSpecialCaseUnused(subOp, equalities, remaining))
+ return OpTable.empty() ;
+
+ // Special case: the deep left op of a OpConditional/OpLeftJoin is
unit table.
+ // This is
+ // { OPTIONAL{P1} OPTIONAL{P2} ... FILTER(?x = :x) }
+ if ( testSpecialCase1(subOp, equalities, remaining))
+ {
+ // Find backbone of ops
+ List<Op> ops = extractOptionals(subOp) ;
+ ops = processSpecialCase1(ops, equalities) ;
+ // Put back together
+ op = rebuild((Op2)subOp, ops) ;
+ // Put all filters - either we optimized, or we left alone.
+ // Either way, the complete set of filter expressions.
+ op = OpFilter.filter(exprs, op) ;
+ return op ;
+ }
+
+ // ---- Transform
+
+ if ( ! safeToTransform(varsMentioned, op) )
+ return null ;
+ for ( Pair<Var, NodeValue> equalityTest : equalities )
+ op = processFilterWorker(op, equalityTest.getLeft(),
equalityTest.getRight()) ;
+
+ // ---- Place any filter expressions around the processed sub op.
+ if ( remaining.size() > 0 )
+ op = OpFilter.filter(remaining, op) ;
+ return op ;
+ }
+
+ // --- find and extract
+ private static Pair<List<Pair<Var, NodeValue>>, ExprList>
preprocessFilterEquality(ExprList exprs)
+ {
+ List<Pair<Var, NodeValue>> exprsFilterEquality = new
ArrayList<Pair<Var, NodeValue>>() ;
+ ExprList exprsOther = new ExprList() ;
+ for ( Expr e : exprs.getList() )
+ {
+ Pair<Var, NodeValue> p = preprocess(e) ;
+ if ( p != null )
+ exprsFilterEquality.add(p) ;
+ else
+ exprsOther.add(e) ;
+ }
+ if ( exprsFilterEquality.size() == 0 )
+ return null ;
+ return Pair.create(exprsFilterEquality, exprsOther) ;
+ }
+
+ private static Pair<Var, NodeValue> preprocess(Expr e)
+ {
+ if ( !(e instanceof E_Equals) && !(e instanceof E_SameTerm) )
+ return null ;
+
+ ExprFunction2 eq = (ExprFunction2)e ;
+ Expr left = eq.getArg1() ;
+ Expr right = eq.getArg2() ;
+
+ Var var = null ;
+ NodeValue constant = null ;
+
+ if ( left.isVariable() && right.isConstant() )
+ {
+ var = left.asVar() ;
+ constant = right.getConstant() ;
+ }
+ else if ( right.isVariable() && left.isConstant() )
+ {
+ var = right.asVar() ;
+ constant = left.getConstant() ;
+ }
+
+ if ( var == null || constant == null )
+ return null ;
+
+ // Corner case: sameTerm is false for string/plain literal,
+ // but true in the graph for graph matching.
+ if (e instanceof E_SameTerm)
+ {
+ if ( ! ARQ.isStrictMode() && constant.isString() )
+ return null ;
+ }
+
+ // Final check for "=" where a FILTER = can do value matching when the
graph does not.
+ if ( e instanceof E_Equals )
+ {
+ // Value based?
+ if ( ! ARQ.isStrictMode() && constant.isLiteral() )
+ return null ;
+ }
+
+ return Pair.create(var, constant) ;
+ }
+
+ private static Collection<Var>
varsMentionedInEqualityFilters(List<Pair<Var, NodeValue>> equalities)
+ {
+ List<Var> vars = new ArrayList<Var>() ;
+ for ( Pair<Var, NodeValue> p : equalities )
+ vars.add(p.getLeft()) ;
+ return vars ;
+ }
+
+ private static boolean safeToTransform(Collection<Var> varsEquality, Op op)
+ {
+ // Structure as a visitor?
+ if ( op instanceof OpBGP || op instanceof OpQuadPattern )
+ return true ;
+
+ if ( op instanceof OpFilter )
+ {
+ OpFilter opf = (OpFilter)op ;
+ // Expressions are always safe transform by substitution.
+// Collection<Var> fvars = opf.getExprs().getVarsMentioned() ;
+// if ( ! disjoint(fvars, varsEquality) )
+// return false ;
+ return safeToTransform(varsEquality, opf.getSubOp()) ;
+ }
+
+ // This will be applied also in sub-calls of the Transform but queries
+ // are very rarely so deep that it matters.
+ if ( op instanceof OpSequence )
+ {
+ OpN opN = (OpN)op ;
+ for ( Op subOp : opN.getElements() )
+ {
+ if ( ! safeToTransform(varsEquality, subOp) )
+ return false ;
+ }
+ return true ;
+ }
+
+ if ( op instanceof OpJoin || op instanceof OpUnion)
+ {
+ Op2 op2 = (Op2)op ;
+
+ VarFinder vf = new VarFinder(op) ;
+ System.out.println("**** Join") ;
+ System.out.println("fixed: "+vf.getFixed()) ;
+ System.out.println("opt: "+vf.getOpt()) ;
+ System.out.println("filter: "+vf.getFilter()) ;
+
+ return safeToTransform(varsEquality, op2.getLeft()) &&
safeToTransform(varsEquality, op2.getRight()) ;
+ }
+
+ // Not safe unless filter variables are mentioned on the LHS.
+ if ( op instanceof OpConditional || op instanceof OpLeftJoin )
+ {
+ Op2 opleftjoin = (Op2)op ;
+
+ VarFinder vf = new VarFinder(op) ;
+ System.out.println("**** LeftJoin") ;
+ System.out.println("fixed: "+vf.getFixed()) ;
+ System.out.println("opt: "+vf.getOpt()) ;
+ System.out.println("filter: "+vf.getFilter()) ;
+
+ if ( ! safeToTransform(varsEquality, opleftjoin.getLeft()) ||
+ ! safeToTransform(varsEquality, opleftjoin.getRight()) )
+ return false ;
+
+ // Not only must the left and right be safe to transform,
+ // but the equality variable must be known to be always set.
+
+ // If the varsLeft are disjoint from assigned vars,
+ // we may be able to push assign down right
+ // (this generalises the unit table case specialcase1)
+ // Needs more investigation.
+
+ Op opLeft = opleftjoin.getLeft() ;
+ Set<Var> varsLeft = OpVars.visibleVars(opLeft) ;
+ if ( varsLeft.containsAll(varsEquality) )
+ return true ;
+ return false ;
+ }
+
+ if ( op instanceof OpGraph )
+ {
+ OpGraph opg = (OpGraph)op ;
+ return safeToTransform(varsEquality, opg.getSubOp()) ;
+ }
+
+ // Subquery - assume scope rewriting has already been applied.
+ if ( op instanceof OpModifier )
+ {
+ // ORDER BY?
+ OpModifier opMod = (OpModifier)op ;
+ if ( opMod instanceof OpProject )
+ {
+ OpProject opProject = (OpProject)op ;
+ // Writing "SELECT ?var" for "?var" -> a value would need
AS-ification.
+ for ( Var v : opProject.getVars() )
+ {
+ if ( varsEquality.contains(v) )
+ return false ;
+ }
+ }
+ return safeToTransform(varsEquality, opMod.getSubOp()) ;
+ }
+
+ if ( op instanceof OpGroup )
+ {
+ OpGroup opGroup = (OpGroup)op ;
+ VarExprList varExprList = opGroup.getGroupVars() ;
+ return safeToTransform(varsEquality, varExprList) &&
+ safeToTransform(varsEquality, opGroup.getSubOp()) ;
+ }
+
+ if ( op instanceof OpTable )
+ {
+ OpTable opTable = (OpTable)op ;
+ if ( opTable.isJoinIdentity() )
+ return true ;
+ }
+
+ // Op1 - OpGroup
+ // Op1 - OpOrder
+ // Op1 - OpAssign, OpExtend
+ // Op1 - OpFilter - done.
+ // Op1 - OpLabel - easy
+ // Op1 - OpService - no.
+
+ return false ;
+ }
+
+ private static boolean safeToTransform(Collection<Var> varsEquality,
VarExprList varsExprList)
+ {
+ // If the named variable is used, unsafe to rewrite.
+ return disjoint(varsExprList.getVars(), varsEquality) ;
+ }
+
+ // -- A special case
+
+ private static boolean testSpecialCaseUnused(Op op, List<Pair<Var,
NodeValue>> equalities, ExprList remaining)
+ {
+ // If the op does not contain the var at all, for some equality
+ // then the filter expression will be "eval unbound" i.e. false.
+ // We can return empty table.
+ Set<Var> patternVars = OpVars.visibleVars(op) ;
+ for ( Pair<Var, NodeValue> p : equalities )
+ {
+ if ( ! patternVars.contains(p.getLeft()))
+ return true ;
+ }
+ return false ;
+ }
+
+ // If a sequence of OPTIONALS, and nothing prior to the first, we end up
with
+ // a unit table on the left sid of a next of LeftJoin/conditionals.
+
+ private static boolean testSpecialCase1(Op op, List<Pair<Var, NodeValue>>
equalities , ExprList remaining )
+ {
+ while ( op instanceof OpConditional || op instanceof OpLeftJoin )
+ {
+ Op2 opleftjoin2 = (Op2)op ;
+ op = opleftjoin2.getLeft() ;
+ }
+ return isUnitTable(op) ;
+ }
+
+ private static List<Op> extractOptionals(Op op)
+ {
+ List<Op> chain = new ArrayList<Op>() ;
+ while ( op instanceof OpConditional || op instanceof OpLeftJoin )
+ {
+ Op2 opleftjoin2 = (Op2)op ;
+ chain.add(opleftjoin2.getRight()) ;
+ op = opleftjoin2.getLeft() ;
+ }
+ return chain ;
+ }
+
+ private static List<Op> processSpecialCase1(List<Op> ops, List<Pair<Var,
NodeValue>> equalities)
+ {
+ List<Op> ops2 = new ArrayList<Op>() ;
+ Collection<Var> vars = varsMentionedInEqualityFilters(equalities) ;
+
+ for ( Op op : ops )
+ {
+ Op op2 = op ;
+ if ( safeToTransform(vars, op) )
+ {
+ for ( Pair<Var, NodeValue> p : equalities )
+ op2 = processFilterWorker(op, p.getLeft(),
p.getRight()) ;
+ }
+ ops2.add(op2) ;
+ }
+ return ops2 ;
+ }
+
+ private static Op rebuild(Op2 subOp, List<Op> ops)
+ {
+ Op chain = OpTable.unit() ;
+ for ( Op op : ops )
+ {
+ chain = subOp.copy(chain, op) ;
+ }
+ return chain ;
+ }
+
+ private static boolean isUnitTable(Op op)
+ {
+ if (op instanceof OpTable )
+ {
+ if ( ((OpTable)op).isJoinIdentity() )
+ return true;
+ }
+ return false ;
+ }
+
+ // ---- Transformation
+
+ private static Op processFilterWorker(Op op, Var var, NodeValue constant)
+ {
+ return subst(op, var, constant) ;
+ }
+
+ private static Op subst(Op subOp , Var var, NodeValue nv)
+ {
+ Op op = Substitute.substitute(subOp, var, nv.asNode()) ;
+ return OpAssign.assign(op, var, nv) ;
+ }
+
+ // Helper for TransformFilterDisjunction.
+
+ /** Apply the FilterEquality transform or return null if no change */
+
+ static Op processFilter(Expr e, Op subOp)
+ {
+ return apply(new ExprList(e), subOp) ;
+ }
+}
Added:
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java?rev=1468596&view=auto
==============================================================================
---
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
(added)
+++
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
Tue Apr 16 20:17:00 2013
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package reports.archive;
+
+import java.util.Calendar ;
+import java.util.GregorianCalendar ;
+import java.util.Locale ;
+
+import org.junit.Assert ;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDateTime ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.rdf.model.Literal ;
+import com.hp.hpl.jena.rdf.model.ResourceFactory ;
+import com.hp.hpl.jena.tdb.store.NodeId ;
+
+public class Jena437_XSDDatetypeValue
+{
+
+ public static void main(String[] args)
+ {
+ // There are multiple ways to represent internally
+ // the same XSDDateTime value in the millisecond/scale part.
+ // (500,3) = (5,1) so XSDDateTime objects are different
+
+ // But LiteralLabelImpl uses lexical form for .equals
+ // but value for .hashCode. Wrong.
+
+ // Either canonicalize the value (contract: same value => same
hashcode)
+ // or use lexical form in LiteralLabelIMpl.hashCode
+
+ // Is it because the lexical form is in-sensitive to scale? 5.1 and
5.100
+
+ // XSDDateTime.convertCalendar disagrees with parsing.
+
+ Calendar cal=GregorianCalendar.getInstance();
+ cal.setTimeInMillis(1366126807300L);
+ //String lex = "2013-04-16T15:40:07.3Z" ;
+
+ Literal lit1 = ResourceFactory.createTypedLiteral(cal) ;
+ Literal lit2 =
ResourceFactory.createTypedLiteral(lit1.getLexicalForm(), lit1.getDatatype()) ;
+
+ System.out.println(lit1) ;
+ System.out.println(lit2) ;
+
+ Assert.assertEquals(lit1, lit2) ;
+ Assert.assertEquals("hash code: ", lit1.hashCode(), lit2.hashCode());
+ }
+
+ // Alt version of XSDDateTime.hashCode -- also check .equals.
+
+// public int hashCode() {
+// int hash = 0;
+// // Components except fractional seconds.
+// for (int i = 0; i < data.length; i++) {
+// if ( i == ms || i == msscale )
+// // Skip fractional milliseconds
+// continue ;
+// hash = (hash << 1) ^ data[i];
+// }
+// // Slots 6,8 - use the fractional seconds and scale.
+// //hash = (hash << 1) ^ (int)fractionalSeconds ;
+// return hash ;
+// }
+//
+
+
+ //@Test
+ public void nodeId_dateTime_19()
+ {
+ // This is really a check of jena-core XSDDateTime.hashCode but TDB
NodeIds
+ // change the scale but not the value and hence best test the
XSDDateTime.hashCode.
+ Calendar cal = GregorianCalendar.getInstance(Locale.UK) ;
+ cal.setTimeInMillis(1366126807300L);
+
+ Literal literal = ResourceFactory.createTypedLiteral(cal) ;
+ Node n1 = literal.asNode() ;
+ XSDDateTime dt1 = (XSDDateTime)n1.getLiteralValue() ;
+ NodeId nid = NodeId.inline(n1) ;
+ Node n2 = NodeId.extract(nid) ;
+
+ Object v1 = n1.getLiteralValue() ;
+ Object v2 = n2.getLiteralValue() ;
+
+
+
+ n1.sameValueAs(n2) ;
+
+ v1.equals(v2) ;
+
+ Assert.assertTrue(".sameValueAs: ", n1.sameValueAs(n2)) ;
+ Assert.assertEquals(".hashCode: ", v1.hashCode(), v2.hashCode()) ;
+
+ }
+
+}
+