Opening Text File in DataStage BASIC

Post questions here relative to DataStage Server Edition for such areas as Server job design, DS Basic, Routines, Job Sequences, etc.

Moderators: chulett, rschirm, roy

Post Reply
ray.wurlod
Participant
Posts: 54595
Joined: Wed Oct 23, 2002 10:52 pm
Location: Sydney, Australia
Contact:

Opening Text File in DataStage BASIC

Post by ray.wurlod »

I had posted this earlier, but in the ADN downloads area as a DSX file. A few people report that they don't have ADN access and would like it here. It shows the full drama that you should go through when opening a text file. The code is good with any version of DataStage from 1.0 through 8.7.

Code: Select all

FUNCTION OpenSequentialFile(PathName, OpenMode, WriteMode, LogEvents)
$COPYRIGHT "Copyright (c) 2002, Ray Wurlod.  All rights reserved."
$* This code may be used freely with the above copyright notice intact."

$UNDEFINE TESTING

      RoutineName = "OpenSequentialFile"

* Initialize variables

      Ans = @NULL
      ErrMsg = ""


* Check that no arguments are unassigned or null.  If they are, return without attempting to open file.

      If Unassigned(Pathname)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with Pathname argument unassigned."
      End

      If Unassigned(OpenMode)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with OpenMode argument unassigned."
      End

      If Unassigned(WriteMode)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with WriteMode argument unassigned."
      End

      If Unassigned(LogEvents)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with LogEvents argument unassigned."
      End

      If IsNull(Pathname)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with null Pathname argument."
      End

      If IsNull(OpenMode)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with null OpenMode argument."
      End

      If IsNull(WriteMode)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with null WriteMode argument."
      End

      If IsNull(LogEvents)
      Then
         ErrMsg<-1> = "Function " : RoutineName : " invoked with null LogEvents argument."
      End


* If the ErrMsg variable is still empty, there is no problem thus far.

      If Len(ErrMsg) > 0
      Then

         * There is one line in the log event for each error encountered.
         Call DSLogWarn(ErrMsg, RoutineName)
         @User.Return.Code = ErrMsg

      End
      Else

         Ans = 0

         * Default values replace illegal values silently
         If Index("RW", OpenMode, 1) = 0 Then OpenMode = "W"
         If Index("AO", WriteMode, 1) = 0 Then WriteMode = "O"
         If Index("YN", LogEvents, 1) = 0 Then LogEvents = "Y"

         * Attempt to open the file for sequential access.  Handle all possible errors.
         OpenSeq Pathname To Ans
         On Error
            ErrMsg = "Error opening " : Quote(Pathname) : ".  ErrorCode = " : Status() : "."
         End
         Locked
            ErrMsg = "File " : Quote(Pathname) : " in use by user number " : Status() : "."
         End
         Then
            If OpenMode = "W"
            Then
               @User.Return.Code = 0
               If WriteMode = "O"
               Then
                  WeofSeq Ans            ; * truncate file (so overwriting can occur)
               End
               Else
                  Seek Ans,0,2
                  Else
                     ErrMsg = "Unable to position to end of " : Quote(Pathname) : "."
                  End                    ; * Seek
               End                       ; * if WriteMode = "O"
            End                          ; * if OpenMode = "W"
         End
         Else
            If Status() = 0
            Then
               If OpenMode = "W"
               Then
                  @User.Return.Code = 0
                  NULL                   ; * file opened OK for writing, does not yet exist
               End
               Else
                  @User.Return.Code = 2  ; * "file does not exist"
                  ErrMsg = Quote(Pathname) : " can not be opened for reading because it does not exist."
               End                       ; * if OpenMode = "W"
            End
            Else
               @User.Return.Code = Status()
               ErrMsg = Quote(Pathname) : " does not appear to be a file that can be opened."
            End
         End                             ; * end of OpenSeq statement

         If Len(ErrMsg) > 0
         Then
            @User.Return.Code = ErrMsg
            If LogEvents = "Y"
            Then
               Call DSLogWarn(ErrMsg, RoutineName)
            End
         End

      End

$IFDEF TESTING
      If FileInfo(Ans,0)
      Then
         CloseSeq Ans
         Ans = (If Len(ErrMsg) Then "Bad Test" Else "File variable " : Quote(Pathname))
      End
$ENDIF

RETURN(Ans)

Documentation (from the General tab)

Arguments:
Pathname pathname of the file to be opened using OpenSeq
OpenMode "R" = open for reading (file must exist), "W" = open for writing
WriteMode "O" = overwrite existing file, "A" = append to existing file. Ignored if OpenMode = "R".
LogEvents "Y" = generate warnings into caller's job log (default), "N" = do not log warnings

Returns:
file handle file opened successfully
anything else file not opened successfully

If the file is not opened successfully, system variable @User.Return.Code contains text of log event, whether or not that event was logged.
The return value may be the operating system error code, the DataStage user number of a process that already has the file open, or a DataStage error code.


Testing
======

This routine can not be tested in the conventional manner in the Test Grid, because it is not legal to display a file variable (the error message is "improper data type".
To test the routine in the grid, toggle the TESTING token near the top of the code from $UNDEFINE TESTING to $DEFINE TESTING then recompile and test.
Once your testing is complete, toggle the TESTING token back from $DEFINE TESTING to $UNDEFINE TESTING and recompile.


Example
=======

Code: Select all

DEFFUN OpenSequentialFile(filename, openmode, writemode, logevents) CALLING "DSU.OpenSequentialFile"

MyFile = "/usr/mydir/sample.txt"
* Open file for reading
FileVariable = OpenSequentialFile(MyFile, "R", "A", "Y")
If FileInfo(FileVariable, 0)
Then
   * file opened for reading
End
Else
   * file not opened, routine logged warning
   Reason = @User.Return.Code
End
IBM Software Services Group
Any contribution to this forum is my own opinion and does not necessarily reflect any position that IBM may hold.
Post Reply