diff --git a/scripts/generate-db-diagram.sh b/scripts/generate-db-diagram.sh index 5aca63e5..7004dcb4 100755 --- a/scripts/generate-db-diagram.sh +++ b/scripts/generate-db-diagram.sh @@ -201,9 +201,53 @@ dot_label_escape() { printf '%s' "$value" } +table_module() { + local table_name="${1#public.}" + + case "$table_name" in + AspNet*) printf 'Identity' ;; + OrganizationMemberships | Organizations) printf 'Organizations' ;; + Workspaces | WorkspaceInvites) printf 'Workspaces' ;; + Clients) printf 'Clients' ;; + Campaigns) printf 'Campaigns' ;; + Channels) printf 'Channels' ;; + ContentItems | ContentItemRevisions | ContentItemActivityEntries) printf 'ContentItems' ;; + Assets | AssetRevisions) printf 'Assets' ;; + Comments) printf 'Comments' ;; + ApprovalDecisions | ApprovalRequests | ApprovalWorkflowInstances | WorkspaceApprovalStepConfigurations) printf 'Approvals' ;; + NotificationEvents) printf 'Notifications' ;; + Feedback*) printf 'Feedback' ;; + CalendarCatalogEntries | CalendarEvents | CalendarSources | UserCalendarExportFeeds) printf 'CalendarIntegrations' ;; + *) printf 'Other' ;; + esac +} + +cluster_id() { + local value="$1" + value="${value//[^[:alnum:]]/_}" + printf 'cluster_%s' "$value" +} + +write_table_node() { + local table_name="$1" + local id title + + id="$(node_id "$table_name")" + title="$(html_escape "${table_name#public.}")" + printf ' %s [label=<\n' "$id" + printf ' \n' + printf ' \n' "$title" + printf '%s' "${TABLE_COLUMNS[$table_name]}" + printf '
%s
\n' + printf ' >];\n\n' +} + declare -A TABLE_COLUMNS declare -A TABLE_SEEN +declare -A MODULE_SEEN +declare -A MODULE_TABLES declare -a TABLE_ORDER +declare -a MODULE_ORDER while IFS=$'\t' read -r table_name column_name column_type nullable column_markers; do [[ -n "$table_name" ]] || continue @@ -211,6 +255,12 @@ while IFS=$'\t' read -r table_name column_name column_type nullable column_marke if [[ -z "${TABLE_SEEN[$table_name]:-}" ]]; then TABLE_SEEN["$table_name"]=1 TABLE_ORDER+=("$table_name") + module_name="$(table_module "$table_name")" + if [[ -z "${MODULE_SEEN[$module_name]:-}" ]]; then + MODULE_SEEN["$module_name"]=1 + MODULE_ORDER+=("$module_name") + fi + MODULE_TABLES["$module_name"]+="${table_name}"$'\n' fi label="$(html_escape "$column_name")" @@ -267,15 +317,25 @@ digraph database { DOT - for table_name in "${TABLE_ORDER[@]}"; do - id="$(node_id "$table_name")" - title="$(html_escape "${table_name#public.}")" - printf ' %s [label=<\n' "$id" - printf ' \n' - printf ' \n' "$title" - printf '%s' "${TABLE_COLUMNS[$table_name]}" - printf '
%s
\n' - printf ' >];\n\n' + for module_name in "${MODULE_ORDER[@]}"; do + id="$(cluster_id "$module_name")" + label="$(html_escape "$module_name")" + printf ' subgraph %s {\n' "$id" + printf ' label=< %s >;\n' "$label" + printf ' color="#cbd5e1";\n' + printf ' penwidth=1.5;\n' + printf ' style="rounded";\n' + printf ' margin=18;\n' + printf ' fontname="Arial";\n' + printf ' fontsize=16;\n' + printf ' fontcolor="#334155";\n\n' + + while IFS= read -r table_name; do + [[ -n "$table_name" ]] || continue + write_table_node "$table_name" + done <<< "${MODULE_TABLES[$module_name]}" + + printf ' }\n\n' done while IFS=$'\t' read -r constraint_name child_table child_column parent_table parent_column nullable child_column_is_unique; do