>Dear All,
>
>I found the following syntax to make a cursor writeable:
>
>USE DBF("cMyCursor") IN 0 AGAIN ALIAS cAnotherCursor
>
>But if I use the following :
>
>select anyfield from MyTable into cursor cMyCursor
>
>then DBF() gives back the path of the original table, but I don't want to write into the original table.
This happens when the cursor created by the SQL Select comes from a single table, and the result is fully optimizable. Rather than creating an additional temporary file, a filtered view of the table is returned as a result.
>After some reasonong, I have tried using the following:
>
>select anyfield from MyTable into cursor cMyCursor nofilter
>
>then DBF() gives a really temporary filepath.
The addition of the NOFILTER clause forces the creation of a separate temporary file even where a filtered view could have been presented. The return from DBF() will be the name of a temporary file.
>According to the VFP documentation, neither of the previous syntax creates phisical files. But practically, the second syntax still produces one.
>
A file, and an entry in the directory, is created if NOFILTER is specified in all cases. There may not be a physical disk presense if the result can be conveniently held in RAM by VFP, but it's a 'real' file IAC. VFP may write the temporary file to disk at any time during the life of the file.
>Is it sure, that the second syntax always produces a temporary file, and thus, is safe to write into the cursor after making it writeable?
>
Yes, it's writable, and it's as reliable as any other native file within the VFP session that owns it; to make it permanent beyond the life of the VFP session, you need to copy it to a table before VFP makes it go away. I'm not sure if the temporary file would be visible to another VFP instance or another program running on the same system, or if it were visible, if the content would be accessible and reliable during its lifespan. I'm not even sure if the necessary disk space is reserved for it before it has some physical disk presense - I'd hope that it was.
>P.S.: I know, that select anyfield, .t. from MyTable into cursor cMyCursor
>does the job, but I would like to understand the theoretical background.
>
The addition of the expression from outside of the base table prevents VFP from using a filtered view. Similarly, SELECT * FROM MyTable WHERE
fully optimizable expression AND .T. forces the formation of a temporary file rather than a filtered view, since .T. wouldn't be optimizable (no index to build the needed bitmap, so each eligible record would be examined.) The use of a GROUP BY or HAVING clause also forces a temproary file to be created.
Dumb question, but if you know you're going to want to write to it, why not just select to a table and clean up after yourself later? It'd seem to make more sense to keep an object around to track debris and make it empty the garbage and sweep up before VFP turns out the lights...
DEFINE CLASS FileTrash AS CUSTOM
PROTECTED aTempsToTrack[1,4]
PROTECTED nTempAlloc
aTempsToTrack = NULL
nTempAlloc = 0
PROCEDURE AddCleanUpItem
LPARAMETERS tcBaseFile, tlMemo, tlCDX, tlRecycle
#DEFINE KILLOFFMEMO 2
#DEFINE KILLOFFCDX 3
#DEFINE TORECYCLEBIN 4
WITH this
.nTempAlloc = .nTempAlloc + 1
DIMENSION .aTempsToTrack[.nTempAlloc,4]
.aTempsToTrack[.nTempAlloc,1] = FULLPATH(tcBaseFile)
.aTempsToTrack[.nTempAlloc,KILLOFFMEMO] = tlMemo
.aTempsToTrack[.nTempAlloc,KILLOFFCDX] = tlCDX
.aTempsToTrack[.nTempAlloc,TORECYCLEBIN] = tlRecycle
ENDWITH
RETURN this.nTempAlloc
ENDPROC
PROCEDURE AddThisForCleanUp
LPARAMETER tlRecycle
LOCAL cFullPath, lMemo, lCDX, aFlds[1,16], nFlds, nCtr
IF USED()
cFullPath = FULLPATH(DBF())
lMemo = .F.
nFlds = AFIELDS(aFlds)
FOR nCtr = 1 TO nFlds
IF aFlds[nCtr,2] $ 'GM'
lMemo = .T.
EXIT
ENDIF
ENDFOR
lCDX = TAGCOUNT() > 0
RETURN .AddCleanUpItem(cFullPath, lMemo, lCDX, tlRecycle)
ELSE
RETURN 0
ENDIF
ENDPROC
PROCEDURE CleanUpDebris
LOCAL cFileToDrop, nCtr
#DEFINE KILLOFFMEMO 2
#DEFINE KILLOFFCDX 3
#DEFINE TORECYCLEBIN 4
CLOSE DATABASES ALL
CLOSE DATABASES ALL
CLOSE TABLES ALL
WITH this
FOR nCtr = 1 TO .nTempAlloc
cFileToDrop = .aTempsToTrack[nCtr,1]
IF FILE(cFileToDrop)
IF .aTempsToTrack[nCtr,TORECYCLEBIN]
ERASE (cFileToDrop) RECYCLE
ELSE
ERASE (cFileToDrop)
ENDIF
ENDIF
cFileToDrop = FORCEEXT('FPT')
IF FILE(cFileToDrop) AND .aTempsToTrack[nCtr,KILLOFFMEMO]
IF .aTempsToTrack[nCtr,TORECYCLEBIN]
ERASE (cFileToDrop) RECYCLE
ELSE
ERASE (cFileToDrop)
ENDIF
ENDIF
cFileToDrop = FORCEEXT('CDX')
IF FILE(cFileToDrop) AND .aTempsToTrack[nCtr,KILLOFFCDX]
IF .aTempsToTrack[nCtr,TORECYCLEBIN]
ERASE (cFileToDrop) RECYCLE
ELSE
ERASE (cFileToDrop)
ENDIF
ENDIF
ENDFOR
DIMENSION .aTempsToTrack[1,4]
.nTempAlloc = 0
.aTempsToTrack = NULL
ENDWITH
RETURN
ENDPROC
PROCEDURE DESTROY
IF this.nTempAlloc > 0
this.CleanUpDebris()
ENDIF
DODEFAULT()
ENDPROC
ENDDEFINE