   sname text;
   tname text;
   htname text;
+  htable_exists bool;
+  trigger_exists bool;
 BEGIN
   SELECT s.schema_name, t.table_name INTO sname, tname
   FROM _ermrest.known_tables t

    '  END IF;'
    '  RETURN NULL;'
    'END; $$ LANGUAGE plpgsql;' ;
    
  EXECUTE
    'CREATE TRIGGER ermrest_history AFTER INSERT OR UPDATE OR DELETE ON '
    || quote_ident(sname) || '.' || quote_ident(tname)
    || ' FOR EACH ROW EXECUTE PROCEDURE _ermrest_history.' || quote_ident('maintain_' || htname) || '();';
    
  EXECUTE
    'INSERT INTO _ermrest_history.' || quote_ident(htname) || '("RID", during, rowdata)'
    'SELECT'
    '  t."RID",'
    '  tstzrange(t."RMT", NULL, ''[)''),'
    '  (SELECT jsonb_object_agg(' || CASE WHEN sname = '_ermrest' THEN 'j.k' ELSE 'c."RID"::text' END || ', j.v)'
    '   FROM jsonb_each(to_jsonb(t)) j (k, v)'
    '   JOIN _ermrest.known_columns c ON (j.k = c.column_name AND c.table_rid = ' || quote_literal(table_rid) || ')'
    '   WHERE c.column_name NOT IN (''RID'', ''RMT''))'
    'FROM ' || quote_ident(sname) || '.' || quote_ident(tname) || ' t';
END;
$func$ LANGUAGE plpgsql;


  -- we do the same for column names within the history jsonb rowdata blobs below.
  htname := CASE WHEN sname = '_ermrest' THEN tname ELSE 't' || table_rid END;

  IF NOT htable_exists
  THEN
    -- avoid doing dynamic SQL during every trigger event by generating a custom function per table here...
    EXECUTE
      'CREATE TABLE _ermrest_history.' || quote_ident(htname) || '('
      '  "RID" text NOT NULL,'
      '  during tstzrange NOT NULL,'
      '  "RMB" text,'
      '  rowdata jsonb NOT NULL,'
      '  EXCLUDE USING GIST ("RID" WITH =, during with &&)'
      ');' ;
  END IF;

  EXECUTE 'COMMENT ON TABLE _ermrest_history.' || quote_ident(htname) || ' IS '
    || quote_literal('History from ' || now()::text || ' for table ' || quote_ident(sname) || '.' || quote_ident(tname)) || ';';
