From ea9d8db0f842ecb7cbd416c2ea4dca55d43b30dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Mon, 3 Jun 2024 09:15:52 +0200 Subject: [PATCH] [add] output:database:postgresql --- source/outputs/database/postgresql/logic.ts | 235 ++++++++++++++++++++ tools/makefile | 1 + 2 files changed, 236 insertions(+) create mode 100644 source/outputs/database/postgresql/logic.ts diff --git a/source/outputs/database/postgresql/logic.ts b/source/outputs/database/postgresql/logic.ts new file mode 100644 index 0000000..1232048 --- /dev/null +++ b/source/outputs/database/postgresql/logic.ts @@ -0,0 +1,235 @@ +namespace _sindri.outputs.database.postgresql +{ + + /** + */ + function value_encode( + value : any + ) : string + { + if (value === null) { + return "NULL"; + } + else { + switch (typeof(value)) { + case "boolean": { + return (value ? "TRUE" : "FALSE"); + break; + } + case "number": { + return value.toString(); + break; + } + case "string": { + return ("'" + value + "'"); + break; + } + default: { + throw (new Error("unhandled")); + break; + } + } + } + } + + + /** + */ + export function render( + input_data + ) : string + { + return ( + input_data.domains + .map( + (domain) => lib_plankton.string.coin( + "CREATE TABLE\n\t{{name}}(\n{{entries}}\n\t)\n;\n{{comments}}", + { + "name": domain.name, + "entries": ( + ( + [] + // key field + .concat( + (domain.key_field === null) + ? [] + : lib_plankton.string.coin( + "{{name}} {{parameters}}", + { + "name": domain.key_field.name, + "parameters": ( + [ + "SERIAL", + ] + .join(" ") + ), + } + ) + ) + // data fields + .concat( + domain.data_fields + .map( + (data_field) => lib_plankton.string.coin( + "{{name}} {{parameters}}", + { + "name": data_field.name, + "parameters": ( + ( + // type + [ + { + "boolean": "BOOLEAN", + "integer": "INTEGER", + "string_short": "VARCHAR(63)", + "string_medium": "VARCHAR(255)", + "string_long": "TEXT", + }[data_field.type], + ] + // nullability + .concat( + data_field.nullable + ? ["NULL"] + : [] + ) + // default + .concat( + (data_field.default === undefined) + ? [] + : [ + lib_plankton.string.coin( + "DEFAULT {{value}}", + { + "value": value_encode(data_field.default), + } + ), + ] + ) + ) + .join(" ") + ) + } + ) + ) + ) + // constraints + .concat( + domain["constraints"] + .map( + (constraint) => { + switch (constraint.kind) { + default: { + throw (new Error("unhandled constraint kind: " + constraint.kind)); + break; + } + case "foreign_key": { + return lib_plankton.string.coin( + "FOREIGN KEY ({{fields}}) REFERENCES {{reference_name}}({{reference_fields}})", + { + "fields": ( + constraint.parameters["fields"] + .map(x => ('' + x + '')) + .join(",") + ), + "reference_name": constraint.parameters["reference"]["name"], + "reference_fields": ( + constraint.parameters["reference"]["fields"] + .map(x => ('' + x + '')) + .join(",") + ), + } + ); + break; + } + case "unique": { + return lib_plankton.string.coin( + "UNIQUE ({{fields}})", + { + "fields": ( + constraint.parameters["fields"] + .map(x => ('' + x + '')) + .join(",") + ), + } + ); + break; + } + } + } + ) + ) + ) + .map(x => ("\t\t" + x)) + .join(",\n") + ), + "comments": ( + ( + [] + .concat( + (domain.description === null) + ? [] + : [ + { + "kind": "TABLE", + "subject": domain.name, + "value": domain.description, + } + ] + ) + .concat( + (domain.key_field === null) + ? [] + : [ + { + "kind": "COLUMN", + "subject": (domain.name + "." + domain.key_field.name), + "value": domain.description, + } + ] + ) + .concat( + domain.data_fields + .filter( + data_field => (! (data_field.description === null)) + ) + .map( + data_field => ({ + "kind": "COLUMN", + "subject": (domain.name + "." + data_field.name), + "value": data_field.description, + }) + ) + ) + ) + .map( + entry => lib_plankton.string.coin( + "COMMENT ON {{kind}} {{subject}} IS '{{value}}';", + { + "kind": entry.kind, + "subject": entry.subject, + "value": entry.value, + } + ) + ) + .join("\n") + ), + } + ) + ) + .map(x => (x + "\n")) + .join("\n") + ); + } + +} + + +/** + */ +_sindri.add_output( + _sindri.enum_realm.database, + "postgresql", + { + "render": (x) => Promise.resolve(_sindri.outputs.database.postgresql.render(x)), + } +); diff --git a/tools/makefile b/tools/makefile index ca02d17..93923a6 100644 --- a/tools/makefile +++ b/tools/makefile @@ -21,6 +21,7 @@ source/base.ts \ source/outputs/other/jsonschema/logic.ts \ source/outputs/database/sqlite/logic.ts \ source/outputs/database/mysql/logic.ts \ +source/outputs/database/postgresql/logic.ts \ source/outputs/backend/typescript/logic.ts \ source/outputs/frontend/typescript/logic.ts \ source/conf.ts \