What is Panorama thinking about at any given moment?

I thought I should share this event that was annoying until I figured out what I think was happening and leading my family member to ask “what’s all that cursing?” I consistently received an error message during my .Initialize procedure saying a variable did not exist, even though the variable was declared a few lines earlier. Here is the problematic code:

opensecret “TTTimekeepers”
opensecret “TTMatters”

letfileglobal fgworkdate=""
letfileglobal fgworkdateprecursor=""
TryAgain:
letfileglobal fguserid=""
Gettextdialog fguserid,
“Prompt”, “Please enter your ID#…”,
“Subprompt”,"",
“Button”,“Ok”,
“Button”,“Cancel”,
“Button”,"",
“Sheet”,“Yes”
“Width”,100,
“Height”, 24

if info(“dialogtrigger”)=“Cancel”
rtn
endif

fguserid=val(fguserid)

The last line is where the error occurred. I wanted to use the two secret databases in the .Initialize procedure so I opened manually instead of using the Aux database feature. I knew that the active database reverted to the calling database following an opensecret statement, so I believed when the next line was reached that the calling DB was active. But that was not the case.

Eventually I added a wait 0 statement after the second opensecret statement, and that resolved the issue.

I concluded that PanX was still opening the two databases when it reached my declaration of the variable and so the variable was created within the secret database NOT in the calling database. By the time the last statement above was reached, the active database did not match the DB where the variable had been defined. Adding the wait 0 statement ensured that the opensecret statement had completed before the next step in the procedure was executed.

Opensecret might be a statement that Jim could amend to build in this kind of protection, which I know he has done with some statements to help ensure that the code is executing in the order that you want.

FWIW, I learned years ago to always add the line - window “whatever database:secret” before doing anything in a secret database. I know it’s not always necessary, but it creates problems often enough that I always do it and it’s only one line of additional code.

I also ALWAYS check to make sure a secret database is open, as in:

window “WEDatabase:secret”
if error
open “WEDatabase”
window “WEDatabase:secret”
endif

That isn’t what Panorama is thinking (I worded it that way because of your topic title).

Normally the opensecret statement doesn’t affect the active database at all. It doesn’t revert back to the calling database, it simply never changes at all.

However, one (or both) of the databases you are opening is a shared, multi-user database. In order to set up sharing, Panorama must make the database active. So even though it is secret, it is becoming active. In your case, it is remaining active until the gettextdialog statement. After any alert or dialog, the topmost visible database becomes active (because it’s window becomes active when the alert or dialog closes). So the fileglobal variables were actually set up in one of the secret databases (if they are both shared, it would be in TTMatters).

I believe you (Tom) are the only customer using secret databases that are shared. So no one else has encountered this. I’ll have to think about whether to change this. This seems like a situation where in trying to change it, I’m likely to introduce a new bug down the line. I’m not sure it’s worth it.

In the meantime, I don’t think wait 0 is the best fix, though it may be fine. I can tell you that it’s not actually waiting – the opensecret is complete by the time the code gets to that point (the opensecret already has the delay included to contact the server, but the code sets the active database back to the shared database at that point so it can complete setting up sharing).

Wait 0 does have a side effect of making the topmost window active, but I think it would be “cleaner” to just use setactivedatabase. You could do this:

setactivedatabase info("proceduredatabase") 

Or you could hard code the database name, or save the name in a local variable before you open the secret databases.

I’m sure using the window statement this way will always work, but I think it’s cleaner in new code to use the setactivedatabase statement. But they both do the same thing. Just as long as you remember that there really is no such thing as a secret “window”, that is a fictional construction. It’s simply that the active database is not the database associated with the current window.

I can add one piece of information. The two databases opened with opensecret are not shared databases, nor is the calling database. (This is for a personal project.)

That’s weird. If the databases aren’t shared then opensecret should not change the active database, it just silently loads the database into memory and does nothing further. I suggest enabling instrumentation and sprinkling this line into multiple spots in your code to get more information.

zlog labelizeinfo("databasename")

You could add some extra comments to make the log more readable:

zlog "Before first opensecret: "+labelizeinfo("databasename")

I use secret shared databases all the time and in preliminary testing of Pan X server (earlier versions), setactivedatabase was not always reliable for me, which is why I still use the window statement. I haven’t tried it recently.

Internally it is literally the same code. Not a copy of the code, the same code.

Anyway, it’s fine to continue using :secret, it still works and there are no plans to change it.

I think Mr. Heisenberg has intervened in my procedure. I did as you suggested, Jim, and enabled instrumentation and put in several zlog statements. The error did not occur, and the active database was always the calling database. That is, the zlog statements changed the way the procedure worked.

Secondly, I ran the procedure on two computers, one with an Intel processor and one with an M1 processor. The failure occurs ONLY on the M1 computer. This is the only time I have found something different using the M1 computer.

Third, inserting a setactivedatabase statements avoids the failure on the M1 computer.

Fourth, going back to the code as I originally reported it, on the M1 computer, when the procedure is finished, the variable at issue does NOT exist in the calling database, but DOES exist in the second secret database. (I used Formula Workshop to check the variable in each of the three databases.)

I withdraw my suggestion to change to the setactivedatabase statement. The issue is easily handled by the programmer once it is recognized.