{"_id":"@ayatkevich/slon","name":"@ayatkevich/slon","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"type":"module","private":false,"name":"@ayatkevich/slon","version":"0.2.0","author":{"name":"Alex Yatkevich"},"license":"MIT","main":"src/index.js","types":"src/index.d.ts","devDependencies":{"@electric-sql/pglite":"0.2.8","@jest/globals":"29.7.0","jest":"29.7.0"},"wallaby":{"runMode":"onsave","env":{"params":{"runner":"--experimental-vm-modules"}},"hints":{"allowIgnoringCoverageInTests":true}},"prettier":{"printWidth":100},"_id":"@ayatkevich/slon@0.2.0","gitHead":"52cf4e358d634f91456259410dc1cffa82e1f91b","description":"## Introduction","_nodeVersion":"22.9.0","_npmVersion":"10.8.3","dist":{"integrity":"sha512-nJ5hsTPSu8nrgB2rW6sVJwkX4mjECqryd0W7IYou/rWqlI9/oej8X88BTmgIbBfZIhDySk8dCADyMsiPj215fQ==","shasum":"4907f9a061f89558f7e33ee1a596c92bb30719a3","tarball":"https://registry.npmjs.org/@ayatkevich/slon/-/slon-0.2.0.tgz","fileCount":6,"unpackedSize":27555,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZABBEdxO4YcRewxT5Irn/K6RdzVoJUevgnfq0fhFCTgIgeXj3jP8W4wrOD/gUNvbNLJTpz539Mg2bV4vNvXdRN6g="}]},"_npmUser":{"name":"ayatkevich","email":"ayatkevich@gmail.com"},"directories":{},"maintainers":[{"name":"ayatkevich","email":"ayatkevich@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/slon_0.2.0_1728108699067_0.7974879729924456"},"_hasShrinkwrap":false}},"time":{"created":"2024-10-05T06:11:38.917Z","0.2.0":"2024-10-05T06:11:39.266Z","modified":"2024-10-05T06:11:39.600Z"},"maintainers":[{"name":"ayatkevich","email":"ayatkevich@gmail.com"}],"description":"## Introduction","author":{"name":"Alex Yatkevich"},"license":"MIT","readme":"# SLON – Semantically-Loose Object Network\n\n## Introduction\n\nSLON (Semantically-Loose Object Network) is an experimental data structure implemented in PostgreSQL. It provides a flexible and dynamic way to model relationships between objects using custom PostgreSQL types, operators, and functions. SLON is designed to facilitate complex queries and pattern matching over a network of interconnected nodes, making it suitable for representing hierarchical or graph-based data within a relational database.\n\n## Installation\n\nTo use SLON, you need to execute the provided SQL script (`slon.sql`) in your PostgreSQL database. This script defines the custom types, functions, operators, and the main `slon` table that constitute the SLON data structure.\n\n```sql\n-- Execute the SLON SQL script\n\\i slon.sql\n```\n\n## Concepts\n\n### Symbols\n\nA **Symbol** is the basic unit in SLON, identified by a text `id`. Symbols can be constructed using the `@` operator.\n\n**Creation:**\n\n```sql\n-- Create a symbol\nSELECT @'A' AS symbol;\n```\n\n**Special Symbol:**\n\n- `'*'`: A wildcard symbol that matches any symbol during equality checks.\n\n**Equality:**\n\nTwo symbols are considered equal if:\n\n- Their `id`s are equal, or\n- Either symbol is the wildcard `'*'`.\n\n**Example:**\n\n```sql\n-- Symbols equality\nSELECT @'A' = @'A' AS result;  -- true\nSELECT @'A' = @'B' AS result;  -- false\nSELECT @'A' = @'*' AS result;  -- true\n```\n\n### Objects\n\nAn **Object** in SLON is a pair of symbols: a `left` symbol and a `right` symbol. Objects can represent relationships or properties.\n\n**Construction:**\n\n```sql\n-- Create an object from two symbols\nSELECT @'A' | @'a' AS object;\n\n-- Simplified syntax without '@' operator\nSELECT 'A' | 'a' AS object;\n```\n\n**Equality:**\n\nObjects are equal if:\n\n- Both their `left` symbols are equal, and\n- Both their `right` symbols are equal.\n\n**Pattern Matching with Wildcards:**\n\n```sql\n-- Object equality with wildcard\nSELECT ('A' | '*') = ('A' | 'a') AS result;  -- true\nSELECT ('*' | '*') = ('B' | 'b') AS result;  -- true\nSELECT ('A' | '*') = ('B' | 'b') AS result;  -- false\n```\n\n### Nodes\n\nA **Node** is an object that may optionally have a payload (another object). Nodes represent entities with potential additional data.\n\n**Construction:**\n\n```sql\n-- Create a node with an effect and a payload\nSELECT ('A' | 'a') & ('B' | 'b') AS node;\n\n-- Create a node with only an effect\nSELECT &('A' | 'a') AS node;\n```\n\n**Equality:**\n\nNodes are equal if:\n\n- Their effects are equal, and\n- Their payloads are equal, or\n- One of the effects is `'* | *'` and the payload is `NULL`.\n\n**Example:**\n\n```sql\n-- Nodes equality\nSELECT ('A' | 'a') & ('B' | 'b') = ('A' | 'a') & ('B' | 'b') AS result;  -- true\nSELECT ('A' | 'a') & ('B' | 'b') = ('A' | 'a') & ('*' | 'b') AS result;  -- true\nSELECT ('A' | 'a') & ('B' | 'b') = ('B' | 'b') & ('A' | 'a') AS result;  -- false\n```\n\n### The Network (SLON Table)\n\nThe **Network** is represented by the `slon` table, which stores nodes and their relationships.\n\n**Table Structure:**\n\n```sql\nCREATE TABLE \"slon\" (\n  \"node\" \"slon_node\" NOT NULL,\n  \"related_to\" TEXT REFERENCES \"slon\" (\"id\") ON DELETE CASCADE,\n  \"index\" SERIAL,\n  \"id\" TEXT PRIMARY KEY GENERATED ALWAYS AS (\"index\" || '. ' || (\"node\").\"id\") STORED\n);\n```\n\n**Inserting Nodes:**\n\n- **Top-Level Node:**\n\n  ```sql\n  INSERT INTO \"slon\" (\"node\") VALUES (&('program' | 'A'));\n  ```\n\n- **Related Node:**\n\n  ```sql\n  INSERT INTO \"slon\" (\"node\", \"related_to\")\n  VALUES (&('trace' | 'A'), '1. program | A');\n  ```\n\n## Usage\n\n### Building the Network\n\n**Example:**\n\n```sql\n-- Insert a program node\nWITH program AS (\n  INSERT INTO \"slon\" (\"node\")\n  VALUES (&('program' | 'A'))\n  RETURNING id\n)\n-- Insert a trace node related to the program\nINSERT INTO \"slon\" (\"node\", \"related_to\")\nVALUES (&('trace' | 'A'), (SELECT id FROM program));\n```\n\n### Querying the Network\n\nSLON provides custom operators and functions to query nodes and their relationships.\n\n**Basic Queries:**\n\n```sql\n-- Query top-level nodes\nSELECT (? ('*' | '*')).id FROM \"slon\";\n\n-- Query nodes matching a specific pattern\nSELECT (? ('program' | '*')).id FROM \"slon\";\n```\n\n**Chained Queries:**\n\n```sql\n-- Query steps of all traces of any program\nSELECT (? ('trace' | ? ('program' | '*')) ? ('*' | '*')).id FROM \"slon\";\n```\n\n**Alternative Syntax:**\n\n```sql\nSELECT\n  program.id AS programId,\n  trace.id AS traceId,\n  step.id AS stepId\nFROM\n  slon_query('program' | '*') AS program,\n  slon_query('trace' | program) AS trace,\n  slon_query(trace, '*' | '*') AS step\nORDER BY step.index;\n```\n\n### Pattern Matching with Wildcards\n\nWildcards allow for flexible pattern matching within queries.\n\n**Example:**\n\n```sql\n-- Query nodes where the left symbol is 'A' and any right symbol\nSELECT (? ('A' | '*')).id FROM \"slon\";\n```\n\n## Use Cases\n\n### Simplified PostgreSQL Schema Navigation\n\nSLON can simplify navigating and querying the PostgreSQL schema.\n\n**Inserting Tables and Columns into SLON:**\n\n```sql\nWITH\n  tables AS (\n    INSERT INTO \"slon\" (\"node\")\n    SELECT ('table' | pg_class.relname) & ('oid' | pg_class.oid::text)\n    FROM pg_class\n    WHERE relkind = 'r' AND relnamespace = 'public'::regnamespace\n    RETURNING id\n  ),\n  columns AS (\n    INSERT INTO \"slon\" (\"node\", \"related_to\")\n    SELECT &('column' | pg_attribute.attname), tables.id\n    FROM tables\n    JOIN pg_attribute ON (tables.node).payload.right.id = pg_attribute.attrelid::text\n    WHERE pg_attribute.attnum > 0\n    RETURNING id\n  )\nSELECT * FROM tables, columns;\n```\n\n**Querying Columns of a Specific Table:**\n\n```sql\n-- Get all columns of the 'slon' table\nSELECT ((? ('table' | 'slon') ? ('column' | '*')).node).id FROM \"slon\";\n```\n\n**Result:**\n\n```text\ncolumn | node\ncolumn | related_to\ncolumn | index\ncolumn | id\n```\n\n## Testing\n\nThe provided test suite (`spec.js`) demonstrates various use cases and validates the behavior of the SLON data structure.\n\n## License\n\nThis project is licensed under the MIT License.\n","readmeFilename":"readme.md"}