Module Reportds.pkg

     1//************************************************************************
     2//
     3// Confidential Trade Secret.
     4// Copyright 1987-1995 Data Access Corporation, Miami FL, USA
     5// All Rights reserved
     6// DataFlex is a registered trademark of Data Access Corporation.
     7//
     8//************************************************************************
     9
    10//************************************************************************
    11// ReportDS.Pkg
    12// Version: 1.1
    13//  Wed  11-25-1992  Created
    14//
    15// Author: John J. Tuohy
    16//
    17//************************************************************************
    18// 2/26/2002  JJT - 8.2 clean up (indirect_file, local, self, etc.)
    19// 12/13/2001 JJT - Added Validate_items dummy method to report object
    20// 10/19/97 JJT - changed find_init to send clear to srvr when DD used.
    21//                Otherwise parent is not cleared and it is attached in for
    22//                a find first.
    23// 06/09/97 JJT - made mods for DD support. Request_Save in RO now sends
    24
    25//************************************************************************
    26
    27//
    28// Report_Ds - Report class that can optionally use data_sets.
    29//
    30// If Data_sets are used the report can support batch updates where files
    31// are saved and deleted (via request_save and request_delete).
    32//
    33// IMPORTANT: All constraints including "relates to" constraints MUST be
    34// handled by the data_set and not the report object (when in Rome do as the
    35// Romans). Also, the report's relate_main_file, No_Constrained_Find_State and
    36// No_relate_state are ignored - these same properties in the data_set are used
    37// instead.
    38//
    39// This class can be used as a non-data_set class (just don't set the server).
    40//
    41// New Syntax:
    42//
    43// To hook into a Data_set, three syntaxes
    44//       Object Order_Rpt is a Report_ds Using DATA_SET_NAME
    45//
    46// <or>  Object Order_Rpt is a Report_ds
    47//          Report_Data_Set DATA_SET_NAME
    48//
    49// <or>  Object Order_Rpt is a Report_ds
    50//         Set Server to DATA_SET_NAME
    51//
    52// New Public Interface:
    53//
    54//   PROPERTY: Server
    55//      This is the object ID of the data_set. If 0, the report will behave
    56//      exactly like a non_ds report. This is usually only set once and
    57//      usually when the object is created. This can be done with the USING
    58//      object command line parameter, the SET SERVER TO command, or the
    59//      RPT_DATA_SET command.
    60//
    61//   PROPERTY: Deferred_State (Default=TRUE)
    62//      This determines if accesses to the data_set causes refresh messages
    63//      to get sent to other objects using this data_set. Setting this TRUE
    64//      reduces traffic a bit. This can be set FALSE but you should know what
    65//      you are doing.
    66//
    67//   PROCEDURE: Request_Save
    68//      If sent, will save the current record. Usually sent in Body section.
    69//      Use Entry_Update message to make the changes during the save process.
    70//      All parent files are properly modified. This is M/U solid.
    71//
    72//   PROCEDURE: Request_Delete
    73//      If sent (usually in the body) this will delete the current record thru
    74//      the data_set. After delete the record remains unchanged in the buffer
    75//      (including the recnum). All parent files are properly updated and
    76//      all multi-user requirements are met.
    77//
    78//   PROCEDURE Entry_Update
    79//      Does nothing. This is the user hook that you fill out to make changes
    80//      the record you are saving. If this were a DEO this would get called
    81//      when you need to update from the forms to the database. This is a
    82//      manual version of this.
    83//
    84//   PROCEDURE Refresh
    85//      This is normally a stub that does nothing. A clever data_set expert
    86//      might be able to make use of this.
    87//
    88
    89// Changes for RowId
    90//    Removed Read_by_recnum, Replaced with RowId
    91//    removed Found_rec       to priFoundRec
    92
    93
    94
    95use report.pkg
    96use data_set.pkg
    97
    98{ Classtype=Abstract }
    99{ HelpTopic=Report_DS }
   100Class Report_DS is a Report STARTMAC Report_DS_Start
   101
   102  Procedure Construct_Object // Integer Img#
   103    Forward Send Construct_Object // Img#
   104
   105    //**// I had toyed with supporting constraints in both data_sets and
   106    //**// the report object. I decided against this because data_sets get
   107    //**// too complicated when you deal with saves and deletes, and, I felt
   108    //**// it was best to work "within the system" and let Data_sets do what
   109    //**// they want.
   110    //**//
   111    //**// Constrain_by_Report_State: If true and using data_sets
   112    //**//                            nesting of reports determines the
   113    //**//                            relates_to constraint. Server constraints
   114    //**//                            are always respected
   115    //**Property Integer Constrain_by_Report_State FALSE  // alter with care
   116
   117    { DesignTime=False }
   118    Property Integer Server                    0      // data_set
   119    // When used with DDs, deferred_state will really not work properly and
   120    // should therefore be avoided.
   121    { Visibility=Private }
   122    Property Integer Deferred_State            False  // makes less traffic
   123    { Visibility=Private }
   124    Property Integer Auto_Fill_State           False  // Required not used
   125  End_Procedure  // Construct_Object
   126
   127  { MethodType=Event Visibility=Private }
   128  Procedure Refresh          // Display - required
   129  End_Procedure
   130
   131  { Visibility=Private }
   132  Procedure Entry_Update     // Update from report to datafile.
   133  End_Procedure              // User hook routine.
   134
   135  { Visibility=Private }
   136  Function Validate_Items integer iFg returns integer // Could be sent by validate_items from DDO. -required
   137       function_return 0                              // never used.
   138  End_Function
   139
   140  Procedure Request_Delete   // Supports deletes. Should be called in body
   141    Integer Srvr# iRec       //                   procedure.
   142    integer iFile iStat
   143    Boolean bSupportRecnum
   144    Get Server to Srvr#
   145    If Srvr# Begin
   146       if (Deferred_State(self)) ;
   147           send Request_Assign to srvr# 0  //0 means main_file of Server
   148      // when deleted the record number is lost. Remember this number
   149      // and restore it so that findings will work properly.
   150      Get main_file of srvr# to iFile
   151      Move (IsRecnumTable(self,iFile)) to bSupportRecnum
   152      If bSupportRecnum Begin
   153          Get_Field_value iFile 0 to iRec     // compatibility w/ recnum
   154      end
   155      Send Request_Delete to Srvr#
   156      If bSupportRecnum Begin
   157        // now move rec back into file if a delete really occured
   158        Get_Attribute DF_FILE_STATUS of iFile to iStat
   159        If (iStat=DF_FILE_INACTIVE) Begin
   160            Set_Field_value iFile 0 to iRec   // compatibility w/ recnum
   161        end
   162      end
   163    End
   164  End_Procedure
   165
   166  Procedure Request_Save   // supports saves
   167    Integer Srvr#    // entry_update should handle updating.
   168    Integer NotOK
   169    Get Server to Srvr#
   170    If Srvr# Begin
   171       if (Deferred_State(self)) ;
   172           send Request_Assign to srvr# 0  //0 means main_file of Server
   173       Set Changed_state of Srvr# to TRUE
   174       Get Request_Validate of Srvr# to NotOK
   175       If NotOk Procedure_return
   176       Send Request_Save to Srvr# // note: returns ERR if error occurred
   177    End
   178  End_Procedure
   179
   180  //
   181  //  Augmented to add this object from the Data_set's user interface
   182  //
   183  { NoDoc=True }
   184  Function Start_Report returns integer
   185    Integer Retval
   186    // 11.1 change. The outer report will attach all child reports to their DDs at the start of the
   187    // report and not every time a child starts (this slowed down reports). This connection is only needed
   188    // if you are sending request_save from your report and you are counting on using entry_update to update
   189    // your fields. This is an old technique and is not recommended. It would be better to interact directly
   190    // with the DD using the DD interface. All of this extra work of attaching and detaching is only provided
   191    // for backwards compatibility. Also, this might make more sense in Starting_main_report, but we are keeping
   192    // it here for compatibility reasons. Otherwise, we'd just remove all of the attaching/detaching completely.
   193    // All of the above appliues to End_report.
   194    If (not(Child_Rpt_State(self))) begin
   195        Send AddReportsToServer
   196    end
   197    forward get start_Report to retval
   198    Function_Return retval
   199  End_Function // Start_Report
   200
   201  //
   202  //  Augmented to remove this object from the Data_set's user interface
   203  // See notes in Start_report about 11.1 change
   204  { NoDoc=True }
   205  Function End_Report integer rpt_Status returns integer
   206    Integer Retval
   207    forward get end_report rpt_status to retval
   208    If (not(Child_Rpt_State(self))) begin
   209        Send RemoveReportsFromServer
   210    end
   211    Function_Return retval
   212  End_Function
   213
   214
   215    // See notes in Start_report. Added in 11.1 Attaches all reports to all DDs just once in outer report
   216    { Visibility=Private }
   217    Procedure AddReportsToServer
   218        Handle hoDD
   219        Boolean bHasChildren
   220        Get Has_Children_Rpt_State to bHasChildren
   221        get Server to hoDD
   222        If hoDD Begin
   223            Send Add_User_Interface of hoDD self
   224        end
   225        if bHasChildren Begin
   226           Broadcast Send AddReportsToServer
   227        end
   228    end_Procedure
   229
   230    // See notes in Start_report. Added in 11.1 detaches all reports from all DDs just once in outer report
   231    { Visibility=Private }
   232    Procedure RemoveReportsFromServer
   233        Handle hoDD
   234        Boolean bHasChildren
   235        Get Has_Children_Rpt_State to bHasChildren
   236        get Server to hoDD
   237        // remove in childmost order. This is what the old behavior did, so just keep using it
   238        if bHasChildren begin
   239           Broadcast Send RemoveReportsFromServer
   240        end
   241        If hoDD Begin
   242            Send Remove_User_Interface of hoDD self
   243        end
   244    end_Procedure
   245
   246  //
   247  // Procedure: Find_Init
   248  // set up this file for finding... This clears the needed buffers
   249  //
   250  { NoDoc=True }
   251  Procedure Find_Init
   252    Integer Srvr# Mode file# ndx#
   253    Get Server to Srvr#
   254    If Srvr# eq 0 Forward send Find_init
   255    Else begin
   256      Move (if(Find_Down_State(self),1,3)) to Mode // LE or GE
   257      Get main_file of srvr# to File#
   258      Get Ordering to Ndx#
   259      // 9/7/98 JJT - we do not need to set the DDO
   260      //              ordering
   261      //Set Ordering of Srvr# to Ndx#
   262      Send Rebuild_Constraints to Srvr#
   263      // we only want to clear parents of the outer report. This was changed in 11.1. The Clear
   264      // message is not needed with child reports and it can really slows things down because it
   265      // adds a lot of DD messages (even when deferred). This clear is only needed at the top report
   266      // level where a buffer may contain unknown parent data. With child reports this is controlled.
   267      If Not (Child_Rpt_State(self)) begin
   268          Send Clear to Srvr# // this will clear needed parents as well
   269      End
   270      Constrained_Clear Mode File# BY Ndx#
   271      Send establish_find_direction to srvr# mode file# Ndx#
   272    end
   273  End_Procedure
   274
   275  //
   276  // Augment to find record in Data_set if Server exists
   277  //
   278  { NoDoc=True }
   279  Function Find_Rec Returns Integer
   280    Integer srvr# rval
   281    Integer File# Ndx# Dfrd
   282    Integer iRec
   283
   284    Get server to srvr#
   285
   286    if (srvr# = 0) begin                 // if no server do
   287       forward get find_rec to rval     // standard finding
   288       function_return rval             // behavior
   289    end
   290    //
   291    // Server exists. Channel the Find through the data_set
   292    //
   293    Get main_file to File#
   294    Get Ordering to Ndx#
   295    Get Deferred_State to Dfrd
   296    // if not deferred find next record and notify all other DEOs
   297    // if deferred just find the record
   298    If not Dfrd Send Request_Find to Srvr# Next_record file# Ndx#
   299    Else        Send Locate_Next to Srvr#
   300    If (Found) Begin                   // set priFoundRec
   301      Set priFoundRec to (GetRowId(File#))
   302      // for compatibility sake.
   303      If (IsRecnumTable(self,File#)) begin
   304          Get_field_value File# 0 to iRec     // compatibility w/ recnum
   305          Set Found_Rec to  iRec
   306      end
   307      Function_Return RPT_OK
   308    End
   309    Function_return RPT_END
   310  End_Function
   311
   312    //
   313    //  Procedure : ReadByRowId
   314    //              Augmented to direct read to server
   315    { Visibility=Private NoDoc=True }
   316    Procedure ReadByRowId RowId riRec
   317        Handle hoDD
   318        integer iFile eStat
   319        rowId riCrnt riDDO
   320        Boolean bSameRec
   321
   322        // optimized for 11.1: If no find is needed, don't find. If DD is up to date, leave it alone
   323        // We will not find if rec if active and is the same RowId. If DDOs and not-deferred, CurrentRowId must also match
   324
   325        Get Server to hoDD
   326        Get Main_File of (if(hoDD,hoDD,self)) to iFile // main-file from Object or DDO (if ddo)
   327
   328        // if no main file we cannot find
   329        If (iFile=0) Begin
   330            indicate Found False
   331            Procedure_Return    
   332        End
   333        
   334        Get_Attribute DF_FILE_STATUS of iFile to eStat
   335        Move (eStat<>DF_FILE_INACTIVE) to bSameRec
   336        If bSameRec begin
   337            Move (GetRowID(iFile)) to riCrnt
   338            Move (IsSameRowId(riRec,riCrnt)) to bSameRec
   339            Indicate Found True // you should not rely on this - but just in case.
   340        End
   341
   342        If not hoDD begin
   343            If not bSameRec Begin
   344                Forward send ReadByRowId riRec
   345            end
   346        end
   347        Else Begin
   348
   349            If (Deferred_state(self)) begin
   350                If not bSameRec begin
   351                    Send ReadbyRowId of hoDD iFile riRec // if deferred
   352                End
   353            end
   354            Else Begin
   355                Get CurrentRowId of hoDD to riDDO
   356                If ( Not(bSameRec) or Not(IsSameRowId(riRec,riDDO)) ) begin
   357                    Send FindByRowId of hoDD iFile riRec // if not deferred
   358                End
   359            end
   360        End
   361    End_procedure
   362//    Procedure ReadByRowId RowId riRec
   363//        Handle hoDD
   364//        integer iFile
   365//        Get Server to hoDD
   366//        If not hoDD begin
   367//            Forward send ReadByRowId riRec
   368//        end
   369//        Else Begin
   370//            Get Main_File of hoDD to iFile
   371//            If (Deferred_state(self)) begin
   372//                Send ReadbyRowId of hoDD iFile riRec // if deferred
   373//            end
   374//            Else Begin
   375//                Send FindByRowId of hoDD iFile riRec // if not deferred
   376//            end
   377//        End
   378//    End_procedure
   379
   380{ Visibility=Private NoDoc=True }
   381//  Procedure Read_By_Recnum Integer Rec#
   382//    Integer srvr# File#
   383//    Get Server to Srvr#
   384//    If Srvr# eq 0 Forward send Read_by_Recnum Rec#
   385//    Else Begin
   386//      Get Main_File of Srvr# to File#
   387//      If (Deferred_state(self)) ;
   388//           Send Read_by_Recnum to srvr# File# rec# // if deferred
   389//      Else Send Find_by_Recnum to srvr# File# rec# // if not deferred
   390//    End
   391//  End_procedure
   392
   393  //
   394  // Augment to set Report Object's main_file if server exists
   395  //
   396  Procedure End_Construct_Object
   397    Integer Srvr# File#
   398    Get Server to Srvr#
   399    If Srvr# Begin
   400       Get Main_file of Srvr# to File#
   401       Set Main_File to File#
   402    End
   403    Forward Send End_Construct_Object
   404  End_Procedure
   405
   406
   407End_Class
   408
   409
   410#COMMAND Report_DS_Start
   411  FORWARD_BEGIN_CONSTRUCT !1 !2 !3 !4 !5 !6 !7 !8 !9
   412  bind_Report_Data_set !1 !2 !3 !4 !5 !6 !7 !8 !9
   413#ENDCOMMAND
   414
   415#COMMAND bind_report_Data_set
   416  #IF (!0>0)
   417    #IFSAME !1 USING
   418      Report_Data_set !2
   419    #ELSE
   420      bind_report_data_set !2 !3 !4 !5 !6 !7 !8 !9
   421    #ENDIF
   422  #ENDIF
   423#ENDCOMMAND
   424
   425//
   426//  Set a report's dataset
   427//
   428#COMMAND Report_Data_Set R .
   429   #IFDEF !1
   430     set Server to !1
   431   #ELSE
   432     set Server to !1.obj
   433   #ENDIF
   434#ENDCOMMAND
   435