project BLF > class Persistence (other) > method WriteData

Description

Write the data to the database.
This takes care of the transfer of data from the class temp-tables to the real database tables.
It also takes care of the optimistic locking checkings (using t_i<table>).


Parameters


tDynRelinputtemp-tableDescription of the data to write.
ihClassinputhandleHandle to the class that is using the persistence layer. In most of the cases, this handle will be available in the preprocessor {&TARGETPROCEDURE}.
ihRowidConvertinputhandleHandle to the temp-table tFcRowidConvert.
icUserLogininputcharacter
oiReturnStatusoutputinteger


Internal usage


unused


program code (program1/other.p)

assign oiReturnStatus = -98
       vhOldRowid     = ihRowidConvert:buffer-field("tcFcOldRowid":U)
       vhNewRowid     = ihRowidConvert:buffer-field("tcFcNewRowid":U).
 
&if defined(DEBUGSQL) > 0 &then
run SqlDebugWrite in {&TARGETPROCEDURE} ("* ":U + program-name(1), 1).
&endif

/* Clean up the garbage */
for each tBufferFields where
         not valid-handle(tBufferFields.thTempBuffer):
    delete tBufferFields.
end.
 
/* copy tDynRel into method data items that cannot be changed by other
   instances of this method (as started by ref.integrity programs. */
for each tDynRel on error undo, throw:
    assign viDynrelNum = viDynrelNum + 1
           vcDynrelTo[viDynrelNum] = tDynRel.tcFcTo
           vhDynrelBuffer[viDynrelNum] = tDynRel.thFcBuffer
           vhDynrelIbuffer[viDynrelNum] = tDynRel.thFcIBuffer.
end.
 
do viDynrelCount = 1 to viDynrelNum:
 
    /* ================================================================= */
    /* Create recordsets for original and changed data                   */
    /* ================================================================= */
    <M-1 run UpdateBufferInfo (input  vhDynrelBuffer[viDynrelCount] (ihDestinationBuffer), 
                           input  vhDynrelIBuffer[viDynrelCount] (ihIDestinationBuffer), 
                           output viFcReturnSuper (oiReturnStatus)) in other>
    if viFcReturnSuper <> 0
    then do:
        assign oiReturnStatus = viFcReturnSuper.
        return.
    end.
 
    assign vhPdatabaseInst = ihClass.
    <M-16 run GetKeyFields (input-output vcDynrelTo[viDynrelCount] (bcTableName), 
                        output vcPkey (ocPrimaryKey), 
                        output vcDummy (ocAlternateKey), 
                        output vcDummy (ocObjectID), 
                        output vcDummy (ocObjectStatus), 
                        output viFcReturnSuper (oiReturnStatus)) in database>
    
    run SqlBufCreate in {&TARGETPROCEDURE}
       (input vcDynrelTo[viDynrelCount],
        output viBufferId,
        output viFcReturnSuper).
    if viFcReturnSuper <> 0
    then do:
        assign oiReturnStatus = viFcReturnSuper.
        return.
    end.
    
    for each tBufferFields where
             tBufferFields.thTempBuffer = vhDynrelBuffer[viDynrelCount] and
             tBufferFields.tcFieldName <> "tc_ParentRowid":U and
             tBufferFields.tcFieldName <> "tc_Rowid":U and
             tBufferFields.tcFieldName <> "tc_Status":U:
        run SqlBufAddField in {&TARGETPROCEDURE}

           (input viBufferId,
            input tBufferFields.tcFieldName,
            input tBufferFields.thDestinationField:data-type,
            input (if can-do(vcPKey, tBufferFields.tcFieldName) then 1 else 0),
            output viFieldId,
            output viFcReturnSuper).
        if viFcReturnSuper <> 0
        then do:
            assign oiReturnStatus = viFcReturnSuper.
            return.
        end.
    end.
    
    /* ================================================================= */
    /* Fill recordset with changed data.                                 */
    /* ================================================================= */
    create query vhCQuery.
    vhCQuery:set-buffers(vhDynrelBuffer[viDynrelCount]).
    create query vhOQuery.
    vhOQuery:set-buffers(vhDynrelIbuffer[viDynrelCount]).
    
    vhCQuery:query-prepare
        ("for each ":U + vhDynrelBuffer[viDynrelCount]:name +
         " where ":U + vhDynrelBuffer[viDynrelCount]:name + ".tc_status <> ''":U).
    vhCQuery:query-open().
    vhCQuery:get-first().
    
    assign vhStatusField = vhDynrelBuffer[viDynrelCount]:buffer-field("tc_Status":U)
           vhRowidField  = vhDynrelBuffer[viDynrelCount]:buffer-field("tc_Rowid":U)
           vhRefInt      = ?.
    
    do while not vhCQuery:query-off-end :
 
        vhOQuery:query-prepare(
            "for each ":U + vhDynrelIbuffer[viDynrelCount]:name + 
            " where tc_Rowid = '":U + vhRowidField:buffer-value + "'":U).
        vhOQuery:query-open().
        vhOQuery:get-first().
        
        if vhOQuery:query-off-end 
        then do:
            vhOQuery:query-close().
            vhCQuery:get-next().
            next.
        end.
 
        if vhStatusField:buffer-value = "D":U
        then do:
            if vhRefInt = ?
            then run value ("ref_int/dc_":U + vcDynrelTo[viDynrelCount] + ".p":U)
                     persistent set vhRefInt.
            run gipr_RefInt in vhRefInt
               (input vhDynrelBuffer[viDynrelCount],
                input ihClass,
                input {&TARGETPROCEDURE},
                input icUserLogin,
                output viFcReturnSuper).
            if viFcReturnSuper < 0
            then do:
                assign oiReturnStatus = viFcReturnSuper.
                if vhRefInt <> ?
                then do:
                    delete procedure vhRefInt.
                    assign vhRefInt = ?.
                end.
                vhOQuery:query-close().
                delete object vhOQuery.
                vhCQuery:query-close().
                delete object vhCQuery.
                run SqlBufDestroy in {&TARGETPROCEDURE}
                   (input viBufferId,
                    output viFcReturnSuper).
 
                return.
            end.
        end.
        
        /* set UPDATED values */
        assign viFieldId = 0.
        for each tBufferFields where
                 tBufferFields.thTempBuffer = vhDynrelBuffer[viDynrelCount] and
                 tBufferFields.tcFieldName <> "tc_ParentRowid":U and
                 tBufferFields.tcFieldName <> "tc_Rowid":U and
                 tBufferFields.tcFieldName <> "tc_Status":U :
            
            if tBufferFields.thDestinationField:buffer-value = ?
            then run SqlFldSetNull in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 1,
                     output viLocalReturn).
            else if tBufferFields.thDestinationField:data-type = "CHARACTER":U
                 or tBufferFields.thDestinationField:data-type = "DECIMAL":U
            then run SqlFldSetString in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 1,
                     input string (tBufferFields.thDestinationField:buffer-value),
                     output viLocalReturn).
            else run SqlFldSetInteger in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 1,
                     input integer(tBufferFields.thDestinationField:buffer-value),
                     output viLocalReturn).
            if viLocalReturn <> 0 then leave.
            
            assign viFieldId = viFieldId + 1.
        end.
        if viLocalReturn <> 0 then leave.
    
        
        /* set ORIGINAL values */
        assign viFieldId = 0.
        for each tBufferFields where
                 tBufferFields.thTempBuffer = vhDynrelBuffer[viDynrelCount] and
                 tBufferFields.tcFieldName <> "tc_ParentRowid":U and
                 tBufferFields.tcFieldName <> "tc_Rowid":U and
                 tBufferFields.tcFieldName <> "tc_Status":U :
            
            if tBufferFields.thIDestinationField:buffer-value = ?
            then run SqlFldSetNull in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 0,
                     output viLocalReturn).
            else if tBufferFields.thDestinationField:data-type = "CHARACTER":U
                 or tBufferFields.thDestinationField:data-type = "DECIMAL":U
            then run SqlFldSetString in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 0,
                     input string (tBufferFields.thIDestinationField:buffer-value),
                     output viLocalReturn).
            else run SqlFldSetInteger in {&TARGETPROCEDURE}
                    (input viBufferId,
                     input viFieldId,
                     input 0,
                     input integer(tBufferFields.thIDestinationField:buffer-value),
                     output viLocalReturn).
            if viLocalReturn <> 0 then leave.

            assign viFieldId = viFieldId + 1.
        end.
        if viLocalReturn <> 0 then leave.
        
        vcRowid = vhRowidField:buffer-value.
        run SqlBufWriteData in {&TARGETPROCEDURE}
           (input viBufferId,
            input vhStatusField:buffer-value,
            input vcRowid,
            output viLocalReturn).
        if viLocalReturn = -2
        then do:
            run SqlGetError in {&TARGETPROCEDURE} (output viErrAddr, output viErrCode).
            if viErrAddr > 0
            then assign vcOptLock = <M-14 getString (input  viErrAddr (iiAddr)) in other>.
        end.
        if viLocalReturn <> 0 then leave.

        run SqlBufGetRowid in {&TARGETPROCEDURE}
           (input viBufferId,
            output viCnt,
            output viLocalReturn).
        if viLocalReturn <> 0 then leave.

        ihRowidConvert:buffer-create().
        assign vhOldRowid:buffer-value = vhRowidField:buffer-value
               vhNewRowid:buffer-value = string(viCnt).
        ihRowidConvert:buffer-release().
        
        vhOQuery:query-close().
        vhCQuery:get-next().
    end.
    
    vhOQuery:query-close().
    delete widget vhOQuery.
    vhCQuery:query-close().
    delete widget vhCQuery.
    
    if vhRefInt <> ?
    then do:
        delete procedure vhRefInt.
        assign vhRefInt = ?.
    end.
 
    run SqlBufDestroy in {&TARGETPROCEDURE}
       (input viBufferId,
        output viFcReturnSuper).
 
    if viLocalReturn < 0
    then do:
        assign viCnt = 0.
        
        if vcOptLock = ""
        then do:
            <M-10 run SqlErrorMessage (input  ihClass (ihClass), 
                           output viFcReturnSuper (oiReturnStatus)) in other>
        end.
        else do while true:
 
            assign viCnt = viCnt + 1.
            if viCnt > num-entries(vcOptLock,chr(2))
            then leave.
 
            assign viNum = integer(entry(viCnt,vcOptLock,chr(2)))
                   vhPDatabaseInst = ihClass.
 
            if viNum = 1
            then do:
                <M-7 run SetMessage
                   (input  #T-1'This field was changed from $1 to $2 by another user.':255(82)T-1# (icMessage), 
                    input  entry(viCnt + 2,vcOptLock,chr(2)) + chr(2) + entry(viCnt + 3,vcOptLock,chr(2)) (icArguments), 
                    input  't':U + vcDynrelTo[viDynrelCount] + '.':U + entry(viCnt + 1,vcOptLock,chr(2)) (icFieldName), 
                    input  entry(viCnt + 4,vcOptLock,chr(2)) (icFieldValue), 
                    input  'D':U (icType), 
                    input  integer(entry(viCnt + 6,vcOptLock,chr(2))) (iiSeverity), 
                    input  entry(viCnt + 5,vcOptLock,chr(2)) (icRowid), 
                    input  'BLF-367':U (icFcMsgNumber), 
                    input  '' (icFcExplanation), 
                    input  '' (icFcIdentification), 
                    input  '' (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in database>
                assign viCnt = viCnt + 6.
            end.
            else do:
                if viNum = 4
                then vcError = #T-17'A detail line you tried to create was already created by another user.':255(85)T-17#.
                else if viNum = 3
                then vcError = #T-18'A detail line you tried to delete was already deleted by another user.':255(84)T-18#.
                else vcError = #T-19'A detail line you tried to change was deleted by another user.':255(83)T-19#.

                <M-8 run SetMessage
          (input  vcError (icMessage), 
           input  '' (icArguments), 
           input  't':U + vcDynrelTo[viDynrelCount] (icFieldName), 
           input  '' (icFieldValue), 
           input  'D':U (icType), 
           input  2 (iiSeverity), 
           input  entry(viCnt + 1,vcOptLock,chr(2)) (icRowid), 
           input  'BLF-368':U (icFcMsgNumber), 
           input  '' (icFcExplanation), 
           input  '' (icFcIdentification), 
           input  '' (icFcContext), 
           output viFcReturnSuper (oiReturnStatus)) in database>
                assign viCnt = viCnt + 1.
            end.
        end.
        
        return.
    end.
end.
 
assign oiReturnStatus = viLocalReturn.