SPARQL 1.2 RL

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-sparql12-rl-20261021/
최신 게시 버전:
https://www.w3.org/TR/sparql12-rl/
최신 편집자 초안:
https://w3c.github.io/data-shapes/sparql12-rl/
이력:
https://www.w3.org/standards/history/sparql12-rl/
커밋 이력
테스트 스위트:
https://github.com/w3c/data-shapes/tree/gh-pages/shacl12-test-suite/tests/sparql-rl
편집자:
Robert David (GraphWise)
(KurrawongAI)
Andy Seaborne (Apache Software Foundation)
Simon Steyskal (Siemens AG)
피드백:
GitHub w3c/data-shapes (풀 리퀘스트, 새 이슈, 열린 이슈)

초록

이 문서는 RDF를 위한 Datalog 스타일의 규칙 언어인 SPARQL-RL을 정의합니다.

SPARQL-RL은 입력 RDF 그래프에 대해 선언적 규칙 집합을 평가하여 새로운 RDF 데이터를 생성합니다. 규칙은 SPARQL과 유사한 텍스트 구문으로 작성됩니다.

이 명세는 W3C 데이터 셰이프 워킹 그룹에서 발행했습니다.

이 문서의 상태

이 절에서는 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

이 문서는 데이터 셰이프 워킹 그룹에서 권고안 트랙을 사용하여 작업 초안으로 발행했습니다.

작업 초안으로 발행되었다고 해서 W3C 및 그 회원이 이를 승인한다는 의미는 아닙니다.

이 문서는 초안 문서이며 언제든 다른 문서로 갱신되거나 대체되거나 폐기될 수 있습니다. 이 문서를 진행 중인 작업이 아닌 다른 것으로 인용하는 것은 적절하지 않습니다. 향후 이 권고안의 갱신에는 새로운 기능이 포함될 수 있습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 해당 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하고 있으며, 해당 페이지에는 특허를 공개하는 방법도 포함되어 있습니다. 자신이 알고 있는 특허에 필수 청구항이 포함되어 있다고 판단하는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

이 문서는 SPARQL-RL을 소개합니다. 이는 선언적 규칙을 통해 기존 RDF 데이터에서 새로운 RDF 트리플을 도출하는 메커니즘입니다. 이 문서는 규칙 기반 추론의 구문과 의미론을 정의합니다.

SPARQL-RL 구현은 추론 및 질의 연산 중 하나 또는 둘 다를 제공합니다. 추론 연산은 주어진 기본 그래프에 규칙을 적용하고 기본 그래프에 나타나지 않는, 규칙 평가를 통해 도출된 RDF 트리플을 포함하는 추론 그래프를 생성합니다. 추론 그래프와 기본 그래프를 결합하는 것은 선택 사항이며 사용자에게 맡겨집니다. 질의 연산은 주어진 목표 패턴이 규칙을 사용하여 기본 그래프에서 도출될 수 있는지, 그리고 어떻게 도출되는지를 결정합니다.

SPARQL-RL은 규칙의 헤드에 있는 트리플 템플릿에서 사용할 수 있는 빈 노드를 포함하여 새로운 RDF 용어를 생성할 수 있습니다.

SPARQL-RL은 실패에 의한 부정을 지원하며, 이로 인해 규칙이 평가되는 순서에 따라 서로 다른 추론 그래프가 생성될 수 있습니다. 이를 방지하기 위해 규칙은 계층화 기법을 사용하여 평가되며, 이 기법은 규칙 간의 순서를 정해 항상 동일한 추론 그래프가 생성되도록 보장합니다.

SPARQL-RL은 그룹화와 집계를 지원하며, 규칙 본문에서 집계 함수의 결과를 변수에 할당할 수 있습니다.

문맥이 명확한 경우 SPARQL-RL을 SRL이라고 부를 수 있습니다.

1.1 용어

다음 명세는 이 문서에서 사용되는 기본 용어를 제공합니다.

1.2 문서 규칙

이 문서의 RDF 데이터 예제에서는 RDF 1.2 Turtle [RDF12-TURTLE]을 사용합니다.

이 문서에서는 다음 네임스페이스 접두사 바인딩을 사용합니다.

접두사 네임스페이스
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
xsd: http://www.w3.org/2001/XMLSchema#
: http://example/

문서 전체에서 색상으로 구분된 상자는 SPARQL-RL 구문의 규칙을 포함하거나 Turtle 구문의 RDF 그래프를 포함합니다.

# 이 상자는 규칙을 나타냅니다
# 이 상자는 입력 데이터를 나타냅니다
# 이 상자는 추론된 데이터를 나타냅니다

2. 적합성

비규범적으로 표시된 절 외에도 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 나머지 모든 내용은 규범적입니다.

이 문서에서 사용되는 핵심 단어 MAY, MUST 및 MUST NOT은 여기에 표시된 것처럼 모두 대문자로 표기된 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.

이 명세는 다음에 대한 적합성 기준을 정의합니다.

적합한 SPARQL-RL 문서는 UTF-8 [RFC3629]로 인코딩된 RDF 문자열이며, 7.6 문법에서 정의된 문법과 추가 제약 조건을 준수합니다.

참고

이 명세는 SPARQL-RL 프로세서가 적합하지 않은 SPARQL-RL 문서를 처리하는 방법을 정의하지 않습니다.

3. SPARQL-RL 개요

이 절은 비규범적입니다.

SPARQL-RL은 기본 그래프와 규칙 집합이 주어지면 새로운 트리플을 추론합니다. 평가의 출력은 기본 그래프에 나타나지 않는 도출된 트리플을 포함하는 추론 그래프입니다.

각 규칙에는 본문이라고 하는 패턴과 헤드라고 하는 결과 템플릿이 있습니다. 규칙은 본문이 결합된 기본 그래프 및 이 시점까지의 실행에서 추론된 모든 트리플과 일치하도록 본문의 변수 값을 찾아 실행됩니다. 그런 다음 이 값은 규칙 헤드의 트리플 템플릿을 인스턴스화하여 새로운 추론 트리플을 생성하는 데 사용됩니다.

규칙은 더 이상 트리플이 추론되지 않을 때까지 실행되며, 새롭게 추론된 트리플을 사용할 수 있게 됨에 따라 규칙은 두 번 이상 실행될 수 있습니다.

SPARQL-RL 실행은 새로운 빈 노드를 포함하여 새로운 RDF 용어를 생성하거나 패턴의 부재를 검사할 때 규칙 실행 순서가 서로 다른 결과를 초래하지 않도록 정의됩니다. 즉, 규칙 실행 순서와 관계없이 동일한 추론 그래프가 생성됩니다.

SPARQL-RL에는 SPARQL 1.2 질의 언어에서 영감을 받은 사람이 이해하기 쉬운 구문이 있습니다. 규칙 집합 평가는 SPARQL과 유사한 요소를 포함하지만, 규칙 실행 순서와 관계없이 동일한 추론 그래프가 생성되도록 세부 사항에는 차이가 있습니다.

이 절의 예제에서는 소프트웨어 구성 요소와 그 종속성을 설명합니다. 프런트엔드는 애플리케이션 서버를 호출하고, 애플리케이션 서버는 알려진 취약점이 있는 데이터베이스를 질의합니다.

3.1 트리플 패턴

하나의 트리플 패턴은 트리플 데이터와 매칭되어 변수에 값을 부여합니다. 패턴에는 세 요소가 있으며, 각각 RDF 용어, 변수, 또는 다음과 같은 패턴입니다. 트리플 용어에 변수가 포함된 패턴입니다.

이 첫 번째 예제에서는 기본 그래프와 규칙 집합에 다음 데이터가 있습니다.

위 규칙을 데이터에 적용하면 다음과 같은 결론을 도출합니다. :frontend는 :app에 의존하고, :app는 :db에 의존하며, 이는 의존성의 종류와 무관합니다.

그런 다음 의존하는 규칙을 추가하여 :exposedTo 관계를 도출할 수 있습니다. 이 규칙은 다른 규칙이 생성한 :dependsOn 트리플에 의존합니다. (아래 4.3 규칙 의존성도 참조하세요):

3.2 재귀

이전 절의 :exposedTo 규칙은 직접적인 의존성에만 도달합니다. :frontend는 :db에 직접 의존하지 않으므로 :frontend에 대한 :exposedTo 트리플은 추론되지 않습니다. 길이에 관계없이 의존성 사슬을 따라 노출을 전파하기 위해, 해당 규칙을 두 규칙으로 대체합니다. 구성 요소는 자신이 가진 취약점에 노출되며, 구성 요소는 직접적인 의존 대상이 노출된 모든 취약점에도 노출됩니다.

이전 예제와 비교하면 다음이 추가됩니다. :db :exposedTo :vuln1 — 데이터베이스가 자신의 취약점에 노출됩니다 — 및 :frontend :exposedTo :vuln1: 노출은 사슬을 통해 :frontend에 도달하며, 그 의존성 사슬의 길이와는 무관합니다.

이 마지막 규칙은 재귀 규칙입니다. 규칙의 본문이 규칙의 머리부에 의존합니다.

3.3 필터링

규칙 본문에서 표현식을 사용하여 변수의 값을 제한할 수 있습니다. 이 제한은 본문을 매칭할 때 적용됩니다. 예를 들어 각 취약점의 심각도가 주어지면, 심각한 취약점에 노출된 구성 요소에 상태를 부여할 수 있습니다.

FILTER는 표현식을 평가하며, 현재 변수 바인딩 집합을 표현식이 참으로 평가되면 유지하고, 표현식이 거짓으로 평가되면 현재 변수 바인딩 집합을 버립니다. 이는 다음과 동일합니다. FILTER 연산(SPARQL) 또한 SPARQL-RL은 SPARQL과 동일한 함수 및 연산자를 다수 제공합니다.

3.4 부정

부정은 매칭되지 않아야 하는 패턴을 지정하는 데 사용됩니다. 이를 "실패에 의한 부정"이라고 합니다.

부정 요소를 평가하기 위해 규칙 집합 평가 알고리즘은 해당 패턴과 매칭되는 트리플을 생성할 수 있는 모든 규칙이 부정 요소의 평가 전에 완료되도록 보장합니다. 이를 계층화라고 하며, 부정이 기반으로 삼는 대상에 데이터에서 비롯되든 다른 규칙에서 비롯되든 관련된 모든 가능한 트리플이 포함되도록 보장합니다. 부정을 포함하는 규칙은 이러한 트리플을 생성하는 규칙에 의존한다고 합니다. (아래 4.3 규칙 의존성을 참조하세요).

3.5 할당 및 RDF 용어 생성

할당을 통해 규칙은 표현식의 결과를 변수에 할당할 수 있습니다. 이는 규칙 본문에서 이루어지며, 새로운 RDF 용어를 생성하는 데 사용할 수 있습니다. 이때 데이터를 기반으로 합니다.

규칙 머리부에 빈 노드를 사용할 수 있으며, 각각 새로운 빈 노드를 생성합니다. 이는 규칙 평가가 트리플을 생성할 때마다 이루어집니다.

규칙에 포함되는 할당, 빈 노드를 생성하는 규칙에서 평가하는 규칙 머리부, 그리고 템플릿이 있는 규칙에서 포함하는 트리플 용어에 포함된 변수 가 있는 경우, 해당 규칙은 단일 실행 규칙입니다. 이러한 규칙은 자신이 의존하는 데이터를 생성할 수 있는 모든 규칙 이후에 실행되며, 자신이 생성하는 데이터에 의존하는 모든 규칙 이전에 실행됩니다.

이 조건은 이러한 규칙이 자기 자신으로 되돌아가 반복하여 무한한 수의 RDF 용어를 생성하지 않도록 보장합니다.

참고

상수인 RDF 용어가 규칙 머리부에 있더라도 해당 규칙이 단일 실행 규칙이 되는 것은 아니며, 해당 용어가 기본 그래프에 나타나지 않아도 마찬가지입니다. 규칙은 매번 동일한 용어를 평가 시 제공하므로, 유한한 수의 용어만 추가할 수 있습니다.

표현식을 평가할 때 할당에서 오류가 발생하면, 현재 해 매핑은 다음에 의해 거부됩니다. 할당.

3.6 그룹화 및 집계

다음 그룹 요소를 포함하는 규칙은 일회 실행 규칙입니다. 이러한 규칙은 자신이 의존하는 데이터를 생성할 수 있는 모든 규칙이 실행된 후, 자신이 생성하는 데이터에 의존하는 규칙이 실행되기 전에 실행됩니다. 하나의 그룹 요소는 다음의 모든 해 시퀀스를 소비하며, 이는 앞선 규칙 요소가 규칙 본문에서 생성한 것입니다. 그런 다음 이를 그룹 키를 기준으로 그룹화하고 집계 할당을 평가합니다.

출력은 각 해결 매핑이 현재 해결 매핑에 그룹 키와 집계 변수의 값을 추가한 해결 시퀀스입니다.

@@ 예제

3.7 규칙 집합 가져오기

SPARQL-RL 규칙 집합은 다른 규칙 집합을 통합할 수 있으며, 이를 위해 해당 URL을 규칙 집합 가져오기에 포함합니다. 이를 통해 규칙을 규칙 집합 간에 공유되는 라이브러리로 구조화할 수 있습니다.

규칙 집합의 IMPORTS 문은 어떤 규칙이든 규칙 집합 내에서 평가되기 전에 처리됩니다. 가져오기 단계에서 가져온 규칙 집합에 자체 가져오기가 있으면, 이들도 재귀적으로 처리됩니다. 규칙 집합을 처리하는 동안 IMPORTS 문을 순회하면 순환 가져오기를 만날 수 있습니다. 규칙 집합은 한 번만 가져옵니다. 가져오기 문 그래프의 순환은 무한 루프를 유발하지 않습니다.

규칙 집합 가져오기 지원은 다음에서 선택 사항입니다. SPARQL-RL 처리기. 자세한 내용은 4.5 처리: 가져오기를 참조하세요.

3.8 데이터 블록

데이터 블록은 규칙 집합 평가에 RDF 트리플을 직접 제공합니다. 데이터 블록의 트리플은 추론 그래프에 추가되며, 규칙 본문에서 매칭에 사용할 수 있습니다.

예를 들어 규칙 집합은 알려진 사실을 포함하여 제공될 수 있으며, 이 사실은 데이터에서 도출되지 않고 직접 단언됩니다.

참고

데이터 블록은 본문이 비어 있는 규칙과 동등합니다. 그 트리플은 어떠한 규칙도 평가되지 않은 상태에서 추론 그래프의 일부가 됩니다.

3.9 기본 데이터 매칭

규칙 집합 평가 중에는 원래의 대상에만 패턴 매칭을 수행해야 할 수 있습니다. 기본 그래프가 그 대상이며, 추론된 트리플은 대상이 아닙니다.

기본값 설정이 이에 해당하는 예입니다. 규칙은 기본 그래프에 이미 값이 있는지 검사해야 하며, 값이 없으면 규칙은 기본값을 계산할 수 있습니다.

NOT DATA를 사용하면 규칙 본문의 다른 부분에서 추론된 트리플을 매칭할 수 있습니다. 또한 전체 규칙 본문 매칭을 다음 대상으로 수행할 수도 있습니다. 기본 그래프를 대상으로, WHERE DATA를 사용합니다. 그러면 이러한 규칙은 기본 그래프의 매칭에만 의존합니다.

참고

이 절의 매칭 대상은 기본 그래프입니다. 여기에는 다음에 의해 추가된 트리플이 포함되지 않습니다. 규칙 집합 평가가 다음에서 추가한 트리플입니다. 규칙 집합의 DATA 블록 (3.8 데이터 블록).

3.10 규칙 집합 평가

규칙은 다음으로 구성됩니다. 규칙 집합. 규칙 집합과 데이터 그래프(즉, 기본 그래프)는 평가의 입력입니다. 출력은 그래프이며, 다음과 같이 부릅니다. 추론 그래프, 이는 평가 과정에서 생성된 트리플의 집합으로, 다음에 나타나지 않는 트리플로 이루어집니다. 기본 그래프.

평가 중에 한 규칙을 기반으로 추론된 트리플은 다른 규칙의 매칭에 사용할 수 있습니다. 규칙 집합 평가는 다음 시점까지 진행됩니다. 더 이상 트리플을 추론할 수 없는 시점이며, 이때 입력은 규칙 집합과 기본 그래프입니다.

평가는 다음 단계로 시작됩니다. 규칙 집합을 준비합니다. 이는 규칙 자체를 평가하기 전에 수행됩니다.

  1. 지원되는 경우, 입력 규칙 집합의 가져오기를 해석하여 모든 규칙을 포함하는 규칙 집합을 구성합니다. 가져온 모든 규칙 집합의 규칙이 포함됩니다. 처리기는 가져오기 중 하나라도 수용할 수 없으면 오류를 알립니다. 이는 해당 처리기를 기준으로 합니다(4.5 가져오기 처리).
  2. 각 규칙이 올바른 형식의 규칙인지 확인합니다.
  3. 다음을 계산합니다. 의존성 그래프.
  4. 하나의 계층화를 계산합니다. (4.4 계층화) 이를 통해 부정 요소 및 단일 실행 규칙이 일관되고, 예측 가능한 결과를 생성하도록 합니다. 계층화에는 다음의 검사가 포함됩니다. 의존성을 검사하며, 이는 규칙 간의 의존성입니다. (4.3.1 의존성 그래프).

하나의 규칙 집합이 준비되면, 평가는 각각의 계층을 계층화에서 순서대로 가져와, 해당 계층의 규칙을 완료될 때까지 평가하고, 그런 다음 다음 계층으로 이동하는 방식으로 진행됩니다. 규칙 실행으로 트리플이 추론되면, 해당 트리플은 즉시 다른 규칙이 실행될 때 사용할 수 있게 됩니다.

4. SPARQL-RL 추상 구문

SPARQL-RL 추상 구문은 SPARQL-RL의 논리적 구조입니다. 이는 SPARQL-RL의 실행 알고리즘을 정의하는 데 사용됩니다.

4.1 추상 구문의 요소

변수
하나의 변수는 가능한 RDF 용어를 트리플 패턴에서 나타냅니다. 변수는 또한 표현식에서도 사용됩니다.
표현식
하나의 표현식은 RDF 용어, 변수, 또는 함수나 함수형 형식을 인수에 적용한 것이며, 각 인수는 그 자체로 하나의 표현식입니다. 표현식은 다음을 기준으로 평가됩니다: 해 매핑. 평가 결과는 하나의 RDF 용어로 주어지거나, 평가 결과 오류가 발생합니다. 표현식은 다음과 호환됩니다: SPARQL 표현식.
데이터 블록
하나의 데이터 블록은 트리플의 집합입니다. 이러한 트리플은 추가 사실로서 추론 그래프에 추가되며 추론 과정에 포함됩니다.
트리플 패턴
하나의 트리플 패턴은 각 요소가 다음 중 하나인 3-튜플입니다: 하나의 변수, 하나의 RDF 용어, 또는 다음에 대한 패턴: 트리플 용어(다음 포함: 변수). 튜플의 두 번째 요소는 IRI 또는 변수입니다. 트리플 패턴은 본문에 나타나며, 해당 규칙에서 다음을 일치시키는 데 사용됩니다: RDF 트리플.
트리플 템플릿

하나의 트리플 템플릿은 각 요소가 다음 중 하나인 3-튜플입니다: 하나의 변수, 하나의 RDF 용어, 또는 다음에 대한 템플릿: 트리플 용어(다음 포함: 변수). 튜플의 두 번째 요소는 IRI 또는 하나의 변수입니다. 트리플 템플릿은 헤드에 나타나며, 해당 규칙에서 다음을 생성하는 데 사용됩니다: RDF 트리플.

참고

다음에 대한 패턴이나 템플릿: 트리플 용어에 어떤 변수도 나타나지 않으면, 이는 트리플 용어이며, 따라서 하나의 RDF 용어이기도 합니다.

트리플 패턴 요소
하나의 트리플 패턴 요소는 트리플 패턴으로, 다음으로 나타납니다: 규칙 요소.
필터 요소
하나의 필터 요소는 하나의 표현식으로, 다음으로 나타납니다: 규칙 요소. 이는 변수의 값을 제한하는 데 사용되며, 패턴 일치 과정에 적용됩니다.
부정 요소
하나의 부정 요소는 하나의 규칙 요소입니다. 여기에는 부정 요소 본문이 있으며, 이는 다음의 시퀀스로 구성됩니다: 트리플 패턴 요소와 필터 요소. 하나의 부정 요소에는 하나의 플래그, .evaldata가 있으며, 일치에 사용할 그래프를 나타냅니다. 그 대상은 부정 요소 본문입니다.
할당 요소
하나의 할당 요소는 하나의 규칙 요소이며, 다음으로 구성된 쌍입니다: 하나의 변수(명칭: 할당 변수), 그리고 하나의 표현식(명칭: 할당 표현식).
그룹 요소
하나의 그룹 요소는 하나의 규칙 요소이며, 다음과 같은 변수 집합(명칭: 그룹 키), 하나의 그룹 패턴, 그리고 다음의 집합을 가집니다: 집계 할당. 각 집계 할당은 다음으로 구성된 쌍입니다: 하나의 변수(명칭: 집계 변수), 그리고 하나의 집계 함수. 이 그룹 패턴은 다음의 시퀀스로 구성됩니다: 트리플 패턴 요소와 필터 요소.
규칙 요소
하나의 규칙 요소는 다음 중 하나입니다: 트리플 패턴 요소, 필터 요소, 부정 요소, 할당 요소, 또는 그룹 요소.
규칙 헤드
하나의 규칙 헤드는 다음의 시퀀스입니다: 트리플 템플릿.
규칙 본문
하나의 규칙 본문는 다음의 시퀀스입니다: 규칙 요소; 즉, 각 시퀀스 요소는 다음 중 하나입니다: 하나의 트리플 패턴 요소, 하나의 필터 요소, 하나의 부정 요소, 하나의 할당 요소, 또는 하나의 그룹 요소.
규칙 집합 가져오기
규칙 집합 가져오기(흔히 간단히 "가져오기")는 URL의 모음입니다. 이는 IMPORTS 문에서 가져온 것으로, 평가 중에 포함될 다른 규칙 집합을 위한 것입니다.
규칙
하나의 규칙은 다음을 포함합니다: 규칙 헤드(흔히 간단히 "헤드"), 하나의 규칙 본문(흔히 간단히 "본문"), 그리고 플래그 .evaldata. 이 플래그는 어떤 그래프를 일치에 사용할지 나타내며, 대상은 트리플 패턴으로, 본문에 있습니다. 규칙을 식별하는 데 도움이 되도록 URI나 빈 노드를 부여할 수 있습니다.
단일 실행 규칙

하나의 단일 실행 규칙은 정확히 한 번만 실행되는 규칙으로, 규칙 집합 평가의 특정 시점에 실행됩니다. 하나의 규칙은 단일 실행 규칙에 해당합니다. 다음 중 하나라도 성립하는 경우입니다:

일반 규칙
하나의 일반 규칙은 다음에 해당하지 않는 규칙입니다: 단일 실행 규칙. 일반 규칙은 규칙 집합 평가 중에 두 번 이상 실행될 수 있습니다.
규칙 집합
하나의 규칙 집합은 0개 이상의 규칙 모음, 0개 이상의 데이터 블록 모음, 그리고 0개 이상의 규칙 집합 가져오기 모음입니다. 하나의 해결된 규칙 집합은 하나의 규칙 집합으로, 가져오기가 없습니다. 하나의 해결된 규칙 집합은 다른 규칙 집합으로부터 가져오기 과정을 적용하여 생성됩니다.
기본 그래프
하나의 기본 그래프는 RDF 그래프로, 입력으로 주어집니다. 그 대상은 평가 과정입니다.
추론 그래프
하나의 추론 그래프는 하나의 RDF 그래프로, 다음에 의해 생성됩니다: 하나의 규칙 집합 평가. 여기에는 다음에 존재하지 않는 모든 추론된 트리플이 포함됩니다: 기본 그래프. 이러한 트리플은 다음을 적용하여 추론됩니다: 규칙 집합을 기본 그래프에 적용합니다.
규칙 집합 평가
하나의 규칙 집합 평가는 다음을 적용하는 과정입니다: 규칙 집합을 하나의 기본 그래프에 적용하여 하나의 추론 그래프를 생성합니다. 하나의 규칙 평가는 규칙을 한 번 평가하는 과정입니다. 규칙을 평가하면 다음에 의해 주어지는 모든 트리플이 생성됩니다: 규칙 헤드. 이는 다음의 평가에 따른 것입니다: 규칙 본문. 이때 트리플이 기본 그래프에 있는지, 이미 다음 과정에서 추론되었는지: 규칙 집합 평가, 또는 새롭게 추론된 트리플인지와는 관계없습니다. 규칙 집합 평가 중에 규칙은 한 번보다 더 많이 평가될 수 있습니다.

SPARQL-RL은 두 연산을 제공합니다. 추론 및 질의입니다.

추론
추론은 다음을 적용하는 연산입니다. 규칙 집합을 주어진 기본 그래프에 적용하고 추론 그래프를 생성하며, 여기에는 추론된 트리플이 포함됩니다. 이 연산은 전체 규칙 집합 평가를 적용합니다.
질의

질의는 주어진 패턴을 도출할 수 있는지 결정하는 연산이며, 도출의 출발점은 기본 그래프이고, 다음을 사용합니다. 규칙 집합. 또한 하나의 해 시퀀스를 반환하며, 여기서 각 해 매핑은 변수에 대한 RDF 용어를 제공합니다.

질의는 다음을 수행하는 효과를 가집니다. 추론 연산을 수행한 후, 목표 패턴을 다음의 결합 결과와 매칭합니다. 기본 그래프 및 추론 그래프.

해당 질의 연산은 모든 규칙을 평가하지 않을 수 있으며, 대신 질의 목표에 답하는 데 필요한 규칙만 평가할 수 있습니다.

SPARQL-RL 처리기
하나의 SPARQL-RL 처리기는 다음을 구현하는 시스템입니다. SPARQL-RL 명세를 구현하고, 규칙 집합을 평가할 수 있으며, 하나 또는 둘 다를 제공합니다. 해당 연산은 추론 및 질의입니다.

하나의 트리플 패턴 또는 트리플 템플릿에서, 튜플의 위치 1은 비공식적으로 주어라고 부르고, 위치 2는 비공식적으로 술어라고 부르며, 위치 3은 비공식적으로 목적어라고 부릅니다.

참고

시퀀스의 요소인 규칙 요소에는 1부터 번호가 부여됩니다.

규칙 집합과 규칙의 다양한 구성 요소에는 다음 표기법이 사용됩니다.

구성 요소 표기법
구성 요소 용도
ruleset.rules 규칙들로, 규칙 집합에 속합니다.
ruleset.data 해당 RDF 그래프는 다음의 합집합으로 형성됩니다: 데이터 블록(규칙 집합 내).
ruleset.imports 다음의 집합입니다: 가져오기. 이는 규칙 집합에 속합니다.
rule.head 해당 트리플 템플릿들은 규칙 헤드에 속합니다.
rule.body 해당 규칙 요소들은 규칙에 속합니다.
rule.evaldata 불리언 플래그입니다. false이면, 해당 규칙 본문의 일치 여부를 확인하며, 그 대상은 기본 그래프입니다.
rule.id 규칙의 식별자로, 빈 노드 또는 IRI입니다.
filter.expr 해당 표현식은 필터 요소에 속합니다.
assign.var 해당 할당 변수는 할당 요소에 속합니다.
assign.expr 해당 할당 표현식입니다.
negation.inner 해당 부정 요소 본문은 하나의 부정 요소에 속합니다.
negation.evaldata 불리언 플래그입니다. false이면, negation.inner의 일치 여부를 확인하며, 그 대상은 기본 그래프입니다.
group.keys 다음의 집합입니다: 그룹 키. 이는 그룹 요소에 속합니다.
group.pattern 해당 그룹 패턴은 그룹 요소에 속합니다.
group.aggregations 해당 집계 할당들은 그룹 요소에 속합니다.
aggregation.variable 해당 집계 변수는 집계 할당에 속합니다.
aggregation.function 해당 집계 함수는 집계 할당에 속합니다.

4.2 정형성 조건

올바른 형식은 추상 구문에 대한 조건들의 집합으로, 하나의 규칙 집합에 적용됩니다. 이 조건들은 함께 다음을 보장합니다. 하나의 변수가 헤드에 있는 규칙에서는 그 값이 본문에 정의되어 있다는 점; 각 변수가 필터 요소 또는 할당 표현식에 있을 때 평가 시점에 값을 갖는다는 점; 그리고 각 할당 변수 및 집계 변수가 규칙에서 새로 도입되며 규칙 본문에서 앞서 사용되지 않았다는 점입니다.

S를 규칙 요소의 시퀀스라고 합니다.

elti를 S의 i번째 요소라고 하고, N을 시퀀스의 길이라고 합니다.

V0를 변수 집합이라고 하며, 이를 초기 변수라고 부릅니다. 이 변수들은 시퀀스 S의 초기 변수입니다.

vars(S, i, V0)를 변수들의 집합으로 정의하며, 이 변수들은 시퀀스 S의 i번째 요소 이후에 유효 범위에 있습니다. 이때 초기 변수 V0가 주어집니다. vars(S, i, V0)는 귀납적으로 정의됩니다:

  • vars(S, 0, V0)를 V0라고 합니다.
  • 1부터 N까지의 각 i에 대해 vars(S, i, V0)를 다음과 같이 정합니다.
    • elti가 트리플 패턴 요소이고 X가 다음에 나타나는 변수들의 집합이면, 트리플 패턴 요소, 다음과 같습니다.
      • vars(S, i, V0)는 집합 X ∪ vars(S, i-1, V0)입니다.
    • elti가 할당 요소이며 그 할당 변수가 avar이면 다음과 같습니다.
      • vars(S, i, V0)는 집합 { avar } ∪ vars(S, i-1, V0)입니다.
    • elti가 그룹 요소 GRP이고, 집합 aggVars가 다음의 집합일 때, 집계 변수(GRP의), 다음과 같습니다.
      • vars(S, i, V0)는 집합 vars(S, i-1, V0) ∪ GRP.keys ∪ aggVars입니다.
    • 그렇지 않으면,
      • vars(S, i, V0)는 집합 vars(S, i-1, V0)와 같습니다.

vars(S, V0), 즉 S에서 유효 범위에 있는 변수들의 집합을 vars(S, N, V0)로 정의합니다. 이는 유효 범위에 있는 변수들의 집합이며, 시퀀스의 마지막 요소 이후를 기준으로 합니다.

다음 규칙 요소의 시퀀스 S는 올바른 형식의 시퀀스입니다. 변수 집합 V0가 주어졌을 때, 다음 조건들이 각 i에 대해 충족되는 경우이며, 그 범위는 1부터 N까지입니다:

하나의 규칙은 올바른 형식의 규칙입니다. 다음 조건이 성립하는 경우입니다. 규칙 요소의 시퀀스가 속한 규칙 본문에서, 이 시퀀스가 올바른 형식의 시퀀스이며, 시작 시 V0가 공집합이고, 각 변수가 트리플 템플릿에 있으며, 이 템플릿이 규칙 헤드에 속할 때, 각 변수가 vars(S, V0)의 원소인 경우입니다.

하나의 규칙 집합이 올바른 형식의 규칙 집합인 것은 모든 규칙이 해당 규칙 집합에서 올바른 형식의 규칙인 경우와 그 경우에만 해당합니다.

4.3 규칙 종속성

규칙 R1이 규칙 R2에 의존하는 경우는 두 번째 규칙의 출력이 첫 번째 규칙의 본문 평가에 영향을 미칠 때입니다. 즉, R2의 헤드에는 하나의 트리플 템플릿이 있으며, 이는 다음에 일치하는 트리플을 생성할 수 있습니다: 하나의 트리플 패턴으로, R1의 본문에 있으며, 하나의 트리플 패턴 요소로 나타나거나, 하나의 부정 요소 또는 하나의 그룹 패턴 안에 있습니다.

의존성에는 두 종류가 있습니다: 닫힌 의존성 및 열린 의존성. 닫힌 의존성은 규칙 R2가 규칙 R1이 실행되기 전에 가능한 모든 출력을 생성했음을 보장합니다. 규칙 의존성이 닫혀 있지 않으면 열린 의존성입니다. 이는 첫 번째 규칙 R1이 실행될 수 있게 하며, 그동안 규칙 R2는 추가 트리플을 생성하기 위해 다시 실행될 수 있고, 이에 따라 R1이 R2의 새 트리플로 재평가될 수 있습니다.

플래그 .evaldata가 false로 설정된 규칙은 기본 그래프를 사용하여 매칭하며, 해당 규칙에는 의존성이 없습니다.

이 첫 번째 예제에서 첫 번째 규칙은 열린 의존성을 가집니다. 그 대상은 두 번째 규칙입니다.

이 두 번째 예제에서 첫 번째 규칙은 닫힌 의존성을 가집니다. 그 대상은 두 번째 규칙입니다. 트리플 패턴 ?x :status :criticallyExposed는 다음의 내부에 나타납니다. 부정 요소로서 첫 번째 규칙에 속하며, 다음과 매칭됩니다. 트리플 템플릿으로서 두 번째 규칙의 머리부에 있습니다. 첫 번째 규칙은 두 번째 규칙이 가능한 모든 출력을 생성할 때까지 평가할 수 없습니다.

트리플 패턴 매칭

하나의 트리플 패턴은 트리플 템플릿과 매칭되며, 이는 해당 트리플 템플릿이 트리플을 생성할 수 있고, 해당 트리플이 매칭되는 대상이 해당 트리플 패턴인 경우입니다.

트리플 패턴 의존성

하나의 트리플 패턴이 의존하는 대상은 트리플 템플릿이며, 이는 해당 트리플 패턴이 매칭될 수 있는 대상이 해당 트리플 템플릿인 경우입니다.

규칙 의존성

규칙 R1은 의존 관계에 있습니다 규칙 R2에 대해 다음 조건이 성립하는 경우입니다. R1.evaldata가 true이고, 어떤 트리플 패턴이 R1의 본문에 있으며, 그 형태가 트리플 패턴 요소이든, 다음의 내부에 있든: 부정 요소 neg(여기서 neg.evaldata는 true), 또는 그룹 패턴 내부에 있든, 의존하는 트리플 템플릿이 R2의 헤드에 있는 경우입니다.

닫힌 의존성

하나의 규칙 의존성이 규칙 R1에서 규칙 R2로 향할 때, 이는 닫힌 의존성이며, 다음 조건 중 하나라도 성립하는 경우입니다:

열린 의존성

하나의 규칙 의존성이 규칙 R1에서 규칙 R2로 향할 때, 이는 열린 의존성이며, 해당 의존성이 닫힌 의존성이 아닌 경우입니다.

트리플 템플릿은 트리플 템플릿의 변수에 대한 값이 존재하여 템플릿의 변수를 값으로 대체했을 때 트리플 T2가 되고, T2가 T1과 같으면 RDF 트리플 T1을 생성할 수 있습니다.

마찬가지로, 트리플 패턴과 일치하는 트리플 T1은 해당 패턴의 변수에 할당할 값들이 존재하는 경우입니다. 트리플 패턴의 변수를 해당 값으로 치환할 때에는 빈 노드를 변수로 취급하는 경우도 포함되며, 패턴에서 치환한 결과 트리플 T2가 생성되고, 이 T2와 동일한 T1이어야 합니다.

트리플 템플릿 또는 트리플 패턴에서 변수가 두 번 이상 사용되면, 대체할 때 동일한 RDF 용어가 사용됩니다.

트리플 패턴에서 변수를 RDF 용어로 대체하는 것은 트리플 용어 내부의 변수를 대체하는 것도 포함합니다.

4.3.1 종속성 그래프

규칙 간의 종속성은 종속성 그래프라고 하는 방향 그래프로 표현됩니다. 그래프의 정점은 규칙 집합의 규칙이며, 간선에는 종속성이 열린 종속성인지 닫힌 종속성인지에 따라 open 또는 closed라는 레이블이 지정됩니다.

종속성 그래프
규칙 집합의 종속성 그래프는 각 정점이 규칙 집합의 규칙이고, R1이 R2에 의존하면 규칙 R1에서 규칙 R2로 향하는 간선이 존재하는 방향 그래프입니다. 간선에는 종속성이 열린 종속성인지 닫힌 종속성인지에 따라 open 또는 closed라는 레이블이 지정됩니다.
전이적 규칙 종속성
종속성 그래프에서 R1에서 R2로 가는 경로가 존재하면 규칙 R1은 규칙 R2에 대해 전이적 종속성을 가집니다.
재귀적 규칙 종속성

종속성 그래프에 R이 관여하는 순환 경로가 있으면 규칙 R은 재귀적 종속성을 가집니다.

참고

종속성 그래프는 기본 그래프의 영향을 받지 않습니다.

4.3.2 종속성 그래프 알고리즘

다음 알고리즘은 한 가지 가능한 구성 방법을 제시합니다. 그 대상은 의존성 그래프이며, 그 출발점은 규칙 집합입니다. 적합성은 의존성 그래프를 생성하는 데 달려 있으며, 그 그래프는 의존성 그래프의 정의를 충족해야 합니다. 이 절차의 사용 여부에 달려 있지는 않습니다.

define mergeLabel(oldLabel, newLabel):
    # 닫힌 의존성이 열린 의존성보다 우선합니다.
    if oldLabel == "open" and newLabel == "open":
        the result is "open"
    else:
        the result is "closed"
    endif
enddefine

# 출력 -- 규칙 정점과 레이블이 지정된 간선이 있는 의존성 그래프.
define buildDependencyGraph(ruleSet):
    # edgeLabelMap은 (R1, R2)를 "open" 또는 "closed"에 매핑합니다
    let edgeLabelMap be a map from pair (rule, rule) to label

    foreach rule R1 in ruleSet.rules:
        let bodyDependencies = {}

        if R1.evaldata then:
            # 규칙의 각 트리플 패턴 TP를 "open" 또는 "closed"가 필요한 것으로 분류합니다
            # 부정 요소나 그룹 패턴 안에 있는지 여부에 따라 분류합니다.
            foreach rule element RBE in R1.body:
                if RBE is a triple pattern element of triple pattern TP:
                    let item be a pair (TP, "open")
                    add item to bodyDependencies
                else if RBE is a filter element:
                    # 아무 작업도 하지 않습니다
                else if RBE is a negation element:
                    if RBE.evaldata then:
                        foreach triple pattern TP in RBE.inner:
                            let item be a pair (TP, "closed")
                            add item to bodyDependencies
                        endfor
                    endif
                else if RBE is an assignment element:
                    # 아무 작업도 하지 않습니다
                else if RBE is a group element:
                    foreach triple pattern TP in RBE.pattern:
                        let item be a pair (TP, "closed")
                        add item to bodyDependencies
                    endfor
                endif
            endfor
        endif

        foreach pair (triple pattern TP, depLabel) in bodyDependencies:
            if R1 is a run-once rule:
                set depLabel to "closed"
            endif
            # 이 트리플 패턴 요소 또는 부정 요소의 의존성을 찾습니다.
            foreach rule R2 in ruleSet.rules:
                foreach triple template TT in R2.head:
                    if triple pattern TP matches triple template TT:
                        let key = (R1, R2)
                        if edgeLabelMap contains key:
                            let oldLabel = edgeLabelMap.get(key)
                            let merged = mergeLabel(oldLabel, depLabel)
                            edgeLabelMap.set(key, merged)
                        else:
                            edgeLabelMap.set(key, depLabel)
                        endif
                    endif
                endfor
            endfor
        endfor
    endfor

    let DP = { }
    foreach entry ((R1, R2), label) in edgeLabelMap:
        add an edge (R1 -> R2) labeled with label to DP
    endfor

    the result is DP
enddefine

4.4 계층화

층화는 하나의 규칙 집합을 순서 있는 시퀀스로 분할하는 과정이며, 그 구성 요소는 층화 계층입니다(다른 명칭은 "strata"이며, 단수형은 "stratum"입니다). 낮은 계층의 규칙은 더 높은 계층의 규칙보다 먼저 평가됩니다.

층화는 다음 사이의 의존성에 제약을 부과합니다: 규칙. 이를 통해 부정 요소, 그룹 요소, 그리고 단일 실행 규칙이 오직 앞선(더 낮은) 계층과 기본 그래프를 사용하여 계산한 결과에만 의존하도록 보장합니다. 이는 단일하고, 명확히 정의되며, 유한한 평가 결과를 보장합니다. 평가 대상은 규칙 집합이며, 주어진 기본 그래프에 대해 평가합니다.

참고

층화 과정은 다른 평가 관련 결정을 내리는 데에도 사용할 수 있습니다. 이 문서는 필요한 조건을 설명합니다. 이는 일관된 평가를 위한 조건이며, 또한 하나의 가능한 층화 구성 방법을 제시합니다. 구현은 조건을 충족해야 합니다. 호환되는 동작을 얻으려면 여기에 설명된 조건을 충족해야 하지만, 제시된 그대로 알고리즘을 구현해야 하는 것은 아닙니다.

층화 계층

하나의 층화 계층 SL은 쌍이며, 서로소인 두 집합으로 구성됩니다. 이들은 규칙 집합 (SL.once, SL.general)입니다. SL.once는 정확히 단일 실행 규칙들로 이루어지며, 이 규칙들은 해당 계층에 속합니다; 이 규칙들은 각각 평가되며, 다음의 평가 시작 시 정확히 한 번 평가됩니다: 층화 계층. SL.general은 해당 계층의 나머지 규칙들의 집합이며, 이 규칙들은 새로운 트리플이 더 이상 추론되지 않을 때까지 반복적으로 평가됩니다.

층화

하나의 층화는 하나의 규칙 집합에 대한 것으로, 층화 계층의 시퀀스입니다. 각 규칙은 하나의 규칙 집합에서 정확히 하나의 집합에 속하며, 그 집합은 하나의 층화 계층에 속합니다.

해당 층화 계층들은 하나의 층화에 속하며, 번호가 부여됩니다. 번호는 0부터 시작합니다. 계층 번호는 하나의 규칙에 대해 부여되는 번호이며, 해당 층화 계층, 즉 그 규칙을 포함하는 계층의 번호입니다. 규칙의 계층 번호가 더 작으면, 더 낮은 계층에 있습니다; 규칙의 계층 번호가 더 크면, 더 높은 계층에 있습니다.

규칙 R1에서 규칙 R2로 향하는 모든 간선에 대해, 해당 의존성 그래프가 속한 규칙 집합에서:

  • 간선의 레이블이 closed이면, 해당 계층 번호는 R1의 경우 다음보다 엄격히 큽니다: 계층 번호(R2의).
  • 간선의 레이블이 open이면, 해당 계층 번호는 R1의 경우 다음보다 크거나 같습니다: 계층 번호(R2의).
참고

하나의 규칙 집합에는 둘 이상의 층화가 있을 수 있습니다. 구현은 어떤 층화든 사용할 수 있으며, 이는 해당 규칙 집합의 층화입니다.

4.4.1 계층화 조건

층화는 다음 조건이 충족될 때에만 정의됩니다. 하나의 규칙 집합이 이 조건을 충족하지 않으면, 이 명세는 다음의 평가 결과를 정의하지 않습니다: 그러한 규칙 집합.

층화 조건
해당 층화 조건은 다음을 요구합니다: 존재하지 않아야 하는 재귀 의존성은 다음을 포함하는 의존성입니다: 닫힌 의존성. 그 범위는 의존성 그래프이며, 하나의 규칙 집합에 대한 그래프입니다.
참고

해당 층화 조건은 정확히 다음이 존재하기 위한 조건입니다: 층화. 하나의 층화를 하나의 규칙 집합에 대해 구성할 수 있는 필요충분조건은 다음 의존성 그래프의 어떤 순환 경로도, 해당 규칙 집합에 대해, 하나의 닫힌 의존성을 포함하지 않는 것입니다.

4.4.2 계층화 알고리즘

다음 알고리즘은 하나의 가능한 층화를 제시하며, 그 기반은 오직 규칙 집합입니다.

define stratification(ruleSet):

    let DP = Dependency graph for the rule set.
    let stratumMap be a map from rule to integer

    # 의존성 그래프는 층화 조건을 충족해야 합니다.
    # 상한 없는 층화를 검사하는 것은 방어 조치입니다
    # 층화 조건 위반에 대비하기 위한 것입니다.
    let limit = num rules + 1
    let maxStratum = 0

    # stratumMap을 초기화합니다
    foreach rule in ruleSet.rules:
        stratumMap.set(rule, 0)
    endfor

    let changed = true
    while changed:
        changed = false
        foreach edge E in DP:
            # pRule에서 qRule로 향하는 레이블이 있는 간선
            let pRule = source of edge
            let qRule = destination of the edge
            let label = edge label

            if label == "open":
                if stratumMap.get(pRule) < stratumMap.get(qRule):
                    stratumMap.set(pRule, stratumMap.get(qRule))
                    changed = true
                endif
            endif
            if label == "closed":
                if stratumMap.get(pRule) <= stratumMap.get(qRule):
                    let xStratum = 1 + stratumMap.get(qRule)
                    if xStratum > limit:
                        # 층화 요구 사항 위반
                        error "층화 오류"
                    endif
                    stratumMap.set(pRule, xStratum)
                    maxStratum = max(maxStratum, xStratum)
                    changed = true
                endif
            endif
        endfor
    endwhile

    # 결과 맵을 초기화합니다.
    let stratumRules be a map from integer to rules
    foreach i = 0 to maxStratum:
        stratumRules.set(i, {})
    endfor

    # stratumMap에서 계층 번호가 같은 규칙을 모읍니다
    foreach rule R in map stratumMap:
        let stratumNum = stratumMap.get(R)
        add R to stratumRules.get(stratumNum)
    endfor

    # 각 계층을 once와 general로 분할합니다
    let stratumLevels be a sequence of pairs of sets of rules
    foreach i = 0 to maxStratum:
        let rules = stratumRules.get(i)
        let once = { R in rules | R is a run-once rule }
        let general = rules \ once
        stratumLevels.set(i, pair(once, general))
    endfor

    the result is stratumLevels
enddefine
참고

다음 층화 조건에 따른 결과는 일단 하나의 단일 실행 규칙이 평가되면, 규칙의 결과를 결정하는 데 사용된 데이터는 이후 평가 중에 변경되지 않는다는 것입니다.

의존성 분석의 단계별 적용과 완전한 규칙 집합의 층화부터 평가까지 진행하는 과정은 다음에 제시되어 있습니다: 6.6 풀이 예제.

4.5 가져오기 처리

웹에서 문서를 읽는 작업에는 보안상 영향이 있습니다. 규칙 집합 가져오기 지원 여부는 SPARQL-RL 처리기에서 선택 사항입니다. 또한 구현은 부분적으로 지원할 수 있으며, 예를 들어 일부 규칙 집합의 가져오기만 지원하고 다른 규칙 집합은 지원하지 않거나, 검증된 사본에서만 가져오도록 할 수도 있습니다.

가져오기 처리에는 다음 조건이 적용됩니다.

하나의 해결된 규칙 집합은 다른 규칙 집합에서 가져오기에 언급된 모든 규칙 집합을 재귀적으로 읽어 생성되며, 이 가져오기는 해당 다른 규칙 집합에 속합니다.

알고리즘의 한 예는 B. 가져오기 알고리즘 예제에서 확인할 수 있습니다.

5. SPARQL-RL과 SPARQL의 관계

이 절은 비규범적입니다.

SRL과 SPARQL은 밀접한 관계가 있습니다. SRL은 호환되도록 설계되었으며, 그 대상은 SPARQL이고, SRL의 많은 구문은 다음에서 가져오거나 영감을 받았습니다. SPARQL 패턴 매칭입니다. 그러나 몇 가지 차이점이 있습니다.

SRL에서 RULE 변수는 사용 전에 항상 바인딩되며, 이는 FILTER 또는 SET의 표현식에서 사용되든, 트리플 템플릿에서 사용되든 마찬가지입니다. 이 템플릿은 규칙 머리부에 속합니다. SPARQL CONSTRUCT 질의 및 INSERT 업데이트는 변수가 CONSTRUCT 또는 INSERT 템플릿에 나타나지만 WHERE 절에서 값이 주어지지 않으면 부분적인 결과를 생성합니다.

그 밖의 차이점은 다음과 같습니다:

6. 규칙 집합 평가

이 절에서는 주어진 데이터에 대해 규칙 집합을 평가한 결과를 정의합니다. 구현에서 이 알고리즘을 사용할 필요는 없습니다. 구현은 동일한 결과를 생성하는 어떤 알고리즘이든 사용할 수 있습니다.

입력: 기본 그래프라고 하는 그래프 G와 규칙 집합 RS.
출력: 추론된 트리플의 RDF 그래프 GI

추론된 트리플에는 기본 그래프에 존재하는 트리플이 포함되지 않습니다.

6.1 평가 정의

해 매핑
하나의 해 매핑 μ는 부분 함수 μ : V → T이며, 여기서 V는 모든 변수의 집합이고 T는 모든 RDF 용어의 집합입니다. μ의 정의역은 dom(μ)로 나타내며, 이는 V의 부분집합으로, μ가 정의되는 변수들로 이루어집니다. 용어 해는 다음을 의미한다는 것이 명확할 때 사용할 수 있습니다: 해 매핑. 해 매핑을 μ0로 표기하며, 이때 dom(μ0)는 공집합입니다.
치환 함수

해당 치환 함수, 또는 간단히 치환은, 함수 subst(μ, 트리플 패턴)이며 반환하는 것은 하나의 트리플 패턴입니다. 이때 원래 트리플 패턴에서 변수 var가 다음에 속하면, dom(μ), 해당 변수의 모든 출현은 다음 RDF 용어로 대체되며, 이는 해 매핑이 var에 대해 제공하는 값입니다. 결과 트리플 패턴에 변수가 없으면, 이는 하나의 RDF 트리플입니다.

함수 subst(μ, 트리플 템플릿)도 유사하게 정의됩니다. 변수의 모든 출현은, 해당 트리플 템플릿에서, 다음 RDF 용어로 대체되며, 이는 해 매핑이 var에 대해 제공하는 값입니다.

템플릿 인스턴스 함수
해당 템플릿 인스턴스 함수는 함수 replaceBlankNodes(트리플 템플릿 목록)이며 이 함수는 다음의 목록을 반환합니다: 트리플 템플릿. 이때 각 빈 노드는 인수 내에서 새 빈 노드로 대체됩니다. 동일한 빈 노드가 여러 번 나타나면, 모두 동일한 새 빈 노드로 대체됩니다.
평가 그래프
하나의 평가 그래프는 하나의 RDF 그래프로, 해당 기본 그래프와 규칙 집합 평가 중 생성된 모든 트리플을 결합한 것입니다.
그래프 일치
하나의 그래프 일치가 찾는 것은 트리플 패턴을 다음에 있는 트리플에 매핑하는 방법입니다: RDF 그래프.

G를 하나의 RDF 그래프라고 하고, TP를 하나의 트리플 패턴이라고 합니다. 함수 graphMatch(G, TP)는 가능한 모든 해의 집합을 반환합니다. 이 해들을 트리플 패턴에 적용하면 생성되는 트리플은 그래프 G에 속합니다.

G를 하나의 RDF 그래프, TP를 하나의 트리플 패턴, 그리고 V를 TP에 나타나는 변수들의 집합이라고 합니다.

graphMatch(G, TP) = { μ | dom(μ) = V and subst(μ, TP) is a triple in G }
해 호환성
두 해 S1과 S2는 호환됩니다. 이는 변수의 값이 일치할 때이며, 그 변수들은 두 해가 공통으로 갖는 변수입니다.

S1과 S2를 해라고 합니다.

compatible(μ1, μ2) = true
                      if forall v in dom(μ1) intersection dom(μ2)
                          μ1(v) = μ2(v)
compatible(μ1, μ2) = false otherwise
해 시퀀스
하나의 해 시퀀스는 해들의 다중집합입니다. 시퀀스에 정의된 순서는 없습니다. 이는 순서 없는 목록과 동등하며 중복을 포함할 수 있습니다.
해 병합
두 해가 호환되면, 두 해의 병합 결과는 하나의 해이며, 각 해의 변수를 다음 RDF 용어에 매핑합니다. 해당 용어는 두 해 중 하나에서 가져옵니다.
μ1, μ2를 해 매핑이라고 하고, S1과 S2를 해 시퀀스라고 합니다.
merge(μ1, μ2) = μ such that
                    μ(v) = μ1(v) if v in dom(μ1)
                    μ(v) = μ2(v) otherwise
merge(S1, S2) = { μ |
                    μ1 in S1, μ2 in S2
                    and compatible(μ1, μ2)
                    μ = merge(μ1, μ2) }
참고

merge(μ1, μ2)의 정의역은 domain(μ1) ∪ domain(μ2)입니다.

두 해에 공통 변수가 없으면 두 해는 호환되며, 두 해의 병합 결과는 다음의 합집합입니다: μ1과 μ2.

유효 불리언 값
함수 EBV(x)는 유효 불리언 값을 반환하며, 그 대상은 하나의 RDF 용어입니다.

6.2 평가 준비

규칙 집합 평가에는 가져온 모든 규칙 집합을 수집하고 4.5 가져오기 처리에 설명된 대로 하나의 결합된 규칙 집합을 구성하는 과정이 포함됩니다.

그런 다음 다음 단계에 따라 결합된 규칙 집합을 평가할 수 있도록 준비합니다.

  1. 4.2 정형성 조건에 설명된 대로 각 규칙이 정형 규칙인지 확인합니다.
  2. 4.3.2 종속성 그래프 알고리즘에 설명된 대로 종속성 그래프를 계산합니다.
  3. 4.4 계층화에 설명된 대로 결합된 규칙 집합의 계층화를 계산합니다. 4.4.2 계층화 알고리즘은 계층화를 계산하는 한 가지 방법을 제시합니다.

6.3 표현식 평가

표현식은 필터 요소에서 사용되든 할당 요소에서 사용되든, 평가에는 하나의 해 매핑이 기준으로 사용됩니다. 해 매핑은 표현식의 각 변수에 대한 RDF 용어 값을 제공합니다. 4.2 올바른 형식 조건의 올바른 형식 요구 사항은 표현식의 모든 변수가 해 매핑에 나타나도록 보장합니다.

define evalFunction(F, μ):
    # F는 표현식이며, RDF 용어, 변수 또는 op(expr1, ..., exprN)입니다.
    #   여기서 op는 함수 또는 함수 형식입니다.
    # μ는 해 매핑입니다.

    # 평가 중 오류가 발생하면 evalFunction은 오류를 반환합니다.
    if F is an error:
        return error
    endif
    if F is an RDF term:
        return F
    endif
    if F is a variable:
        # 올바른 형식 조건에 따라 F ∈ dom(μ)입니다.
        return μ(F)
    endif
    # F는 F = op(expr1, ..., exprN) 형식입니다.
    if op is a functional form (e.g., IF, logical-or):
        # op에 정의된 방식으로 평가합니다. op는 일부 인수만 평가할 수도 있습니다.
        # 예를 들어, IF(c, t, f)는 c를 평가한 다음,
        # t 또는 f 중 정확히 하나만 평가합니다.
        return the value defined for op over expr1, ..., exprN under μ
    endif
    # op는 일반 함수이므로 모든 인수를 먼저 평가합니다.
    return op(evalFunction(expr1, μ), ..., evalFunction(exprN, μ))
enddefine
define evalAggregate(AGGF, SEQ):
@@
    # AGGF는 변수와 해 시퀀스를 인수로 받는
    # 집계 함수입니다. RDF 용어 값을 반환합니다.

    # DISTINCT는 COUNT에만 허용됩니다.
    # COUNT(*)는 특수한 경우입니다.
enddefine
집계 함수
집계 함수 이에 해당하는 SPARQL 함수
COUNT SPARQL COUNT (distinct를 false로 설정)
COUNT DISTINCT SPARQL COUNT (distinct를 true로 설정)
MIN SPARQL MIN
MAX SPARQL MAX
SUM SPARQL SUM
편집자 참고

집계 함수 계산 중 오류가 발생하면 평가 오류가 발생하며 해당 그룹은 결과에 추가되지 않습니다.

6.4 규칙 평가

하나의 규칙은 해 시퀀스를 규칙 본문에서 계산한 뒤, 각 해 매핑을 해당 해 시퀀스에서 가져와 트리플을 생성하는 데 규칙 헤드를 사용하는 방식으로 평가됩니다.

규칙 본문에서 빈 노드는 트리플 패턴 내에서 변수처럼 동작합니다. 이는 SPARQL 그래프 패턴 일치와 호환됩니다.

빈 노드를 변수로 취급
빈 노드는 트리플 패턴 내에서 변수로 취급되며, 이는 규칙 본문의 각 빈 노드를 해당 규칙에서 사용하지 않는 변수로 바꾸는 방식으로 이루어집니다. 여기에는 트리플 용어 내부의 빈 노드를 바꾸는 것도 포함됩니다. 동일한 빈 노드가 나타나는 모든 위치에는 동일한 변수를 사용하며, 서로 다른 빈 노드에는 각각 다른 변수를 사용합니다.
# 규칙 본문을 평가합니다.
# 이 함수는 해 시퀀스를 반환합니다.

define evalRuleElements(B, SEQ, G, GD):
    where
        B is a sequence of rule elements
        SEQ is a solution sequence
        G and GD are RDF graphs

    foreach rule element rElt in B:

        if rElt is a triple pattern element TP:
            X = graphMatch(G, TP)
            SEQ1 = {}
            foreach μ1 in X:
                foreach μ2 in SEQ:
                    if compatible(μ1, μ2):
                        μ3 = merge(μ1, μ2)
                        add μ3 to SEQ1
                    endif
                endfor
            endfor
        endif

        if rElt is a filter element F:
            SEQ1 = {}
            foreach solution μ in SEQ:
                let x = evalFunction(F.expr, μ)
                if x is not an error and EBV(x) is true:
                    add μ to SEQ1
                endif
            endfor
        endif

        if rElt is a negation element N:
            SEQ1 = {}
            foreach solution μ in SEQ:
                S = sequence{ μ }
                if N.evaldata:
                    NEG = evalRuleElements(N.inner, S, G, GD)
                else:
                    NEG = evalRuleElements(N.inner, S, GD, GD)
                endif
                if NEG is empty:
                    add μ to SEQ1
                endif
            endfor
        endif

        if rElt is an assignment element A:
            SEQ1 = {}
            foreach solution μ in SEQ:
                let x = evalFunction(A.expr, μ)
                if x is not an error:
                    # 매핑 A.var -> x를 해 μ에 추가합니다.
                    let μ2 be a solution mapping μ ∪ { (A.var, x) }
                    add μ2 to SEQ1
                else:
                    # 오류: 해 μ를 제외합니다.
                endif
            endfor
        endif

        ## COUNT(*)는 어떻게 처리하나요?
        if rElt is a group element GRP:
            SEQ1 = {}
            foreach solution μ in SEQ:
                let μp be the restriction of μ to GRP.keys
                let SEQX = evalRuleElements(GRP.pattern, { μp }, G, GD)
                # 해 매핑을 그룹에 배정합니다.
                let KGRP = empty map of solution mappings to solution sequences
                foreach solution μx in SEQX:
                    let μk be the restriction of μx to GRP.keys
                    if KGRP[μk] is defined:
                        add μx to the solution sequence KGRP[μk]
                    else:
                        KGRP[μk] = solution sequence of one element μx
                    endif
                endfor
                # 각 그룹에 대해 집계 함수를 계산하고,
                # 현재 해 매핑 μ를 그룹 키와
                # 집계 할당 결과로 확장합니다.
                foreach key K of map KGRP:
                    let X be the solution sequence of KGRP[K]
                    let Z be an empty solution mapping
                    foreach aggregation function F in GRP.aggregations:
                        let V = calculate F.function(X)
                        add solution mapping (F.var, V) to Z
                    endfor
                    Z = merge(Z, K)
                    Z = merge(Z, μ)
                    add Z to SEQ1
                endfor
            endfor
        endif
        SEQ = SEQ1
    endfor

    return SEQ
enddefine

define evalRule(R, G, GD):
    where
        R is a well-formed rule
        G and GD are RDF graphs
    let B be R.body
        treating 빈 노드를 변수로.

    # 어떤 변수도 매핑하지 않는 해 하나로 이루어진 해 시퀀스입니다.
    let SEQ0 be the solution sequence { μ0 }

    if R.evaldata:
        let SEQ = evalRuleElements(B, SEQ0, G, GD)
    else:
        let SEQ = evalRuleElements(B, SEQ0, GD, GD)
    endif

    # 규칙 헤드를 평가합니다.
    let OUT = empty set
    foreach μ in SEQ:
        let S = {}
        # 각 빈 노드를 새 빈 노드로 바꾼 규칙 헤드입니다.
        let HT = replaceBlankNodes(R.head)
        foreach triple template TT in HT:
            let triple = subst(μ, TT)
            add triple to S
        endfor
        OUT = OUT ∪ S
    endfor
    return OUT
enddefine
참고

OUT에는 기본 그래프에도 있는 트리플이 포함될 수 있습니다.

6.5 규칙 집합 평가

하나의 규칙 집합을 평가하는 것은 해당 규칙 집합의 각 계층을 실행하는 것으로 정의되며, 각 계층은 해당 규칙 집합의 계층화에 속하고, 다음 계층으로 이동하기 전에 순서대로 완전히 실행되어야 합니다. 계층은 이러한 순서에 따라 실행됩니다. 하나의 계층은 먼저 해당 계층의 각 일회 실행 규칙을 평가한 다음, 해당 계층의 일반 규칙을 새로운 트리플이 더 이상 생성되지 않을 때까지 반복해서 평가합니다.

let G0 be the input base graph
let RS be the rule set
let D be the graph of all DATA triples in RS

Apply stratification to RS

let LS be the sequence of layers after stratification

# 추론 그래프
let GI = { t ∈ D | t ∉ G0 }

# 평가 그래프: 기본 그래프와 데이터 블록
let GE = G0 ∪ D

foreach stratum ST in LS:
    foreach rule R in ST.once:
        let X = evalRule(R, GE, G0)
        let Y = { t ∈ X | t ∉ GE }
        GI = GI ∪ Y
        GE = GE ∪ Y
    endfor

    let finished = false
    while ! finished:
        finished = true
        foreach rule R in ST.general:
            let X = evalRule(R, GE, G0)
            let Y = { t ∈ X | t ∉ GE }
            if Y is not empty:
                finished = false
                GI = GI ∪ Y
                GE = GE ∪ Y
            endif
        endfor
    endwhile
endfor
the result is GI

6.6 실제 예제

이 절은 비규범적입니다.

이 절에서는 완전한 규칙 집합의 평가 과정을 단계별로 살펴봅니다. 즉, 규칙 종속성을 결정하고 (4.3 규칙 종속성), 계층화를 계산하고 (4.4 계층화), 각 계층을 차례로 평가하여 추론 그래프를 생성합니다 (6.5 규칙 집합 평가).

이 예제에서는 소프트웨어 구성 요소와 그 종속성을 설명합니다. 프런트엔드는 애플리케이션 서버에 의존하고, 애플리케이션 서버는 데이터베이스와 로깅 라이브러리에 의존합니다. 데이터베이스에는 알려진 취약점이 있습니다. 규칙은 종속성 체인을 따라 취약점에 대한 노출을 전파하고, 심각한 취약점에 노출된 구성 요소에 :criticallyExposed 상태를 부여하고, 심각하지 않은 구성 요소에 :safeToDeploy 상태를 부여하며, 심각하게 노출된 각 구성 요소에 대한 알림을 생성합니다. (실제로 취약점이 구성 요소에 영향을 미치는지 여부는 배포된 버전에 따라 달라집니다. 이 예제에서는 버전을 생략하고 취약점을 직접 명시합니다.) 간결성을 위해 기본 그래프에서는 3.1 트리플 패턴에서처럼 더 구체적인 관계에서 도출하는 대신 :dependsOn 트리플을 직접 명시합니다.

규칙은 주석에서 R1부터 R5까지의 레이블이 지정되어 있으며, 이 절의 나머지 부분에서는 이러한 레이블로 참조됩니다. 이 규칙들은 3.2 재귀부터 3.5 할당 및 RDF 용어 생성까지에서 소개한 규칙입니다. 규칙 집합에는 IMPORTS가 없으므로 가져오기 처리를 거쳐도 변경되지 않으며, DATA 블록도 없으므로 평가는 기본 그래프만으로 시작됩니다.

6.6.1 종속성 결정

어떤 규칙이 어떤 규칙에 의존하는지 결정하기 위해 각 규칙 본문의 각 트리플 패턴을 모든 규칙 헤드의 트리플 템플릿과 비교합니다 (4.3 규칙 종속성).

  • R1의 본문은 단일 트리플 패턴 ?x :hasVulnerability ?v입니다. 어떤 규칙 헤드에도 술어가 :hasVulnerability인 트리플을 생성할 수 있는 트리플 템플릿이 없으므로, 이 패턴은 데이터에만 매칭될 수 있습니다. R1에는 종속성이 없습니다.
  • R2의 본문에는 두 개의 트리플 패턴이 있습니다. ?x :dependsOn ?y는 어떤 규칙 헤드와도 매칭되지 않으므로 데이터에만 매칭됩니다. ?y :exposedTo ?v는 R1의 헤드 템플릿 ?x :exposedTo ?v과 매칭되고, R2 자체의 헤드와도 매칭됩니다. 두 출현 모두 트리플 패턴 요소이며 (부정 요소 안에 나타나지 않고, R2도 한 번 실행되는 규칙이 아닙니다), 따라서 R2는 R1에 대해 열린 종속성을 가지며 자신에 대해서도 열린 종속성을 가집니다. R2가 자신에게 의존하므로 R2는 재귀 규칙입니다.
  • R3의 본문에서 패턴 ?x :exposedTo ?v는 R1과 R2의 헤드와 매칭되므로 R3는 각각에 대해 열린 종속성을 가집니다. 패턴 ?v :severity ?s는 어떤 규칙 헤드와도 매칭되지 않습니다.
  • R4의 본문에서 패턴 ?x rdf:type :Component는 어떤 규칙 헤드와도 매칭되지 않습니다. 술어가 rdf:type인 유일한 헤드 템플릿은 R5에 있으며, 그 목적어 :Notification은 :Component와 다른 RDF 용어이므로 생성된 어떤 트리플도 매칭될 수 없습니다. 패턴 ?x :status :criticallyExposed은 부정 요소 NOT { ?x :status :criticallyExposed } 안에 나타나며 R3의 헤드 템플릿과 매칭됩니다. 패턴이 부정 요소에 나타나므로 R4는 R3에 대해 닫힌 종속성을 가집니다.
  • R5의 본문에서 패턴 ?x :status :criticallyExposed은 R3의 헤드와 매칭됩니다. R5의 헤드에는 빈 노드가 있으므로, 이 패턴이 일반적인 트리플 패턴 요소임에도 불구하고 R3에 대한 종속성은 닫힌 종속성입니다. 어떤 규칙 본문의 패턴도 R5의 헤드 템플릿과 매칭되지 않으므로 어떤 규칙도 R5에 의존하지 않습니다.

따라서 종속성 그래프에는 5개의 정점과 6개의 간선이 있습니다.

  • R2 → R1 (열림)
  • R2 → R2 (열림)
  • R3 → R1 (열림)
  • R3 → R2 (열림)
  • R4 → R3 (닫힘)
  • R5 → R3 (닫힘)

R4와 R5는 R1 또는 R2에 직접적으로 의존하지 않지만, 각각 R3을 통해 두 규칙 모두에 대한 전이적 종속성을 가집니다.

실제 예제 규칙 집합의 종속성 그래프 R1, R2, R3, R4 및 R5라는 레이블이 지정된 다섯 개의 정점입니다. 점선 화살표는 열린 종속성을 나타냅니다. R2에서 R1로, R2에서 자기 자신으로, R3에서 R1로, R3에서 R2로 향합니다. 실선 화살표는 닫힌 종속성을 나타냅니다. R4에서 R3으로 그리고 R5에서 R3으로 향합니다. R2 R1 R3 R4 R5 열린 종속성 닫힌 종속성
그림 1 실제 예제 규칙 집합의 종속성 그래프입니다. 열린 종속성은 점선 화살표로, 닫힌 종속성은 실선 화살표로 표시됩니다. 각 간선은 본문에 매칭되는 트리플 패턴이 포함된 규칙에서 매칭되는 트리플을 생성할 수 있는 헤드가 있는 규칙을 향합니다.

그래프의 유일한 순환은 자기 자신을 향하는 간선 R2 → R2이며, 이는 열린 종속성입니다. 어떤 순환에도 닫힌 종속성이 포함되지 않으므로 계층화 조건이 충족되며 규칙 집합에는 잘 정의된 결과가 있습니다.

6.6.2 계층화 계산

계층화 알고리즘에 따라 모든 규칙은 계층 0에서 시작합니다. 그런 다음 아무것도 변경되지 않을 때까지 간선을 반복해서 검사합니다.

  • 열린 간선은 출발 규칙이 대상과 같은 계층 또는 더 높은 계층에 있어야 함을 요구합니다. 네 개의 열린 간선은 모든 규칙이 계층 0에 있는 상태에서 이미 이 조건을 충족하므로 아무런 변경도 일으키지 않습니다.
  • 닫힌 간선은 대상 규칙이 먼저 완료될 때까지 실행되어야 하므로 출발 규칙이 대상보다 엄격히 높은 계층에 있어야 합니다. 간선 R4 → R3 (닫힘)는 R4와 R3가 모두 계층 0에 있으므로 R4를 계층 1로 이동시킵니다. 마찬가지로 간선 R5 → R3 (닫힘)는 R5를 계층 1로 이동시킵니다.

간선을 한 번 더 순회해도 변경되는 내용이 없으므로 계층이 확정됩니다. 그런 다음 각 계층은 한 번 실행되는 규칙과 일반 규칙으로 나뉩니다. R5는 헤드에 빈 노드가 있으므로 한 번 실행되는 규칙입니다. 규칙 집합의 다른 규칙 중 한 번 실행되는 규칙은 없습니다. 계층화는 다음과 같습니다.

  • 계층 0: 일반 R1, R2, R3; 한 번 실행되는 규칙 없음
  • 계층 1: 한 번 실행되는 R5; 일반 R4

이 순서는 더 높은 계층에 있는 규칙의 의도를 반영합니다. 구성 요소를 배포해도 안전한지, 그리고 어떤 구성 요소에 알림이 필요한지는 모든 :status :criticallyExposed 트리플이 도출된 후에만 결정할 수 있습니다. 이 트리플을 도출하는 규칙 R3는 바로 아래 계층에서, 자신에게 데이터를 제공하는 규칙 R1 및 R2와 함께 완료됩니다.

6.6.3 계층 평가

평가는 6.5 규칙 집합 평가의 알고리즘을 따릅니다. 평가 그래프 GE는 기본 그래프로 시작하고 추론 그래프 GI는 비어 있는 상태로 시작합니다. 각 계층은 순서대로 완료될 때까지 평가됩니다. 계층의 규칙은 패스 단위로 평가되며, 한 패스에서 새로운 트리플이 생성되지 않을 때까지 패스를 반복합니다. 알고리즘은 한 패스 내에서 계층의 규칙이 평가되는 순서를 정하지 않습니다. 이 실행 과정에서는 R1, R2, R3 순서를 사용합니다. 다른 순서는 동일한 추론 결과를 서로 다른 수의 패스에 분산시킬 수 있지만, 계층 0이 완료될 때까지 실행되므로 동일한 최종 그래프를 생성합니다.

이 규칙 집합에는 DATA 블록이 없으므로 평가의 모든 시점에서 GE는 G0와 GI를 더한 것입니다. 따라서 실행 과정에서는 GI만 추적하며, 평가가 진행됨에 따른 상태와 각 새 트리플을 생성한 규칙을 표시합니다.

계층 0, 첫 번째 패스.

  • R1: 본문이 :db :hasVulnerability :vuln1과 매칭되어 ?x = :db와 ?v = :vuln1이 바인딩됩니다. 헤드는 :db :exposedTo :vuln1을 생성합니다. 이 트리플은 GE에 없으므로 GE와 GI에 추가됩니다.
  • R2: 본문은 ?x :dependsOn ?y와 ?y :exposedTo ?v를 조인합니다. 이제 GE에는 :db :exposedTo :vuln1이 있으므로 조인에서 하나의 솔루션이 나옵니다. ?x = :app, ?y = :db, ?v = :vuln1입니다 (:app :dependsOn :db에서 도출됩니다). 헤드는 :app :exposedTo :vuln1을 생성하며, 이는 새 항목이므로 추가됩니다. 아직 :frontend에 대한 솔루션은 없습니다. 이 R2 평가가 시작될 때는 :app :exposedTo :vuln1이 GE에 없었기 때문입니다.
  • R3: 이제 ?x :exposedTo ?v는 :db와 :app에 대해 매칭됩니다. :vuln1 :severity 9.1과 조인하고 FILTER(?s >= 9.0)을 적용하면 두 솔루션이 모두 유지됩니다. 헤드는 :db :status :criticallyExposed와 :app :status :criticallyExposed를 생성하며, 둘 다 새 항목입니다.
# 계층 0의 첫 번째 패스 후 GI
:db  :exposedTo :vuln1 .                    # 새 항목 (R1)
:app :exposedTo :vuln1 .                    # 새 항목 (R2)
:db  :status :criticallyExposed .           # 새 항목 (R3)
:app :status :criticallyExposed .           # 새 항목 (R3)

새 트리플이 생성되었으므로 계층 0의 평가는 다음 패스로 계속됩니다.

계층 0, 두 번째 패스.

  • R1: 이전과 동일하게 매칭됩니다. :db :exposedTo :vuln1은 이미 GE에 있으므로 새로 생성되는 항목이 없습니다.
  • R2: 이제 조인에서는 ?x = :frontend, ?y = :app, ?v = :vuln1도 나오며, 새 트리플 :frontend :exposedTo :vuln1을 생성합니다. 노출이 종속성 체인을 따라 두 단계를 이동하는 데 두 번의 패스가 필요했습니다.
  • R3: 새 트리플 :frontend :status :criticallyExposed을 생성합니다.
# 계층 0의 두 번째 패스 후 GI
:db       :exposedTo :vuln1 .
:app      :exposedTo :vuln1 .
:frontend :exposedTo :vuln1 .               # 새 항목 (R2)
:db       :status :criticallyExposed .
:app      :status :criticallyExposed .
:frontend :status :criticallyExposed .      # 새 항목 (R3)

계층 0, 세 번째 패스. 이제 모든 규칙의 모든 솔루션은 이미 GE에 있는 트리플만 생성합니다. GI는 변경되지 않습니다. 새로운 트리플이 없으므로 계층 0이 완료됩니다. 즉, 도출할 수 있는 모든 :exposedTo 트리플과 모든 :status :criticallyExposed 트리플이 도출되었습니다.

계층 1, 한 번 실행되는 규칙. 이 계층의 한 번 실행되는 규칙이 먼저 평가되며, 각각 정확히 한 번 평가됩니다.

  • R5: 본문은 세 개의 :status :criticallyExposed 트리플과 매칭되어 ?x = :db, ?x = :app, ?x = :frontend 솔루션을 제공합니다. 각 솔루션에 대해 헤드를 인스턴스화하면 새로운 빈 노드가 생성되어 솔루션마다 두 개의 트리플이 생성되며, 이들은 심각하게 노출된 각 구성 요소에 대한 알림입니다. 이후 이 계층의 일반 규칙이 반복해서 평가되더라도 R5는 다시 평가되지 않습니다.

계층 1, 일반 규칙의 첫 번째 패스.

  • R4: 패턴 ?x rdf:type :Component는 :frontend, :app, :db, :logger와 매칭됩니다. (방금 R5가 생성한 rdf:type :Notification 트리플과는 매칭되지 않습니다.) 부정 요소 NOT { ?x :status :criticallyExposed }는 :frontend, :app, :db에 대한 솔루션을 거부합니다. GE가 각각에 대한 :status :criticallyExposed 트리플을 포함하기 때문입니다. ?x = :logger 솔루션만 남으며, 새로운 트리플 :logger :status :safeToDeploy을 생성합니다.
# 계층 1 후 GI
:db       :exposedTo :vuln1 .
:app      :exposedTo :vuln1 .
:frontend :exposedTo :vuln1 .
:db       :status :criticallyExposed .
:app      :status :criticallyExposed .
:frontend :status :criticallyExposed .
_:n1      rdf:type :Notification .          # 새 항목 (R5)
_:n1      :concerns :db .                   # 새 항목 (R5)
_:n2      rdf:type :Notification .          # 새 항목 (R5)
_:n2      :concerns :app .                  # 새 항목 (R5)
_:n3      rdf:type :Notification .          # 새 항목 (R5)
_:n3      :concerns :frontend .             # 새 항목 (R5)
:logger   :status :safeToDeploy .           # 새 항목 (R4)

계층 1, 일반 규칙의 두 번째 패스. 새로운 트리플이 없습니다. 평가가 완료되며, 위에 표시된 GI가 결과 추론 그래프입니다.

이러한 결과를 신뢰할 수 있게 하는 것은 계층화입니다. :frontend :status :criticallyExposed이 도출되기 전인 계층 0의 첫 번째 패스 중에 평가되었다면 R4는 :frontend :status :safeToDeploy이라고 잘못 결론 내렸을 것이며, R5는 :db와 :app에 대한 알림은 생성했지만 :frontend에 대해서는 생성하지 않았을 것입니다. 두 규칙 모두 계층 1까지 지연하면 완전한 :status :criticallyExposed 트리플 집합을 볼 수 있으므로, 각 계층 내에서 규칙이 평가되는 순서는 최종 결과에 영향을 미치지 않습니다.

7. SPARQL-RL 문법

SPARQL-RL 문서는 RDF 문자열이며, UTF-8 [RFC3629]로 인코딩되고, 문법과 추가 제약 조건을 준수합니다. 이러한 문법과 제약 조건은 다음 절에 정의되어 있습니다: 7.6 문법. 허용되는 문자는 유니코드 스칼라 값뿐이며, 그 범위는 U+0000에서 U+D7FF까지 및 U+E000에서 U+10FFFF까지로 제한됩니다. 따라서 서로게이트 코드 포인트, 즉 U+D800에서 U+DFFF까지의 범위는 제외됩니다.

7.1 버전 선언

버전 레이블은 SPARQL-RL의 구문 및 의미론에 대한 적합성을 식별하는 문자열입니다.

버전 레이블
버전 레이블
"1.2"

버전 선언은 힌트입니다. 이 선언은 문서의 앞부분에, 해당 버전에 의존하는 모든 기능보다 먼저 제시하는 것이 좋습니다.

여러 VERSION 지시문이 하나의 SPARQL-RL 문서에 나타날 수 있습니다. 각 지시문은 해당 지시문 다음에 나오는 문서 부분에 적용되며, 다른 지시문을 만나거나 문서의 끝에 도달할 때까지 적용됩니다.

버전 레이블은 version 매개변수로도 지정할 수 있으며, 이 매개변수는 미디어 유형에 속합니다. 현재 적용되는 VERSION 지시문이 없으면, 미디어 유형의 일부로 지정된 버전을 고려합니다.

7.2 공백

공백 (생성 규칙 WS)은 그렇지 않으면 하나의 터미널로 잘못 인식될 두 터미널을 구분하는 데 사용됩니다. 아래에서 대문자로 표기된 규칙 이름은 공백이 중요한 위치를 나타내며, 이러한 규칙들은 SPARQL-RL 파서를 구성하기 위한 터미널의 한 가지 선택이 됩니다.

생성 규칙 String에서는 공백이 중요합니다.

7.3 주석

주석은 IRIREF, STRING_LITERAL1, STRING_LITERAL2, STRING_LITERAL_LONG1 또는 STRING_LITERAL_LONG2 외부에 있는 #로 시작하며, 줄의 끝( LF 또는 CR로 표시됨)까지 계속됩니다. 주석 마커 뒤에 줄의 끝이 없으면 파일의 끝까지 계속됩니다. 주석은 공백으로 취급됩니다.

7.4 IRI 참조

상대 IRI 참조는 통합 자원 식별자(URI): 일반 구문 [RFC3986]에 따라 기준 IRI를 사용하여 제5.2절의 기본 알고리즘만으로 해석됩니다. 구문 기반 정규화나 스킴 기반 정규화 (RFC3986의 제6.2.2절 및 제6.2.3절에 설명됨)는 수행되지 않습니다. IRI 참조에서 추가로 허용되는 문자는 국제화 자원 식별자 (IRI) [RFC3987] 제6.5절에 따라 URI 참조에서 예약되지 않은 문자를 처리하는 것과 동일한 방식으로 처리됩니다.

BASE 지시문은 [RFC3986] 제5.1.1절, "콘텐츠에 포함된 기준 URI"에 따라 상대 IRI 참조를 해석하는 데 사용되는 기준 IRI를 정의합니다. 제5.1.2절, "캡슐화 엔티티의 기준 URI"는 범위 내 기준 IRI가 xml:base 지시문이 있는 SOAP 봉투 또는 Content-Location 헤더가 있는 MIME 멀티파트 문서와 같은 캡슐화 문서에서 유래할 수 있는 방법을 정의합니다. 5.1.3, 검색 URI의 기준 "URI"에서 식별되는 "검색 URI"는 특정 SPARQL-RL 문서를 가져온 URL입니다. 위의 어느 것도 기준 URI를 지정하지 않으면 기본 기준 URI(제5.1.4절, "기본 기준 URI")가 사용됩니다. 각 BASE 지시문은 이전 기준 URI를 기준으로 새로운 범위 내 기준 URI를 설정합니다.

7.5 이스케이프 시퀀스

SPARQL-RL 문서에서는 세 가지 형태의 이스케이프가 사용됩니다.

각 종류의 이스케이프 시퀀스를 사용할 수 있는 문맥
숫자
이스케이프
문자열
이스케이프
예약 문자
이스케이프
IRI, RDF 용어, PREFIX 또는 BASE 선언으로 사용됨 예 아니요 아니요
로컬 이름 아니요 아니요 예
문자열 예 예 아니요
참고

%-인코딩된 시퀀스는 IRI의 문자 범위에 속하며 로컬 이름에서는 명시적으로 허용됩니다. 이러한 시퀀스는 % 뒤에 두 개의 16진수 문자가 오는 형태이며, 동일한 세 문자 시퀀스를 나타냅니다. 이러한 시퀀스는 처리 중에 디코딩되지 않습니다. <http://a.example/%66oo-bar>로 작성된 용어는 IRI http://a.example/%66oo-bar를 나타내며 IRI http://a.example/foo-bar를 나타내지 않습니다. 접두사 PREFIX ex: <http://a.example/>와 함께 ex:%66oo-bar로 작성된 용어도 IRI http://a.example/%66oo-bar를 나타냅니다.

7.6 문법

여기에서 사용되는 EBNF는 XML 1.0 [EBNF-NOTATION]에 정의되어 있습니다.

참고 사항:

  1. 문법의 진입점은 RuleSet입니다.
  2. 키워드는 다음을 제외하고 대소문자를 구분하지 않습니다. 'a', 이 키워드는 대소문자를 구분합니다.
  3. 이스케이프 시퀀스 UCHAR 및 ECHAR는 대소문자를 구분합니다.
  4. 변수는 DATA 블록에서 허용되지 않습니다.
  5. 입력을 토큰화하고 문법 규칙을 선택할 때는 가장 긴 일치 항목을 선택합니다.
  6. SPARQL-RL 문법은 이름이 대문자로 표기된 규칙을 터미널로 사용할 경우 LL(1) 및 LALR(1)로 분류됩니다.
[1] RuleSet ::= RuleOrDataBlock
[2] RuleOrDataBlock ::= Prologue ( RuleOrData+ ( Prologue1 RuleOrData* )* )?
[3] RuleOrData ::= Rule | Data
[4] Prologue ::= Prologue1*
[5] Prologue1 ::= BaseDecl | PrefixDecl | VersionDecl | ImportsDecl
[6] BaseDecl ::= 'BASE' IRIREF
[7] PrefixDecl ::= 'PREFIX' PNAME_NS IRIREF
[8] VersionDecl ::= 'VERSION' VersionSpecifier
[9] VersionSpecifier ::= STRING_LITERAL1 | STRING_LITERAL2
[10] ImportsDecl ::= 'IMPORTS' iri
[11] Rule ::= 'RULE' iri? HeadTemplate 'WHERE' 'DATA'? BodyPattern
[12] Data ::= 'DATA' '{' DataTriplesBlock? '}'
[13] HeadTemplate ::= '{' HeadTemplateBlock? '}'
[14] BodyPattern ::= '{' BodyTriplesBlock? ( BodyNotTriples '.'? BodyTriplesBlock? )* '}'
[15] BodyNotTriples ::= Filter | Negation | Assignment | GroupAggregate
[16] Filter ::= 'FILTER' Constraint
[17] Constraint ::= BrackettedExpression | BuiltInCall | FunctionCall
[18] Negation ::= 'NOT' 'DATA'? '{' NegationPattern '}'
[19] NegationPattern ::= BodyTriplesBlock? ( NegationPatternNotTriples '.'? BodyTriplesBlock? )*
[20] NegationPatternNotTriples ::= Filter
[21] Assignment ::= 'SET' '(' Var ':=' Expression ')'
[22] GroupAggregate ::= 'GROUP' ( 'BY' ListVars )? '{' GroupPattern '}' ( ANON | '[' AggregationAssignment+ ']' )
[23] GroupPattern ::= BodyTriplesBlock? ( GroupPatternNotTriples '.'? BodyTriplesBlock? )*
[24] GroupPatternNotTriples ::= Filter | Assignment
[25] ListVars ::= Var+
[26] AggregationAssignment ::= Var ':=' AggregationFunction
[27] AggregationFunction ::= ( 'COUNT' '(' DISTINCT? VarOrStar ')' | 'MIN' '(' Var ')' | 'MAX' '(' Var ')' | 'SUM' '(' Var ')' )
[28] VarOrStar ::= Var | '*'
[29] DataTriplesBlock ::= TriplesSameSubjectData ( '.' DataTriplesBlock? )?
[30] TriplesSameSubjectData ::= RDFTermData PropertyListNotEmptyData | TriplesNodeData PropertyListData | ReifiedTripleBlockData
[31] PropertyListData ::= PropertyListNotEmptyData?
[32] PropertyListNotEmptyData ::= VerbData ObjectListData ( ';' ( VerbData ObjectListData )? )*
[33] VerbData ::= iri | 'a'
[34] ObjectListData ::= ObjectData ( ',' ObjectData )*
[35] ObjectData ::= GraphNodeData AnnotationData
[36] GraphNodeData ::= RDFTermData | TriplesNodeData | ReifiedTripleData
[37] TriplesNodeData ::= CollectionData | BlankNodePropertyListData
[38] BlankNodePropertyListData ::= '[' PropertyListNotEmptyData ']'
[39] CollectionData ::= '(' GraphNodeData+ ')'
[40] AnnotationData ::= ( ReifierData | AnnotationBlockData )*
[41] AnnotationBlockData ::= '{|' PropertyListNotEmptyData '|}'
[42] ReifierData ::= '~' ReifierIdData?
[43] ReifierIdData ::= iri | BlankNode
[44] ReifiedTripleBlockData ::= ReifiedTripleData PropertyListData
[45] ReifiedTripleData ::= '<<' ReifiedTripleSubjectData VerbData ReifiedTripleObjectData ReifierData? '>>'
[46] ReifiedTripleSubjectData ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTripleData | TripleTermData
[47] ReifiedTripleObjectData ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTripleData | TripleTermData
[48] TripleTermData ::= '<<(' TripleTermSubjectData VerbData TripleTermObjectData ')>>'
[49] TripleTermSubjectData ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTermData
[50] TripleTermObjectData ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTermData
[51] HeadTemplateBlock ::= TriplesBlockTemplate
[52] TriplesBlockTemplate ::= TriplesSameSubjectTemplate ( '.' TriplesBlockTemplate? )?
[53] TriplesSameSubjectTemplate ::= VarOrRDFTerm PropertyListNotEmptyTemplate | TriplesNodeTemplate PropertyListTemplate | ReifiedTripleBlockTemplate
[54] PropertyListTemplate ::= PropertyListNotEmptyTemplate?
[55] PropertyListNotEmptyTemplate ::= Verb ObjectListTemplate ( ';' ( Verb ObjectListTemplate )? )*
[56] ObjectListTemplate ::= ObjectTemplate ( ',' ObjectTemplate )*
[57] ObjectTemplate ::= GraphNodeTemplate AnnotationTemplate
[58] GraphNodeTemplate ::= VarOrRDFTerm | TriplesNodeTemplate | ReifiedTriple
[59] TriplesNodeTemplate ::= CollectionTemplate | BlankNodePropertyListTemplate
[60] BlankNodePropertyListTemplate ::= '[' PropertyListNotEmptyTemplate ']'
[61] CollectionTemplate ::= '(' GraphNodeTemplate+ ')'
[62] AnnotationTemplate ::= ( Reifier | AnnotationBlockTemplate )*
[63] AnnotationBlockTemplate ::= '{|' PropertyListNotEmptyTemplate '|}'
[64] ReifiedTripleBlockTemplate ::= ReifiedTriple PropertyListTemplate
[65] BodyTriplesBlock ::= TriplesBlockPattern
[66] TriplesBlockPattern ::= TriplesSameSubjectPattern ( '.' TriplesBlockPattern? )?
[67] ReifiedTripleBlockPattern ::= ReifiedTriple PropertyListPattern
[68] TriplesSameSubjectPattern ::= VarOrRDFTerm PropertyListNotEmptyPattern | TriplesNodePattern PropertyListPattern | ReifiedTripleBlockPattern
[69] PropertyListPattern ::= PropertyListNotEmptyPattern?
[70] PropertyListNotEmptyPattern ::= ( VerbPath | Var ) ObjectListPattern ( ';' ( ( VerbPath | Var ) ObjectListPattern )? )*
[71] ObjectListPattern ::= ObjectPattern ( ',' ObjectPattern )*
[72] ObjectPattern ::= GraphNodePattern AnnotationPattern
[73] TriplesNodePattern ::= CollectionPattern | BlankNodePropertyListPattern
[74] BlankNodePropertyListPattern ::= '[' PropertyListNotEmptyPattern ']'
[75] CollectionPattern ::= '(' GraphNodePattern+ ')'
[76] AnnotationPattern ::= ( Reifier | AnnotationBlockPattern )*
[77] AnnotationBlockPattern ::= '{|' PropertyListNotEmptyPattern '|}'
[78] GraphNodePattern ::= VarOrRDFTerm | TriplesNodePattern | ReifiedTriple
[79] Reifier ::= '~' ReifierId?
[80] ReifierId ::= Var | iri | BlankNode
[81] ReifiedTriple ::= '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
[82] ReifiedTripleSubject ::= Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
[83] ReifiedTripleObject ::= Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
[84] TripleTerm ::= '<<(' TripleTermSubject Verb TripleTermObject ')>>'
[85] TripleTermSubject ::= Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
[86] TripleTermObject ::= Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
[87] Verb ::= VarOrIri | 'a'
[88] VerbPath ::= Path
[89] Path ::= PathSequence
[90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
[91] PathEltOrInverse ::= PathElt | '^' PathElt
[92] PathElt ::= ( iri | 'a' | '(' Path ')' )
[93] RDFTermData ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTermData
[94] VarOrRDFTerm ::= Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTerm
[95] VarOrIri ::= Var | iri
[96] Var ::= VAR1 | VAR2
[97] RDFLiteral ::= String ( LANG_DIR | '^^' iri )?
[98] NumericLiteral ::= NumericLiteralUnsigned | NumericLiteralPositive | NumericLiteralNegative
[99] NumericLiteralUnsigned ::= INTEGER | DECIMAL | DOUBLE
[100] NumericLiteralPositive ::= INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
[101] NumericLiteralNegative ::= INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
[102] BooleanLiteral ::= 'true' | 'false'
[103] String ::= STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
[104] iri ::= IRIREF | PrefixedName
[105] PrefixedName ::= PNAME_LN | PNAME_NS
[106] BlankNode ::= BLANK_NODE_LABEL | ANON
[107] Expression ::= ConditionalOrExpression
[108] ConditionalOrExpression ::= ConditionalAndExpression ( '||' ConditionalAndExpression )*
[109] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
[110] ValueLogical ::= RelationalExpression
[111] RelationalExpression ::= NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
[112] NumericExpression ::= AdditiveExpression
[113] AdditiveExpression ::= MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
[114] MultiplicativeExpression ::= UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
[115] UnaryExpression ::= '!' PrimaryExpression
| '+' PrimaryExpression
| '-' PrimaryExpression
| PrimaryExpression
[116] PrimaryExpression ::= BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[117] FunctionCall ::= iri ArgList
[118] ArgList ::= NIL | '(' Expression ( ',' Expression )* ')'
[119] ExpressionList ::= NIL | '(' Expression ( ',' Expression )* ')'
[120] iriOrFunction ::= iri ArgList?
[121] ExprTripleTerm ::= '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
[122] ExprTripleTermSubject ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var
[123] ExprTripleTermObject ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[124] BrackettedExpression ::= '(' Expression ')'
[125] BuiltInCall ::= 'STR' '(' Expression ')'
| 'LANG' '(' Expression ')'
| 'LANGMATCHES' '(' Expression ',' Expression ')'
| 'LANGDIR' '(' Expression ')'
| 'DATATYPE' '(' Expression ')'
| 'IRI' '(' Expression ')'
| 'URI' '(' Expression ')'
| 'BNODE' ( '(' Expression ')' | NIL )
| 'ABS' '(' Expression ')'
| 'CEIL' '(' Expression ')'
| 'FLOOR' '(' Expression ')'
| 'ROUND' '(' Expression ')'
| 'CONCAT' ExpressionList
| 'SUBSTR' '(' Expression ',' Expression ( ',' Expression )? ')'
| 'STRLEN' '(' Expression ')'
| 'REPLACE' '(' Expression ',' Expression ',' Expression ( ',' Expression )? ')'
| 'UCASE' '(' Expression ')'
| 'LCASE' '(' Expression ')'
| 'ENCODE_FOR_URI' '(' Expression ')'
| 'CONTAINS' '(' Expression ',' Expression ')'
| 'STRSTARTS' '(' Expression ',' Expression ')'
| 'STRENDS' '(' Expression ',' Expression ')'
| 'STRBEFORE' '(' Expression ',' Expression ')'
| 'STRAFTER' '(' Expression ',' Expression ')'
| 'YEAR' '(' Expression ')'
| 'MONTH' '(' Expression ')'
| 'DAY' '(' Expression ')'
| 'HOURS' '(' Expression ')'
| 'MINUTES' '(' Expression ')'
| 'SECONDS' '(' Expression ')'
| 'TIMEZONE' '(' Expression ')'
| 'TZ' '(' Expression ')'
| 'NOW' NIL
| 'UUID' NIL
| 'STRUUID' NIL
| 'IF' '(' Expression ',' Expression ',' Expression ')'
| 'STRLANG' '(' Expression ',' Expression ')'
| 'STRLANGDIR' '(' Expression ',' Expression ',' Expression ')'
| 'STRDT' '(' Expression ',' Expression ')'
| 'sameTerm' '(' Expression ',' Expression ')'
| 'isIRI' '(' Expression ')'
| 'isURI' '(' Expression ')'
| 'isBLANK' '(' Expression ')'
| 'isLITERAL' '(' Expression ')'
| 'isNUMERIC' '(' Expression ')'
| 'hasLANG' '(' Expression ')'
| 'hasLANGDIR' '(' Expression ')'
| 'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')'
| 'isTRIPLE' '(' Expression ')'
| 'TRIPLE' '(' Expression ',' Expression ',' Expression ')'
| 'SUBJECT' '(' Expression ')'
| 'PREDICATE' '(' Expression ')'
| 'OBJECT' '(' Expression ')'

터미널 생성 규칙:

[126] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR )* '>'
[127] PNAME_NS ::= PN_PREFIX? ':'
[128] PNAME_LN ::= PNAME_NS PN_LOCAL
[129] BLANK_NODE_LABEL ::= '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
[130] VAR1 ::= '?' VARNAME
[131] VAR2 ::= '$' VARNAME
[132] LANG_DIR ::= '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ('--' [a-zA-Z]+)?
[133] INTEGER ::= [0-9]+
[134] DECIMAL ::= [0-9]* '.' [0-9]+
[135] DOUBLE ::= ( ([0-9]+ ('.'[0-9]*)? ) | ( '.' ([0-9])+ ) ) [eE][+-]?[0-9]+
[136] INTEGER_POSITIVE ::= '+' INTEGER
[137] DECIMAL_POSITIVE ::= '+' DECIMAL
[138] DOUBLE_POSITIVE ::= '+' DOUBLE
[139] INTEGER_NEGATIVE ::= '-' INTEGER
[140] DECIMAL_NEGATIVE ::= '-' DECIMAL
[141] DOUBLE_NEGATIVE ::= '-' DOUBLE
[142] STRING_LITERAL1 ::= "'" ( ([^#x27#x5C#xA#xD]) | ECHAR | UCHAR )* "'"
[143] STRING_LITERAL2 ::= '"' ( ([^#x22#x5C#xA#xD]) | ECHAR | UCHAR )* '"'
[144] STRING_LITERAL_LONG1 ::= "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR | UCHAR ) )* "'''"
[145] STRING_LITERAL_LONG2 ::= '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR | UCHAR ) )* '"""'
[146] ECHAR ::= '\' [tbnrf\"']
[147] UCHAR ::= ('\u' HEX HEX HEX HEX) | ('\U' HEX HEX HEX HEX HEX HEX HEX HEX)
[148] NIL ::= '(' WS* ')'
[149] WS ::= #x20 | #x9 | #xD | #xA
[150] ANON ::= '[' WS* ']'
[151] PN_CHARS_BASE ::= [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[152] PN_CHARS_U ::= PN_CHARS_BASE | '_'
[153] VARNAME ::= ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
[154] PN_CHARS ::= PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
[155] PN_PREFIX ::= PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)?
[156] PN_LOCAL ::= (PN_CHARS_U | ':' | [0-9] | PLX ) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX) )?
[157] PLX ::= PERCENT | PN_LOCAL_ESC
[158] PERCENT ::= '%' HEX HEX
[159] HEX ::= [0-9] | [A-F] | [a-f]
[160] PN_LOCAL_ESC ::= '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%' )

이 문법의 텍스트 버전은 다음 파일에서 확인할 수 있습니다: sparql-rl-grammar.bnf.

7.7 선택된 터미널 리터럴 문자열

이 문서에서는 일부 터미널 리터럴 문자열을 사용합니다. [EBNF-NOTATION]. 이러한 문자열에 사용된 유니코드 코드 포인트를 명확히 하기 위해 다음 표에서는 해당 터미널 리터럴 문자열에 사용된 구체적인 문자를 설명합니다.

코드 글리프 설명
U+000A LF 줄 바꿈
U+000D CR 캐리지 리턴
U+0023 # 숫자 기호
U+0025 % 퍼센트 기호
U+005C \ 백슬래시

A. SPARQL-RL에서 SPARQL로의 변환

이슈 1303: SRL: SRL을 SPARQL 질의로 변환하는 과정을 보여주는 알고리즘 제공 SPARQL-RL

SPARQL-RL을 SPARQL 질의로 변환하는 과정을 보여주는 알고리즘을 제공하세요.

B. 가져오기 알고리즘 예제

이 절은 규범적이지 않습니다.

다음 알고리즘은 참조된 모든 문서를 재귀적으로 방문하여 IMPORTS 문을 해석하는 한 가지 방법을 보여 줍니다.

두 규칙 집합 RS1과 RS2의 규칙 집합 병합은 다음과 같이 정의되는 규칙 집합 MR을 생성합니다.

let RS be a rule set
let V = {}
if RS has a location:
    V = { location of RS }
endif

define ruleSetMerge(rule set RS1, rule set RS2):
    let MR be a rule set
    MR.rules = RS1.rules ∪ RS2.rules
    MR.data = rdf_merge(RS1.data, RS2.data)
    MR.imports = {}
    the result is MR
enddefine

define imports(rule set RS):
    let RS2 be a rule set formed from RS.rules and RS.data
    foreach URL x in RS.imports:
        if x ∉ V:
            V = V ∪ { x }
            read rule set RS3 from URL x
            RS2 = ruleSetMerge(RS2, imports(RS3))
        endif
    endfor
    the result is RS2
enddefine

result is imports(RS)

여기서 rdf_merge는 RDF 병합 연산입니다.

C. 인터넷 미디어 유형 및 파일 확장자

SPARQL-RL의 인터넷 미디어 유형(이전에는 MIME 유형이라고 함)은 "application/sparql-rl"입니다.

다음 정보는 검토, 승인 및 IANA 등록을 위해 인터넷 엔지니어링 운영 그룹(IESG)에 제출되었습니다.

유형 이름:
application
하위 유형 이름:
sparql-rl
필수 매개변수:
없음
선택적 매개변수:
version
이 매개변수는 선택 사항입니다. 지정된 경우 허용되는 version 값은 버전 레이블에 정의되어 있습니다.
profile
이 매개변수는 선택 사항이며 추가 정보를 포함하는 데 사용됩니다. 프로필에 대한 지식 없이 처리하더라도 리소스 표현의 의미를 변경하지 않습니다. profile 매개변수의 값은 공백으로 구분된 URI의 비어 있지 않은 목록입니다. 자세한 정보와 배경 설명은 [RFC6906]을 참조하시기 바랍니다.
인코딩 고려 사항:
SPARQL-RL의 구문은 유니코드 코드 포인트로 표현됩니다. [UNICODE]. 인코딩은 항상 UTF-8입니다 [RFC3629].
유니코드 코드 포인트는 \uXXXX(U+0부터 U+FFFF까지) 또는 \UXXXXXXXX 구문(U+10000 이상)을 사용하여 표현할 수도 있으며, 여기서 X는 16진수 숫자 [0-9A-Fa-f]이고, U+D800부터 U+DFFF까지의 서로게이트 코드 포인트는 제외됩니다.
보안 고려 사항:
D. 보안 고려 사항과 UTF-8, ISO 10646의 변환 형식 [RFC3629]의 7절, 보안 고려 사항을 참조하시기 바랍니다.
상호 운용성 고려 사항:
알려진 상호 운용성 문제는 없습니다.
발행된 규격:
이 규격입니다.
추가 정보:
매직 넘버:
SPARQL-RL 파일에는 문서의 시작 부분 근처에 'PREFIX' 문자열이 포함될 수 있으며 (대소문자는 구분하지 않습니다), 해당 문자열은 문서의 앞부분에 위치할 수 있습니다.
파일 확장자:
".srl"
기본 URI:
SPARQL-RL의 'BASE <IRIref>' 용어는 언어에서 IRIref를 해석하는 데 사용되는 현재 기본 URI를 변경할 수 있습니다.
추가 정보 문의 이메일 주소:
Data Shapes 워킹 그룹 <public-shacl@w3.org>
사용 목적:
COMMON
사용 제한:
없음
작성자/변경 관리 주체:
SPARQL-RL 규격은 월드 와이드 웹 컨소시엄의 Data Shapes 워킹 그룹이 작성한 결과물입니다. W3C는 이 규격의 변경을 관리할 권한을 보유합니다.

D. 보안 고려 사항

이 절은 규범적이지 않습니다.

SPARQL-RL 문서에는 IMPORTS 문이 포함될 수 있습니다. 이 문은 다른 SPARQL-RL 문서를 참조하고 그 내용을 현재 문서로 가져옵니다. 가져온 문서 자체에 IMPORTS 문이 포함되어 있으면, 해당 문서들도 가져옵니다.

규칙 집합을 모듈화하는 데 유용하지만, IMPORTS 문을 사용하면 보안 위험이 발생할 수 있습니다. 위험에는 다음과 같은 경우가 포함되지만, 이에 국한되지는 않습니다. 규칙 집합이 평가 중 악의적으로든 우발적으로든 과도한 연산을 유발하는 경우, HTTP 요청이 가로채어져 다른 문서가 반환되는 경우가 있으며, 여기에는 오래된 사본이 반환되는 경우도 포함됩니다.

SPARQL-RL 규칙 집합을 RDF 그래프에 적용하면 상당한 연산과 메모리 사용이 발생할 수 있으며, 이를 악용하여 서비스 거부를 유발할 수 있습니다. 애플리케이션은 SPARQL-RL 규칙 집합을 적용할 때 발생할 수 있는 연산량과 메모리 사용량을 제한하도록 주의해야 합니다.

SPARQL-RL 구문은 UTF-8 [RFC3629]로 인코딩되며, 문자열 데이터에서 이스케이프하지 않은 제어 문자의 사용을 허용합니다. 이 명세는 이러한 내용을 최종 사용자에게 직접 노출하지 않지만, 사용자 에이전트를 통해 표시될 수 있으며, 이러한 문자로 인해 표시된 텍스트가 오해를 일으킬 수 있습니다.

SPARQL-RL은 임의의 애플리케이션 데이터를 처리하고 생성하는 데 사용할 수 있으며, 보안 고려 사항은 사용 분야에 따라 달라집니다. 텍스트에 적용할 수 있는 보안 도구와 프로토콜 (예: PGP 암호화, 체크섬 검증, 비밀번호로 보호된 압축)은 SPARQL-RL 문서에도 사용할 수 있습니다. SPARQL-RL 규칙 집합 평가 결과에 포함된 정보의 민감도를 반영하도록 보안/개인정보 보호 프로토콜을 적용해야 합니다.

SPARQL-RL의 보안 고려 사항에는 다음에 대한 보안 고려 사항도 포함됩니다: RDF 데이터 및 다음과 같은 형식: RDF Turtle.

E. 개인정보 보호 고려 사항

이 절은 규범적이지 않습니다.

SPARQL-RL 문서에는 추가적인 애플리케이션 데이터가 포함될 수 있으며, 여기에는 개인 식별 정보(PII)를 표현한 내용이나 민감한 것으로 간주될 수 있는 기타 정보가 포함될 수 있습니다. 이러한 정보가 포함된 규칙 집합을 게시하는 작성자는 해당 정보를 게시할 필요성과 용도를 신중하게 고려하고, 데이터가 사용되거나 잠재적으로 공개될 것으로 예상되는 지역에 적용되는 규정(예: GDPR, CCPA, 기타 규정)도 고려해야 하며, 특히 데이터 접근에 승인 조치가 필요한지 검토하는 것이 좋습니다.

F. 감사의 말

이 절은 규범적이지 않습니다.

다음 분들은 Data Shapes 작업 그룹의 규칙 태스크 포스에서 SPARQL-RL 개발에 기여했습니다: Robert David, David Habgood, Livio Robaldo, Ognjen Savkovic, Andy Seaborne, Simon Steyskal 및 Ted Thibodeau Jr.

Data Shapes 워킹 그룹의 구성원에는 @@가 포함되었습니다.

G. 색인

G.1 이 규격에서 정의한 용어

G.2 참조를 통해 정의된 용어

H. 문제 요약

I. 참고 문헌

I.1 규범적 참고 문헌

[EBNF-NOTATION]
EBNF 표기법. Tim Bray; Jean Paoli; Michael Sperberg-McQueen; Eve Maler; François Yergeau 외. W3C. W3C 권고안. URL: https://www.w3.org/TR/xml/#sec-notation
[I18N-GLOSSARY]
국제화 용어집. Richard Ishida; Addison Phillips. W3C. 2024년 10월 17일. W3C 워킹 그룹 참고 문서. URL: https://www.w3.org/TR/i18n-glossary/
[RDF12-CONCEPTS]
RDF 1.2 개념 및 추상 데이터 모델. Andy Seaborne; Gregg Kellogg; Olaf Hartig; Pierre-Antoine Champin. W3C. 2026년 4월 7일. W3C 후보 권고안. URL: https://www.w3.org/TR/rdf12-concepts/
[RDF12-TURTLE]
RDF 1.2 Turtle. Gregg Kellogg; Andy Seaborne; Dominik Tomaszuk. W3C. 2026년 10월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/rdf12-turtle/
[RFC2119]
요구사항 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc2119/
[RFC3629]
UTF-8, ISO 10646의 변환 형식. F. Yergeau. IETF. 2003년 11월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc3629/
[RFC3986]
통일 자원 식별자(URI): 일반 구문. T. Berners-Lee; R. Fielding; L. Masinter. IETF. 2005년 1월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc3986/
[RFC3987]
국제화 자원 식별자 (IRI). M. Duerst; M. Suignard. IETF. 2005년 1월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc3987/
[RFC6906]
'profile' 링크 관계 유형. E. Wilde. IETF. 2013년 3월. 정보 제공용. URL: https://www.rfc-editor.org/info/rfc6906/
[RFC8174]
RFC 2119 핵심 단어의 대문자와 소문자 구분에 관한 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[SPARQL12-QUERY]
SPARQL 1.2 쿼리 언어. Olaf Hartig; Andy Seaborne; Ruben Taelman; Gregory Williams; Thomas Pellissier Tanon. W3C. 2026년 10월 11일. W3C 작업 초안. URL: https://www.w3.org/TR/sparql12-query/
[UNICODE]
유니코드 표준. Unicode Consortium. URL: https://www.unicode.org/versions/latest/

I.2 정보 제공용 참고 문헌

[RDF12-SEMANTICS]
RDF 1.2 의미론. Peter Patel-Schneider; Dörthe Arndt; Enrico Franconi. W3C. 2026년 9월 24일. CRD. URL: https://www.w3.org/TR/rdf12-semantics/