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. |