(rdf4j-stardog) StardogRepositoryConnection::hasStatement always returns true when passing BNodes

The following code will always return true regardless of the existence of statements with that subject:

BNode subject = SimpleValueFactory.getInstance().createBNode( "some-id" );
connection.hasStatement( subject, null, null, false );

In the past this code used to work since the implementation of hasStatement was the one that AbstractRepositoryConnection has, but recently this was changed to use a SPARQL query instead. Since SPARQL queries can't reference BNodes directly, the subject gets replaced by a SPARQL variable and returns true always.

Workaround

To make it work, we changed the implementation of the method to:

public boolean hasStatement( Resource subj, IRI pred, Value obj, boolean includeInferred, Resource... contexts ) throws RepositoryException {
	StringBuilder triplePattern = new StringBuilder( "{ " );
	StringBuilder auxiliaryPatterns = new StringBuilder();

	// Subject
	if ( subj == null ) {
		triplePattern.append( " ?s" );
	} else if ( subj instanceof BNode ) {
		triplePattern.append( " ?s" );
		auxiliaryPatterns.append( " FILTER( STR( ?s ) = \"" ).append( ( (BNode) subj ).getID() ).append( "\" ) ." );
	} else {
		triplePattern.append( " " ).append( SesameQueryUtils.getSPARQLQueryString( APIMapping.toSesameValue( subj ) ) );
	}

	// Predicate
	if ( pred == null ) {
		triplePattern.append( " ?p" );
	} else {
		triplePattern.append( " " ).append( SesameQueryUtils.getSPARQLQueryString( APIMapping.toSesameValue( pred ) ) );
	}

	// Object
	if ( obj == null ) {
		triplePattern.append( " ?o" );
	} else if ( obj instanceof BNode ) {
		triplePattern.append( " ?o" );
		auxiliaryPatterns.append( " FILTER( STR( ?o ) = \"" ).append( ( (BNode) obj ).getID() ).append( "\" ) ." );
	} else {
		triplePattern.append( " " ).append( SesameQueryUtils.getSPARQLQueryString( APIMapping.toSesameValue( obj ) ) );
	}

	triplePattern.append( " ." )
	             .append( auxiliaryPatterns )
	             .append( " }" );

	if ( contexts.length > 0 ) {
		for ( Resource context : contexts ) {
			String query = String.format( "ASK { GRAPH <%s> %s }", context.stringValue(), triplePattern );
			if ( this.mConnection.ask( query ).reasoning( includeInferred ).execute() ) return true;
		}

		return false;
	} else {
		String query = String.format( "ASK %s", triplePattern );
		return this.mConnection.ask( query ).reasoning( includeInferred ).execute();
	}
}

Environment

  • Stardog: 5.3.4
  • rdf4j-stardog: 5.3.4

Hi Miguel,

Thank you very much for the detailed bug reports both here and in your other topic.

We have tracked down the underlying cause for these issues and the fix for them will be included in the 5.3.5 release.

1 Like

Hi Stephen,

I was just reviewing this solution and was wondering if you would recommend the filtering process first stated FILTER ( STR( ?s ) = "b0" ) or if an alternative like the following would be a more appropriate solution: FILTER( ?s = bnode( "b0" ) ).

Also, I am using this code along with Stardog's 7.0.1 release and I was wondering if there was a particular reason as to why this issue wasn't resolved.

This is also related to the other topic you mentioned in your comment.

Thanks for your continuous support!