diff --git a/Dockerfile b/Dockerfile index 7690e465bc87d9ccca53a07496b10a0e408f5589..a8f66b9b0fea82622a9701a4ce87045662df2c01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,8 @@ RUN apk add --update --no-cache \ curl \ gawk \ sed +RUN wget https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64 +RUN cp ./jq-linux-amd64 /usr/local/bin/jq && chmod +x /usr/local/bin/jq WORKDIR ./checkup COPY --from=build /go/pghrep/bin/pghrep ./pghrep/bin/ COPY . . diff --git a/checkup b/checkup index 4c1ac7029e3d4eb4a9643290c8d8fb9f1ecdd808..6921fc8cdbd7e87a3ff91e14ac24c77d5e54c6e8 100755 --- a/checkup +++ b/checkup @@ -712,14 +712,14 @@ generate_report_json() { local tmp_output_json_fname=$(mktemp "${JSON_REPORTS_DIR}"/${check_id}_${check_name}_tmp_XXXXXX) jq -r \ - --argfile Results "${tmp_input_json_fname}" \ + --slurpfile Results "${tmp_input_json_fname}" \ --arg CheckId "${check_id}" \ --arg CheckName "${check_name}" \ --arg TimestampTz "${TIMESTAMPTZ}" \ --arg Host "${HOST}" \ --arg Project "${PROJECT}" \ --arg Database "${DBNAME}" \ - '.checkId = $CheckId | .name = $CheckName | ."timestamptz" = $TimestampTz | ."project" = $Project | ."database" = $Database | .results += { ($Host): { data: $Results } }' \ + '.checkId = $CheckId | .name = $CheckName | ."timestamptz" = $TimestampTz | ."project" = $Project | ."database" = $Database | .results += { ($Host): { data: ($Results[0]) } }' \ "${json_input_fname}" \ > "${tmp_output_json_fname}" mv "${tmp_output_json_fname}" "${json_output_fname}" @@ -727,16 +727,16 @@ generate_report_json() { # extend check for current host with actual 'nodes.json' inside a json report tmp_output_json_fname=$(mktemp "${JSON_REPORTS_DIR}"/${check_id}_${check_name}_tmp_ex_XXXXXX) - jq --argfile nodes_json "${PROJECT_DIR}/nodes.json" \ - '.results.'\"${HOST}\"'."nodes.json" = $nodes_json' \ + jq --slurpfile nodes_json "${PROJECT_DIR}/nodes.json" \ + '.results.'\"${HOST}\"'."nodes.json" = ($nodes_json[0])' \ "${json_output_fname}" \ > "$tmp_output_json_fname" mv "$tmp_output_json_fname" "${json_output_fname}" # update json report by attaching 'nodes.json' into top of the report tmp_output_json_fname=$(mktemp "${JSON_REPORTS_DIR}"/${check_id}_${check_name}_tmp_ex_XXXXXX) - jq --argfile nodes_json "${PROJECT_DIR}/nodes.json" \ - '.last_nodes_json = $nodes_json' \ + jq --slurpfile nodes_json "${PROJECT_DIR}/nodes.json" \ + '.last_nodes_json = ($nodes_json[0])' \ "${json_output_fname}" \ > "$tmp_output_json_fname" mv "$tmp_output_json_fname" "${json_output_fname}" diff --git a/resources/checks/F005_index_bloat.sh b/resources/checks/F005_index_bloat.sh index 46691b1211f8bdca1c40d51c7fdac6b27251fd09..9916930fc11d2a951c5bc964af9ce60468933729 100755 --- a/resources/checks/F005_index_bloat.sh +++ b/resources/checks/F005_index_bloat.sh @@ -15,6 +15,17 @@ with data as ( from pg_class pc join pg_namespace pn on pn.oid = pc.relnamespace where reloptions::text ~ 'autovacuum' + ), pg_rel_stats as ( + select n.nspname as schemaname, + c.relname as tablename, + a.attname, + s.stawidth as avg_width, + s.stanullfrac as null_frac + from pg_statistic s + join pg_class c on c.oid = s.starelid + join pg_attribute a on c.oid = a.attrelid AND a.attnum = s.staattnum + left join pg_namespace n on n.oid = c.relnamespace + where not a.attisdropped ), step0 as ( select tbl.oid tblid, @@ -68,7 +79,7 @@ with data as ( i.table_size_bytes from pg_attribute as a join step0 as i on a.attrelid = i.indexrelid - join pg_stats as s on + join pg_rel_stats as s on s.schemaname = i.nspname and ( (s.tablename = i.tblname and s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, true)) -- stats from tbl diff --git a/resources/checks/L003_integer_in_pk.sh b/resources/checks/L003_integer_in_pk.sh index 692ce9df32f5b434338acc084b64ff94ac53355f..b8b989e5488d4d071e50df0c02bcf40f2227c7cf 100644 --- a/resources/checks/L003_integer_in_pk.sh +++ b/resources/checks/L003_integer_in_pk.sh @@ -42,6 +42,7 @@ begin and (c.relpages > MIN_RELPAGES or (select pg_get_serial_sequence(quote_ident(nspname) || '.' || quote_ident(relname), attname)) is not null) and t.typname in ('int2', 'int4') and nspname <> 'pg_toast' + and nspname <> 'pg_catalog' group by 1, 2, 3, 4, 5, 6 having count(*) = 1 -- skip PKs with 2+ columns loop