Metadata-Version: 2.4
Name: relational-schema-analyzer
Version: 0.1.0
Summary: Analyze a relational database schema into a conceptual model (OWL-capable) with mapping back to the source schema.
Project-URL: Homepage, https://github.com/ArthurKeen/relational-schema-analyzer
Project-URL: Repository, https://github.com/ArthurKeen/relational-schema-analyzer
Project-URL: Issues, https://github.com/ArthurKeen/relational-schema-analyzer/issues
Author: Arthur Keen
License: Apache-2.0
License-File: LICENSE
Keywords: conceptual-model,mysql,ontology,owl,postgres,relational,schema,snowflake
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: jsonschema>=4
Requires-Dist: pydantic>=2
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.30; extra == 'anthropic'
Provides-Extra: csv
Requires-Dist: polars>=0.20; extra == 'csv'
Provides-Extra: databricks
Requires-Dist: databricks-sql-connector>=3; extra == 'databricks'
Provides-Extra: dev
Requires-Dist: duckdb>=1; extra == 'dev'
Requires-Dist: fakesnow>=0.11; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: snowflake-connector-python>=3; extra == 'dev'
Provides-Extra: duckdb
Requires-Dist: duckdb>=1; extra == 'duckdb'
Provides-Extra: mcp
Requires-Dist: mcp>=1; extra == 'mcp'
Provides-Extra: mysql
Requires-Dist: pymysql>=1; extra == 'mysql'
Provides-Extra: openai
Requires-Dist: openai>=1; extra == 'openai'
Provides-Extra: openrouter
Requires-Dist: httpx>=0.27; extra == 'openrouter'
Provides-Extra: owl
Requires-Dist: rdflib>=7; extra == 'owl'
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3; extra == 'postgres'
Provides-Extra: snowflake
Requires-Dist: snowflake-connector-python>=3; extra == 'snowflake'
Provides-Extra: sqlserver
Requires-Dist: pymssql>=2; extra == 'sqlserver'
Description-Content-Type: text/markdown

# relational-schema-analyzer

Analyze a **relational database schema** and produce a canonical **conceptual model**
(entities / relationships / properties), a **conceptual → physical mapping** back to the
source relational schema, and **metadata** (confidence, fingerprints, patterns). Optional
exports include **OWL** (Turtle / JSON-LD) for ontology pipelines.

This library is the relational analogue of
[`arangodb-schema-analyzer`](https://pypi.org/project/arangodb-schema-analyzer/) and
emits the **same tool-contract bundle shape** so that downstream consumers
(`arango-ontoextract`, transpilers, and ETL tools such as `r2g`) can treat relational and
ArangoDB sources interchangeably.

```text
PostgreSQL / MySQL / SQL Server / Snowflake / CSV
        │
        ▼  introspect (live catalog views, not DDL parsing)
   Physical Schema  (tables, columns, PKs, FKs, types)
        │
        ▼  infer (deterministic baseline + optional LLM refinement)
   { conceptualSchema, physicalMapping, metadata }   ← canonical JSON bundle
        │
        ├──► OWL Turtle / JSON-LD       (arango-ontoextract, ontology tooling)
        ├──► relational physical view   (SQL-native query tooling, future)
        └──► consumed by r2g            (drives ArangoDB MappingConfig generation)
```

## Status

Early development. **Phases 0–3 implemented**: the physical core (connectors, types,
FK inference) is extracted from `r2g`; the deterministic conceptual baseline emits a
contract-valid `{conceptualSchema, physicalMapping, metadata}` bundle with no LLM; and
OWL (Turtle / JSON-LD) exports + a CLI are in place. Next: optional LLM refinement
(Phase 4) and ecosystem integration (Phase 5). See:

- [`docs/DESIGN.md`](docs/DESIGN.md) — architecture, data model, tool contract, OWL mapping
- [`docs/IMPLEMENTATION-PLAN.md`](docs/IMPLEMENTATION-PLAN.md) — phased delivery plan & extraction inventory

```python
from relational_schema_analyzer import (
    create_connector, RelationalSchemaAnalyzer, export_owl_turtle,
)

physical = create_connector("postgresql", url, schema_name="public").get_schema()
analysis = RelationalSchemaAnalyzer().analyze(physical)   # baseline, no LLM
bundle = analysis.to_bundle()    # {conceptualSchema, physicalMapping, metadata}
ttl = export_owl_turtle(analysis)

# Optional LLM refinement (additive; falls back to baseline on any error):
refined = RelationalSchemaAnalyzer(
    llm_provider="openai",           # or "anthropic" / "openrouter" / a provider object
).analyze(physical)                  # better names + embed/n-ary hints
```

```bash
relational-schema-analyzer snapshot --source postgresql --url "$DSN" -o physical.json
relational-schema-analyzer analyze  --from-snapshot physical.json --pretty
relational-schema-analyzer owl      --from-snapshot physical.json --format turtle -o schema.ttl
```

Sources: `postgresql`, `mysql`, `sqlserver`, `snowflake`, `duckdb`, `databricks`, `csv`.

**MCP server** (optional, `pip install 'relational-schema-analyzer[mcp]'`) exposes the same
`snapshot` / `analyze` / `owl` operations over the v1 tool contract:

```bash
relational-schema-analyzer-mcp                                   # stdio (local IDE)
relational-schema-analyzer-mcp --transport sse --host 0.0.0.0 --port 8000   # remote (set RSA_MCP_TOKEN)
```

## Why this exists

Most of the relational **introspection** layer already exists and is battle-tested inside
the `r2g` (relational-to-graph) project, but it is welded to ArangoDB ETL and cannot be
reused elsewhere. This repo extracts that core into a paradigm-neutral library and adds the
**conceptual / OWL layer** that `r2g` never had, conforming to the contract the ArangoDB
analyzer already publishes.

## License

Apache-2.0 — matching the surrounding Arango ecosystem libraries
(`arangodb-schema-analyzer`, `r2g`). See [`LICENSE`](LICENSE).
