Skip to content

Comments

Made a first implementation of the UNION construct#20

Open
JackJackie wants to merge 2 commits intomainfrom
19-deal-with-union-in-the-where-clause
Open

Made a first implementation of the UNION construct#20
JackJackie wants to merge 2 commits intomainfrom
19-deal-with-union-in-the-where-clause

Conversation

@JackJackie
Copy link
Contributor

No description provided.

@JackJackie JackJackie linked an issue Jan 25, 2026 that may be closed by this pull request
@JackJackie JackJackie requested a review from bnouwt January 25, 2026 16:16
@JackJackie
Copy link
Contributor Author

@bnouwt: I made a first implementation of the UNION construct. It took somewhat more thinking and implementation as a UNION combines two graph patterns with an OR. Each of the graph patterns in itself can have all the supported constructs, so I had to introduce the subdecomposition concept to enabling nesting of multiple graph patterns. Anyways, check it out and see if it works for you. I tested it out on a simple UNION of 2 triple patterns and of a more complex UNION of which one of the patterns also contains multiple VALUES statements. At my end it worked :-) To be continued.

@bnouwt
Copy link
Contributor

bnouwt commented Jan 26, 2026

Good job and thanks, @JackJackie!

I've tested the query described in this comment, but modified it slightly to fit the SPARQL endpoint test in /tests/docker-compose.yml:

select distinct ?s ?p ?o { 
		{<http://example.org/FirstLandingOnTheMoon> ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s . FILTER(isBlank(?s)) . ?s ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s2 . FILTER(isBlank(?s2)) . ?s2 ?p3 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}		
} LIMIT 10000

Unfortunately, it did not work immediately, so I did the following to get it working:

  • removed the 'distinct' keyword, because:

    • Unsupported construct type Distinct.

  • removed the 'LIMIT 10000', because:

    • Unsupported construct type Project.

  • removed all FILTER(isBlank(?s)), because:

    • Unsupported construct type Builtin_isBLANK_Builtin_isBLANK_ in construct type Filter.

and this results in the following UNION query that works! 👍

select ?s ?p ?o { 
		{<http://example.org/FirstLandingOnTheMoon> ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s . ?s ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  ?s1 ?p2 ?s . ?s ?p ?o}
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  ?s1 ?p2 ?s2 . ?s2 ?p3 ?s . ?s ?p ?o}		
}

It seems like the graph patterns are correctly extracted from the SPARQL query and fed to the Knowledge Engine and the first query above could in principle also work if the DISTINCT, LIMIT and FILTER(isBlank(...)) constructs would be supported. If I am understanding correctly, these constructs do not need to be translated into knowledge engine terms, but can just be executed by RDFLlb when executing the SPARQL query?

Curious what you think!

Regards, Barry

@bnouwt
Copy link
Contributor

bnouwt commented Jan 26, 2026

Hi @JackJackie, just a thought: I am wondering whether it is possible to ignore unknown constructs instead of giving errors like the ones I describe in my previous comment and raised by this code. You would recursively traverse the algebra looking for relevant parts of the query that require translation into knowledge engine terms (graph patterns, binding sets, knowledge interactions) and ignoring anything that does not need translation.

@JackJackie
Copy link
Contributor Author

@bnouwt : I just made an attempt to also cover DISTINCT, LIMIT and FILTER of blanks. As the filters do not contain any triple pattern, it is relatively easy to ignore them when contacting the knowledge network. So, only the actual triples are taken as different graph patterns to be asked from the knowledge network. The query below is now handled without exceptions. I'm not sure if the end result of the query is correct :-). This leads to 4 main graph patterns to be asked, one per part of the UNIONs. Check it out!

select distinct ?s ?p ?o { 
		{<http://example.org/FirstLandingOnTheMoon> ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s . FILTER(isBlank(?s)) . ?s ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s2 . FILTER(isBlank(?s2)) . ?s2 ?p3 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}		
} LIMIT 10000

The logs thus show the following main graph patterns extracted from the query and fired on the knowledge network. Let me know if this is correct!

sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s1 
sparql-endpoint-1  |     ?s1 ?p2 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s1 
sparql-endpoint-1  |     ?s1 ?p2 ?s2 
sparql-endpoint-1  |     ?s2 ?p3 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 

@bnouwt
Copy link
Contributor

bnouwt commented Feb 19, 2026

@bnouwt : I just made an attempt to also cover DISTINCT, LIMIT and FILTER of blanks. As the filters do not contain any triple pattern, it is relatively easy to ignore them when contacting the knowledge network. So, only the actual triples are taken as different graph patterns to be asked from the knowledge network. The query below is now handled without exceptions. I'm not sure if the end result of the query is correct :-). This leads to 4 main graph patterns to be asked, one per part of the UNIONs. Check it out!

select distinct ?s ?p ?o { 
		{<http://example.org/FirstLandingOnTheMoon> ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s . FILTER(isBlank(?s)) . ?s ?p ?o} 
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
		UNION 
		{<http://example.org/FirstLandingOnTheMoon> ?p1 ?s1 .  FILTER(isBlank(?s1)) . ?s1 ?p2 ?s2 . FILTER(isBlank(?s2)) . ?s2 ?p3 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}		
} LIMIT 10000

The logs thus show the following main graph patterns extracted from the query and fired on the knowledge network. Let me know if this is correct!

sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s1 
sparql-endpoint-1  |     ?s1 ?p2 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 
sparql-endpoint-1  | INFO:request_processor:Derived the following main graph pattern from the request:
sparql-endpoint-1  |     ex:FirstLandingOnTheMoon ?p1 ?s1 
sparql-endpoint-1  |     ?s1 ?p2 ?s2 
sparql-endpoint-1  |     ?s2 ?p3 ?s 
sparql-endpoint-1  |     ?s ?p ?o 
sparql-endpoint-1  | 

The UNION query seems to be working as expected now, so I think this PR can be merged. 👍

I was unfortunately not able to fully test the LodView tool, because issue #21, #22, #23 were still preventing correct functioning, but we are getting there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deal with union in the where clause

2 participants