Files
cleveragents-core/features/postgresql_analyzer.feature
T
hamza.khyari 13618fb8d5
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 15s
CI / quality (pull_request) Successful in 17s
CI / security (pull_request) Successful in 33s
CI / typecheck (pull_request) Successful in 47s
CI / unit_tests (pull_request) Successful in 2m35s
CI / integration_tests (pull_request) Successful in 3m13s
CI / docker (pull_request) Successful in 39s
CI / coverage (pull_request) Successful in 4m26s
CI / benchmark-regression (pull_request) Has been cancelled
fix(acms): address PR #611 review findings F1-F7
- F1/F2 [P1]: Split postgresql_analyzer.py (695→310 lines) by
  extracting regex patterns, URI builders, and parsing functions
  into _postgresql_helpers.py (440 lines).  Split
  domain_analyzers.feature (605→217 lines) into separate
  postgresql_analyzer.feature (201) and
  docker_compose_analyzer.feature (199).

- F3 [P1]: Fix _extract_body and _split_entries to track
  single-quoted SQL string literals so parentheses inside
  DEFAULT/CHECK values (e.g. 'func(x)') do not corrupt depth
  counting.  Added regression scenarios.

- F4 [P2]: Remove prohibited `# type: ignore[arg-type]` by
  adding a static protocol assertion for _DuplicatePyAnalyzer.

- F5 [P2]: Add 1 MiB size guard before yaml.safe_load in
  DockerComposeAnalyzer to mitigate billion-laughs alias
  expansion attacks.

- F6 [P2]: Fix quoted-keyword column names (e.g. "primary")
  being silently dropped by checking raw_first.startswith('"')
  before keyword filtering.  Added regression scenario.

- F7 [P2]: Out-of-scope file changes resolved by rebase onto
  master (changes already merged via other PRs).

All nox gates pass: lint (0 errors), typecheck (0 errors),
security_scan, behave (57 scenarios, 211 steps, 0 failures).
2026-03-06 20:07:03 +00:00

202 lines
7.7 KiB
Gherkin

@phase2 @acms @analyzer @postgresql_analyzer
Feature: PostgreSQLAnalyzer
As a CleverAgents developer
I want a PostgreSQL DDL analyzer that produces UKO triples from SQL files
So that the ACMS can index database schemas into the UKO knowledge graph
Scenario: Analyze CREATE TABLE
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE users (
id SERIAL,
name VARCHAR(100)
);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:Table"
And the triples should include predicate "rdf:type" with object_uri "uko-data:Column"
And the triples should include predicate "uko-data:dataType"
Scenario: Analyze table with NOT NULL and PRIMARY KEY
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL
);
"""
Then the triples should include predicate "uko-data:isPrimaryKey" with object_value "true"
And the triples should include predicate "uko-data:isNullable" with object_value "false"
Scenario: Analyze FOREIGN KEY
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:ForeignKey"
And the triples should include predicate "uko-data:foreignKeyTo"
Scenario: Analyze CREATE VIEW
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE VIEW active_users AS
SELECT * FROM users WHERE active = true;
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:View"
And the triples should include predicate "rdfs:label" with object_value "active_users"
Scenario: Analyze CREATE SCHEMA
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE SCHEMA IF NOT EXISTS app;
CREATE TABLE app.users (
id SERIAL PRIMARY KEY
);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:Schema"
And the triples should include predicate "rdfs:label" with object_value "app"
And the triples should include predicate "uko:contains" linking subject "schema" to object "users"
Scenario: Analyze schema-qualified table includes schema in column URIs
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE myschema.items (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:Table"
And the triples should include predicate "rdf:type" with object_uri "uko-data:Column"
And the triples should include predicate "uko:contains" linking subject "myschema" to object "items"
Scenario: Analyze table with composite PRIMARY KEY
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE user_roles (
user_id INTEGER NOT NULL,
role_id INTEGER NOT NULL,
PRIMARY KEY (user_id, role_id)
);
"""
Then the triples should include predicate "uko-data:isPrimaryKey" with object_value "true"
Scenario: Analyze empty SQL content raises ValueError
Given a PostgreSQLAnalyzer analyzer
Then analyzing empty content with this analyzer should raise ValueError
Scenario: Analyze whitespace-only SQL content raises ValueError
Given a PostgreSQLAnalyzer analyzer
Then analyzing whitespace-only content with this analyzer should raise ValueError
Scenario: Analyze SQL with empty resource_uri raises ValueError
Given a PostgreSQLAnalyzer analyzer
Then analyzing content with empty resource_uri should raise ValueError
Scenario: Analyze SQL with comments does not produce phantom triples
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
-- CREATE TABLE phantom (id INT);
/* CREATE VIEW ghost AS SELECT 1; */
CREATE TABLE real_table (id SERIAL PRIMARY KEY);
"""
Then the triples should include predicate "rdfs:label" with object_value "real_table"
And the triples should not include predicate "rdfs:label" with object_value "phantom"
And the triples should not include predicate "rdfs:label" with object_value "ghost"
Scenario: Analyze multi-column FOREIGN KEY
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE user_roles (
user_id INTEGER NOT NULL,
role_id INTEGER NOT NULL,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id, role_id) REFERENCES lookup(uid, rid)
);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:ForeignKey"
And the triples should include predicate "uko-data:foreignKeyTo" with object_uri containing "uid"
And the triples should include predicate "uko-data:foreignKeyTo" with object_uri containing "rid"
Scenario: Analyze CREATE VIEW captures viewDefinition
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE VIEW active_users AS
SELECT id, name FROM users WHERE active = true;
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:View"
And the triples should include predicate "uko-data:viewDefinition"
Scenario: Duplicate CREATE TABLE is deduplicated
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE items (id SERIAL);
CREATE TABLE items (id SERIAL, name TEXT);
"""
Then the triples should include predicate "rdf:type" with object_uri "uko-data:Table"
And the number of Table type triples should be 1
Scenario: Analyze invalid SQL returns empty list
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
THIS IS NOT VALID SQL AT ALL;
JUST RANDOM TEXT HERE;
"""
Then no triples should be returned
# -- Regression tests for F3 (string-literal parentheses) --
Scenario: DEFAULT with parentheses in string literal does not truncate columns
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE config (
col1 TEXT DEFAULT 'hello(world)',
col2 INTEGER
);
"""
Then the triples should include predicate "rdfs:label" with object_value "col1"
And the triples should include predicate "rdfs:label" with object_value "col2"
Scenario: CHECK constraint with string containing parentheses
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE validated (
status TEXT CHECK (status IN ('active(1)', 'inactive(0)')),
amount INTEGER
);
"""
Then the triples should include predicate "rdfs:label" with object_value "status"
And the triples should include predicate "rdfs:label" with object_value "amount"
# -- Regression test for F6 (quoted keyword column names) --
Scenario: Quoted keyword column names are not silently dropped
Given a PostgreSQLAnalyzer analyzer
When I analyze the SQL content:
"""
CREATE TABLE reserved_words (
"primary" INTEGER,
"check" VARCHAR(50),
normal_col TEXT
);
"""
Then the triples should include predicate "rdfs:label" with object_value "primary"
And the triples should include predicate "rdfs:label" with object_value "check"
And the triples should include predicate "rdfs:label" with object_value "normal_col"