202 lines
7.7 KiB
Gherkin
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"
|