#!/usr/bin/env bash

set -o errexit

# Follow symlinks to find the real script
cd "$(dirname "$0")" || exit 1
script_file=$(pwd)/$(basename "$0")
while [[ -L "$script_file" ]]; do
    script_file=$(readlink "$script_file")
    cd "$(dirname "$script_file")" || exit 1
    script_file=$(pwd)/$(basename "$script_file")
done
parent_script_dir="$( (cd "$(dirname "${script_file}")/.." && pwd -P))"

# establish PXF_HOME and global vars used by all commands
export PXF_HOME=${parent_script_dir}

# Path to PXF_BASE directories, defaults to PXF_HOME
export PXF_BASE=${PXF_BASE:=$PXF_HOME}

# Path to Log directory
export PXF_LOGDIR=${PXF_LOGDIR:=${PXF_BASE}/logs}

: "${GPHOME:?GPHOME must be set before running this script}"
if [[ -f "${GPHOME}/greenplum_path.sh" ]]; then
  # shellcheck source=/dev/null
  . "${GPHOME}/greenplum_path.sh"
elif [[ -f "${GPHOME}/cloudberry-env.sh" ]]; then
  # shellcheck source=/dev/null
  . "${GPHOME}/cloudberry-env.sh"
else
  echo "ERROR: expected to find greenplum_path.sh or cloudberry-env.sh under ${GPHOME}" >&2
  exit 1
fi

# create a log file with a timestamp in the name
# example: $PXF_LOGDIR/pxf-pre-gpupgrade.20220302135812.log
log_file="${PXF_LOGDIR}/$(basename "${0}").$(date +%Y%m%d%H%M%S).log"
touch "${log_file}"

export PGHOST="${PGHOST:-localhost}"
export PGPORT=${PGPORT:-5432}
export PGDATABASE="${PGDATABASE:-gpadmin}"
export PGUSER=${PGUSER:-gpadmin}
export PGPASSWORD=${PGPASSWORD:-}

cat <<EOF >>"${log_file}"
Postgres Connection Parameters
    \$PGHOST='${PGHOST}'
    \$PGPORT='${PGPORT}'
    \$PGDATABASE='${PGDATABASE}'
    \$PGUSER='${PGUSER}'
    \$PGPASSWORD='${PGPASSWORD//?/*}'
EOF

metadata_file="${PXF_HOME}/gpextable/metadata"
pxf_gpdb_major_version=""
if [[ -f "${metadata_file}" ]]; then
    pxf_gpdb_major_version="$(awk 'BEGIN { FS = "=" } /cloudberry.major-version/{ print $2 }' "${metadata_file}")"
else
    echo "WARNING: metadata file '${metadata_file}' not found; skipping PXF/Cloudberry compatibility check" >>"${log_file}"
fi
gp_version="$(psql --no-align --tuples-only --command "SHOW server_version")"
pxf_version="$(cat "${PXF_HOME}"/version)"

echo "PXF ${pxf_version} compiled against Cloudberry major version '${pxf_gpdb_major_version}'" >>"${log_file}"
echo "Running Cloudberry cluster is version '${gp_version}'" >>"${log_file}"

if [[ -n "${pxf_gpdb_major_version}" && "${pxf_gpdb_major_version}" != "${gp_version%%.*}" ]]; then
    echo "ERROR: This version of PXF only works with Cloudberry ${pxf_gpdb_major_version}+ but the targeted Cloudberry cluster is ${gp_version}" | tee -a "${log_file}"
    exit 1
fi

coordinator_data_dir_query="SELECT datadir FROM pg_catalog.gp_segment_configuration WHERE dbid = 1"
export COORDINATOR_DATA_DIRECTORY="${COORDINATOR_DATA_DIRECTORY:-$(psql --no-align --tuples-only --command "${coordinator_data_dir_query}")}"
echo "Cloudberry coordinator data directory is '${COORDINATOR_DATA_DIRECTORY}'" >>"${log_file}"

if [[ -d "${PXF_HOME}/gpextable" ]]; then
    PXF_HOME_REGEX="(.*:)*\/gpextable.*"
    dynamic_library_path="$(gpconfig --show dynamic_library_path | grep 'Master.*value:' | sed -e 's/Master.*value: \(.*\)/\1/')"

    if [[ "${dynamic_library_path}" =~ $PXF_HOME_REGEX ]]; then
        echo "GUC 'dynamic_library_path=${dynamic_library_path}' already contains \$PXF_HOME/gpextable" >>"${log_file}"
        echo "Skipping adding '${PXF_HOME}/gpextable' to 'dynamic_library_path'" >>"${log_file}"
    else
        echo "Adding '${PXF_HOME}/gpextable' to 'dynamic_library_path=${dynamic_library_path}'" >>"${log_file}"
        new_dynamic_library_path="${PXF_HOME}/gpextable:${dynamic_library_path}"
        # for GPDB 5, must `\`-escape dollar-sign ($) in the value passed to gpconfig
        if [[ "${gp_version}" = 5* ]]; then
            new_dynamic_library_path="${new_dynamic_library_path//$/\\$}"
        fi
        {
            echo "New value for 'dynamic_library_path' is '${new_dynamic_library_path}'"
            gpconfig --change dynamic_library_path --value "${new_dynamic_library_path}"
            gpstop -u
        } &>>"${log_file}"
    fi
else
    echo "PXF gpextable directory not found under ${PXF_HOME}; skipping dynamic_library_path update" >>"${log_file}"
fi

echo "Updating PXF function definitions" >>"${log_file}"
psql --no-align --tuples-only --command "SELECT datname FROM pg_catalog.pg_database WHERE datname != 'template0';" | while read -r dbname; do
    echo -n "checking if database '${dbname}' has PXF extension installed... " >>"${log_file}"
    if ! psql --dbname="${dbname}" --no-align --tuples-only --command "SELECT extname FROM pg_catalog.pg_extension WHERE extname = 'pxf'" | grep . &>/dev/null; then
        echo "skipping database '${dbname}'" >>"${log_file}"
        continue
    fi
    echo "updating PXF extension UDFs in database '${dbname}'" >>"${log_file}"
    psql --dbname="${dbname}" --set ON_ERROR_STOP=on &>>"${log_file}" <<-END_OF_SQL
		CREATE OR REPLACE FUNCTION pg_catalog.pxf_write() RETURNS integer
		AS 'pxf', 'pxfprotocol_export'
		LANGUAGE C STABLE;

		CREATE OR REPLACE FUNCTION pg_catalog.pxf_read() RETURNS integer
		AS 'pxf', 'pxfprotocol_import'
		LANGUAGE C STABLE;

		CREATE OR REPLACE FUNCTION pg_catalog.pxf_validate() RETURNS void
		AS 'pxf', 'pxfprotocol_validate_urls'
		LANGUAGE C STABLE;

		CREATE OR REPLACE FUNCTION pg_catalog.pxfwritable_import() RETURNS record
		AS 'pxf', 'gpdbwritableformatter_import'
		LANGUAGE C STABLE;

		CREATE OR REPLACE FUNCTION pg_catalog.pxfwritable_export(record) RETURNS bytea
		AS 'pxf', 'gpdbwritableformatter_export'
		LANGUAGE C STABLE;
	END_OF_SQL

    # PXF extension 2.1 introduces a new function, only update the function if it exists
    # bash and POSIX sh don't support decimals in numbers, however we are doing a string comparison
    # on the version here so let us ignore the shellcheck error
    # shellcheck disable=SC2072
    if [[ $(psql --dbname="${dbname}" --no-align --tuples-only --command "SELECT extversion FROM pg_catalog.pg_extension WHERE extname = 'pxf'") > 2.0 ]]; then
    psql --dbname="${dbname}" --set ON_ERROR_STOP=on &>>"${log_file}" <<-END_OF_SQL
		CREATE OR REPLACE FUNCTION pg_catalog.pxfdelimited_import() RETURNS record
		AS 'pxf', 'pxfdelimited_import'
		LANGUAGE C STABLE;
	END_OF_SQL
    fi
done

echo "Success" | tee -a "${log_file}"
