{"id":15337246,"url":"https://github.com/vy/sst","last_synced_at":"2025-10-16T13:30:41.433Z","repository":{"id":542046,"uuid":"171945","full_name":"vy/sst","owner":"vy","description":"A Common Lisp program that transforms an s-expression based database schema format medium into appropriate SQL commands for specified RDBMS.","archived":false,"fork":false,"pushed_at":"2013-04-12T09:42:22.000Z","size":120,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-12-06T15:22:07.188Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2009-04-09T14:27:02.000Z","updated_at":"2024-03-23T16:14:11.000Z","dependencies_parsed_at":"2022-07-07T14:10:21.130Z","dependency_job_id":null,"html_url":"https://github.com/vy/sst","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vy%2Fsst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vy%2Fsst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vy%2Fsst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vy%2Fsst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vy","download_url":"https://codeload.github.com/vy/sst/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236721586,"owners_count":19194455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T10:20:17.778Z","updated_at":"2025-10-16T13:30:36.159Z","avatar_url":"https://github.com/vy.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"          \n      ,-#\u0026%\u0026%-,  ,-#\u0026%\u0026%-,  ,-#\u0026%\u0026#%-,  \n     / .-----~  / .-----~  /___  ___/\n     \\ \\____    \\ \\____       / /\n      \\_____`\\   \\_____`\\    / /\n     ______/ /  ______/ /   / /\n    /_______/  /_______/   /_/\n\n# SST (SQL Schema Transformer)\n\nSST is a Common Lisp program that transforms an s-expression based database\nschema format medium into appropriate SQL commands for specified RDBMS. SST is\ncapable of\n\n* Dividing produced queries into logically separate (schemas, tables, primary keys, foreign keys, indexes) files.\n* Customized (and extendable) identifier formatters. (You can adopt a naming scheme you prefer to name tables, indexes, etc.)\n* `FOREIGN KEY` data type mismatch detection.\n* Invalid `FOREIGN KEY` reference detection.\n* Missing index detection for `ON DELETE`/`UPDATE CASCADE` references.\n* `FOREIGN KEY` reference auto-completion. (You don't need to supply column of the referenced table. SST infers it for you.)\n\n# Why SST?\n\nSST is used to keep database schema consistency between various RDBMSes. At time\nof this writing, SST is used to produce schema creation queries from an SST\nmedium containing ~200 tables in a CVS repository for PostgreSQL and Microsoft\nSQL Server systems that are in production use. Every modification commited into\nthe SST medium in CVS repository gets propogated to production systems for\nvarious RDBMes. Using such a scheme supplied below advantages:\n\n* Unified synchronization between saveral R\u0026D developments being worked on concurrently.\n* Database schema modification history. (One can easily switch to a database schema branch of a point in time he/she wants.)\n* Avoids writing RDBMS specific SQL queries. (One medium to rule them all!)\n\nWhile there are [some other projects](http://sqlfairy.sourceforge.net/) on the\nweb that are (so called) capable of doing what SST is designed for, several\nreasons (huge package dependency, complicated interface, lack of a proper\ndocumentation, no (community) support, etc.) drived me to roll my own\nsolution.\n\n# Installation\n\nSST is `ASDF-INSTALL`able. On most modern Common Lisp implementations, ASDF\ncomes builtin. Assuming your Common Lisp implementation supports ASDF,\ninstallation is just a single step:\n\n    CL-USER\u003e (asdf-install:install :sst)\n\n# Example Usage\n\n    $ cat /home/vy/projects/sst/examples/schema.lisp\n    (with-schema ()\n        \"public\"\n      (with-table ()\n          \"companies\"\n          ((id serial :primary-key t)\n           (name text :not-null t)))\n      (with-table ()\n          \"units\"\n          ((\"id\" (serial :start 10 :increment 2) :primary-key t)\n           (\"type\" char :foreign-key (\"types\" :schema \"meta\"))\n           (\"code\" float :default -3.4)\n           (\"company\" text :foreign-key \"companies\"))\n        (with-index (:unique t) \"type\")\n        (with-index () (\"code\" :descending t) \"type\")))\n\n    (with-schema ()\n        \"meta\"\n      (with-table ()\n          \"types\"\n          ((\"id\" serial :primary-key t)\n           (\"name\" text))))\n\n    $ sbcl\n    ...\n    CL-USER\u003e (asdf:oos 'asdf:load-op :cl-sst)\n    ...\n    CL-USER\u003e (sst:produce-sql-output\n    \t  \"/home/vy/projects/sst/examples/schema.lisp\"\n    \t  \"/home/vy/projects/sst/examples/pgsql/\"\n    \t  'sst:rdbms-pgsql)\n\n    WARNING: Expected (CHAR) data type doesn't match with the referenced (SERIAL)\n    data type for constraint #\u003cSQL-FOREIGN-KEY-CONSTRAINT {10038A6FA1}\u003e on \"type\"\n    column of \"units\" table in \"public\" schema.\n    NIL\n    CL-USER\u003e (sst:produce-sql-output\n    \t  \"/home/vy/projects/sst/examples/schema.lisp\"\n    \t  \"/home/vy/projects/sst/examples/mssql/\"\n    \t  'sst:rdbms-mssql\n    \t  :identifier-case :upcase)\n    WARNING: Expected (CHAR) data type doesn't match with the referenced (SERIAL)\n    data type for constraint #\u003cSQL-FOREIGN-KEY-CONSTRAINT {10047DA3C1}\u003e on \"type\"\n    column of \"units\" table in \"public\" schema.\n    NIL\n\n    $ cd /home/vy/projects/sst/examples\n\n    $ ls -l pgsql/\n    total 24\n    -rw-r--r-- 1 vy vy 170 2008-09-20 14:31 foreign-keys\n    -rw-r--r-- 1 vy vy 214 2008-09-20 16:49 foreign-keys.sql\n    -rw-r--r-- 1 vy vy 122 2008-09-20 16:49 indexes.sql\n    -rw-r--r-- 1 vy vy 216 2008-09-20 16:49 primary-keys.sql\n    -rw-r--r-- 1 vy vy  42 2008-09-20 16:49 schemas.sql\n    -rw-r--r-- 1 vy vy 294 2008-09-20 16:49 tables.sql\n\n    $ cat pgsql/{schemas,tables,primary-keys,indexes,foreign-keys}.sql\n    CREATE SCHEMA meta;\n    CREATE SCHEMA public;\n    CREATE TABLE meta.types (\n        id serial,\n        name text\n    );\n    CREATE TABLE public.companies (\n        id serial,\n        name text NOT NULL\n    );\n    CREATE TABLE public.units (\n        id serial,\n        type char,\n        code float DEFAULT -3.4,\n        company int\n    );\n    ALTER SEQUENCE public.units_id_seq START 10 INCREMENT 2;\n    ALTER TABLE meta.types ADD CONSTRAINT types_id_pk PRIMARY KEY (id);\n    ALTER TABLE public.companies ADD CONSTRAINT companies_id_pk PRIMARY KEY (id);\n    ALTER TABLE public.units ADD CONSTRAINT units_id_pk PRIMARY KEY (id);\n    CREATE INDEX units_code_desc_type_idx ON public.units (code DESC, type);\n    CREATE UNIQUE INDEX units_type_unq ON public.units (type);\n    ALTER TABLE public.units ADD CONSTRAINT units_company_fk FOREIGN KEY (company)\n    REFERENCES public.companies (id);\n    ALTER TABLE public.units ADD CONSTRAINT units_type_fk FOREIGN KEY (type)\n    REFERENCES meta.types (id);\n\n    $ ls -l mssql/\n    total 20\n    -rw-r--r-- 1 vy vy 218 2008-09-20 16:51 foreign-keys.sql\n    -rw-r--r-- 1 vy vy 124 2008-09-20 16:51 indexes.sql\n    -rw-r--r-- 1 vy vy 222 2008-09-20 16:51 primary-keys.sql\n    -rw-r--r-- 1 vy vy  46 2008-09-20 16:51 schemas.sql\n    -rw-r--r-- 1 vy vy 293 2008-09-20 16:51 tables.sql\n\n    $ cat mssql/{schemas,tables,primary-keys,indexes,foreign-keys}.sql\n    CREATE SCHEMA META\n    GO\n    CREATE SCHEMA PUBLIC\n    GO\n    CREATE TABLE META.TYPES (\n        ID int IDENTITY(1,1),\n        NAME varchar(max)\n    )\n    GO\n    CREATE TABLE PUBLIC.COMPANIES (\n        ID int IDENTITY(1,1),\n        NAME varchar(max) NOT NULL\n    )\n    GO\n    CREATE TABLE PUBLIC.UNITS (\n        ID int IDENTITY(10,2),\n        TYPE char,\n        CODE float DEFAULT -3.4,\n        COMPANY int\n    )\n    GO\n    ALTER TABLE META.TYPES ADD CONSTRAINT PK_TYPES_ID PRIMARY KEY (ID)\n    GO\n    ALTER TABLE PUBLIC.COMPANIES ADD CONSTRAINT PK_COMPANIES_ID PRIMARY KEY (ID)\n    GO\n    ALTER TABLE PUBLIC.UNITS ADD CONSTRAINT PK_UNITS_ID PRIMARY KEY (ID)\n    GO\n    CREATE INDEX IX_UNITS_CODE_DESC_TYPE ON PUBLIC.UNITS (CODE DESC, TYPE)\n    GO\n    CREATE UNIQUE INDEX UK_UNITS_TYPE ON PUBLIC.UNITS (TYPE)\n    GO\n    ALTER TABLE PUBLIC.UNITS ADD CONSTRAINT FK_UNITS_COMPANY FOREIGN KEY (COMPANY)\n    REFERENCES PUBLIC.COMPANIES (ID)\n    GO\n    ALTER TABLE PUBLIC.UNITS ADD CONSTRAINT FK_UNITS_TYPE FOREIGN KEY (TYPE)\n    REFERENCES META.TYPES (ID)\n    GO\n\n# Syntax\n\n    (PRODUCE-SQL-OUTPUT\n      PATHNAME OUTPUT-DIRECTORY RDBMS\n      \u0026KEY IDENTIFIER-CASE SCHEMA-OUTPUT-FILE TABLE-OUTPUT-FILE\n           PRIMARY-KEY-OUTPUT-FILE FOREIGN-KEY-OUTPUT-FILE INDEX-OUTPUT-FILE)\n\n\u003e `PRODUCE-SQL-OUTPUT` expands macros in the SST medium pointed by `PATHNAME`. It places output files under `OUTPUT-DIRECTORY`. Produced commands will be specific to given RDBMS and identifiers are case converted according to `IDENTIFIER-CASE`. (Valid values for `IDENTIFIER-CASE` are `:DOWNCASE`, `:UPCASE`, and `:QUOTE`.)\n\n    (WITH-SCHEMA ATTRIBUTES SCHEMA-NAME \u0026REST WITH-TABLE-COMPONENTS)\n    (WITH-TABLE ATTRIBUTES TABLE-NAME COLUMNS \u0026REST WITH-INDEX-COMPONENTS)\n\n\u003e List of `COLUMNS` forms are gets transformed to `WITH-COLUMN` expressions.\n\n    (WITH-COLUMN COLUMN-NAME DATA-TYPE\n      \u0026KEY NOT-NULL DEFAULT PRIMARY-KEY FOREIGN-KEY)\n\n\u003e `DATA-TYPE`, `PRIMARY-KEY`, and `FOREIGN-KEY` forms are respectively transformed into `WITH-DATA-TYPE`, `WITH-PRIMARY-KEY`, and `WITH-FOREIGN-KEY` expressions.\n\n\n    (WITH-DATA-TYPE DATA-TYPE \u0026REST ATTRIBUTES)\n\n\u003e Supported data-types and relevant attributes are\n\n    (BIGINT)\n    (BIGSERIAL \u0026KEY START INCREMENT)\n    (BIT \u0026OPTIONAL SIZE)\n    (CHAR \u0026OPTIONAL SIZE \u0026KEY UNICODE)\n    (FLOAT)\n    (INT)\n    (SERIAL \u0026KEY START INCREMENT)\n    (SMALLINT)\n    (TEXT \u0026KEY UNICODE)\n    (TIMESTAMP \u0026KEY WITH-TIME-ZONE)\n    (VARCHAR \u0026OPTIONAL SIZE \u0026KEY UNICODE)\n\n\u003e Caveats are\n\u003e\n\u003e - At the moment, `UNICODE` key is meaningful only to Microsoft SQL Server.\n\u003e - At the moment, `WITH-TIME-ZONE` key is meaningful only to PostgreSQL.\n\u003e\n\u003e If one won't use any attributes of a data type, using list representation is optional.\n\n    (WITH-FOREIGN-KEY TABLE \u0026KEY SCHEMA ON-DELETE-CASCADE ON-UPDATE-CASCADE)\n\n\u003e Unless `SCHEMA` of the referenced `TABLE` is not in the current schema of current parsing scope, it's optional to supply a `SCHEMA`.\n\n    (WITH-INDEX (\u0026KEY UNIQUE) COLUMNS)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvy%2Fsst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvy%2Fsst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvy%2Fsst/lists"}