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
tDynRel | input | temp-table | Description of the data to write. |
ihClass | input | handle | Handle to the class that is using the persistence layer. In most of the cases, this handle will be available in the preprocessor {&TARGETPROCEDURE}. |
ihRowidConvert | input | handle | Handle to the temp-table tFcRowidConvert. |
icUserLogin | input | character | |
oiReturnStatus | output | integer | |
Internal usage
unused
program code (program1/progress.p)
&scoped-define TBF tBufferFields.thBufferField
&scoped-define TDF tBufferFields.thDestinationField
&scoped-define TIF tBufferFields.thIDestinationField
if transaction = no
then do:
<M-42 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.
/* 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:
assign vhRefInt = ?.
/* ================================================================= */
/* First, take care that all buffer fields are known for this table */
/* ================================================================= */
<M-41 run UpdateBufferInfo
(input vcDynrelTo[viDynrelCount] (icTableName),
input vhDynrelBuffer[viDynrelCount] (ihDestinationBuffer),
input vhDynrelIbuffer[viDynrelCount] (ihIDestinationBuffer),
input ihClass (ihClass),
output vhBuffer (ohBuffer),
output vhDummy (ohQuery),
output viFcReturnSuper (oiReturnStatus)) in Progress>
if viFcReturnSuper <> 0
then do:
assign oiReturnStatus = viFcReturnSuper.
return.
end.
/* ================================================================= */
/* Now, create the queries for retrieval of t and t_i data */
/* ================================================================= */
create query vhTQuery in widget-pool "non-persistent".
vhTQuery:forward-only = yes.
vhTQuery:set-buffers(vhDynrelBuffer[viDynrelCount]).
/* ================================================================= */
/* delete records */
/* ================================================================= */
vhTQuery:query-prepare
("for each ":U + vhDynrelBuffer[viDynrelCount]:name +
" where ":U + vhDynrelBuffer[viDynrelCount]:name + ".tc_status = 'D'":U).
vhTQuery:query-open().
vhTQuery:get-first().
do while not vhTQuery:query-off-end :
/* Check for optimistic lock */
vhDynrelIbuffer[viDynrelCount]:find-unique ("where tc_rowid = '":U + vhDynrelBuffer[viDynrelCount]::tc_Rowid + "'":U) no-error.
if not vhDynrelIbuffer[viDynrelCount]:available
then do:
<M-51 run ErrorMessage
(input 'Invalid rowid ($1)':U (icMessage),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icArguments),
input vhDynrelBuffer[viDynrelCount]:name (icFieldName),
input '' (icFieldValue),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icRowid),
input ihClass (ihClass)) in Progress>
assign oiReturnStatus = -3.
if vhRefInt <> ?
then do:
delete procedure vhRefInt.
assign vhRefInt = ?.
end.
return.
end.
if vlOptLock
then vhBuffer:find-by-rowid(to-rowid(string(vhDynrelBuffer[viDynrelCount]::tc_Rowid)), no-lock) no-error.
else do:
do viFcCount1 = 1 to 5:
vhBuffer:find-by-rowid(to-rowid(string(vhDynrelBuffer[viDynrelCount]::tc_Rowid)),
exclusive-lock, no-wait) no-error.
if vhBuffer:locked
then pause 3 no-message.
else leave.
end.
if vhBuffer:locked
then do:
<M-43 run ErrorMessage
(input #T-41'Update failed: database record stays locked.':255(90)T-41# (icMessage),
input '' (icArguments),
input vhBuffer:table (icFieldName),
input '' (icFieldValue),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icRowid),
input ihClass (ihClass)) in Progress>
assign oiReturnStatus = -3.
if vhRefInt <> ?
then do:
delete procedure vhRefInt.
assign vhRefInt = ?.
end.
return.
end.
end.
if not vhBuffer:available
then do:
/* optimistic lock, record is deleted */
assign vlOptLock = yes.
<M-44 run ErrorMessage
(input #T-42'A detail line you tried to delete was already deleted by another user.':255(84)T-42# (icMessage),
input '' (icArguments),
input vcDynrelTo[viDynrelCount] (icFieldName),
input '' (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
vhTQuery:get-next ().
next.
end.
for each tBufferFields where
tBufferFields.thTempBuffer = vhDynrelBuffer[viDynrelCount]
on error undo, throw:
if {&TDF}:help = ?
or ({&TDF}:help = "OL-C":U and {&TDF}:buffer-value <> {&TIF}:buffer-value)
then do:
if {&TIF}:buffer-value <> {&TBF}:buffer-value
then do:
/* optimistic lock, record is changed */
assign vlOptLock = yes.
<M-45 run ErrorMessage
(input #T-43'This field was changed from $1 to $2 by another user.':255(82)T-43# (icMessage),
input substitute ('&1' + chr(2) + '&2',{&TIF}:buffer-value,{&TBF}:buffer-value) (icArguments),
input vcDynrelTo[viDynrelCount] + '.':U + {&TDF}:name (icFieldName),
input string({&TDF}:buffer-value) (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
end.
end.
else if {&TDF}:buffer-value = {&TIF}:buffer-value
then assign {&TDF}:buffer-value = {&TBF}:buffer-value.
end.
if search ("ref_int/dc_":U + lc(vcDynrelTo[viDynrelCount]) + ".r":U) <> ?
or search ("ref_int/dc_":U + lc(vcDynrelTo[viDynrelCount]) + ".p":U) <> ?
then do:
if vhRefInt = ?
then run value ("ref_int/dc_":U + lc(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.
return.
end.
end.
if not vlOptLock
then do:
publish "Logging.DatabaseAccess"
("delete ":U + vcDynrelTo[viDynrelCount], vhBuffer).
vhBuffer:buffer-delete().
end.
vhTQuery:get-next ().
end.
vhTQuery:query-close().
if vhRefInt <> ?
then do:
delete procedure vhRefInt.
assign vhRefInt = ?.
end.
/* ================================================================= */
/* create or update records (update first, create last) */
/* ================================================================= */
vhTQuery:query-prepare
("for each ":U + vhDynrelBuffer[viDynrelCount]:name +
" where ":U + vhDynrelBuffer[viDynrelCount]:name + ".tc_status = 'N'":U +
" or ":U + vhDynrelBuffer[viDynrelCount]:name + ".tc_status = 'C'":U +
" by ":U + vhDynrelBuffer[viDynrelCount]:name + ".tc_status":U).
vhTQuery:query-open().
vhTQuery:get-first().
do while not vhTQuery:query-off-end :
if vhDynrelBuffer[viDynrelCount]::tc_Status = "N":U
then do:
if vlOptLock = no
then vhBuffer:buffer-create().
end.
else do:
/* Check for optimistic lock */
vhDynrelIbuffer[viDynrelCount]:find-unique ("where tc_rowid = '":U + vhDynrelBuffer[viDynrelCount]::tc_Rowid + "'":U) no-error.
if not vhDynrelIbuffer[viDynrelCount]:available
then do:
<M-52 run ErrorMessage
(input 'Invalid rowid ($1)':U (icMessage),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icArguments),
input vhDynrelBuffer[viDynrelCount]:name (icFieldName),
input '' (icFieldValue),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icRowid),
input ihClass (ihClass)) in Progress>
assign oiReturnStatus = -3.
return.
end.
if vlOptLock
then vhBuffer:find-by-rowid(to-rowid(string(vhDynrelBuffer[viDynrelCount]::tc_Rowid)), no-lock) no-error.
else do:
do viFcCount1 = 1 to 5:
vhBuffer:find-by-rowid(to-rowid(string(vhDynrelBuffer[viDynrelCount]::tc_Rowid)),
exclusive-lock, no-wait) no-error.
if vhBuffer:locked
then pause 3 no-message.
else leave.
end.
if vhBuffer:locked
then do:
<M-46 run ErrorMessage
(input #T-44'Update failed: database record stays locked.':255(90)T-44# (icMessage),
input '' (icArguments),
input vhBuffer:table (icFieldName),
input '' (icFieldValue),
input vhDynrelBuffer[viDynrelCount]::tc_Rowid (icRowid),
input ihClass (ihClass)) in Progress>
assign oiReturnStatus = -3.
return.
end.
end.
if vhBuffer:available
then for each tBufferFields where
tBufferFields.thTempBuffer = vhDynrelBuffer[viDynrelCount]
on error undo, throw:
if {&TDF}:help = ?
or ({&TDF}:help = "OL-C":U and {&TDF}:buffer-value <> {&TIF}:buffer-value)
then do:
if {&TIF}:buffer-value <> {&TBF}:buffer-value
then do:
/* optimistic lock, record is changed */
assign vlOptLock = yes.
<M-47 run ErrorMessage
(input #T-45'This field was changed from $1 to $2 by another user.':255(82)T-45# (icMessage),
input substitute ('&1' + chr(2) + '&2',{&TIF}:buffer-value,{&TBF}:buffer-value) (icArguments),
input vcDynrelTo[viDynrelCount] + '.':U + {&TDF}:name (icFieldName),
input string({&TDF}:buffer-value) (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
end.
end.
else if {&TDF}:buffer-value = {&TIF}:buffer-value
then assign {&TDF}:buffer-value = {&TBF}:buffer-value.
end.
else do:
/* optimistic lock, record is deleted */
assign vlOptLock = yes.
<M-48 run ErrorMessage
(input #T-46'A detail line you tried to change was deleted by another user.':255(83)T-46# (icMessage),
input '' (icArguments),
input vcDynrelTo[viDynrelCount] (icFieldName),
input '' (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
end.
end.
if not vlOptLock
then do:
vhBuffer:buffer-copy(vhDynrelBuffer[viDynrelCount]) no-error.
if error-status:error
then do:
assign vlOptLock = yes.
if error-status:get-message(1) matches "*(132)":U
then do:
assign vcTemp = error-status:get-message (1)
vcWork = #T-36'A detail line you tried to create was already created by another user.':255(85)T-36# + " - ":U + vcTemp.
<M-49 run ErrorMessage
(input vcWork (icMessage),
input '' (icArguments),
input vcDynrelTo[viDynrelCount] (icFieldName),
input '' (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
leave.
end.
else do viFcCount1 = 1 to error-status:num-messages:
<M-50 run ErrorMessage
(input error-status:get-message(viFcCount1) (icMessage),
input '' (icArguments),
input vcDynrelTo[viDynrelCount] (icFieldName),
input '' (icFieldValue),
input string(vhDynrelBuffer[viDynrelCount]::tc_Rowid) (icRowid),
input ihClass (ihClass)) in Progress>
end.
end.
if vhDynrelBuffer[viDynrelCount]::tc_Status = "N":U
then do:
ihRowidConvert:buffer-create().
assign ihRowidConvert::tcFcOldRowid = vhDynrelBuffer[viDynrelCount]::tc_Rowid
ihRowidConvert::tcFcNewRowid = string(vhBuffer:rowid).
ihRowidConvert:buffer-release().
end.
publish "Logging.DatabaseAccess"
((if vhDynrelBuffer[viDynrelCount]::tc_Status = "N":U then "create " else "update ") + vcDynrelTo[viDynrelCount], vhBuffer).
end.
vhBuffer:buffer-release().
vhTQuery:get-next ().
end.
vhTQuery:query-close().
delete object vhTQuery.
vhTQuery = ?.
end.
if vlOptLock
then assign oiReturnStatus = -2.
finally:
if vhTQuery <> ?
then do:
vhTQuery:query-close().
delete object vhTQuery.
end.
end finally.