sindri/source/outputs/database/postgresql/logic.ts

256 lines
5.5 KiB
TypeScript
Raw Normal View History

2024-06-03 09:15:52 +02:00
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}}",
{
2024-10-25 11:26:43 +02:00
"name": ('"' + domain.key_field.name + '"'),
2024-06-03 09:15:52 +02:00
"parameters": (
[
"SERIAL",
]
.join(" ")
),
}
)
)
// data fields
.concat(
domain.data_fields
.map(
(data_field) => lib_plankton.string.coin(
"{{name}} {{parameters}}",
{
2024-10-25 11:26:43 +02:00
"name": ('"' + data_field.name + '"'),
2024-06-03 09:15:52 +02:00
"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
2024-06-03 09:33:24 +02:00
? []
: ["NOT NULL"]
2024-06-03 09:15:52 +02:00
)
// default
.concat(
(data_field.default === undefined)
? []
: [
lib_plankton.string.coin(
"DEFAULT {{value}}",
{
"value": value_encode(data_field.default),
}
),
]
)
)
.join(" ")
)
}
)
)
)
// constraints
.concat(
domain["constraints"]
2024-10-25 11:26:43 +02:00
.concat(
(domain.key_field === null)
?
[]
:
[
{
"kind": "unique",
"parameters": {
"fields": [
domain.key_field.name,
]
}
},
]
)
2024-06-03 09:15:52 +02:00
.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"]
2024-10-25 11:26:43 +02:00
.map(x => ('"' + x + '"'))
2024-06-03 09:15:52 +02:00
.join(",")
),
2024-10-25 11:26:43 +02:00
"reference_name": ('"' + constraint.parameters["reference"]["name"] + '"'),
2024-06-03 09:15:52 +02:00
"reference_fields": (
constraint.parameters["reference"]["fields"]
2024-10-25 11:26:43 +02:00
.map(x => ('"' + x + '"'))
2024-06-03 09:15:52 +02:00
.join(",")
),
}
);
break;
}
case "unique": {
return lib_plankton.string.coin(
"UNIQUE ({{fields}})",
{
"fields": (
constraint.parameters["fields"]
2024-10-25 11:26:43 +02:00
.map(x => ('"' + x + '"'))
2024-06-03 09:15:52 +02:00
.join(",")
),
}
);
break;
}
}
}
)
)
)
.map(x => ("\t\t" + x))
.join(",\n")
),
"comments": (
(
[]
.concat(
2024-06-03 09:33:24 +02:00
(! (domain.description === null))
? [
2024-06-03 09:15:52 +02:00
{
"kind": "TABLE",
"subject": domain.name,
"value": domain.description,
}
]
2024-06-03 09:33:24 +02:00
: []
2024-06-03 09:15:52 +02:00
)
.concat(
2024-06-03 09:33:24 +02:00
(
(! (domain.key_field === null))
&&
(! (domain.key_field.description === null))
)
? [
2024-06-03 09:15:52 +02:00
{
"kind": "COLUMN",
"subject": (domain.name + "." + domain.key_field.name),
2024-06-03 09:33:24 +02:00
"value": domain.key_field.description,
2024-06-03 09:15:52 +02:00
}
]
2024-06-03 09:33:24 +02:00
: []
2024-06-03 09:15:52 +02:00
)
.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<string>(_sindri.outputs.database.postgresql.render(x)),
}
);