#! /bin/bash

SEPLINE="@___@---@===@***@===@---@___@"

function murksel()
{
  awk -v SEPLINE="$SEPLINE" '

    function printArray( arr, end ) {
      # print array up to index end
      for ( i = 0; i < end; ++i )
	print arr[i]
    }


    BEGIN {
      pstate = 0	# 0:search 1:replace 2:process
      sidx = ridx = 0
    }


    ( pstate < 2 && $0 == SEPLINE ) {
      pstate += 1
      next
    }

    ( pstate == 0 ) {
      ### collect search text
      ### printf "- %s\n", $0 > "/dev/stderr"
      spat[sidx] = $0
      sidx += 1
      next
    }

    ( pstate == 1 ) {
      ### collect replace text
      ### printf "+ %s\n", $0 > "/dev/stderr"
      rpat[ridx] = $0
      ridx += 1
      next
    }

    ( pstate == 2 ) {
      ### search/replace pattern checks (if any)
      if ( !sidx || !ridx ) {
	printf "*** EMPTY PATTERN: s %d / r %d\n", sidx, ridx > "/dev/stderr"
	exit 99
      }
      ### print "GOOD TO GO...." > "/dev/stderr"
      pstate += 1
      sidx = 0
    }


    ( sidx && $0 != spat[sidx] ) {
      ### thats been a partial match
      printArray( spat, sidx )
      sidx = 0
      ### ...but maybe its start of a new match...
    }

    ( $0 == spat[sidx] ) {
      ### collect matching lines
      sidx += 1
      if ( sidx == length(spat) ) {
	### gotcha - print replacement
	printArray( rpat, ridx )
	sidx = 0
      }
      next
    }

    ### context
    { print }


    END {
      if ( sidx ) {
	### partial match at the end
	printArray( spat, sidx )
      }
    }
  '
}


### --------------------------------------------------
{
  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION _get_log_auth() RETURNS numeric
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $_$
    global the_user_id
    return $the_user_id
$_$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION _get_log_auth() RETURNS numeric
    LANGUAGE plpgsql
    AS $$
begin
    return 0;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION _get_log_id() RETURNS numeric
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $_$
    global the_log_id
    return $the_log_id
$_$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION _get_log_id() RETURNS numeric
    LANGUAGE plpgsql
    AS $$
begin
    return 0;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION _get_log_stamp() RETURNS character varying
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $_$
    global the_stamp
    return $the_stamp
$_$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION _get_log_stamp() RETURNS character varying
    LANGUAGE plpgsql
    AS $$
begin
    return '';
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION _set_log_auth(user_id numeric, stamp character varying) RETURNS void
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $_$
    global the_user_id
    set the_user_id $1
    global the_stamp
    set the_stamp $2
$_$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION _set_log_auth(user_id numeric, stamp character varying) RETURNS void
    LANGUAGE plpgsql
    AS $$
begin
    return;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION _set_log_id(log_id numeric) RETURNS void
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $_$
    global the_log_id
    set the_log_id $1
    return
$_$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION _set_log_id(log_id numeric) RETURNS void
    LANGUAGE plpgsql
    AS $$
begin
    return;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION clear_log_id() RETURNS void
    LANGUAGE pltclu
    SET search_path TO logging,"$user",public
    AS $$
    global the_log_id
    set the_log_id 0
    global the_user_id
    set the_user_id 0
    global the_stamp
    set the_stamp ""
    return
$$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION clear_log_id() RETURNS void
    LANGUAGE plpgsql
    AS $$
begin
    return;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'
CREATE FUNCTION set_log_auth(user_id numeric) RETURNS void
    LANGUAGE plpgsql
    SET search_path TO logging,"$user",public
    AS $$
begin
    perform _set_log_auth(user_id, current_timestamp::varchar);
end
$$;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
CREATE FUNCTION set_log_auth(user_id numeric) RETURNS void
    LANGUAGE plpgsql
    AS $$
begin
    return;
end;
$$;

EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'

CREATE EXTENSION IF NOT EXISTS pltclu WITH SCHEMA pg_catalog;

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
-- EXTENSION pltclu dropped
EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel | {

  ### SEARCH:
  cat <<'EOF'

COMMENT ON EXTENSION pltclu IS 'PL/TclU untrusted procedural language';

EOF

  echo "$SEPLINE"

  ### REPLACE:
  cat <<'EOF'
-- EXTENSION pltclu dropped
EOF

  echo "$SEPLINE"
  ### DBDUMP:
  cat

} | murksel
