Charlie, thank you. This is helpful, and I have some responses in-line.
AUSED() - can return an array of all aliases in use (and you can specify a
datasession if you want)
DBC() - returns the path and name of the actual "file" that us associated
with an alias
So, if you build an array of aliases using AUSED() you can then loop
through the array using DBC() and log which file is actually used. This
works for cursors created by SQL queries too.
I think before I scrap the code I will add this to the error logging and
see what I get. That should help me understand what's going on, for sure.
Side note: A standard programming practice I've taken is to always add the
NOFILTER clause to my SQL. This ensures the resulting cursor is not just a
"filter alias" (a long time ago I think you could get a bit of a
performance boost if the resulting cursor was just a subfilter of the
source table, and indexed on the WHERE clause - but nowadays with loads of
PC memory, fast drives, etc, I don't think there is a reason to want a
"filter alias").
My previous understanding was that if there is a WHERE clause or an ORDER
BY clause in the query, then VFP always creates the temp file on disk.
Therefore, to avoid this precise problem, my query class always adds
"NOFILTER" to queries that don't have WHERE or ORDER BY clauses.
However, your example:
>*-- assume MYTABLE is indexed on a field "id"
>SELECT * FROM mytable WHERE id=25 into cursor tempitem
>USE IN (SELECT("MYTABLE"))
>USE MYTABLE in 0 && this will error out because "tempitem" is actually
just >an alias to MYTABLE with a 'SET FILTER TO ID==25'
indicates that my assumption is wrong. I get the same results as you, even
if I add an ORDER BY clause. I don't get the error if I add a JOIN to the
query though.
However, if this really was the ultimate source of my problem, I would be
deluged with error emails every time somebody used the system. That's not
happening.
And adding NOFILTER to a complex query that doesn't happen to have a JOIN
can still slow it down considerably. I don't have a "hot" development
machine; I write and test code on the same machines everybody else here
has. Currently my Win 7 Ultimate 32-bit machine is a few years old; it has
an AMD Athlon X2 (I think that's duo-core) processor running at 2.9 GHz and
4 GB of RAM. Other machines here are older and slower. So I'm reluctant to
adopt this practice as a default, and the particular query involved in this
scenario does contain a JOIN.
I'll repeat that all of my code to open tables resides in a single method
in my framework. That code never assigns a specific alias to the table, and
it never issues "USE AGAIN". Also, I never use private datasessions;
everything occurs in the default datasession.
Before my query class runs a query, it makes a list of all of the tables in
the field list, and any JOIN expressions, of the query that are not already
open. Then I can tell it to close any tables that were opened expressly by
the query after the query runs.
Some time ago I read somewhere (I can't remember) that VFP may open some
tables in a work area called "QUERY" when running a SQL SELECT query
without an INTO clause. If there are more than one of these, a digit is
appended to "QUERY". (In testing I see that it actually puts the results
cursor in that work area, not tables opened by the query.) So although I
never run queries without an INTO clause in production code, and these
"hidden" work areas should contain only results cursors if there is no INTO
clause, in the spirt of "just in case" my code for closing queried tables
also contains a little DO WHILE loop that looks for work areas whose names
begin with "QUERY" and closes them also.
In the situation being described, the command to close the query-opened
tables is issued after the user responds to a display of the query results.
The display appears in a modal picklist window if there are any matches;
otherwise s/he gets a MESSAGEBOX() saying "no matches". I suppose if some
bizarre event prevents the display of either of these, or if the user can
somehow defeat the modality of the picklist window to shut down the
application, then that command would not get executed and there would be
open tables when the shutdown code runs. This should not be possible but
under certain circumstances the modality of VFP windows is not 100% reliable.
However, again, when my shutdown code runs, it explicitly checks for USED()
on every table and will SELECT it if it's open instead of trying to USE it.
However, I have also seen this before, rarely, in other situations:
IF NOT USED("mytable")
USE mytable IN 0 && Error 3; File in use.
ENDIF
I kid you not. It's very strange.
I actually think there are processes in VFP that impose locks on tables
that aren't always detected correctly. In the above case, it would seem
that some OTHER user has the table open and locked for some purpose. The
error reported should be 108, but sometime's it's 3.
>FYI in 100% of my tracing problems of this nature, it has always been
software >code that caused the condition. In other words, a table got
opened exclusive, or >I tried to open something exclusive that was shared
(and thought was closed), >etc. An FLOCK() or RLOCK() will not prevent
another open in Shared mode.
I'm going to add the status of SET("EXCLUSIVE") and SET("MULTILOCKS") to my
error logging.
>Others may have already pointed this out but in your sample above,
"USE >MYTABLE IN 0" will throw an error if the table was opened under
another alias. >With the functions above, you could easily determine if the
table is actually >open or not.
See above; I never assign other aliases or issue USE AGAIN.
>Also as others have mentioned, other applications can lock files (like
AV). >Plus, if you allow ODBC access to the tables I think the it defaults
to >EXCLUSIVE when trying to pull data (not sure though, and it can be
changed).
We use the server-based (business) version of avast!. It has global
exclusions for .dbf, .cdx, and .fpt files set at the server. Users cannot
change any settings on the avast! client; it requires a password that they
don't have.
There are no ODBC implementations.
Again, this was very helpful.
I'd appreciate any further thoughts you have on my additional information.
Ken
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message:
http://leafe.com/archives/byMID/profox/[email protected]
** All postings, unless explicitly stated otherwise, are the opinions of the
author, and do not constitute legal or medical advice. This statement is added
to the messages for those lawyers who are too stupid to see the obvious.