#! /usr/bin/perl
########################################################################
# (c) Copyright IBM Corp. 2007 All rights reserved.
#
# The following sample of source code ("Sample") is owned by International
# Business Machines Corporation or one of its subsidiaries ("IBM") and is
# copyrighted and licensed, not sold. You may use, copy, modify, and
# distribute the Sample in any form without payment to IBM, for the purpose of
# assisting you in the development of your applications.
#
# The Sample code is provided to you on an "AS IS" basis, without warranty of
# any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR
# IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do
# not allow for the exclusion or limitation of implied warranties, so the above
# limitations or exclusions may not apply to you. IBM shall not be liable for
# any damages you suffer as a result of using, copying, modifying or
# distributing the Sample, even if IBM has been advised of the possibility of
# such damages.
#########################################################################
#
# SOURCE FILE NAME: wlmhist.pl
#
# TITLE: Generate historical data
#
# PURPOSE: Generates historical data for activities that are captured
#          in the event_activity and event_activitystmt logical data 
#          groups.
#
# DETAILS: This tool will extract information from the event_activity
#          and event_activitystmt logical data groups (such as the activity
#          statement) based on user input and for each activity extracted
#          it will:
#          - run explain on the activity
#          - extract information from the explain tables
#          - message the extracted information
#          - insert historical data into the wlmhist table (which this tool
#            will create if the it does not exist)
# 
#          Data from the wlmhist table as well as from the 
#          event_activity logical data group will be used as input to 
#          the wlmhistrep tool to generate historical reports
#
# FORMAT: wlmhist.pl dbname user password [fromTime toTime workloadid
#         serviceClassName serviceSubclassName activityTable activityStmtTable]
#         Use - to bypass any optoinal parameters.
#
#               data put into the wlmhist table.                     
##########################################################################

select STDERR; $|=1;
select STDOUT; $|=1;

use strict;
use warnings; 
use DBI;
use Data::Dumper;

# access the module for historical common functions 
#--------------------------------------------------
use DB2WlmHist;

# check and parse the command line arguments
# call the subroutine WLMArgChk to verify the arguments passed in.
#------------------------------------------------------------------
my ($database, $user, $password, $fromTime, $toTime, $workloadId,
    $serviceClassName, $serviceSubClassName, $activity, $activityStmt) 
          = WLMArgChk(@ARGV);
my $schemaName;

# If the activity and activitystmt parms were not specified, set their
# defaults
#---------------------------------------------------------------------
my $activityTable;
$schemaName = $user;

# hang on to the activity table name without the schema to be used later to
# determine whether we are in EEE or EE
if ($activity eq "-")
{
  $activityTable = "ACTIVITY_DB2ACTIVITIES";
  $activity = "$schemaName.ACTIVITY_DB2ACTIVITIES";
} else {
  $activityTable = $activity;
  $activity = "$schemaName.$activity";
}
if ($activityStmt eq "-")
{
  $activityStmt = "$schemaName.ACTIVITYSTMT_DB2ACTIVITIES";
} else {
  $activityStmt = "$schemaName.$activityStmt";
}


# declare return code, statement handler, database handler and local variable
#----------------------------------------------------------------------------
my ($rc, $sth, $dbh, $i, $numberProcessed, $numberProcessedSucc);

my @tables;     # Will contain all the table names that we have
                # accessed during the historical generate.  This is
                # a performance enhancement so that we don't have to 
                # perform a query for every table..if it has already been
                # accessed, then it will, instead, already be in this list


print "Generate historical data for database of $database \n";

# Set value indicating how many queries to process before doing a commit.
# This is for performance reasons so we are not committing all the time
#-----------------------------------------------------------------------
my $numRequestsToProcess = 100;

# connect to the database
#------------------------
print "\n  Connecting to database...\n";
if ($password eq "-")
{
  $dbh = DBI->connect($database, "", "", {AutoCommit => 0})
              or die "Can't connect to $database: $DBI::errstr";
} 
else 
{
  $dbh = DBI->connect($database, $user, $password, {AutoCommit => 0})
              or die "Can't connect to $database: $DBI::errstr";
}

print "\n  Connected to database.\n";


# Call the subroutine CreateWLMHISTTable to create the WLMHIST table
#--------------------------------------------------------------------
$rc = CreateWLMHISTTable();
if ($rc != 0)
{
  die "\nFailed to create WLMHIST table.\n";
}
  
# Call routine to remove any information from the explain tables
# that may have been added from the last run but somehow were not
# removed
#------------------------------------------------------------------
RemoveInfoFromExplainTables(1);

# Call routine to determine whether or not we are on EE or EEE
#--------------------------------------------------------------
my $isEEE = CheckPartition($dbh, $schemaName, $activityTable);

# call the subroutine MainGenerate to extract the activity text for
# all activities that meet the criteria specified by the input arguments and
# for each activity, run explain on it, extract information from the
# explain tables, massage the data and then insert that data into the 
# WLMHIST table
#----------------------------------------------------------------------------
$numberProcessed = 0;
$numberProcessedSucc = 0;
$rc = MainGenerate($schemaName, $fromTime, $toTime, $workloadId, $serviceClassName, $serviceSubClassName);
if (!defined $rc)
{
  die "\nSomething went wrong with generating historical data\n";
}

# disconnect from the database
#-------------------------------
print "\n  Disconnecting from database...\n";
$dbh->disconnect
  or die $DBI::errstr;

print "\n  Disconnected from database.\n";
print "\n  Total number of activities processed by historical generator: $numberProcessed Total number of activities processed successfully: $numberProcessedSucc \n\n";

##########################################################################
# Description : Checks and parses the command line arguments
# Input       : An array containing the command line arguments that was 
#               passed to the calling function
# Output      : Database name, user name, password, schemaName, fromTime, 
#               toTime, workloadId, serviceClassName, serviceSubclassName             
###########################################################################
sub WLMArgChk
{
  my $arg_c = @_; # number of arguments passed to the function
  my @arg_l; # arg_l holds the values to be returned to calling function
  my $i = 0;

  if($arg_c > 10 or $arg_c < 3 or ($arg_c == 1 and (($_[0] eq "?") or
                                  ($_[0] eq "-?") or
                                  ($_[0] eq "/?") or
                                  ($_[0] eq "-h") or
                                  ($_[0] eq "/h") or
                                  ($_[0] eq "-help" ) or
                                  ($_[0] eq "/help" ) ) ) or
      ($arg_c == 2 and $_[1] eq "-") or
      ($arg_c == 3 and $_[2] eq "-") or
      ($arg_c > 3 and ($_[1] eq "-" or $_[2] eq "-")))
  {
    die << "EOT";
Usage: 
 wlmhist.pl dbAlias userId passwd [fromTime toTime workloadid serviceClassName serviceSubclassName activityTable activityStmtTable] 

 Use - to bypass optional parameters.

 The from_time and to_time must be specified in timestamp format
    For example 2007-06-06-17.00.00
      
EOT
  }   

  # Set the database, user, password arguments
  #-------------------------------------------
  $arg_l[0] = "dbi:DB2:".$_[0];
  $arg_l[1] = $_[1];
  $arg_l[2] = $_[2];

  # Rest of the arguments are optional so if they are not specified
  # set them to - for now
  #----------------------------------------------------------------
  if ($arg_c <= 10)
  {
    $i = 3;
    while ($i <= 10)
    {
      if ($i < $arg_c)
      {
        $arg_l[$i] = $_[$i];
      } 
      else 
      {
        $arg_l[$i] = "-";
      }
      $i = $i + 1;
    }
  }

  return @arg_l;
} # WLM ArgChk


#######################################################################
# Description : Creates the wlmhist table if it does not already exist
# Input       : None 
# Output      : Returns 0 on success, exits otherwise
#######################################################################
sub CreateWLMHISTTable
{
  # Uppercase the user to use in 
  #------------------------------
  $schemaName =~ tr/a-z/A-Z/;

  # prepare and execute SQL statement to determine if the wlmhist table
  # already exists or not 
  #---------------------------------------------------------------------
  my $selectStmt = "select count(*) from sysibm.systables where name = 'WLMHIST' and creator ='$schemaName'";
  my $numberFound = 0;
  $sth = PrepareExecuteSql($dbh, $selectStmt);
  $numberFound = $sth->fetchrow();

  # commit the transaction or call TransRollback() from DB2SampUtil.pm 
  # if it fails
  #--------------------------------------------------------------------
  $dbh->commit() or 
    TransRollback($dbh);
  $sth->finish;

  # Only create the table if it does not yet exist  
  #------------------------------------------------
  if ($numberFound == 0)
  {
    
    # SQL to create the wlm hist table
    #---------------------------------
    my $sql = 
     "CREATE TABLE $schemaName.WLMHIST".
     "(ACTIVITY_ID BIGINT not null, UOW_ID INTEGER not null, ".
       "APPL_ID VARCHAR(64) not null, ".
       "ACTIVITY_SECONDARY_ID SMALLINT not null,  ".
       "ACTIVITY_TYPE VARCHAR(64) not null, ".
       "OBJECT_TYPE char(1), OBJECT_SCHEMA VARCHAR(128), ".
       "OBJECT_NAME VARCHAR(128), TABLE_SCHEMA VARCHAR(128) not null, ".
       "TABLE_NAME VARCHAR(128) not null, TIME_CREATED TIMESTAMP not null, ".
       "TIME_STARTED TIMESTAMP not null, TIME_COMPLETED TIMESTAMP not null, ".
       "CREATOR VARCHAR(128) not null)";

    # prepare and execute the SQL statement.
    # call the subroutine PrepareExecuteSql() from DB2WlmHist.pm
    #-------------------------------------------------------------
    $sth = PrepareExecuteSql($dbh, $sql); 

    # commit the transaction or call TransRollback() from DB2WlmHist.pm 
    # if it fails
    #---------------------------------------------------------------------
    $dbh->commit() or 
      TransRollback($dbh);
    $sth->finish;
  } 
  else 
  {
    print "\n  WLMHIST table already exists\n";
  }
 

  return 0;
} # CreateWLMHISTTable

#######################################################################
# Description : Main subroutine for generating historical data
# Input       : None 
# Output      : Returns 0 on success, exits otherwise
#######################################################################
sub MainGenerate
{
  my ($stmtText, $timeCreated, $timeStarted, $timeCompleted, $activityId, $uowId, $applicationId, $activitySecondaryId, $activityType, $creator, $compEnv);
 
  # set up SQL to run that will select the stmt text for all of the
  # activities based on input parameters/filters
  #----------------------------------------------------------------
  my $fromTimeText = "";
  my $toTimeText = "";
  my $workloadIdText = "";
  my $serviceClassText = "";
  my $serviceSubClassText = "";
  my $checkPartitionText = "";
  if ($fromTime ne "-")
  {
    $fromTimeText = " and a1.time_started > timestamp('$fromTime')";  
  }
  if ($toTime ne "-")
  {
    $toTimeText = " and a1.time_started <= timestamp('$toTime')";  
  }
  if ($workloadId ne "-")
  {
    $workloadIdText = " and a1.workload_id = ".$workloadId;
  }
  if ($serviceClassName ne "-")
  {
    $serviceClassText = " and a1.service_superclass_name = '$serviceClassName'";
  }
  if ($serviceSubClassName ne "-")
  {
    $serviceSubClassText = " and a1.service_subclass_name = '$serviceSubClassName'";
  }
 
  # If this is EEE, then we want to make sure we only get the activities 
  # from the coord partition.
  #---------------------------------------------------------------------- 
  if ($isEEE)
  {
    $checkPartitionText = 
              "a1.partition_number = a1.coord_partition_num and ";
  }

  # Query to extract the activity text from the monitor activity table.
  # Only extract DML
  #---------------------------------------------------------------------
  my $sqlToGetStmt = 
       "select a2.stmt_text, a1.time_created, a1.time_started, ".
              "a1.time_completed, a1.activity_id, a1.uow_id, a1.appl_id, ".
              "a1.activity_secondary_id, ".
              "a1.activity_type, a1.session_auth_id, a2.comp_env_desc ".
       "from $activity as a1, $activityStmt as a2 ".
       "where a1.activity_id = a2.activity_id and a1.uow_id = a2.uow_id and ".
              "a1.appl_id = a2.appl_id and ".
              "a1.activity_secondary_id = a2.activity_secondary_id and ".
              "$checkPartitionText".
              "partial_record = 0 and ".
              "appl_name != 'DB2HMON' and ".
              "(a1.activity_type = 'DML' or a1.activity_type = 'READ_DML' or ".
               "a1.activity_type = 'WRITE_DML') ".
        "$fromTimeText $toTimeText $workloadIdText $serviceClassText ".
        "$serviceSubClassText";

  my $sqlToRunExplain = qq(explain all set querytag = 'DB2WLMQUERY' for);
  my $sqlToSetComp = "set compilation environment = ?";
  my $sqlToRunExplainStmt = "";
  my ($cth, $tth);

  # Prepare and execute SQL to fetch the information from the monitor
  # tables
  #-----------------------------------------------------------------------
  $sth = PrepareExecuteSql($dbh, $sqlToGetStmt); 

  my $compEnvLength = 0;

  my $i = 0;
  # Fetch activities and for each:
  # - set the compilation env
  # - run explain
  # - extract info from explain tables
  # - insert info into wlmhist table
  # - remove info from explain tables for activity
  #-------------------------------------------------
  while (($stmtText, $timeCreated, $timeStarted, $timeCompleted, 
          $activityId, $uowId, $applicationId, $activitySecondaryId, 
          $activityType, $creator, 
          $compEnv) = $sth->fetchrow())
  {

    # Only try generating historical data for activities that
    # have a compilation environment
    #--------------------------------------------------------
    $compEnvLength = length($compEnv);
    if ($compEnvLength > 0)
    {

      # Set the compilation environment
      #---------------------------------
      $cth = $dbh->prepare($sqlToSetComp); 
      $cth->execute($compEnv);
      $cth->finish;
     
 
      # Set up SQL to run explain on activity statement
      #-------------------------------------------------
      $sqlToRunExplainStmt = "$sqlToRunExplain $stmtText";

      # Execute the explain statement
      #-------------------------------------------
      $tth = $dbh->do($sqlToRunExplainStmt) or
            print("\n Error running explain ".$DBI::errstr." for statement ".$stmtText."\n\n");

      if (defined $tth)
      {
        $numberProcessedSucc++;
      }
      
      # Call routine to extract the information from the explain tables
      # and insert it into the wlmhist table    
      #-----------------------------------------------------------------
      $rc = ExtractExplainInfo($activityId, $uowId, $applicationId, $activitySecondaryId, $activityType, $timeCreated, $timeStarted, $timeCompleted, $creator );

      # Call routine to remove the information just added from the 
      # explain tables
      #------------------------------------------------------------
      $rc = RemoveInfoFromExplainTables(0);

      # Increment counter and commit after every 10 activities. 
      #---------------------------------------------------------
      $i = $i + 1;
      $numberProcessed++;
      if ($i >= $numRequestsToProcess)
      {
        $dbh->commit();
        $i = 0;
        print "\n $numberProcessed activities processed....\n";
      }

    }
  }
  $sth->finish;
  $dbh->commit();
} #MainGenerate

#######################################################################
# Description : Extracts information from the explain tables and
#               inserts them into the wlmhist table
# Input       : Variables used to filter down what to extract from the
#               explain tables.  Filter consists of:
#               - activity_id
#               - uow_id
#               - application_id
#               - activity_secondary_id
#               - activity_type
#               - time_created
#               - time_completed
#               - creator
# Output      : Returns 0 on success, exits otherwise
#######################################################################
sub ExtractExplainInfo
{
  # Get input variables
  #--------------------
  my ( $activityId,
       $uowId,
       $applicationId,
       $activitySecondaryId,
       $activityType,
       $timeCreated,
       $timeStarted,
       $timeCompleted,
       $creator) = @_;

  # variables that will contain information extracted from the explain tables
  #--------------------------------------------------------------------------
  my ($exRequester, $exTime, $exSourceName, $exSourceSchema, $exSourceVersion, $exSourceType, $exObjectSchema, $exObjectName, $exStatementType, $exColumnNames);

  # Set up SQL to run extract information from the explain tables.  
  #----------------------------------------------------------------
  my $sqlToGetInfo = 
       "SELECT S2.explain_requester, S2.explain_time, S2.source_name, ".
              "S2.source_schema, S2.source_version, S2.source_type, ".
              "S2.object_schema, S2.object_name, S1.statement_type, ".
              "S2.column_names ".
       "FROM $schemaName.EXPLAIN_STATEMENT S1, $schemaName.EXPLAIN_STREAM S2 ".
       "WHERE S1.explain_requester = S2.explain_requester AND ".
             "S1.explain_time = S2.explain_time AND ".
             "S1.source_name = S2.source_name AND ".
             "S1.source_schema = S2.source_schema AND ".
             "S1.source_version = S2.source_version AND ".
             "S1.explain_level = S2.explain_level AND ".
             "S1.stmtno = S2.stmtno AND ".
             "S1.sectno = S2.sectno AND ".
             "S1.querytag = 'DB2WLMQUERY' order by S1.explain_time desc";

  # prepare and execute the SQL statement to fetch all the 
  # information from the explain tables.
  #----------------------------------------------------------
  my $eth = PrepareExecuteSql($dbh, $sqlToGetInfo); 
  my ($isIndex, $syscatTabName, $syscatTabSchema, $i, $numCols, @arr, $element,
      @arr2, $colName);
  my $numberOfColumns = 0;
  
  # SQL to insert information from explain tables into wlmhist table
  #------------------------------------------------------------------
  my $insertSql = 
      "insert into $schemaName.WLMHIST (".
         "ACTIVITY_ID, UOW_ID, APPL_ID, ACTIVITY_SECONDARY_ID, ACTIVITY_TYPE, ".
         "OBJECT_TYPE, ".
         "OBJECT_SCHEMA, OBJECT_NAME, TABLE_SCHEMA, TABLE_NAME, TIME_CREATED, ".
         "TIME_STARTED, TIME_COMPLETED, CREATOR) ".
      "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

  my $ith = $dbh->prepare($insertSql);

  my $rc;
  my $objectType = 'C';
  my $empty = '';

  # Loop around and fetch all the information from the explain tables
  # for this one particular activity.
  # - Massage the data
  #   - if the entry is an index, need to get the table schema and table
  #     from the syscat.indexes table.
  #   - If the entry is a column, some parsing must be done to get the 
  #     column information out
  # - Insert data into wlmhist table
  #-----------------------------------------------------------------------
  while (($exRequester, $exTime, $exSourceName, $exSourceSchema, 
          $exSourceVersion, $exSourceType, $exObjectSchema, $exObjectName, 
          $exStatementType, $exColumnNames) = 
          $eth->fetchrow())
  {
    # remove trailing blanks
    #--------------------------
    if (defined $exSourceSchema)
    {
      $exSourceSchema =~ s/\s+$//;
    }
    if (defined $exObjectSchema)
    {
      $exObjectSchema =~ s/\s+$//;
    }

    # Find out if the object is an index.  If it is, then message the data
    # and add it to the wlmhist table
    #----------------------------------------------------------------------
    if (defined $exObjectName)
    {
      ($isIndex, $syscatTabName, $syscatTabSchema) = 
         IsIndex($exObjectName, $exObjectSchema);

      if ($isIndex)
      {
        
        # remove trailing blanks
        #-------------------------
        $syscatTabSchema =~ s/\s+$//;
        $syscatTabName =~ s/\s+$//;
       
        # We know the object is an index so set the type
        #------------------------------------------------ 
        $objectType = 'I';

        # Based on information from the activity monitor tables and 
        # the explain tables, insert record into the wlmhist table
        #------------------------------------------------------------
        $rc = InsertRowToWLMHIST($activityId,
                                 $uowId,
                                 $applicationId,
                                 $activitySecondaryId,
                                 $activityType,
                                 $objectType,
                                 $exObjectSchema,
                                 $exObjectName,
                                 $syscatTabSchema,
                                 $syscatTabName,
                                 $timeCreated,
                                 $timeStarted,
                                 $timeCompleted,
                                 $creator);

        # Copy the Table name and schema into the proper variables
        # for the next insert if there are columns for this statement
        #-------------------------------------------------------------
        $exObjectSchema = $syscatTabSchema;
        $exObjectName = $syscatTabName;
      }

      # Now get the columns
      #---------------------
      $objectType = 'C';
      if (defined $exColumnNames)
      {
        # Parse through the excolumn_names which comes in the format 
        # something like q1.colname+q1.colname2.q1.RID.....
        #------------------------------------------------------------
        @arr = split('\+', $exColumnNames);
        $numCols = scalar @arr;
        for ($i = 0; $i < $numCols; $i++)
        {
          $element = $arr[$i];
        
          # Get rid of the qualifier (i.e. Q1.COLNAME..remove the Q1)
          #---------------------------------------------------------
          @arr2 = split('\.', $element);
          $colName = $arr2[1];
         
          # Get rid of any $RID$ that exists
          #----------------------------------
          if ( defined $colName and
               length($colName) > 0 and
               !($colName eq "\$RID\$"))
          {
          
            $numberOfColumns++;

            # Insert extracted information into the wlmhist table
            #----------------------------------------------------           
            $rc = InsertRowToWLMHIST($activityId,
                                     $uowId,
                                     $applicationId,
                                     $activitySecondaryId,
                                     $activityType,
                                     $objectType,
                                     $empty,
                                     $colName,
                                     $exObjectSchema,
                                     $exObjectName,
                                     $timeCreated,
                                     $timeStarted,
                                     $timeCompleted,
                                     $creator);

          }
        }
      }
      # If there were no columns, then just add an entry for the table
      # ---------------------------------------------------------------
      if ($numberOfColumns == 0)
      {
        # There were no columns so insert the table name into the wlmhist table
        #----------------------------------------------------------------------
        $rc = InsertRowToWLMHIST($activityId,
                                 $uowId,
                                 $applicationId,
                                 $activitySecondaryId,
                                 $activityType,
                                 $objectType,
                                 $empty,
                                 $empty,
                                 $exObjectSchema,
                                 $exObjectName,
                                 $timeCreated,
                                 $timeStarted,
                                 $timeCompleted,
                                 $creator);


      }
    }

  }
  $eth->finish;
  return 0;
} #ExtractExplainInfo

#######################################################################
# Description : Determines whether an entry is an index or not.   
# Input       : Object name, Object schema
# Output      : - value indicating whether it is an index or not   
#               - table name (if index)
#               - table schema (if index)
#######################################################################
sub IsIndex
{
  my @arg_l; # arg_l holds the values to be returned to calling function
  my ($exObjName,
      $exObjSchema) = @_;
  my $isIndex = 0;
  my ($tableName, $tableSchema);

  # Set up SQL to run extract table name and schema for index from
  # index table
  #-----------------------------------------------------------------
  my $sqlToCheckIndex = 
       "SELECT tabname, tabschema ".
        "from SYSCAT.INDEXES ".
        "where indname = '$exObjName' and indschema = '$exObjSchema'";

  # prepare and execute the SQL statement to find out if the index 
  # exists and if it does, to get the table name and table schema for
  # that index
  #-------------------------------------------------------------------
  my $ith = $dbh->prepare($sqlToCheckIndex);
  my $rc = $ith->execute();
  if (!defined $rc)
  {
    print("\n error ".$ith->err."\n");
  }
  # Fetch information from the syscat.indexes table
  #------------------------------------------------
  ($tableName, $tableSchema) = $ith->fetchrow();
  if (defined $tableName)
  {
    $isIndex = 1;
  }

  $arg_l[0] = $isIndex;
  $arg_l[1] = $tableName;
  $arg_l[2] = $tableSchema;
  $ith->finish;
  return @arg_l;
} #IsIndex

#######################################################################
# Description : Removes the information from the explain tables   
# Input       : docommit - indicates whether or not to perform
#                          a commit after removing the items from the
#                          explain tables
# Output      : RC will be 0 if it delete was successful   
#######################################################################
sub RemoveInfoFromExplainTables
{
  
  my $doCommit = $_[0];

  # Set up SQL to run extract all the information from the explain 
  # tables that have a query tag of DB2WLMQUERY
  #-----------------------------------------------------------------
  my $sqlToGetExpInfo = 
     "SELECT explain_requester, explain_time, source_name, source_schema, ".
            "source_version from $schemaName.explain_statement ".
      "where querytag = 'DB2WLMQUERY' order by explain_time";

  my ($exRequester, $exTime, $exSourceName, $exSourceSchema, 
      $exSourceVersion, $i);
  
  # Set up SQL to delete the information from the explain tables   
  # that we added in ( with query tag DB2WLMQUERY from above query)
  #-----------------------------------------------------------------
  my $sqlToDelExpInfo = 
       "DELETE from $schemaName.explain_instance ".
          "where explain_requester = ? and explain_time = ? and ".
                "source_name = ? and source_schema = ? and source_version = ?";
 
  my $dth = $dbh->prepare($sqlToDelExpInfo) or
          TransRollback($dbh);

  # prepare and execute the SQL statement to find all of the rows  
  # in the explain tables with the query tag of DB2WLMQUERY to remove 
  # from the explain tables
  #-------------------------------------------------------------------
  my $eth = $dbh->prepare($sqlToGetExpInfo) or
          TransRollback($dbh);

  my $rc = $eth->execute() or
          TransRollback($dbh);

  if (!defined $rc)
  {
    print("\n error ".$eth->err."\n");
  }

  # Loop around and find all the entries in the explain table that
  # we added in as a result of this historical generator.  
  #----------------------------------------------------------------
  $i = 0;
  while (($exRequester, $exTime, $exSourceName, $exSourceSchema, 
          $exSourceVersion) = 
          $eth->fetchrow())
  {
    # fill in all of the ? with the proper values for the delete
    #------------------------------------------------------------
    $dth->bind_param_inout(1, \$exRequester, 128) or die $dth->errstr;
    $dth->bind_param_inout(2, \$exTime, 128) or die $dth->errstr;
    $dth->bind_param_inout(3, \$exSourceName, 128) or die $dth->errstr;
    $dth->bind_param_inout(4, \$exSourceSchema, 128) or die $dth->errstr;
    $dth->bind_param_inout(5, \$exSourceVersion, 64) or die $dth->errstr;
        
    # Execute insert
    #----------------
    $rc = $dth->execute() or 
          TransRollback($dbh);
    if (!defined $rc)
    {
      print("\nrc not defined for insert errorstring ". $dth->err."\n");
    }

    # Increment counter and commit after every 10 activities only
    # if we are called to do a commit.  We are only doing it every
    # 10 activities to help improve the performance
    #-------------------------------------------------------------
    $i = $i + 1;
    if ($i > $numRequestsToProcess and $doCommit)
    {
      $dbh->commit();
      $i = 0;
    }

  }
  
  # do finial commit at end if we are told to commit
  #-------------------------------------------------
  if ($doCommit)
  {
    $dbh->commit() or TransRollback($dbh);
  }

  $dth->finish;
  return $rc;
} #RemoveInfoFromExplainTables

#######################################################################
# Description : Verifies that the table exists.  If it was an alias
#               it will get the real name of the table
# Input       : Table name, Table schema
# Output      : Table name, Table schema   
#######################################################################
sub CheckTable
{
  # Set up SQL to run extract all the information from the explain 
  # tables that have a query tag of DB2WLMQUERY
  #-----------------------------------------------------------------
  my @arg_l; # arg_l holds the values to be returned to the calling function
  my ($tabSchema,
      $tabName) = @_;

  my $objectType = ""; # will hold the result from the select to determine whether
                  # the table was a view, alias, or table

  my $sqlToGetTable = 
    "SELECT CASE TYPE ".
       "WHEN 'T' then 'TABLE' ".
       "WHEN 'V' then 'VIEW' ".
       "WHEN 'A' then 'ALIAS' ".
       "else 'SUMMARY' end ".
    "from SYSCAT.TABLES WHERE tabschema = ? and tabname = ?";
  
  my ($i, $rc, $found);

  # First check to determine whether we have seen this table or not
  #----------------------------------------------------------------
  my $numTables = scalar @tables;
  $found = 0;
  for ($i = 0; $i < $numTables; $i++)
  {
    
    if ($tables[$i] eq ($tabSchema.".".$tabName))
    {
      $found = 1;
      last;
    }
  }
   
  # The table was not found in the table array so we have to
  # do a query to make sure it exists in the syscat.systables table
  #-----------------------------------------------------------------
  if (!$found)
  {
    my $tth = $dbh->prepare($sqlToGetTable);
    $tth->bind_param_inout(1, \$tabSchema, 128);
    $tth->bind_param_inout(2, \$tabName, 128);
  
    my $rc = $tth->execute();
    if (!defined $rc)
    {
      print("\n error finding table".$tth->err."\n");
    }
    else
    {
      ($objectType) = $tth->fetchrow();
      $tth->finish;

      # If it was an alias, then we need to find the proper table
      # name from the systables table
      if (defined $objectType)
      {
        if ($objectType eq "ALIAS")
        {
          my $sqlToGetAliasTable = 
             "select base_tabschema, base_tabname ".
             "from syscat.tables ".
             "where tabschema = ? and tabname = ?";

          my $ath = $dbh->prepare($sqlToGetAliasTable);
          $ath->bind_param_inout(1, \$tabSchema, 128);
          $ath->bind_param_inout(2, \$tabName, 128);
          $rc = $ath->execute();
          if (!defined $rc)
          {
            print("\n error finding alias table".$ath->err."\n");
          }
          else
          {
            ($tabSchema, $tabName) = $ath->fetchrow();
            $found = 1;
          }
          $ath->finish;
 
        }
        else
        {
          # Add the table to the list of tables so we don't have to
          # query this table again from the tables
          #---------------------------------------------------------
          $tables[$numTables] = $tabSchema.".".$tabName;
          $found = 1;
        }
      }
    }
  }
  $arg_l[0] = $found;
  $arg_l[1] = $tabSchema;
  $arg_l[2] = $tabName;

  return @arg_l;
} #CheckTable

#######################################################################
# Description : Inserts a row to the WLMHIST table.
# Input       : Values for each column.  Consists of:
#               - activity id
#               - uow id
#               - application id
#               - activity secondary id
#               - activity type
#               - object type (i.e. column or index)
#               - object schema
#               - object name   
#               - table schema
#               - table name
#               - time created
#               - time started
#               - time completed
#               - user
# Output      : rc   
#######################################################################
sub InsertRowToWLMHIST
{
  my $rc;

  my ($activityId,
      $uowId,
      $applId,
      $activitySecondaryId,
      $actType,
      $objType,
      $objSchema,
      $objName,
      $tabSchema,
      $tabName,
      $timeCreated,
      $timeStarted,
      $timeCompleted,
      $thisUser) = @_;

  my $empty = '';

  # SQL to insert information from explain tables into wlmhist table
  #------------------------------------------------------------------
  my $insertsql = 
      "insert into $schemaName.WLMHIST ".
            "(ACTIVITY_ID, UOW_ID, APPL_ID, ACTIVITY_SECONDARY_ID, ".
             "ACTIVITY_TYPE, OBJECT_TYPE, ".
             "OBJECT_SCHEMA, OBJECT_NAME, TABLE_SCHEMA, TABLE_NAME, ".
             "TIME_CREATED, TIME_STARTED, TIME_COMPLETED, CREATOR) ".
      "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

  my $ith = $dbh->prepare($insertsql);

  # Check if table exists and also if the table was
  # an alias, then get the proper table name
  #--------------------------------------------------
  my @arr = CheckTable($tabSchema, $tabName);
  if ($arr[0])
  {
    $tabSchema = $arr[1];
    $tabName = $arr[2];

    # fill in all of the ? with the proper values for the insert
    #------------------------------------------------------------
    $ith->bind_param_inout(1, \$activityId, 8);
    $ith->bind_param_inout(2, \$uowId, 4);
    $ith->bind_param_inout(3, \$applId, 64);
    $ith->bind_param_inout(4, \$activitySecondaryId, 2);
    $ith->bind_param_inout(5, \$actType, 64);
    $ith->bind_param_inout(6, \$objType, 1);
    $ith->bind_param_inout(7, \$objSchema, 128);
    $ith->bind_param_inout(8, \$objName, 128);
    $ith->bind_param_inout(9, \$tabSchema, 128);
    $ith->bind_param_inout(10, \$tabName, 128);
    $ith->bind_param_inout(11, \$timeCreated, 128);
    $ith->bind_param_inout(12, \$timeStarted, 128);
    $ith->bind_param_inout(13, \$timeCompleted, 128);
    $ith->bind_param_inout(14, \$thisUser, 128);
      
    # Execute insert
    #----------------
    $rc = $ith->execute();
    if (!defined $rc)
    {
      print("\nrc not defined for insert of index errorstring ". 
            $ith->err."\n");
    }

  }
  $ith->finish;

  return $rc;
} #InsertRowToWLMHIST