× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



 >> First off, why the Select Distinct?

To dispose of the blanks returned by the UDF. Every UDF must return something. 
I looked at the manual and you cannot return nothing so I will tell it to 
return a one byte char field for each call . Cannot return a NULL so it would 
know that there is only one possibility. Be nice if IBM added that.  

If I have it correctly, the operating system(SQL Runtime) is going to read a 
record from data base, Build the string in the WRITEIFS, call the UDF and then 
back to get another record same as any other SELECT so if you did not put the 
DISTINCT in I would get 1.5 million blanks returned if processing a file with 
1.5 million records just as if I was using my AS400DATE UDF but I would get 
back 1.5 million date data types.

>> Note the use of the MAX function.

You know Charles, you have got it. If I use MAX instead of DISTINCT, I don't 
have any of the problems I was thinking about. Each time it runs the UDF, it 
returns a blank, compares it to the previous value and does nothing because 
they are the same. That's it. Thank you very much. 

>> I'd do the headers like so

>> Set dummyVar = WriteIFS( stringToWrite )
  
You are forgetting that you must have a SELECT statement. There is only one 
WRITEIFS issued for the whole 1.5 million records so it has to know where the 
get the data from just like any other SELECT. The set only works for, I think, 
for UDF that just do one thing like Opening the IFS. I haven't tested it yet so 
I don't know if it even works. 
I can use a SET for OPENIFS because the manual shows an example of a function 
SET :VALUEX = SUBSTR(:VALUEY,1,1) so Set :DummyField = OPENIFS(:FileName) will 
work. 

You know, it just occurs to me that it doesn't really make any sense to use SET 
on some and EXECUTE IMMEDIATE on others. Might as well just have one function 
that receives the string and does an EXECUTE IMMEDIATE. 

Again I would like to emphasize that that I am not going to be reading the 
records into the HLL. The HLL is there only to build and execute the SQL 
String. All the work occurs in the SQL Statement itself. This seems to be a 
point of a lot of confusion.  The execution in the HLL is:

OPEN
WRITE Header1
WRITE Header2
WRITE 1.5 million records
CLOSE

No loops. Just these 5 statements plus what is needed to build the string to 
execute.

I see the high level code as just being:

BuildFieldTable(FileNametoCopy);
ExecuteSQLString(BuildOpenString('/Home/YourDirectory/YourFile.txt'));
ExecuteSQLString(BuildFirstHeader());
ExecuteSQLString(BuildSecondHeader());
ExecuteSQLString(BuildCopyString());
ExecuteSQLString(BuildCloseString());
ReleaseFieldTable();

That should be it. 

You know Rich, it just occurred to me. You don't even need the field table 
build. Simply have a table:

TableName
TableLibrary
BuildHeaderOneSQLString
BuildHeaderTwoSQLString
CopyRecordsSQLString

By rules of normalization, I would normalize to two tables:
                          Unique
    TableName
    TableLibrary
    TransmitFileName
K TableName
K TableLibrary

                        Unique
    TableName
    TableLibrary
    TypeOfString
    SQL String
K TableName
K TableLibrary
K TypeOfString


Now, if you realize you need to add another type of record to the FTP file, 
just add another SQL string type and program works the same.

You could just build the statements in STRSQL or OPS NAV and paste them in. If 
you need to add a field, just edit the SQL string. The only statements you 
would need is for the WRITEIFS. You could still build the string dynamically 
but is it worth it?

"Make everything as simple as possible, but not simpler." Albert Einstein
 
So at this point, we have reduced the code down to a few dozen lines of code 

Ok, so know the high level code is just:

Chain (FileNameToCopy:LibraryName) FileNameHeader;
ExecuteSQLStatement(BuildOpenString(TransmitFileName));
Setll (FileNameToCopy:LibraryName) FileNameSQLStatements;
DoU 0 = 1;
    Read FileNameSQLStatements;
    If %EOF or FileNameChanged;
        Exit;
    EndIf;
    ExecuteSQLString(SQLString);
EndDo;
ExecuteSQLString(BuildCloseString());

>> stm = 'values Select MAX(WriteIFS(' + wDataFormatString + ') from ' + 
>> wInputFileName + ') into ?'

>> /exec SQL prepare s from :stm

This is exactly what I am doing with the EXECUTE IMMEDIATE. I just don't have 
to bother with parameter markers and you cannot use parameter markers with 
EXECUTE IMMEDIATE. Manual says to use EXECUTE IMMEDIATE if the string is 
different each time and it would be. The wData FormatString iand wInputFileName 
is different each time it is executed. 

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.