# Tests for PERFORMANCE_SCHEMA
# Verify the orthogonality of iterators (table*::rnd_next()),
# for every table and instruments.

--source include/not_embedded.inc
--source include/have_perfschema.inc

--disable_warnings
drop procedure if exists check_instrument;
--enable_warnings

delimiter $;
create procedure check_instrument(in instr_name varchar(128))
begin
  declare count_expected integer;
  declare count_actual integer;
  declare is_wait integer;
  declare is_stage integer;
  declare is_statement integer;
  declare is_wait_table integer;
  declare is_stage_table integer;
  declare is_statement_table integer;
  declare pfs_table_name varchar(64);
  declare msg varchar(512);
  declare msg_detail varchar(512);
  declare cmd_1 varchar(512);
  declare cmd_2 varchar(512);
  declare done integer default 0;
  declare debug integer default 0;

  declare pfs_cursor CURSOR FOR
    select table_name from information_schema.tables
      where table_schema= 'performance_schema'
      and table_name like "events_%_by_event_name%";

  declare continue handler for sqlstate '02000'
    set done = 1;

  select (instr_name like "wait/%") or (instr_name like "idle/%") into is_wait;
  select (instr_name like "stage/%") into is_stage;
  select (instr_name like "statement/%") into is_statement;

  select instr_name, is_wait, is_stage, is_statement;

  select count(name)
    from performance_schema.setup_instruments
    where (name like (concat(instr_name, "%")))
    and (not name like "%/abstract/%")
    into count_expected;

  set cmd_1= "select count(*) from (select distinct event_name from performance_schema.";
  set cmd_2= concat(" where event_name like \"",
                    instr_name,
                    "%\") t into @count_actual");

  open pfs_cursor;
  repeat
    fetch pfs_cursor into pfs_table_name;
    if not done then
      select (pfs_table_name like "%waits%") into is_wait_table;
      select (pfs_table_name like "%stages%") into is_stage_table;
      select (pfs_table_name like "%statements%") into is_statement_table;

      select concat("Checking table ", pfs_table_name, " ...") as status;
      select concat(cmd_1, pfs_table_name, cmd_2) into @cmd;
      if debug = 1
      then
        select @cmd;
      end if;
      prepare stmt from @cmd;
      execute stmt;
      drop prepare stmt;
      set msg_detail= concat("table ", pfs_table_name,
                             ", instruments ", count_expected,
                             ", found ", @count_actual);

      if is_wait = 1 and is_wait_table = 1 and @count_actual <> count_expected
      then
        set msg= concat("Missing wait events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

      if is_wait = 1 and is_wait_table = 0 and @count_actual <> 0
      then
        set msg= concat("Unexpected wait events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

      if is_stage = 1 and is_stage_table = 1 and @count_actual <> count_expected
      then
        set msg= concat("Missing stage events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

      if is_stage = 1 and is_stage_table = 0 and @count_actual <> 0
      then
        set msg= concat("Unexpected stage events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

      if is_statement = 1 and is_statement_table = 1 and @count_actual <> count_expected
      then
        set msg= concat("Missing statement events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

      if is_statement = 1 and is_statement_table = 0 and @count_actual <> 0
      then
        set msg= concat("Unexpected statement events: ", msg_detail);
        signal sqlstate '05000' set message_text= msg;
      end if;

    end if;
  until done
  end repeat;
  close pfs_cursor;

  -- Dont want to return a 02000 NOT FOUND, there should be a better way
  signal sqlstate '01000' set message_text='Done', mysql_errno=12000;
end
$
delimiter ;$

# Check the configuration is ok
show variables where
    `Variable_name` != "performance_schema_max_statement_classes" and
    `Variable_name` like "performance_schema%";

call check_instrument("wait/synch/mutex/");
call check_instrument("wait/synch/rwlock/");
call check_instrument("wait/synch/cond/");
call check_instrument("wait/synch/");
call check_instrument("wait/io/file/");
call check_instrument("wait/io/net/");
call check_instrument("wait/io/table/");
call check_instrument("wait/io/");
call check_instrument("wait/lock/table/");
call check_instrument("wait/lock/");
call check_instrument("wait/");
call check_instrument("stage/");
call check_instrument("statement/com/");
call check_instrument("statement/sql/");
call check_instrument("statement/abstract/");
call check_instrument("statement/");
call check_instrument("idle/io/socket");
call check_instrument("idle/");

drop procedure check_instrument;

