DROP FUNCTION IF EXISTS microsharding_migration_after(text, text, text);
CREATE OR REPLACE FUNCTION microsharding_migration_after(
  hosts text = NULL,
  only_if_has_schema text = NULL, -- text, because it may not exist here
  dst_schema text = 'public' -- text for symmetry with *_before() function
) RETURNS SETOF text
LANGUAGE plpgsql
SET search_path FROM CURRENT
AS $$
DECLARE
  host_specs text[] := NULL;
BEGIN
  SET client_min_messages TO WARNING;

  only_if_has_schema := COALESCE(only_if_has_schema, microsharding_schema_name_(0));

  IF hosts IS NOT NULL THEN
    IF host_specs IS NULL THEN
      BEGIN
        host_specs := ARRAY(SELECT v FROM json_array_elements_text(hosts::json) v);
      EXCEPTION
        WHEN invalid_json_text THEN
          -- continue
        WHEN invalid_text_representation THEN
          -- continue
        WHEN invalid_parameter_value THEN
          -- continue
      END;
    END IF;
    IF host_specs IS NULL THEN
      BEGIN
        host_specs := hosts::text[];
      EXCEPTION
        WHEN invalid_text_representation THEN
          -- continue
      END;
    END IF;
    IF host_specs IS NULL THEN
      host_specs := string_to_array(hosts, ',');
    END IF;
    IF
      EXISTS (SELECT 1 FROM unnest(host_specs) WHERE unnest !~ '^(.+?)(?::(\d*))?(?:/(.*))?$')
      OR cardinality(host_specs) = 0
    THEN
      RAISE EXCEPTION
        'The list in hosts must be a JSON array, a PostgreSQL array or a comma-separated list of valid hostnames or host:port/db specifiers; "%" provided.',
        hosts;
    END IF;
  END IF;

  -- These queries are expensive, they hold lots of locks and use lots of shared
  -- memory. The error would say "out of shared memory ... You might need to
  -- increase max_locks_per_transaction", which is partially a red herring:
  -- there may be thousands of locks being held, whilst default
  -- max_locks_per_transaction=64, and it would still work. So better keep their
  -- work to zero, by calling microsharding_migration_before() in another
  -- transaction before running microsharding_migration_after().
  PERFORM microsharding_debug_views_drop(dst_schema::text);
  PERFORM microsharding_debug_fdw_drop('debug_fdw');

  IF EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = only_if_has_schema) THEN
    IF host_specs IS NOT NULL THEN
      PERFORM microsharding_debug_fdw_create('debug_fdw', host_specs);
      RETURN QUERY SELECT *
        FROM microsharding_debug_views_create(dst_schema::text, 'debug_fdw');
      PERFORM microsharding_notice_locks_('Done');
    ELSE
      RETURN QUERY SELECT *
        FROM microsharding_debug_views_create(dst_schema::text);
    END IF;
  END IF;
END;
$$;

COMMENT ON FUNCTION microsharding_migration_after(text, text, text)
  IS 'Can be run after all other migration DDL statements to create '
     'cross-shard debug views in the database. If hosts is passed '
     'as a JSON array, a PostgreSQL array or a comma-separated list of '
     'hostnames, then the function will crease FOREIGN DATA WRAPPER schemas '
     'for all shards schemas on the remote host_specs, and then use them in the '
     'created debug views; otherwise, the debug views will union only the '
     'schemas of the current database. This all is done only if the current '
     'host has a schema named only_if_has_schema (defaults to "sh0000"), '
     'i.e. only on the host with "global shard". If dst_schema is passed, '
     'then debug views will be created in that schema (otherwise, in public).';
