Four months ago, I wrote1 about the recursive FILELIST and the fact that two
essential flags were not documented. Over the past few days, I've been working
with the results of that command; I had to copy files to a location in
system/mail, then attach them to financial journal entries, then delete the
files. Nothing worked ... or rather, everything that was not connected to
copying and deleting the files worked properly, but the files were not being
accessed.
Eventually there was no option left but to call for help from Priority
Software, so today we had a grand debugging session. The programmer from PS at
first was at a loss as to why the commands weren't workng. The reason only
became clear when he used a program ('filezila' ?) to access the system/sync
directory from the external side; it turns out that the company that was
placing files in this directory had created a subdirectory system/sync in the
sync directory, thus explaining why we couldn't access any of the files.
To make this clear: the output from EXECUTE FILELIST looked like this
system/sync/dataplus/a191016/
system/sync/dataplus/a191016/dummy.txt
system/sync/dataplus/a191016/5031266_25034.pdf
...
I had assumed that the program was showing the complete path, but in reality
the filename with path was
../../system/sync/system/sync/dataplus/a191016/5031266_25034.pdf. Once this
had been taken into account on the internal side, my code worked perfectly.
Here are a few things that I picked up during the work session. At one stage, the command EXECUTE FILELIST
was executed without any parameters (I think); this caused the program to show
its help - the various flags that can be passed. I discovered that the
mysterious -d parameter means "put directory names in result". Secondly, there
are two integer fields in STACK_ERR (the table that holds the directory
results) that can be useful: INTDATA1 holds the creation date of each file,
and INTDATA2 holds the file size. I didn't need to use the creation date but
this might have been useful. INTDATA2 was definitely useful as I could exclude
accessing 'files' that had a size less than 30 bytes - the first two lines in
the example that I quoted above have such file sizes. Using this field makes the cursor
simpler. Finally, one doesn't have to prefix the file path with
../../system/sync: it's cleaner to do this with SYSPATH ('SYNC', 0) -
actually I had done this at the beginning of the procedure in order to get the
files.
So part of the final code is as follows
SELECT SQL.TMPFILE INTO :ST6 FROM DUMMY;
:CHKDIR = SYSPATH ('SYNC', 0);
EXECUTE FILELIST :CHKDIR, :ST6, '-R', '-d', SQL.TMPFILE;
LINK STACK_ERR TO :ST6;
/* First get the directories */
DECLARE C1 CURSOR FOR
SELECT DISTINCT STRPIECE (MESSAGE, '/', 4, 1)
FROM STACK_ERR
WHERE LINE > 0
AND STRPIECE (MESSAGE, '/', 4, 1) <> ''
AND EXISTS (SELECT 1 FROM ENVIRONMENT
WHERE DNAME = STRPIECE (MESSAGE, '/', 4, 1));
OPEN C1;
GOTO 300 WHERE :RETVAL <= 0;
LABEL 100;
FETCH C1 INTO :COMPANY;
GOTO 200 WHERE :RETVAL <= 0;
ENV :COMPANY; /* switch to current company */
LINK GENERALLOAD TO :$.GEN;
:LINE = 0;
/* Get files */
DECLARE C2 CURSOR FOR
SELECT MESSAGE, STRPIECE (MESSAGE, '/', 5, 1)
FROM STACK_ERR
WHERE LINE > 0
AND STRPIECE (MESSAGE, '/', 4, 1) = :COMPANY
AND INTDATA2 > 30; /* size of file - exclude dummy.txt */
OPEN C2;
LOOP 100 WHERE :RETVAL <= 0;
LABEL 110;
FETCH C2 INTO :BIGFNAME, :GNAME;
GOTO 150 WHERE :RETVAL <= 0;
...
/* copy file */
:HNAME = STRCAT (SYSPATH ('SYNC', 1), :BIGFNAME);
SELECT NEWATTACH (:GNAME) INTO :FOUT FROM DUMMY;
EXECUTE MOVEFILE :HNAME, :FOUT;
...
Apparently no one uses SFTP in order to place files from an external source into the system/sync directory, so in a sense, I and the implementor who hired my services, are pioneers with this file handling code.