Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OntopVirtualRepository fails to initialize for Direct Mapping of Table or View with No Primary Key #748

Open
thomasjtaylor opened this issue Aug 24, 2023 · 1 comment

Comments

@thomasjtaylor
Copy link
Contributor

thomasjtaylor commented Aug 24, 2023

Description

May be similar to #395 (Ontop bootstrap generate mapping without primary keys).

I have a database that has Tables/Views without a primary key. MySQL CREATE TABLE

MySQL CREATE TABLE

-- MySQL 8
CREATE DATABASE `ONTOP_KEYS`;

CREATE TABLE `NoPK` (
  `Column1` varchar(100) DEFAULT NULL,
  `Column2` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


INSERT INTO `ONTOP_KEYS`.`NoPK` (Column1,Column2) VALUES
	 (NULL,NULL),
	 ('2',NULL),
	 (NULL,'3'),
	 ('4','4');

I have a tool that generates a R2RML Direct Mapping for this table. Following the R2RML specs, this mapping should define r2rml:termType r2rml:BlankNode in the r2rml:subjectMap,

R2RML Direct Mapping

#  R2RML Mapping Created Thu Aug 24 18:16:29 EDT 2023
@prefix rdb: <urn:its:r2rml-mapping#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .

rdb:NoPK a rr:TriplesMap;
  rr:logicalTable [
      rr:tableName "\"ONTOP_KEYS\".\"NoPK\""
    ];
  rr:subjectMap [
      rr:graph    rr:defaultGraph;
      rr:termType rr:BlankNode;
      rr:class    <rdb:schemas/ONTOP_KEYS/NoPK>
    ];
  rr:predicateObjectMap [
      rr:graph     rr:defaultGraph;
      rr:predicate <rdb:/schemas/ONTOP_KEYS/NoPK#Column2>;
      rr:objectMap [
          rr:column "\"Column2\"";
          rr:datatype <http://www.w3.org/2001/XMLSchema#string>
        ]
    ], [
      rr:graph     rr:defaultGraph;
      rr:predicate <rdb:schemas/ONTOP_KEYS/NoPK#Column1>;
      rr:objectMap [
          rr:column "\"Column1\"";
          rr:datatype <http://www.w3.org/2001/XMLSchema#string>
        ]
    ] .

ODBA Mapping

(after modifying r2rml-api-core:0.9.0 to permit rr:BlankNode in rr:subjectMap)
>ontop-cli mapping to-odba

[PrefixDeclaration]
rdb:		urn:its:r2rml-mapping#
rr:		    http://www.w3.org/ns/r2rml#
rdf:		http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs:		http://www.w3.org/2000/01/rdf-schema#
owl:		http://www.w3.org/2002/07/owl#
xsd:		http://www.w3.org/2001/XMLSchema#
obda:		https://w3id.org/obda/vocabulary#

[MappingDeclaration] @collection [[
mappingId	mapping--1104171867
target		rr:BlankNode a <rdb:schemas/ONTOP_KEYS/NoPK> ; <rdb:schemas/ONTOP_KEYS/NoPK#Column1> {"Column1"}^^xsd:string ; <rdb:schemas/ONTOP_KEYS/NoPK#Column2> {"Column2"}^^xsd:string . 
source		SELECT * FROM "ONTOP_KEYS"."NoPK"
]]

However, Ontop:5.1 (r2rml-api-core:0.9.0) is throwing an NullPointerException when I try to create an OntopVirtualRepository connection.
It looks like eu.optique-project:r2rml-api-core:0.9.0 doesn't properly support Term Type Blank Nodes in the Subject Map.
eu.optique.r2rml.api.model.impl.R2RMLMappingCollectionImpl github

If I update R2RMLMappingCollectionImpl to allow blank nodes, it fixes the NullPointerException. However, Ontop produces the wrong result.

R2RMLMappingCollectionImpl

// look for RDF star triple
if (resource == null) {
  resource = readObjectInMappingGraph(node, getRDF().createIRI(R2RMLVocabulary.PROP_TERM_TYPE));
  if ((resource instanceof IRI) && resource.toString().equals(RDFStarVocabulary.TERM_STAR_TRIPLE)) {
    termMapType = TermMap.TermMapType.RDF_STAR_VALUED; 
  }	// TODO: Change comparison
// BEGIN-FIX
  else if ((resource instanceof IRI) && resource.toString().equals(R2RMLVocabulary.TERM_BLANK_NODE)) {
    return mfact.createSubjectMap((IRI) resource);
 }
// END-FIX

Running a simple query: SELECT * FROM NoPK produces incorrect results

SPARQL query:
SELECT  (?noPK_1_column1 AS ?Column1) (?noPK_1_column2 AS ?Column2)
WHERE
  { ?_cls_NoPK  a  <rdb:schemas/ONTOP_KEYS/NoPK> ;
      <rdb:schemas/ONTOP_KEYS/NoPK#Column1>  ?noPK_1_column1 ;
      <rdb:schemas/ONTOP_KEYS/NoPK#Column2>  ?noPK_1_column2
  }

Resulting native query:
ans1(Column1, Column2)
CONSTRUCT [Column1, Column2] [Column2/RDF(VARCHARToTEXT(Column21m4),xsd:string), Column1/RDF(VARCHARToTEXT(Column11m5),xsd:string)]
   NATIVE [Column11m5, Column21m4]
SELECT DISTINCT v4.`Column1` AS `Column11m5`, v5.`Column2` AS `Column21m4`
FROM (SELECT 1 AS uselessVariable
FROM `NoPK` v1
LIMIT 1) v3, `NoPK` v4, `NoPK` v5
WHERE (v4.`Column1` IS NOT NULL AND v5.`Column2` IS NOT NULL)

Expected:

Column1 Column2
4 4

Actual:

Column1 Column2
2 3
4 3
2 4
4 4

NullPointerException

java.lang.NullPointerException: A TriplesMap must have a SubjectMap.
	at eu.optique.r2rml.api.model.impl.TriplesMapImpl.setSubjectMap(TriplesMapImpl.java:85) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.TriplesMapImpl.<init>(TriplesMapImpl.java:56) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.MappingFactoryImpl.createTriplesMap(MappingFactoryImpl.java:40) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingCollectionImpl.readTriplesMap(R2RMLMappingCollectionImpl.java:157) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingCollectionImpl.readTriplesMaps(R2RMLMappingCollectionImpl.java:138) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingCollectionImpl.load(R2RMLMappingCollectionImpl.java:103) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingCollectionImpl.<init>(R2RMLMappingCollectionImpl.java:80) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingManagerImpl.extractR2RMLMapping(R2RMLMappingManagerImpl.java:105) ~[r2rml-api-core-0.9.0.jar:?]
	at eu.optique.r2rml.api.model.impl.R2RMLMappingManagerImpl.importMappings(R2RMLMappingManagerImpl.java:66) ~[r2rml-api-core-0.9.0.jar:?]
	at it.unibz.inf.ontop.spec.mapping.parser.impl.R2RMLMappingParser.parse(R2RMLMappingParser.java:102) ~[ontop-mapping-r2rml-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.spec.mapping.parser.impl.R2RMLMappingParser.parse(R2RMLMappingParser.java:78) ~[ontop-mapping-r2rml-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.spec.mapping.impl.SQLMappingExtractor.extractPPMapping(SQLMappingExtractor.java:128) ~[ontop-mapping-sql-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.spec.mapping.impl.SQLMappingExtractor.extract(SQLMappingExtractor.java:108) ~[ontop-mapping-sql-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.spec.impl.DefaultOBDASpecificationExtractor.extract(DefaultOBDASpecificationExtractor.java:51) ~[ontop-mapping-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.impl.OntopMappingConfigurationImpl.loadSpecification(OntopMappingConfigurationImpl.java:140) ~[ontop-mapping-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.impl.OntopMappingSQLConfigurationImpl.loadSpecification(OntopMappingSQLConfigurationImpl.java:85) ~[ontop-mapping-sql-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.impl.OntopMappingSQLAllConfigurationImpl.loadSpecification(OntopMappingSQLAllConfigurationImpl.java:47) ~[ontop-mapping-sql-all-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.impl.OntopSQLOWLAPIConfigurationImpl.loadOBDASpecification(OntopSQLOWLAPIConfigurationImpl.java:35) ~[ontop-system-sql-owlapi-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.impl.OntopOBDAConfigurationImpl.loadSpecification(OntopOBDAConfigurationImpl.java:44) ~[ontop-obda-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.injection.OntopSystemConfiguration.loadQueryEngine(OntopSystemConfiguration.java:20) ~[ontop-system-core-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.rdf4j.repository.impl.OntopVirtualRepository.initializeInternal(OntopVirtualRepository.java:72) ~[ontop-rdf4j-5.1.0.jar:5.1.0]
	at org.eclipse.rdf4j.repository.base.AbstractRepository.init(AbstractRepository.java:36) ~[rdf4j-repository-api-4.2.2.jar:4.2.2]
	at it.unibz.inf.ontop.rdf4j.repository.impl.OntopVirtualRepository.getConnection(OntopVirtualRepository.java:53) ~[ontop-rdf4j-5.1.0.jar:5.1.0]
	at it.unibz.inf.ontop.rdf4j.repository.impl.OntopVirtualRepository.getConnection(OntopVirtualRepository.java:22) ~[ontop-rdf4j-5.1.0.jar:5.1.0]

Steps to Reproduce

  1. Configure Ontop with an R2RML Direct Mapping configuration for a table with no primary key
  2. Instantiate an OntopVirtualRepository with the R2RML Mapping

Versions

Ontop:5.1.0

Additional Information

SEE: Example rdb2rdf test w/o PK: #D012
SEE: #395

@thomasjtaylor
Copy link
Contributor Author

Attached Ontop query reformulation log. ontop-query-plan.txt

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

No branches or pull requests

1 participant