@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"