Compare commits

...

10 commits

Author SHA1 Message Date
01221f0374 [mod] tools:build 2024-06-07 08:23:43 +02:00
31df9cfbaf [mod] tools:build 2024-06-07 08:05:48 +02:00
327b000bf8 [fix] r4 2024-06-03 13:03:49 +02:00
5e91b4565f [upd] sindri 2024-06-03 13:03:39 +02:00
fc06d79001 [mod] r4 2024-05-27 21:28:11 +02:00
00737827a1 [upd] sindri 2024-05-27 21:27:52 +02:00
2877d09c1e [add] r4 2024-05-27 18:12:30 +02:00
0796fc87b1 [add] r3 2024-05-20 12:19:14 +02:00
e83554cf26 [mod] r2 2024-04-29 20:48:01 +02:00
0870f1cef5 [mod] r1:add field member.registered 2024-04-29 00:15:22 +02:00
6 changed files with 588 additions and 86 deletions

View file

@ -88,6 +88,11 @@
"name": "email_redirect_to_private", "name": "email_redirect_to_private",
"type": "boolean", "type": "boolean",
"nullable": false "nullable": false
},
{
"name": "registered",
"type": "boolean",
"nullable": false
} }
], ],
"constraints": [ "constraints": [

View file

@ -1,10 +1,50 @@
{ {
"domains": [ "domains": [
{ {
"name": "member_core", "name": "sessions",
"data_fields": [
{
"name": "key",
"type": "string_medium",
"nullable": false
},
{
"name": "data",
"type": "string_long",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["key"]
}
}
]
}, },
{ {
"name": "member_extras", "name": "name_indices",
"data_fields": [
{
"name": "name_image",
"type": "string_medium",
"nullable": false
},
{
"name": "index",
"type": "integer",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["name_image"]
}
}
]
}, },
{ {
"name": "members", "name": "members",
@ -17,60 +57,55 @@
"type": "string_short", "type": "string_short",
"nullable": false "nullable": false
}, },
{
"name": "name_real_value",
"type": "string_short",
"nullable": false
},
{
"name": "name_real_index",
"type": "integer",
"nullable": true
},
{
"name": "email_address_private",
"type": "string_short",
"nullable": true
},
{
"name": "registered",
"type": "boolean",
"nullable": false
},
{ {
"name": "enabled", "name": "enabled",
"type": "boolean", "type": "boolean",
"nullable": false "nullable": false
}, },
{ {
"name": "name_login", "name": "email_use_veiled_address",
"type": "string_short", "type": "boolean",
"nullable": true "nullable": false
},
{
"name": "email_use_nominal_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_redirect_to_private_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_allow_sending",
"type": "boolean",
"nullable": false
}, },
{ {
"name": "password_image", "name": "password_image",
"type": "string_medium", "type": "string_medium",
"nullable": true "nullable": true
},
{
"name": "name_real_value",
"type": "string_medium",
"nullable": false
},
{
"name": "name_real_extension",
"type": "string_short",
"nullable": true
},
{
"name": "name_display",
"type": "string_medium",
"nullable": true
},
{
"name": "salutation",
"type": "string_short",
"nullable": true
},
{
"name": "email_address_private_value",
"type": "string_short",
"nullable": true
},
{
"name": "email_address_numberbased_use",
"type": "boolean",
"nullable": false
},
{
"name": "email_address_namebased_use",
"type": "boolean",
"nullable": false
},
{
"name": "email_redirect_to_private",
"type": "boolean",
"nullable": false
} }
], ],
"constraints": [ "constraints": [
@ -83,13 +118,7 @@
{ {
"kind": "unique", "kind": "unique",
"parameters": { "parameters": {
"fields": ["name_real_value","name_real_extension"] "fields": ["name_real_value","name_real_index"]
}
},
{
"kind": "unique",
"parameters": {
"fields": ["name_login"]
} }
} }
] ]

View file

@ -0,0 +1,137 @@
{
"domains": [
{
"name": "sessions",
"data_fields": [
{
"name": "key",
"type": "string_medium",
"nullable": false
},
{
"name": "data",
"type": "string_long",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["key"]
}
}
]
},
{
"name": "name_indices",
"data_fields": [
{
"name": "name_image",
"type": "string_medium",
"nullable": false
},
{
"name": "index",
"type": "integer",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["name_image"]
}
}
]
},
{
"name": "members",
"key_field": {
"name": "id"
},
"data_fields": [
{
"name": "membership_number",
"type": "string_short",
"nullable": false
},
{
"name": "name_real_value",
"type": "string_short",
"nullable": false
},
{
"name": "name_real_index",
"type": "integer",
"nullable": true
},
{
"name": "email_address_private",
"type": "string_short",
"nullable": true
},
{
"name": "registered",
"type": "boolean",
"nullable": false
},
{
"name": "enabled",
"type": "boolean",
"nullable": false
},
{
"name": "email_use_veiled_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_use_nominal_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_redirect_to_private_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_allow_sending",
"type": "boolean",
"nullable": false
},
{
"name": "password_image",
"type": "string_medium",
"nullable": true
},
{
"name": "password_change_last_attempt",
"type": "integer",
"nullable": true
},
{
"name": "password_change_token",
"type": "string",
"nullable": true
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["membership_number"]
}
},
{
"kind": "unique",
"parameters": {
"fields": ["name_real_value","name_real_index"]
}
}
]
}
]
}

View file

@ -0,0 +1,131 @@
{
"domains": [
{
"name": "sessions",
"data_fields": [
{
"name": "key",
"type": "string_medium",
"nullable": false
},
{
"name": "data",
"type": "string_long",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["key"]
}
}
]
},
{
"name": "name_indices",
"data_fields": [
{
"name": "name_image",
"type": "string_medium",
"nullable": false
},
{
"name": "index",
"type": "integer",
"nullable": false
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["name_image"]
}
}
]
},
{
"name": "members",
"key_field": {
"name": "id"
},
"data_fields": [
{
"name": "membership_number",
"type": "string_short",
"nullable": true
},
{
"name": "name_real_value",
"type": "string_short",
"nullable": false
},
{
"name": "name_real_index",
"type": "integer",
"nullable": false
},
{
"name": "email_address_private",
"type": "string_short",
"nullable": true
},
{
"name": "registered",
"type": "boolean",
"nullable": false
},
{
"name": "enabled",
"type": "boolean",
"nullable": false
},
{
"name": "email_use_veiled_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_use_nominal_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_redirect_to_private_address",
"type": "boolean",
"nullable": false
},
{
"name": "email_allow_sending",
"type": "boolean",
"nullable": false
},
{
"name": "password_image",
"type": "string_medium",
"nullable": true
},
{
"name": "password_change_last_attempt",
"type": "integer",
"nullable": true
},
{
"name": "password_change_token",
"type": "string_medium",
"nullable": true
}
],
"constraints": [
{
"kind": "unique",
"parameters": {
"fields": ["name_real_value","name_real_index"]
}
}
]
}
]
}

View file

@ -1,36 +1,75 @@
#!/usr/bin/env bash #!/usr/bin/env python3
## functions import typing as _typing
import sys as _sys
function syntaxerror import os as _os
{ import argparse as _argparse
echo "SYNTAX: build <revision> [<format>]" > /dev/stderr
exit 1
}
## consts def main():
## consts
dir_source = "source"
dir_source="source" ## args
dir_build="build" argument_parser = _argparse.ArgumentParser()
argument_parser.add_argument(
"-r",
"--revision",
type = str,
dest = "revision",
default = None,
help = "use '.' for latest",
)
argument_parser.add_argument(
"-f",
"--format",
type = str,
dest = "format",
default = "sqlite",
)
args = argument_parser.parse_args()
## vars
revisions = sorted(
list(
map(
lambda name: name.split(".sindri.json")[0],
_os.listdir(_os.path.join(dir_source, "structure"))
)
)
)
revision = (
args.revision
if
(
(not (args.revision is None))
and
(not (args.revision == ""))
and
(not (args.revision == "."))
)
else
revisions[-1]
)
## exec
if (not (revision in set(revisions))):
_sys.stderr.write("-- invalid revision: %s\n" % revision)
_sys.exit(1)
else:
_sys.stderr.write("-- data\n")
_os.system(
"cat %s/structure/%s.sindri.json | tools/sindri/sindri --format='database:%s'"
% (
dir_source,
revision,
args.format,
)
)
_sys.stderr.write("-- meta\n")
_sys.stdout.write("DROP TABLE IF EXISTS _meta;\n")
_sys.stdout.write("CREATE TABLE _meta(revision VARCHAR(15) NOT NULL);\n")
_sys.stdout.write("INSERT INTO _meta(revision) VALUES ('%s');\n" % revision)
## args main()
if [ $# -ge 1 ] ; then revision=$1 && shift ; else syntaxerror ; fi
if [ $# -ge 1 ] ; then format=$1 && shift ; else format="sqlite" ; fi
## exec
mkdir -p ${dir_build}
echo "-- data"
cat ${dir_source}/structure/${revision}.sindri.json | tools/sindri/sindri -f database:${format}
echo ""
echo "-- meta"
echo "DROP TABLE IF EXISTS _meta;"
echo "CREATE TABLE _meta(revision VARCHAR(15) NOT NULL);"
echo "INSERT INTO _meta(revision) VALUES ('${revision}');"
echo ""

View file

@ -5775,8 +5775,8 @@ var _sindri;
] ]
// nullability // nullability
.concat(data_field.nullable .concat(data_field.nullable
? ["NULL"] ? []
: []) : ["NOT NULL"])
// default // default
.concat((data_field.default === undefined) .concat((data_field.default === undefined)
? [] ? []
@ -5981,6 +5981,167 @@ _sindri.add_output(_sindri.enum_realm.database, "mysql", {
"render": (x) => Promise.resolve(_sindri.outputs.database.mysql.render(x)), "render": (x) => Promise.resolve(_sindri.outputs.database.mysql.render(x)),
}); });
var _sindri; var _sindri;
(function (_sindri) {
var outputs;
(function (outputs) {
var database;
(function (database) {
var postgresql;
(function (postgresql) {
/**
*/
function value_encode(value) {
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;
}
}
}
}
/**
*/
function render(input_data) {
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
? []
: ["NOT 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))
&&
(!(domain.key_field.description === null)))
? [
{
"kind": "COLUMN",
"subject": (domain.name + "." + domain.key_field.name),
"value": domain.key_field.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"));
}
postgresql.render = render;
})(postgresql = database.postgresql || (database.postgresql = {}));
})(database = outputs.database || (outputs.database = {}));
})(outputs = _sindri.outputs || (_sindri.outputs = {}));
})(_sindri || (_sindri = {}));
/**
*/
_sindri.add_output(_sindri.enum_realm.database, "postgresql", {
"render": (x) => Promise.resolve(_sindri.outputs.database.postgresql.render(x)),
});
var _sindri;
(function (_sindri) { (function (_sindri) {
var outputs; var outputs;
(function (outputs) { (function (outputs) {