#!/usr/bin/ksh
#
# NAME:  createCommittedVersions database release level [LOGFILE]
# WHERE: database = DB2 or INFORMIX or ORACLE
#        release  = the desired CMVC release
#        level    = the desired CMVC level
#        logfile  = file name to append the SQL output
#
# An example of the usage is:
#   createCommittedVersions DB2 track-full-1.3 03 log
#
# PURPOSE:
#   To create a table called CommittedVersions which will have
#   the versions of the files in a committed level.
#   Currently, this information resides in a "level map file"
#   located in the $HOME/maps/$release directory of the
#   CMVC family administrator user id, where $release is the
#   appropriate release.
#   All the entries in the map file are added to the new table.
#
# NOTES:
# * This script must be run by the CMVC family administrator user id
#   because a direct access to the database used by the CMVC family
#   is needed.
# * This script exploits the CMVC environment variables for a family setup.
# * The format of the maps file is:
#     pathName  versionId  fileId  changeType
# * The details for database fields in the new table are:
#   * releaseId   corresponds to "id"          in Releases
#   * releaseName corresponds to "name"        in Releases
#   * levelId     corresponds to "id"          in Levels
#   * levelName   corresponds to "name"        in Levels
#   * commitDate  corresponds to "commitDate"  in Levels
#   * versionId   corresponds to "id"          in Versions and
#                 corresponds to "nuVersionId" in Files.
#   * fileId      corresponds to "id"          in Files.
#   * changeType  corresponds to "type"        in Changes.
#   * SID         corresponds to "SID"         in Versions.
#   * changeDate  corresponds to "changeDate"  in Versions.
#   * pathName is the path name from the maps file and it
#                 corresponds to "name"        in Path, which
#                 is obtained via "id"         in Path, refered to in
#                            the "pathId"      in Files.
#
# * The valid changeType values are:
#
#     create:  the file was created
#     delta:   the file was changed
#     noDelta: the file was not changed
#     delete:  the file was deleted
#     link:    the file was linked from another release
#     rename:  the file was renamed (the entry shows the new name)
#
# 5765-207 (C) COPYRIGHT International Business Machines Corp. 1993,2001
# 5765-202 (C) COPYRIGHT International Business Machines Corp. 1993,2001
# 5765-397 (C) COPYRIGHT International Business Machines Corp. 1994,2001
# All Rights Reserved
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADF Schedule Contract with IBM Corp.
#-------------------------------------------------------------------------+

#------------------------------------------------------+
#  Function: createCVTable
#  Purpose:
#  This function creates the committedVersionsTable
#------------------------------------------------------+

createCVTable()
{
if [[ $DATABASE = "INFORMIX" ]]
then
  $SQL_CMD >>$LOG 2>&1 <<!!!
create table CommittedVersions
(
    releaseId           int,
    releaseName         varchar(31),
    levelId             int,
    levelName           varchar(31),
    commitDate          varchar(25),
    versionId           int,
    fileId              int,
    changeType          varchar(8),
    SID                 varchar(47),
    changeDate          varchar(25),
    pathName            varchar(195)
)
$SEMI_STRING
$COMMIT_STRING
!!!

  rc=$?
else   # DB2 and Oracle

  $SQL_CMD >>$LOG 2>&1 <<!!!
create table CommittedVersions
(
    releaseId           int,
    releaseName         varchar(31),
    levelId             int,
    levelName           varchar(31),
    commitDate          varchar(25),
    versionId           int,
    fileId              int,
    changeType          varchar(8),
    SID                 varchar(47),
    changeDate          varchar(25),
    pathName            varchar(195)
)
$SEMI_STRING
$COMMIT_STRING
!!!
  rc=$?
fi  # type of DBMS

if [ $rc != 0 ]
then
  print ""  | tee -a $LOG
  print "ERROR while trying to create the CommittedVersions table." | tee -a $LOG
  print "Exiting now."  | tee -a $LOG
  exit 1
fi

return
}

#------------------------------------------------------+
#  Function: checkDb
#  Purpose:
#  This function checks for database errors
#  Returns:  rc=0 if OK, rc=1 if not OK.
#------------------------------------------------------+

checkDb()
{
  if  [ $DATABASE = "DB2" -o  $DATABASE = "db2" ]
  then
    RESU1=`grep "[Dd][Uu][Pp][Ll][Ii][Cc][Aa][Tt][Ee]" $LOG`
    RESU2=`grep "already exists" $LOG`
    RESU3=`grep "Can't allocate space" $LOG`
    RESU4=`grep "Cannot drop the database" $LOG`
    RESU5=`grep "SQLSTATE=" $LOG`
    RESU6=`grep "DB2....E" $LOG`
    RESU7=`grep "was ended with \"[1-9]" $LOG`
  else
    RESU1=`grep "[Ee][Rr][Rr][Oo][Rr]"                 $LOG`
    RESU2=`grep "[Dd][Uu][Pp][Ll][Ii][Cc][Aa][Tt][Ee]" $LOG`
    RESU3=`grep "already exists" $LOG`
    RESU4=`grep "Can't allocate space" $LOG`
    RESU5=`grep "Cannot drop the database" $LOG`
    RESU6=``
    RESU7=``
  fi

# The -n operator checks if str is not null (has length greater than 0)
# The -z operator checks if str is null (has length 0)

  if [ -n "$RESU1" ] || [ -n "$RESU2" ] || [ -n "$RESU3" ] || [ -n "$RESU4" ] || [ -n "$RESU5" ] || [ -n "$RESU6" ] || [ -n "$RESU7" ]
  then
    print "Database errors were found. For more information, see: $LOG"
    rc=1
  fi
}

#------------------------------------------------------+
#  Function: getDBnum1
#  Returns:  dataitem (1 single integer)
#  Purpose:
#  This function works for a query that fetches 1 numerical value.
#  It assumes anything with non-numeric is junk (header, copyright, etc)
#  For DB2 a select count yields a column header of "1", requiring the NR.
#------------------------------------------------------+

getDBnum1()
{
stmt="$*"

if [[ "$DATABASE" = "DB2" ]]
then

  dataitem=`$SQL_CMD +v "$stmt$SEMI_STRING" 2>/dev/null | awk 'NR > 2 && NF == 1 && $1 ~ /^[0-9]+$/ {print $1; exit}'
`
else

# For Oracle and Informix
    dataitem=`$SQL_CMD <<!!! 2>/dev/null | awk 'NR > 2 && NF == 1 && $1 ~ /^[0-9]+$/ {print $1; exit}'
$stmt
$SEMI_STRING
!!!
`
fi

if [[ -z "$dataitem" ]]
then
  print "getDBnum1: Failed to successfully obtain data for SQL statement: " | tee -a $LOG
  print $stmt | tee -a $LOG
  dataitem=0
fi

return
}

#------------------------------------------------------+
#  Function: getDBstring1
#  Returns:  dataitem (1 single string)
#  Purpose:
#  This function works for a query that fetches 1 string value.
#  It assumes anything with non-numeric is junk (header, copyright, etc)
#  For DB2 a select count yields a column header of "1", requiring the NR.
#------------------------------------------------------+

getDBstring1()
{
stmt="$*"

if [[ "$DATABASE" = "DB2" ]]
then

  dataitem=`$SQL_CMD +v "$stmt$SEMI_STRING" 2>/dev/null | awk 'NR > 3 {print $1; exit}'
`
elif [[ "$DATABASE" = "ORACLE" ]]
then

    dataitem=`$SQL_CMD <<!!! 2>/dev/null | awk 'NR > 14 {print $1; exit}'
$stmt
$SEMI_STRING
`
else

# For Informix
    dataitem=`$SQL_CMD <<!!! 2>/dev/null | awk 'NR > 4 {print $1; exit}'
$stmt
$SEMI_STRING
!!!
`
fi

if [[ -z "$dataitem" ]]
then
  print "getDBstring1: Failed to successfully obtain data for SQL statement: " | tee -a $LOG
  print $stmt | tee -a $LOG
  dataitem=0
fi

return

}

#------------------------------------------------------+
#  Function: getDBdate
#  Returns:  dataitem (1 compound string: date time)
#  Purpose:
#  This function works for a query that fetches 1 compound string value.
#  Specifically, for the date that has 2 sub-fields separated by a
#  blank character: YYYY/MM/DD HH:MM:SS
#  It assumes anything with non-numeric is junk (header, copyright, etc)
#  For DB2 a select count yields a column header of "1", requiring the NR.
#------------------------------------------------------+

getDBdate()
{
stmt="$*"

if [[ "$DATABASE" = "DB2" ]]
then

  dataitem=`$SQL_CMD +v "$stmt$SEMI_STRING" 2>/dev/null | awk 'NR > 3 {print $1,$2; exit}'
`
elif [[ "$DATABASE" = "ORACLE" ]]
then

    dataitem=`$SQL_CMD <<!!! 2>/dev/null | awk 'NR > 14 {print $1,$2; exit}'
$stmt
$SEMI_STRING
`
else

# For Informix
    dataitem=`$SQL_CMD <<!!! 2>/dev/null | awk 'NR > 4 {print $1,$2; exit}'
$stmt
$SEMI_STRING
!!!
`
fi

if [[ -z "$dataitem" ]]
then
  print "getDBdate: Failed to successfully obtain data for SQL statement: " | tee -a $LOG
  print $stmt | tee -a $LOG
  dataitem=0
fi

return
}

#------------------------------------------------------+
#  Main program
#------------------------------------------------------+

if [ "$#" -lt 3 ]
then
  print "Usage: createCommittedVersions database release level [LOGFILE]"
  print "where: database = DB2 or INFORMIX or ORACLE"
  print "       release  = the desired CMVC release "
  print "       level    = the desired CMVC level"
  print "       logfile  = name of a file to append the output"
  exit 1
fi

# Parsing and validation of input parameters

typeset -u DATABASE=$1
releaseName=$2
levelName=$3
LOG=$4

if [ -z "$LOG" ]
then
  LOG=/tmp/dateRest.$$; logtemp=1;
fi

if [ -z "$CMVC_FAMILY" ]
then
  print "The CMVC family must be set with the CMVC_FAMILY environment variable."
  exit 1
else
  FAMILY=`echo $CMVC_FAMILY | cut -d"@" -f1`
fi

# Creating the LOG file
print ""                                      | tee    $LOG

# The argument -a for tee is to append to the end of the file.
print "createCommittedVersions: begin "       | tee -a $LOG
print ""                                      | tee -a $LOG
print "The family name is:      $FAMILY"      | tee -a $LOG
print "The database is:         $DATABASE"    | tee -a $LOG
print "The release name is:     $releaseName" | tee -a $LOG
print "The level name is:       $levelName"   | tee -a $LOG
print "The output log file is:  $LOG"         | tee -a $LOG

# Setup the proper arguments for the desired database

case "$DATABASE" in

 ORACLE|ORACLE7|oracle|oracle7)
  DATABASE=ORACLE
  SQL=$ORACLE_HOME/bin/sqlplus
  U_STRING=""
  COMMIT_STRING=""
  PASSWORD_STRING="/$ORACLE_PASS"
  SEMI_STRING=";"
  SQL_CMD="$SQL $U_STRING $FAMILY$PASSWORD_STRING"
  CATOP="||"
  LENGTH=length
  ;;

 DB2|db2)
  DATABASE=DB2
  SQL=$DB2_HOME/sqllib/bin/db2
# The DB2 command options are:
#   -o   display output
#   -t   set termination character (semicolon)
#   -v   echo current command
#   +p   suppress the display of interactive input
  U_STRING=" -o -t -v +p"
  COMMIT_STRING=""
  PASSWORD_STRING=""
  SEMI_STRING=";"
  SQL_CMD="$SQL $U_STRING"
  CATOP="CONCAT"
  export DB2DBDFT=$FAMILY
  CATOP="||"
  LENGTH=length
  db2 connect to $FAMILY
  ;;

 INFORMIX|informix)
  DATABASE=INFORMIX
  SQL="$INFORMIXDIR/bin/dbaccess"       # Name of the isql routine

  U_STRING=""
  COMMIT_STRING="commit work;"
  PASSWORD_STRING=""
  SEMI_STRING=";"
  SQL_CMD="$SQL $U_STRING $FAMILY$PASSWORD_STRING"
  CATOP="||"
  LENGTH=length
  ;;

 *)
  print "Unrecognized database $DATABASE" | tee -a $LOG
  exit 1
  ;;

esac

print " " | tee -a $LOG
print "Find out if the CommittedVersions table exists." | tee -a $LOG

rc=0  # assume that everything is fine.

if [[ $DATABASE = "INFORMIX" ]]
then
  $SQL_CMD >>$LOG 2>&1 <<!!!
select releaseName,levelName from CommittedVersions
$SEMI_STRING
!!!

  checkDb  # Check for database errors. Modifies return code variable (rc)

else   # DB2 and Oracle
  $SQL_CMD >>$LOG 2>&1 <<!!!
select releaseName,levelName from CommittedVersions
$SEMI_STRING
!!!
  rc=$?

  # For DB2, if a table is created but does not have data yet,
  # then it returns 1, which is fine for us.
  if [ $DATABASE = "DB2" ] && [ $rc = 1 ]
  then
    rc=0   # Table exists.
  fi

  # For Oracle, check for: error ORA-00942: table or view does not exist
  if [ $DATABASE = "ORACLE" ]
  then
    errorOracle=`grep ORA-00942 $LOG`
    if [ $? = 0 ]
    then
      rc=1   # Table does not exist.
    else
      rc=0   # Table exists.
    fi
  fi

fi  # type of DBMS

# If the CommittedVersions table does not exist, then create it.
# If rc=0 then the table exists.

if [ $rc = 0 ]
then
  print " -- The CommittedVersions table already exists." | tee -a $LOG
else
  print ""  | tee -a $LOG
  print " -- The CommittedVersions table does not exist."  | tee -a $LOG
  print "Proceeding to create the CommittedVersions table."  | tee -a $LOG
  rc=0  # assume that everything is fine.
  createCVTable
  print "The CommittedVersions table was created successfully." | tee -a $LOG
fi

mapsFile=$HOME/maps/$releaseName/$levelName
print "Verifing if the maps file exists for: " $mapsFile | tee -a $LOG

if [[ ! -f $mapsFile ]]
then
  print "ERROR: the map file does not exist: " $mapsFile | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 1
else
  print " -- Mapfile exists." | tee -a $LOG
fi

# Verify if there are entries in the CommittedVersions table
# that have both the release and the level. If so, then stop,
# because we do not want to reload the data.

print "Verifying if the release and level have been processed already." | tee -a $LOG
getDBnum1 "select count(*) from CommittedVersions where releaseName='$releaseName' and levelName='$levelName'"

if [[ $dataitem -ne 0 ]]
then
  print "ERROR: the data for the release=$releaseName and level=$levelName" | tee -a $LOG
  print "is already loaded into the CommittedVersions table." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 4
else
  print " -- The release and level have not been processed yet." | tee -a $LOG
fi

print "Processing the map file for release=$releaseName and level=$levelName" | tee -a $LOG

# Get the releaseId from Releases
getDBnum1 "select id from Releases where name='$releaseName'"
if [[ $dataitem -eq 0 ]]
then
  print "ERROR: the release id for release=$releaseName could not be found." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 8
fi
releaseId=$dataitem

# Get the levelId from Levels
getDBnum1 "select id from Levels where name='$levelName' and releaseId=$releaseId"
if [[ $dataitem = "" ]]
then
  print "ERROR: the level id for level=$levelName and release=$releaseName could not be found." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 8
fi
levelId=$dataitem

# Get the commitDate for the Level
getDBdate "select commitDate from Levels where name='$levelName' and releaseId=$releaseId"
if [[ $dataitem = "" ]]
then
  print "ERROR: the commitDate for level=$levelName and release=$releaseName could not be found." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 8
fi
commitDate=$dataitem

# Process the entries in the Maps File
print " " | tee -a $LOG

while read line
do
  words=`print $line | wc -w | awk '{print $1}`
  if [ $words -eq 4 ]
  then
    # Process the pathNames that do not have blanks.
    pathName=`print $line   | cut -d' ' -f1 `  # field 1 is pathName
    versionId=`print $line  | cut -d' ' -f2 `  # field 2 is version id
    fileId=`print $line     | cut -d' ' -f3 `  # field 3 is file id
    changeType=`print $line | cut -d' ' -f4 `  # field 4 is changeType
  else
    # Process the pathNames that do have blanks.
    changeType=`print ${line} | awk '{print ($(NF-0)) }`
    fileId=`print ${line}     | awk '{print ($(NF-1)) }`
    versionId=`print ${line}  | awk '{print ($(NF-2)) }`
    pathName=`print "$line"   | sed "s/ ${versionId} ${fileId} ${changeType}//"`
  fi

  print "Processing file=$pathName versionId=$versionId fileId=$fileId  changeType=$changeType" | tee -a $LOG

# Get the SID data for the file from Versions
getDBstring1 "select SID from Versions where id=$versionId"
if [[ $dataitem = "" ]]
then
  print "ERROR: the SID id for versionId=$versionId cannot be found." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 8
fi
SID=$dataitem

# Get the changeDate from Versions
getDBdate "select changeDate from Versions where id=$versionId"
if [[ $dataitem = "" ]]
then
  print "ERROR: the changeDate for versionId=$versionId cannot be found." | tee -a $LOG
  print "Exiting now." | tee -a $LOG
  exit 8
fi
changeDate=$dataitem

# Inserting data into table

if [[ $DATABASE = "INFORMIX" ]]
then
  $SQL_CMD >>$LOG 2>&1 <<!!!
insert into CommittedVersions (releaseId,releaseName,levelId,levelName,commitDate,versionId,fileId,changeType,SID,changeDate,pathName) values ($releaseId,'$releaseName',$levelId,'$levelName','$commitDate',$versionId,$fileId,'$changeType','$SID','$changeDate','$pathName')
$SEMI_STRING
$COMMIT_STRING
!!!

  rc=$?
else   # DB2 and Oracle
  $SQL_CMD >>$LOG 2>&1 <<!!!
insert into CommittedVersions (releaseId,releaseName,levelId,levelName,commitDate,versionId,fileId,changeType,SID,changeDate,pathName)
      values ($releaseId,'$releaseName',$levelId,'$levelName','$commitDate',$versionId,$fileId,'$changeType','$SID','$changeDate','$pathName')
$SEMI_STRING
$COMMIT_STRING
!!!
  rc=$?
fi  # type of DBMS

  if [ $rc != 0 ]
  then
    print "ERROR: This part could not be inserted."  | tee -a $LOG
    print " " | tee -a $LOG
  fi
done < $mapsFile

# Terminating the program

case "$DATABASE" in
 DB2|db2)
 db2 terminate
 ;;
esac

print "createCommittedVersions: end! " | tee -a $LOG

exit 0

# end of file
