#!/usr/bin/env bash
#
# test/gen-relkinds.sh - emit a psql script defining the canonical set of
# pg_class.relkind values extracted from the PostgreSQL server header we are
# building against.
#
# Usage: test/gen-relkinds.sh /path/to/catalog/pg_class.h
#
# The output is \i'd by test/sql/relation__.sql, which then asserts that every
# relkind PostgreSQL defines is known to cat_tools.relation_relkind. This lets
# the test suite detect a PostgreSQL version that ADDS a new relkind (or renames
# one) that cat_tools does not yet handle.
#
# If the header is not readable (e.g. postgresql-server-dev-NN is not installed)
# the script emits an EMPTY view, so the drift check in relation__.sql passes
# vacuously (zero unknown relkinds) with identical output -- `make test` must
# still work, and produce the same expected output, without server headers.
set -euo pipefail

header="${1:-}"

echo "-- GENERATED by test/gen-relkinds.sh from pg_class.h. DO NOT EDIT."

if [ -n "$header" ] && [ -r "$header" ]; then
	echo "CREATE TEMP VIEW pg_class_relkind_source (relkind, macro, description) AS"
	echo "VALUES"
	# Match:  #define  RELKIND_NAME  'x'  /* comment */
	# Skip the function-like macros (RELKIND_HAS_STORAGE(relkind) etc.): those
	# have '(' after the name instead of whitespace + a quoted char literal.
	# \047 is a single quote, used throughout to avoid shell-quoting grief.
	awk '
		/#define[ \t]+RELKIND_[A-Z_]+[ \t]+\047.\047/ {
			name = $2
			i = index($0, "\047")
			ch = substr($0, i + 1, 1)
			desc = ""
			if (match($0, /\/\*.*\*\//)) {
				desc = substr($0, RSTART + 2, RLENGTH - 4)
				gsub(/^[ \t]+|[ \t]+$/, "", desc)
			}
			# Double any embedded single quotes for SQL literals.
			gsub(/\047/, "\047\047", ch)
			gsub(/\047/, "\047\047", name)
			gsub(/\047/, "\047\047", desc)
			sep = (n++ == 0) ? "  " : ", "
			printf "  %s(\047%s\047, \047%s\047, \047%s\047)\n", sep, ch, name, desc
		}
	' "$header"
	echo ";"
else
	echo "CREATE TEMP VIEW pg_class_relkind_source (relkind, macro, description) AS"
	echo "  SELECT NULL::text, NULL::text, NULL::text WHERE false;"
fi
