
rdb2rdf.dm.xsparql Maven / Gradle / Ivy
The newest version!
(::::::::::::::::::::::::::::::::::::::::::::::::)
(: RDB2RDF Direct Mapping processing in XSPARQL :)
(::::::::::::::::::::::::::::::::::::::::::::::::)
prefix rr:
prefix foaf:
prefix ex:
prefix xsd:
prefix test:
prefix rdf:
declare option saxon:output "method=text";
declare variable $baseURI external;
declare function local:canonical($d, $exponent, $inc) {
if ($d < 10) then
let $pad := if ($d instance of xs:integer or ($d - xs:integer(xs:float($d)) eq 0)) then ".0" else ""
return fn:concat($d, $pad, "E", $exponent)
else local:canonical($d div 10, $exponent + $inc, $inc)
};
declare function local:canonical($d) {
if ($d < 0) then local:canonical($d, 0, 1) (: local:canonical(-$d, 0, -1) :)
else local:canonical($d, 0, 1)
};
(:::::::::::::::::::::::::::::::::::::::::::::::)
(: creates an RDF term with the specified type :)
(:::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createTermWithType($value, $type) {
(: let $type := fn:trace($type, "createTermWithType-type") return :)
if($type eq "BIGINT UNSIGNED" or $type eq "TEXT" or $type eq "CHAR")
then xsparql:createLiteral($value)
else if($type eq "FLOAT" or $type eq "float4" or $type eq "float8" or $type eq "DOUBLE")
then xsparql:createLiteral(local:canonical($value), "", "")
else if($type eq "INT" or $type eq "int4")
then xsparql:createLiteral($value, "", "")
else if($type eq "bytea" or $type eq "VARBINARY")
then xsparql:createLiteral($value, "", "")
else if($type eq "date" or $type eq "DATE")
then xsparql:createLiteral($value, "", "")
else if($type eq "timestamp" or $type eq "TIMESTAMP")
then xsparql:createLiteral($value, "", "")
else if($type eq "bool" or $type eq "BIT" or $type eq "TINYINT")
then xsparql:createLiteral($value, "", "")
else xsparql:createTerm($value)
};
(::::::::::::::::::::::::::::)
(: url escaping as per spec :)
(::::::::::::::::::::::::::::)
declare function local:escape($string) {
let $res := fn:normalize-space($string) return
let $res := fn:replace($res, " ", "%20") return
let $res := fn:replace($res, ",", "%2C") return
let $res := fn:replace($res, "/", "%2F") return
let $res := fn:replace($res, ":", "%3A") return
$res
};
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: return the primary keys of a relation, used to generate the subject URI :)
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:getPKs($row, $tableMetadata) {
let $pks := $tableMetadata//*[@primaryKey]
for $pk in $pks
let $pkName := $pk/@name
return local:escape(fn:concat(fn:replace($pkName, """",""), "=",xsparql:value($row,$pkName)))
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: creates the subject for a row from the database :)
(: if there exist PK create URI based on those, otherwise create a blank node :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createS($tableName, $row, $rowPos, $tableMetadata) {
let $pks := local:getPKs($row, $tableMetadata)
return if(not(fn:empty($pks)))
then xsparql:createURI(fn:concat($baseURI, local:escape(fn:replace($tableName, """", "")), "/", fn:string-join($pks, ";")))
else xsparql:createBNode(fn:concat($tableName,$rowPos))
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: creates the object of a tuple from the database :)
(: if is a foreign key create the respective URI, otherwise a literal :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createO($subject, $predicate, $value, $rowMetadata) {
let $object :=
let $type := data($rowMetadata/@type)
return if ($value) then local:createTermWithType($value, $type) else ()
construct { $subject <{$predicate}> $object }
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: creates the reference predicates, currently needs to retrieve all the data :)
(: from the referenced table in case blank nodes are generated :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createRefs($subject, $row, $tableName, $tableMetadata) {
(: get all the foreign tables :)
for $foreignKey in $tableMetadata//foreignKeys/foreignKey
return
(: create the reference ID :)
let $refs := fn:string-join(
for $key in $foreignKey//@name return fn:replace($key,"""","")
, ";")
(: create the reference predicate URI :)
let $predicate := xsparql:createURI(fn:concat($baseURI, local:escape(fn:replace($tableName,"""","")), "#ref-", $refs))
let $foreignTableName := distinct-values($foreignKey//@foreignKeyTable)
let $attributesWithForeignMetadata := $foreignKey/foreignKeyElem
(: get all the rows in the foreign table :)
let $foreignRows := for row $row from $foreignTableName return $row
let $object :=
(: for each result from the foreign table :)
for $foreignRow at $foreignRowPos in $foreignRows return
(: check if it matches the current row :)
if (every $join in $attributesWithForeignMetadata, $join in $attributesWithForeignMetadata
satisfies (: (fn:empty(xsparql:value($row, $join/@name)) and fn:empty(xsparql:value($foreignRow, $join/@foreignKeyAttribute))) or :)
(xsparql:value($row, $join/@name) eq xsparql:value($foreignRow, $join/@foreignKeyAttribute))
) then
(: collect the attributes of the foreign relation :)
let $foreignTableMetadata := xsparql:getRDBTableAttributes($foreignTableName) return
local:createS(fn:replace($foreignTableName,"""",""), $foreignRow, $foreignRowPos, $foreignTableMetadata)
else ()
construct { $subject $predicate $object }
};
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: creates the triples for a specific result from a relation in the input database :)
(: given the subject, generates the predicate and object and outputs the triples :)
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createPO($tableName, $row, $tableMetadata, $subject) {
for $attribute in $row/*
let $rowMetadata := $tableMetadata//column[@name eq data($attribute/@name)]
let $value := $attribute/text()
let $attribute := fn:replace($attribute/@name,"""","") (: cleanup attribute name :)
let $predicate := xsparql:createURI(fn:concat($baseURI, local:escape($tableName), "#", local:escape($attribute)))
construct { {local:createO($subject, $predicate, $value, $rowMetadata) } }
};
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: determines the URI of the relation, the subject URI and outputs the rdf:type triple :)
(: uses auxiliary function to create the triples for the data :)
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createSPO($tableName, $rows, $tableMetadata) {
let $tableName := fn:replace($tableName,"""","") (: cleanup table name :)
let $tableURI := xsparql:createURI(fn:concat($baseURI, local:escape($tableName)))
for $row at $rowPos in $rows (: for each result from the database :)
let $subject := local:createS($tableName, $row, $rowPos, $tableMetadata) (: create the subject :)
(: output rdf:type triples and call createPO to create triples for data :)
construct { $subject $tableURI .
{ (local:createRefs($subject, $row, $tableName, $tableMetadata),
local:createPO($tableName, $row, $tableMetadata, $subject)) } }
};
(::::::::::::::::::::::::::::::::::::::::)
(: Let's start, get all tables from RDB :)
(::::::::::::::::::::::::::::::::::::::::)
let $tables := xsparql:getRDBTables() (: retreive all the relations from the database :)
for $table in $tables//relation (: iterating over the relations :)
let $tableName := data($table)
let $tableMetadata := xsparql:getRDBTableAttributes($tableName) (: collect the attributes of the relation :)
let $rows := for row $row from $tableName return $row (: collect the data from the database :)
return local:createSPO($tableName, $rows, $tableMetadata) (: generate the triples:)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy