There was a previous thread about this message w/ SQL in which the difficulty of tracking the cause was noted. Having again faced the problem recently, I revisited the situation in an attempt to come up with a debug option to help.
By adding a #pragma and code in the FileManager.EqualBuffer method, I can now easily see the first byte in the file record that appears as having been changed. However, w/ some tables, it can still be difficult to know the exact record field to which the changed byte corresponds.
For instance, if the debug code shows CHR(32) vs CHR(0) at byte 832 in the Clarion record buffer, is there an easy way to determine the relevant field name (other than manually adding up all the field sizes)? My recent tests using various combinations of WHO, WHERE have not been successful.
Here’s some bare-bones code with no error checking. You’d probably want to do a bit of error checking in real life. It makes use of my PrivateClass. https://github.com/jslarve/PrivateClass
PROGRAM
MAP
END
INCLUDE('JSPrivateClass.inc')
JSP JSPrivateClass
G GROUP
F1 STRING(30)
F2 STRING(35)
F3 STRING(900)
F4 LONG
F5 STRING(100)
END
Ndx LONG
CODE
LOOP Ndx = 1 TO 5
IF JSP.GetAnyDataAddress(WHAT(G,Ndx)) - ADDRESS(G) > 832
MESSAGE(WHO(G,Ndx-1))
BREAK
END
END
Years ago I worked with MS SQL, the issue “Changed by another station” happened if sql table had time field. The reason of the issue is that Clarion loses time presicion and thinks that field value has been changed.
Yeah, I believe time has often been part of the problem. The trouble I am seeing now involves several timestamp columns in PostgreSQL. The FileManagerClass will save the buffer with a zero value and if SETNULL is used prior to the the EqualBuffer compare the Changed message results.
Hello Douglas, I don’t know Postgres and don’t know your case, so I’m just wondering… maybe one of the column level driver switches (NoWhere and/or ReadOnly) could help you?
Take a look at “NOWHERE driver switch” in help.
Your field in dictionary may shorter than DB field and if DB value size larger than dictionary field size that may cause your problem.
Also Mike’s date problem happened on my C6 applications. I used smalldatetime or cropped microseconds. But latest versions (after 9) that problem has solved.
Yes, I went through those string size issues awhile ago.
Fortunately, not the situation this time(stamp).
Consider the following:
SqlTs STRING(8)
SqlTsGrp GROUP,OVER
SqlDate DATE
SqlTime TIME
END
IsReviewed BYTE
IF IsReviewed = True
SqlDate = TODAY()
SqlTime = CLOCK()
ELSE
! Which code choice MUST be used to clear SqlTimestamp and avoid Changed by Another?
! CLEAR(SqlTimestamp)?
! SqlTimestamp = ''
! CLEAR(SqlDate) ; CLEAR(SqlTime)
! SETNULL(SqlTimestamp)?
END
Nothing you put there will make any difference, the error will still happen. Putting the NOWHERE driver switch on the SqlTS field should do fix your problem.
The problem comes from (as people have already pointed out)…
get(myfile)
WATCH(myfile) – saves a copy of the buffer for comparison later
…you make various changes to the file buffer
PUT(myfile)
Because of the watch, the Put first does:
select
from myfile
where <column_name1> = ?stored value1
and <column_name2> = ?stored_value2
etc.
Because the stored value was mangled or truncated in some way, the select fails to find the record, and that gives you the “Changed by…” error. In this case, presumably the time_stamp is truncated on being plonked into a clarion TIME.
After more checking, it seems there is more to this than just Changed by Another Station.
How SqlDate & SqlTime are cleared comes into play because it determines the return value from the EqualBuffer method. If cleared using the string SqlTimestamp, the method always forces an update, even when the user just looked at the record and then clicked Ok instead of Cancel.
These frequent updates also forced a change to the LastModifiedTimestamp column by the server. With a small number of test records and multiple users, we were therefore seeing unexpected Changed By Another errors.
In regard to NOWHERE, would it not be wise to avoid use IF a timestamp column has even a slight chance of being relevant to real changes by another station?