databrickslabs / databrickslabs/ontobricks

SWRL rules with builtin atoms (e.g. swrlb:greaterThanOrEqual) silently infer zero triples — four stacked defects, including a Postgres syntax error on the default Lakebase backend

Open
#171 1 comment 0 reactions 1 assignee View on GitHub

@benoitcayladbx is already working on this.

Since Sep 17, 2026.

bug CLA signing needed
Dominant language
Python
Stars
377
Forks
69
Avg merge
7h 42m
Merged PRs (30d)
5

Description

Summary

Attribute-conditioned SWRL rules created in the graphical Business Rules editor never produce inferred triples. The run reports success ("N inferred, 0 errors" — the N being unrelated OWL RL schema entailments), so the failure is silent. We traced it to four independent defects, each fatal on its own, and verified fixes end-to-end.

Reproduction

v0.8.0, any domain with a datatype attribute. Editor-generated rule:

Sailing(?x) ∧ nights(?x, ?nights) ∧ swrlb:greaterThanOrEqual(?nights, 10) → LongSailing(?x)

Run Inference. Expected: one LongSailing type triple per matching instance. Actual: 0, no error surfaced.

A standalone repro script (safe-rule validation, a 3-row fixture whose correct answer is 2, generated-SQL printing) is included in the linked PR as scripts/repro_swrl_builtin_defects.py.

The four defects
  1. SWRLBuiltinRegistry never matches the editor's own output. Registry keys are bare lowercase names; the editor emits the standard swrlb: prefix. is_builtin("swrlb:greaterThanOrEqual") returns False, so the builtin degrades into a triple-pattern atom.
  2. SWRLEngine._build_uri_map skips datatype properties. Object properties are normalised to the data namespace (<base>/prop) to match the predicates the R2RML sync writes, but class dataProperties never enter the map, so nights(?x, ?n) resolves to the ontology # URI and matches nothing.
  3. build_inference_sql and build_materialization_sql partition atoms by arity only. A builtin atom becomes a JOIN on a predicate like <base>#greaterThanOrEqual, which cannot exist. (build_violation_sql already partitions builtins correctly and routes them through _build_builtin_filters — the inference/materialization builders never got that wiring.)
  4. Builtin sql_templates are Databricks-dialect only. TRY_CAST(... AS DOUBLE) — Postgres has neither TRY_CAST nor bare DOUBLE, and LakebaseBase.get_query_translator() returns the generic translator with no dialect. So even with 1–3 fixed, every builtin filter is a syntax error on the default (Lakebase) backend.

Generated SQL before the fix (defects visible):

JOIN <t> a2 ON a2.predicate = 'https://.../PCP#nights' ...            -- defect 2 (# vs /)
JOIN <t> a3 ON a3.predicate = 'https://.../PCP#greaterThanOrEqual' ...-- defects 1+3
Verification
  • Pristine v0.8.0 + 3-row fixture (expected 2): 0 inferred.
  • Fixed branch + fixture: 2/2.
  • Fixed branch + a real 2,846-instance graph, expected count computed independently from the source table before any fix: 263/263.
  • Existing test suite: the 373 swrl/reasoning/builtin/lakebase unit tests pass unchanged.
Why the existing suite did not catch this

Not a reproach — the gap pattern is worth naming so the fix can close it:
execute_rules is unit-tested against a MagicMock store, so generated SQL
never executes; build_inference_sql is asserted once in the whole suite
(empty params → None, in a Neo4j test); parser tests use only bare builtin
names, never the swrlb: prefix the editor emits; and
test_greater_than_uses_try_cast pins the Databricks-only template as
expected behaviour, which enshrines defect 4. The attached PR adds a
regression file covering all four defects at the translator/registry/engine
level, plus the standalone end-to-end harness.

Environment

v0.8.0 tag, Lakebase (Postgres) graph backend, SQL inference path.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.