{"id":46570722,"url":"https://github.com/meaningfy-ws/diff-query-generator","last_synced_at":"2026-03-07T08:11:42.274Z","repository":{"id":40481205,"uuid":"405991870","full_name":"meaningfy-ws/diff-query-generator","owner":"meaningfy-ws","description":"Generates SPARQL delta queries and diff report templates for RDF Differ—automate semantic change detection with configurable application profile (AP) templates.","archived":false,"fork":false,"pushed_at":"2025-11-28T19:51:25.000Z","size":4914,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-11-30T22:46:21.075Z","etag":null,"topics":["linked-data","query-generator","rdf-diffing","semantic-web","skos-history","sparql","sparql-diff"],"latest_commit_sha":null,"homepage":"https://github.com/meaningfy-ws/diff-query-generator","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meaningfy-ws.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-13T13:48:23.000Z","updated_at":"2025-11-28T19:51:24.000Z","dependencies_parsed_at":"2025-11-30T12:04:09.342Z","dependency_job_id":null,"html_url":"https://github.com/meaningfy-ws/diff-query-generator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/meaningfy-ws/diff-query-generator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meaningfy-ws%2Fdiff-query-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meaningfy-ws%2Fdiff-query-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meaningfy-ws%2Fdiff-query-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meaningfy-ws%2Fdiff-query-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meaningfy-ws","download_url":"https://codeload.github.com/meaningfy-ws/diff-query-generator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meaningfy-ws%2Fdiff-query-generator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30209825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T05:23:27.321Z","status":"ssl_error","status_checked_at":"2026-03-07T05:00:17.256Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linked-data","query-generator","rdf-diffing","semantic-web","skos-history","sparql","sparql-diff"],"created_at":"2026-03-07T08:11:41.594Z","updated_at":"2026-03-07T08:11:42.216Z","avatar_url":"https://github.com/meaningfy-ws.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# diff-query-generator\n\nA service for generating SPARQL queries necessary for the RDF Diffing, which calculates the difference between versions of a given RDF dataset. \n\nPlease refer to  the current implementation of  the [rdf-differ](https://github.com/eu-vocabularies/rdf-differ) and \nthe [skos-history tool](https://github.com/eu-vocabularies/skos-history).\nSee the [Wiki page of the original repository](https://github.com/jneubert/skos-history/wiki/Tutorial) for more technical details.\n\n\n# Installation\n\nTo be added ... \n\n# Usage\n\nFirst have your Application Profile defined (in a CSV file) covering all the classes and the properties for which you want to see changes in a dataset.\nThen run the script providing this AP definition and an output folder where the per-change-type SPARQL queries will be generated.  \n\nTo be continued ...\n\n# Change type inventory\n\nThis section provides a change type inventory along with the patterns captured by each change type. We model the change as state transition operator between old (on the left) and teh new (on the right). The transition operator is denoted by the arrow symbol (--\u003e). On each sides of the transition operator, we use a compact notation following SPARQL triple patterns. \n\nWe use a set of conventions for each variable in the triple pattern, ascribing meaning to each of them and a few additional notations. These conventions are presented in teh table below.\n\n| Notation                   | Meaning                                                                                                                                                    | Example                 |\n|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|\n| triple pattern \u003c _s p o_ \u003e   | each item in the triple represents a SPARQL variable or an URI. For brevity we omit the question mark prefix (?) otherwise the SPARQL reading shall apply. | i p v                   |\n| arrow (_ --\u003e _)              | state transition operator (from one version to the next)                                                                                                   | i1 p o  --\u003e  i2 p o     |\n| _i_ - in the triple pattern  | the instance subject (assuming class instantiation)                                                                                                        | i p v                   |\n| _p_ - in the triple pattern  | the main predicate                                                                                                                                         | i p v                   |\n| _op_ - in the triple pattern | the secondary predicate in a property chain (/)                                                                                                            | i p/op v                |\n| _v_ - in the triple pattern  | the value of interest, which is object of the main or secondary predicate                                                                                  | i p v                   |\n| _@l_ - in the triple pattern | the language tag of the value, if any                                                                                                                      | v@l                     |\n| slash (_/_)                  | the property chaining operation.                                                                                                                           | p1/p2/p3/p4             |\n| number (_#_)                 | the numeric suffixes help distinguish variables of teh same type                                                                                           | i1 p1 o1  --\u003e  i2 p2 o2 |\n| zero (_0_)                   | denotes \"empty set\" or \"not applicable\"                                                                                                                    | 0                       |\n\n\nThe table below presents the patterns of change likely to occur in the context of maintaining SKOS vocabularies, but the abstraction proposed here may be useful way beyond this use case. The table represents a power product between the four types of change relevant to the current diffing context and the possible triple patterns in which they can occur. Cells that are marked with zero (0) mean that no check shall be performed for such a change type as it is included in onw of its siblings. The last two columns indicate whether quantification assumptions apply on either side of the transition operator.  \n\n| change type / pattern    | instance  | property value free  | property value language dependent | reified property value    | property value langauge dependent | reification object | Left condition checking | Right condition checking |\n|---------------------------|-----------|----------------------|-----------------------------------|---------------------------|-----------------------------------|--------------------|-------------------------|--------------------------|\n| Addition                  | 0  --\u003e  i | 0  --\u003e  i p v        | 0 --\u003e i p v@l                                | 0  --\u003e  i p/op v          | 0                                 | 0                  |                       0 | x                        |\n| Deletion                  | i  --\u003e  0 | i p v  --\u003e  0        | i p v@l  --\u003e  0                   | i p/op v  --\u003e  0          |                                   | 0                  | x                       |                        0 |\n| Value update              | 0         | i p v1  --\u003e  i p v2  | i p v1@l  --\u003e  i p v2@l           | i p/op v1  --\u003e  i p/op v2 | i p/op v1@l  --\u003e  i p/op v2@l     | 0                  | x                       | x                        |\n| Movement (cross instance) | 0         | i1 p v  --\u003e  i2 p v  | 0                                 | i1 p/op v  --\u003e  i2 p/op v | 0                                 | 0                  | x                       | x                        |\n| Movement (cross property) | 0         | i p1 v  --\u003e  i p2 v  | 0                                 | i p1/op v  --\u003e  i p2/op v | 0                                 | 0                  | x                       | x                        |\n\nThe state transition patterns presented in the table above can be translated to SPARQL queries. The last two columns, referring to the quantification assumptions, are useful precisely for this purpose indicating what filters shall be used in the SPARQL query.  \n\n\nBefore we introduce the quantification assumptions, we need to mention that the current diffing is performed by subtracting teh new version of the dataset from the old one resulting in the set of deletions between the two and, conversely, subtracting the old version of the dataset from the new one resulting in a set of insertions between the two. Therefore we conceptualise four content graphs: _OldVersion_, _NewVersion_, _Insertions_ and _Deletions_. Below is the table that summarises the quantification assumptions as conditions that apply to either left or right side of the transition operator and involve one of the four graphs introduced here.  \n\n\n| Conditions on the left side of the transition operator                                                                                                                              | Conditions on the right side of the transition operator                                                                                                                            |\n|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| does NOT exist in the Insertion graph \t\t\t\t| exists in the Insertion graph \t|\n| does NOT exist in the NewVersion graph [redundant]\t| exists in the NewVersion graph [redundant]\t\t|\n| exists in the Deletions graph\t\t\t\t\t\t| does NOT exist in the Deletions graph [redundant]\t\t|\n| exists in the OldVersion graph [redundant] \t\t\t| does NOT exist in the OldVersion graph \t|\n\n## Test Dataset elaboration\n### ds.A.1 - ds.A.2 (skos model \u0026 skos lexicalisation)\n#### Model coverage:\n\t- skos:Cocnept (5), skos:ConceptScheme (1)\n\t- skos:prefLabel (1-5 per each concept), skos:altLabel (0-5 epr concept), skos:notation (0-5 per concept)\n\n#### Operations coverage\n\t- addition instance (2)\n\t- deletion instance (2)\n\t- addition property value (2 - skos:altLabel  )\n\t- deletion property value (2 - skos:prefLabel )\n\t- value update property (1 - skos:notation)\n\t- value update property (1 - skos:altLabel)\n\t- movement (cross instance) - (1 skos:notation and 1 skos:altLabel move to anotehr concept)\n\t- movement (cross property) - (1 skos:notation becomes owl:versionInfo on the same concept; and 1 skos:prefLabel becomes an skos:altLabel)\n\n*note*: make sure that each operations is performed on an independent set of triples. That is, for example, a value update shall not be conflated with a movement, or a value addition shall not be conflated with an update. \n\n\n### ds.B.1 - ds.B.2 (skos model \u0026 skosxl lexicalisation)\n#### Model coverage:\n\t- skos:Cocnept (5), skos:ConceptScheme (1)\n\t- skosxl:prefLabel (1-5 per each concept), skosxl:altLabel (1-5 per each concept)\n\n#### Operations coverage\n\t- addition reified property value (2 - skosxl:prefLabel)\n\t- deletion reified property value (2 - skosxl:altLabel)\n\t- value update reified property (2 - skosxl:prefLabel )\n\t- value update reified property (2 - skosxl:altLabel )\n\t- movement (cross instance) - (1 skosxl:altLabel moves to anotehr concept)\n\t- movement (cross property) - (1 skosxl:prefLabel becomes a skosxl:altLabel)\n\n\n*note*: make sure that each operations is performed on an independent set of triples. That is, for example, a value update shall not be conflated with a movement, or a value addition shall not be conflated with an update. \n\n#SPARQL queries\n## Naming conventions\n### Operations\nLooking at patterns of change likely to occur in the context of maintaining SKOS vocabularies or to find in a diffing context\nwe've identified 5 change types and mapped them for easy referencing as follows:\n* Addition --\u003e Added  \n* Deletion --\u003e Deleted\n* Value update --\u003e Updated\n* Movement (cross property) --\u003e Changed\n* Movement (cross instance) --\u003e Moved\n### Query file name\nIn order to name a query file that will represent what is the query for ,but in the same time to be easy to read,\nthe file name will be constructed from five parts. These are operation, rdf type, class name, property name and object property name.\nAll names are only the local segment of the Qname (compressed URI) provided and the rdf types are instance, property and reified (reified property).\n\nFile name examples: \n\nStructure --\u003e operation_rdfType_className    \nFile name: added_instance_collection\n\nStructure --\u003e operation_rdfType_className_propertyName   \nFile name: changed_property_concept_broader\n\n##Structure\nIn this project the SPARQL query is constructed from five parts that will be explained below. \n###Prefixes section\nPrefixes are declared in this section before the select statement of the query. It can have as many possible prefixes \nand values as the query will use only the ones that it needs.\n### Query variables\nA SPARQL query file could sometimes be long and hard to read. To improve readability and minimize use of hidden variables, the query parameters should express in some manner\nwhat is the query used for and also to have the same values in the entire query. For easy referencing a change from the SPARQL query parameters , a good option \nis to add a prefix to the parameters that will have the value changed in the diffing context.\nTo avoid pollutions of variables names the convention will add prefix in front of the variables that is changing in the diffing context by using the query. \nThis can only be old or new (i.e ?oldInstance ?newInstance).\n###Version history graph block\nThis block will remain unchanged for all diffing queries as it's defining the graphs that are used later in the query.\nAs a mention there is only one part that can change here and that is the value injection for the query which will be \npresent in the next section. The logic of the query is based on this four graphs that are built here. We can see below \nthat we are going to have access to newVersionGraph, oldVersionGraph, insertionsGraph and deletionsGraph, so we can filter\nour data.\n\n      GRAPH ?versionHistoryGraph {\n\n        # parameters\n        VALUES ( ?versionHistoryGraph ?oldVersion ?newVersion ?class) {\n            ( undef \n              undef \n              undef  \n              skos:Concept \n            )\n        }\n        # get the current and the previous version as default versions\n        ?versionset dsv:currentVersionRecord/xhv:prev/dc:identifier ?previousVersion .\n        ?versionset dsv:currentVersionRecord/dc:identifier ?latestVersion .\n        # select the versions to actually use\n        BIND(coalesce(?oldVersion, ?previousVersion) AS ?oldVersionSelected)\n        BIND(coalesce(?newVersion, ?latestVersion) AS ?newVersionSelected)\n        # get the delta and via that the relevant graphs\n        ?delta a sh:SchemeDelta ;\n          sh:deltaFrom/dc:identifier ?oldVersionSelected ;\n          sh:deltaTo/dc:identifier ?newVersionSelected ;\n          sh:deltaFrom/sh:usingNamedGraph/sd:name ?oldVersionGraph ;\n          sh:deltaTo/sh:usingNamedGraph/sd:name ?newVersionGraph .\n        ?insertions a sh:SchemeDeltaInsertions ;\n          dct:isPartOf ?delta ;\n          sh:usingNamedGraph/sd:name ?insertionsGraph .\n        ?deletions a sh:SchemeDeltaDeletions ;\n          dct:isPartOf ?delta ;\n          sh:usingNamedGraph/sd:name ?deletionsGraph .\n      }\n\n###Value injection\nAs mentioned in the previous section there is a value injection block where we can assign values to variables that \nare going to be used in the query logic.\n\n       # parameters\n        VALUES ( ?versionHistoryGraph ?oldVersion ?newVersion ?class) {\n            ( undef \n              undef \n              undef  \n              skos:Concept \n            )\n        }\n\n###Query logic\nThis part of the query is filtering the data by looking for triples in the graphs made available in the version history \ngraph block. The graphs are made available through the delta generated ([see Versions and Deltas as Named Graphs](https://github.com/jneubert/skos-history/wiki/Versions-and-Deltas-as-Named-Graphs)) by the diffing process, and they are as follows:\n- oldVersionGraph - contains triples existing in the old version file\n- newVersionGraph - contains triples existing in the new version file\n- insertionsGraph - contains added triples to the old version file\n- deletionsGraph - contains triples deleted from the old version file\n\nAs an example, will want to look for new instances that are of a certain class and to achieve this will \nwant to look into the insertions graph.\n\n      GRAPH ?insertionsGraph {\n        ?instance a ?class .\n        \n        optional {\n          ?instance skos:prefLabel ?prefLabelEn .\n          FILTER (lang(?prefLabelEn) = \"en\")\n        }\n\nThe query logic can continue to filter the results by verifying existence of triples in other available graphs. This can \nbe done by using another graph block as showed below.\n\n      # ... and the instance must not exist in the old version\n      FILTER NOT EXISTS {\n        GRAPH ?oldVersionGraph {\n          ?instance ?p [] .\n        }\n      }\n\n##Example of diffing query\nBuilding a query to get all added skos:altLabel property per instance of a certain class.\n1. Prefixes section\n\n\n    # basic namespaces\n    PREFIX owl: \u003chttp://www.w3.org/2002/07/owl#\u003e\n    PREFIX rdf: \u003chttp://www.w3.org/1999/02/22-rdf-syntax-ns#\u003e\n    PREFIX rdfs: \u003chttp://www.w3.org/2000/01/rdf-schema#\u003e\n    PREFIX xsd: \u003chttp://www.w3.org/2001/XMLSchema#\u003e\n    .\n    .\n    .\n    # versioning namespaces\n    PREFIX dsv: \u003chttp://purl.org/iso25964/DataSet/Versioning#\u003e\n    PREFIX sd: \u003chttp://www.w3.org/ns/sparql-service-description#\u003e\n    PREFIX sh: \u003chttp://purl.org/skos-history/\u003e\n    PREFIX xhv: \u003chttp://www.w3.org/1999/xhtml/vocab#\u003e\n\n\n2. Query variables\n\nFor the results and the query itself to be easy to read we need to choose good variable names and make sure the variables\nwill bring the expected result format. In this case we want to see instance URI, instance label, property and \nvalue of the property.\n\n\n      SELECT DISTINCT ?instance ?prefLabel ?property ?value \n      WHERE {\n\n4. Version history graph block and value injection\n\n    \n     GRAPH ?versionHistoryGraph {\n        # defining values for our variables that are we going to use in the query (instance class and property)\n        VALUES ( ?versionHistoryGraph ?oldVersion ?newVersion ?class ?property) {\n          ( undef\n            undef\n            undef\n            skos:Concept \n            skos:altLabel \n          )\n        }\n        # get the current and the previous version as default versions\n        ?versionset dsv:currentVersionRecord/xhv:prev/dc:identifier ?previousVersion .\n        ?versionset dsv:currentVersionRecord/dc:identifier ?latestVersion .\n        # select the versions to actually use\n        BIND(coalesce(?oldVersion, ?previousVersion) AS ?oldVersionSelected)\n        BIND(coalesce(?newVersion, ?latestVersion) AS ?newVersionSelected)\n        # get the delta and via that the relevant graphs\n        ?delta a sh:SchemeDelta ;\n          sh:deltaFrom/dc:identifier ?oldVersionSelected ;\n          sh:deltaTo/dc:identifier ?newVersionSelected ;\n          sh:deltaFrom/sh:usingNamedGraph/sd:name ?oldVersionGraph ;\n          sh:deltaTo/sh:usingNamedGraph/sd:name ?newVersionGraph ;\n          dct:hasPart ?insertions ;\n          dct:hasPart ?deletions .\n        ?deletions a sh:SchemeDeltaDeletions ;\n          sh:usingNamedGraph/sd:name ?deletionsGraph .\n        ?insertions a sh:SchemeDeltaInsertions ;\n          sh:usingNamedGraph/sd:name ?insertionsGraph .\n      }\n\n\n5. Query logic\nIn this part we need to filter the results to get only the instances that had the skos:altLabel property added. As\na starting point we will look in the insertions graph to get all inserted skos:altLabel properties for all instances. \nFor this to be a true addition and not a change or a movement operation we need to make sure that the property was\nnot attached to some other instance before and to do this will look into the deletions graph and old version graph. \nAfter filtering the result we can get all the values that are needed from the new version graph.\n\n\n\n      # get inserted properties for instances\n      GRAPH ?insertionsGraph {\n        ?instance ?property [] .\n      }\n      # ... which were not attached to some (other) instance before\n      FILTER NOT EXISTS {\n        GRAPH ?deletionsGraph {\n          ?instance ?property [] .\n        }\n      }\n        FILTER NOT EXISTS {\n        GRAPH ?oldVersionGraph {\n          [] ?property ?value .\n        }\n      }\n        # get instances with those property values\n      GRAPH ?newVersionGraph {\n\n        ?instance a ?class .\n        ?instance ?property ?value .\n        \n        optional {\n          ?instance skos:prefLabel ?prefLabel .\n          FILTER (lang(?prefLabelEn) = \"en\")\n        }\n      }\n    }\n\n\n# Contributing\nYou are more than welcome to help expand and mature this project. We adhere to [Apache code of conduct](https://www.apache.org/foundation/policies/conduct), please follow it in all your interactions on the project.   \n\nWhen contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the maintainers of this repository before making a change.\n\n## Licence \nThis project is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) licence. \n\nPowered by [Meaningfy](https://github.com/meaningfy-ws).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeaningfy-ws%2Fdiff-query-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeaningfy-ws%2Fdiff-query-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeaningfy-ws%2Fdiff-query-generator/lists"}