project BLF > class Persistence (Progress) > method WriteCopy

Description

Like WriteDirect, this method writes directly to the database, without using any temp-tables.
Unlike WriteDirect, this method does not update the original record, but makes a copy first and updates this copy.


Parameters


icTableNameinputcharacter
icPrepareinputcharacterProgress for each statement defining what record(s) must be copied.
icFieldListinputcharacterComma seperated list of field names to update.
This list should always contain at least one field of every unique index defined on the updated table.
icFieldListDataTypesinputcharacter
icUpdateValueinputcharacterchr(2) seperated list of values to write to the fields of icFieldList. The same value(s) will be written to each record to update.
ihClassinputhandle
icUserLogininputcharacter
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BMfgDomain.PreSave


program code (program1/progress.p)

if transaction = no
then do:
    <M-17 run ErrorMessage
       (input  'No transaction was started before writing to the database.':U (icMessage), 
        input  '' (icArguments), 
        input  '' (icFieldName), 
        input  '' (icFieldValue), 
        input  '' (icRowid), 
        input  ? (ihClass)) in Progress>
    assign oiReturnStatus = -3.
    return.
end.

assign oiReturnStatus  = -98
       vgDebugTime     = etime
       viFields        = num-entries(icFieldList).

create temp-table vhCopyTable in widget-pool "non-persistent".
vhCopyTable:create-like(icTableName).
vhCopyTable:temp-table-prepare("z":U + icTableName).
vhCopyBuffer = vhCopyTable:default-buffer-handle.
vhCopyBuffer:buffer-create().
create buffer vhTargetBuffer for table icTableName in widget-pool "non-persistent".
if can-do(vcDisableLoadTriggersFor,icTableName)
then vhTargetBuffer:disable-load-triggers(false).
create buffer vhBuffer for table icTableName in widget-pool "non-persistent".
create query vhQuery in widget-pool "non-persistent".
vhQuery:forward-only = yes.
vhQuery:set-buffers(vhBuffer).
assign vlFcOk = vhQuery:query-prepare (icPrepare) no-error.
if vlFcOk
then assign vlFcOk = vhQuery:query-open() no-error.
if not vlFcOk
then do:
    publish "Logging.DatabaseAccess"
           ("read ":U + icTableName + chr(10) +
            icPrepare + chr(10) + "FAILED":U, ?).

    <M-18 run ErrorMessage
       (input  #T-2'Invalid database query ($1).':255(88)T-2# (icMessage), 
        input  icPrepare (icArguments), 
        input  '' (icFieldName), 
        input  '' (icFieldValue), 
        input  '' (icRowid), 
        input  ? (ihClass)) in Progress>
    
    assign oiReturnStatus = -3.
    return.
end.

vhQuery:get-first(no-lock).

do while not vhQuery:query-off-end:

    vhCopyBuffer:buffer-copy(vhBuffer).

    do viFieldCount = 1 to viFields:

        assign vhField = ?.
        assign vhCopyField = vhCopyBuffer:buffer-field(entry(viFieldCount,icFieldList))
               vhField = vhBuffer:buffer-field(entry(viFieldCount,icFieldList)) no-error.
        if vhField = ?
        then do:
            <M-19 run ErrorMessage
               (input  'Invalid field ':U + entry(viFieldCount,icFieldList) (icMessage), 
                input  '' (icArguments), 
                input  '' (icFieldName), 
                input  '' (icFieldValue), 
                input  '' (icRowid), 
                input  ? (ihClass)) in Progress>
            assign oiReturnStatus = -3.
            return.
        end.
        case vhField:data-type:
            when "character":U
            then assign vhCopyField:buffer-value = entry(viFieldCount,icUpdateValue,chr(2)).
            when "date":U
            then assign vhCopyField:buffer-value = date(entry(viFieldCount,icUpdateValue,chr(2))).
            when "decimal":U
            then assign vdAB =
                        (if entry(viFieldCount,icUpdateValue,chr(2)) begins "Sequence:":U
                         then <M-16 GetNextDecimalValue
                                 (input  substring(entry(viFieldCount,icUpdateValue,chr(2)),10,-1,'CHARACTER':U) (icsequence)) in Progress>
                         else decimal(entry(viFieldCount,icUpdateValue,chr(2))))
                        vhCopyField:buffer-value = vdAB.
            when "integer":U
            then assign viFcCount2 =
                        (if entry(viFieldCount,icUpdateValue,chr(2)) begins "Sequence:":U
                         then <M-15 GetNextValue (input  substring(entry(viFieldCount,icUpdateValue,chr(2)),10,-1,'CHARACTER':U) (icSequence)) in Progress>
                         else integer(entry(viFieldCount,icUpdateValue,chr(2))))
                        vhCopyField:buffer-value = viFcCount2.
            when "logical":U
            then assign vhCopyField:buffer-value = (entry(viFieldCount,icUpdateValue,chr(2)) = "true":U).
            otherwise do:
                return.
            end.
        end case.
    end.

    vhTargetBuffer:buffer-create().
    vhTargetBuffer:buffer-copy(vhCopyBuffer).

    publish "Logging.DatabaseAccess"
           ("create ":U + icTableName, vhTargetBuffer).

    assign viReadCount = viReadCount + 1.

    vhQuery:get-next(no-lock).
end.

publish "Logging.DatabaseAccess"
       ("read ":U + icTableName + chr(10) +
        icPrepare + chr(10) +
        "Record count=":U + string(viReadCount) + chr(10) +
        "time(ms)=" + string(etime - vgDebugTime), ?).

assign oiReturnStatus = (if viReadCount = 0 then -4 else 0).

finally:

    if vhQuery <> ?
    then do:
        vhQuery:query-close().
        delete object vhQuery.
    end.
    if vhCopyTable <> ?
    then delete object vhCopyTable.
    if vhTargetBuffer <> ?
    then delete object vhTargetBuffer.
    if vhBuffer <> ?
    then delete object vhBuffer.

end finally.