|
From: <jer...@us...> - 2014-01-23 22:38:34
|
Revision: 7825
http://bigdata.svn.sourceforge.net/bigdata/?rev=7825&view=rev
Author: jeremy_carroll
Date: 2014-01-23 22:38:27 +0000 (Thu, 23 Jan 2014)
Log Message:
-----------
Fix for trac 804: Update: Insert/Delete now sets quads mode on construct, which may use quad based equality rather than triple based equality for filtering
Modified Paths:
--------------
branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java
branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java
branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java
branches/BIGDATA_RELEASE_1_3_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/NamedGraphUpdateTest.java
Added Paths:
-----------
branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/model/BigdataQuadWrapper.java
Added: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/model/BigdataQuadWrapper.java
===================================================================
--- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/model/BigdataQuadWrapper.java (rev 0)
+++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/model/BigdataQuadWrapper.java 2014-01-23 22:38:27 UTC (rev 7825)
@@ -0,0 +1,75 @@
+/**
+
+Copyright (C) SYSTAP, LLC 2014. All rights reserved.
+
+Contact:
+ SYSTAP, LLC
+ 4501 Tower Road
+ Greensboro, NC 27410
+ lic...@bi...
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ * Created onJan 24, 2014
+ */
+
+package com.bigdata.rdf.model;
+
+import com.bigdata.rdf.internal.IV;
+
+/**
+ * This class wraps a {@link BigdataStatement}
+ * and provides {@link #hashCode()} and {@link #equals(Object)}
+ * respecting all four fields rather than SPO as per the {@link org.openrdf.model.Statement} contract
+ * @author jeremycarroll
+ *
+ */
+public class BigdataQuadWrapper {
+
+ private final BigdataStatement delegate;
+ public BigdataQuadWrapper(BigdataStatement cspo) {
+ delegate = cspo;
+ }
+ @Override
+ public int hashCode() {
+ if (hash == 0) {
+
+ if ( delegate.getContext() == null ) {
+ hash = delegate.hashCode();
+ } else {
+ hash = delegate.getContext().hashCode() + 31 * delegate.hashCode();
+ }
+ }
+
+ return hash;
+ }
+ private int hash = 0;
+ @Override
+ public boolean equals(Object o) {
+ if (! (o instanceof BigdataQuadWrapper)) {
+ return false;
+ }
+ final BigdataStatement oo = ((BigdataQuadWrapper)o).delegate;
+ return delegate.equals(oo) && equals(delegate.getContext(),oo.getContext());
+ }
+
+ private boolean equals(BigdataResource a, BigdataResource b) {
+ return a == b || (a != null && a.equals(b));
+ }
+ public BigdataStatement statement() {
+ return delegate;
+ }
+
+}
Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java
===================================================================
--- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java 2014-01-23 15:06:01 UTC (rev 7824)
+++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java 2014-01-23 22:38:27 UTC (rev 7825)
@@ -52,7 +52,7 @@
public interface Annotations extends AbstractStatementContainer.Annotations {
/**
- * Boolean property (default {@value #DEFAULT_ALL_GRAPHS}) which is
+ * Boolean property (default {@value #DEFAULT_NATIVE_DISTINCT}) which is
* <code>true</code> iff a native DISTINCT {@link ISPO} filter should be
* applied (large cardinality is expected for the constructed graph).
* When <code>false</code>, a JVM based DISTINCT {@link ISPO} filter
@@ -66,7 +66,23 @@
*/
String NATIVE_DISTINCT = "nativeDistinct";
+ /**
+ * Internal boolean property (default {@value #DEFAULT_DISTINCT_QUDS}) which is
+ * <code>true</code> when used internally for constructing sets of quads rather
+ * than sets of triples.
+ * <p>
+ * Note: This can only be set programmatically using {@link ConstructNode#setDistinctQuads(boolean)}
+ * <p>
+ * Note: When this property is set and mixed quads are detected or suspected then the {@link #NATIVE_DISTINCT} property is ignored.
+ *
+ * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/579">
+ * CONSTRUCT should apply DISTINCT (s,p,o) filter </a>
+ */
+ String DISTINCT_QUADS = "quadsDistinct";
+
boolean DEFAULT_NATIVE_DISTINCT = false;
+
+ boolean DEFAULT_DISTINCT_QUADS = false;
}
@@ -143,6 +159,17 @@
}
+ public boolean isDistinctQuads() {
+
+ return getProperty(Annotations.DISTINCT_QUADS,
+ Annotations.DEFAULT_DISTINCT_QUADS);
+
+ }
+ public void setDistinctQuads(final boolean quads) {
+
+ setProperty(Annotations.DISTINCT_QUADS, quads);
+ }
+
@Override
public String toString(final int indent) {
@@ -167,4 +194,5 @@
}
+
}
Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java
===================================================================
--- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2014-01-23 15:06:01 UTC (rev 7824)
+++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2014-01-23 22:38:27 UTC (rev 7825)
@@ -743,6 +743,8 @@
final ConstructNode template = op.getDeleteClause()
.getQuadData().flatten(new ConstructNode(context));
+
+ template.setDistinctQuads(true);
final ASTConstructIterator itr = new ASTConstructIterator(
context.conn.getTripleStore(), template,
@@ -813,6 +815,8 @@
final ConstructNode template = op.getInsertClause()
.getQuadData().flatten(new ConstructNode(context));
+ template.setDistinctQuads(true);
+
final ASTConstructIterator itr = new ASTConstructIterator(
context.conn.getTripleStore(), template,
op.getWhereClause(), null/* bnodesMap */,
@@ -923,6 +927,8 @@
final ConstructNode template = quadData
.flatten(new ConstructNode(context));
+ template.setDistinctQuads(true);
+
// Set the CONSTRUCT template (quads patterns).
queryRoot.setConstruct(template);
Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java
===================================================================
--- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java 2014-01-23 15:06:01 UTC (rev 7824)
+++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java 2014-01-23 22:38:27 UTC (rev 7825)
@@ -54,6 +54,7 @@
import com.bigdata.bop.rdf.filter.NativeDistinctFilter;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.model.BigdataBNode;
+import com.bigdata.rdf.model.BigdataQuadWrapper;
import com.bigdata.rdf.model.BigdataStatement;
import com.bigdata.rdf.model.BigdataValue;
import com.bigdata.rdf.model.BigdataValueFactory;
@@ -278,7 +279,13 @@
this.src = src;
- /*
+ filter = createDistinctFilter(tripleStore, construct, whereClause);
+
+ }
+
+ IFilterTest createDistinctFilter(final AbstractTripleStore tripleStore, final ConstructNode construct,
+ final GraphPatternGroup<?> whereClause) {
+ /*
* Setup the DISTINCT SPO filter.
*
* Note: CONSTRUCT is sometimes used to materialize all triples for some
@@ -289,79 +296,124 @@
* graph is large.
*/
- final boolean isObviouslyDistinct = isObviouslyDistinct(
- tripleStore.isQuads(), templates, whereClause);
-
- if (isObviouslyDistinct) {
+ final boolean isObviouslyDistinct = isObviouslyDistinct(tripleStore.isQuads(), templates, whereClause);
+ if (isObviouslyDistinct) {
+
// Do not impose a DISTINCT filter.
- filter = null;
+ return null;
- } else {
-
- final boolean nativeDistinct = construct.isNativeDistinct();
-
- if (nativeDistinct) {
+ }
+
- /*
- * Construct a predicate for the first triple template. We will
- * use that as the bias for the scalable DISTINCT SPO filter.
- */
- @SuppressWarnings("rawtypes")
- final IPredicate pred;
- {
+
+ final boolean distinctQuads = construct.isDistinctQuads() && tripleStore.isQuads() && hasMixedQuadData(templates);
+
+ if (distinctQuads) {
+
+ return createDistinctQuadsFilter(construct);
+ }
+
+ return createDistinctTriplesFilter(construct);
+
+ }
- final StatementPatternNode sp = templates.get(0/* index */);
+ @SuppressWarnings("serial")
+ private IFilterTest createDistinctQuadsFilter(final ConstructNode construct) {
+ return new DistinctFilter.DistinctFilterImpl(construct){
+ @Override
+ public boolean isValid(Object o){
+ return super.isValid(new BigdataQuadWrapper((BigdataStatement)o));
+ }
+ };
+ }
- @SuppressWarnings("rawtypes")
- final IVariableOrConstant<IV> s = sp.s()
- .getValueExpression();
+ private boolean hasMixedQuadData(List<StatementPatternNode> templates) {
+ if (templates.size() == 0) {
+ return false;
+ }
+ TermNode singleValue = templates.get(0).c();
+ if (singleValue instanceof VarNode) {
+ return true;
+ }
+ for (StatementPatternNode spn:templates) {
+ TermNode tn = spn.c();
+ if (!equals(singleValue ,tn )) {
+ // this is a little too strong, but it is merely inefficient not incorrect
+ // to return true when false would be correct.
+ return true;
+ }
+ }
+ return false;
+ }
- @SuppressWarnings("rawtypes")
- final IVariableOrConstant<IV> p = sp.p()
- .getValueExpression();
-
- @SuppressWarnings("rawtypes")
- final IVariableOrConstant<IV> o = sp.o()
- .getValueExpression();
+ private boolean equals(TermNode a, TermNode b) {
+ return a == b || ( a != null && a.equals(b));
+ }
- // // The graph term/variable iff specified by the query.
- // final TermNode cvar = sp.c();
- // final IVariableOrConstant<IV> c = cvar == null ? null :
- // cvar
- // .getValueExpression();
+ IFilterTest createDistinctTriplesFilter(final ConstructNode construct) {
+
+ final boolean nativeDistinct = construct.isNativeDistinct();
- final BOp[] vars = new BOp[] { s, p, o /* , c */};
+ if (nativeDistinct) {
- pred = new SPOPredicate(vars, BOp.NOANNS);
+ /*
+ * Construct a predicate for the first triple template. We will
+ * use that as the bias for the scalable DISTINCT SPO filter.
+ */
+ @SuppressWarnings("rawtypes")
+ final IPredicate pred;
+ {
- }
+ final StatementPatternNode sp = templates.get(0/* index */);
- /*
- * The index that will be used to read on the B+Tree access
- * path.
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- final SPOKeyOrder indexKeyOrder = SPOKeyOrder.getKeyOrder(
- (IPredicate) pred, 3/* keyArity */);
+ @SuppressWarnings("rawtypes")
+ final IVariableOrConstant<IV> s = sp.s()
+ .getValueExpression();
- construct.setProperty(
- NativeDistinctFilter.Annotations.KEY_ORDER,
- indexKeyOrder);
+ @SuppressWarnings("rawtypes")
+ final IVariableOrConstant<IV> p = sp.p()
+ .getValueExpression();
+
+ @SuppressWarnings("rawtypes")
+ final IVariableOrConstant<IV> o = sp.o()
+ .getValueExpression();
- // Native memory based DISTINCT filter.
- filter = new NativeDistinctFilter.DistinctFilterImpl(construct);
+ // // The graph term/variable iff specified by the query.
+ // final TermNode cvar = sp.c();
+ // final IVariableOrConstant<IV> c = cvar == null ? null :
+ // cvar
+ // .getValueExpression();
- } else {
+ final BOp[] vars = new BOp[] { s, p, o /* , c */};
- // JVM Based DISTINCT filter.
- filter = new DistinctFilter.DistinctFilterImpl(construct);
+ pred = new SPOPredicate(vars, BOp.NOANNS);
}
+
+ /*
+ * The index that will be used to read on the B+Tree access
+ * path.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final SPOKeyOrder indexKeyOrder = SPOKeyOrder.getKeyOrder(
+ (IPredicate) pred, 3/* keyArity */);
+
+ construct.setProperty(
+ NativeDistinctFilter.Annotations.KEY_ORDER,
+ indexKeyOrder);
+
+ // Native memory based DISTINCT filter.
+ return new NativeDistinctFilter.DistinctFilterImpl(construct);
+
+ } else {
+
+ // JVM Based DISTINCT filter.
+ return new DistinctFilter.DistinctFilterImpl(construct);
+
}
-
- }
+ }
/**
* Return <code>true</code> iff this CONSTRUCT template will obviously
Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/NamedGraphUpdateTest.java
===================================================================
--- branches/BIGDATA_RELEASE_1_3_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/NamedGraphUpdateTest.java 2014-01-23 15:06:01 UTC (rev 7824)
+++ branches/BIGDATA_RELEASE_1_3_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/NamedGraphUpdateTest.java 2014-01-23 22:38:27 UTC (rev 7825)
@@ -107,7 +107,8 @@
assertTrue(result.contains(expected));
}
- private void updateAFewTimes(boolean useHint, int numberOfTimes, int numberOfUpdatesPerTime) throws IOException {
+ private void updateAFewTimes(boolean useHint, int numberOfUpdatesPerTime) throws IOException {
+ final int numberOfTimes = 5;
for (int i=0; i<numberOfTimes; i++) {
for (int j=0; j<numberOfUpdatesPerTime;j++) {
makeUpdate(insertData);
@@ -117,29 +118,29 @@
}
}
- public void test_t_20_1() throws IOException {
- updateAFewTimes(true, 20, 1);
+ public void test_t_1() throws IOException {
+ updateAFewTimes(true, 1);
}
- public void test_t_20_2() throws IOException {
- updateAFewTimes(true, 20, 2);
+ public void test_t_2() throws IOException {
+ updateAFewTimes(true, 2);
}
- public void test_t_20_3() throws IOException {
- updateAFewTimes(true, 20, 3);
+ public void test_t_3() throws IOException {
+ updateAFewTimes(true, 3);
}
- public void test_t_20_5() throws IOException {
- updateAFewTimes(true, 20, 5);
+ public void test_t_5() throws IOException {
+ updateAFewTimes(true, 5);
}
- public void test_f_20_1() throws IOException {
- updateAFewTimes(false, 20, 1);
+ public void test_f_1() throws IOException {
+ updateAFewTimes(false, 1);
}
- public void test_f_20_2() throws IOException {
- updateAFewTimes(false, 20, 2);
+ public void test_f_2() throws IOException {
+ updateAFewTimes(false, 2);
}
- public void test_f_20_3() throws IOException {
- updateAFewTimes(false, 20, 3);
+ public void test_f_3() throws IOException {
+ updateAFewTimes(false, 3);
}
- public void test_f_20_5() throws IOException {
- updateAFewTimes(false, 20, 5);
+ public void test_f_5() throws IOException {
+ updateAFewTimes(false, 5);
}
public void test_double_triple_delete() throws IOException {
setMethodisPostUrlEncodedData();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|