There is a problem, the system is written in Clarion 5 came from the past and now it needs to be rewrite in Java.
To do this I need to deal with its current state and how it works.
I'm generate the executable file via Application Generator (\*.APP-> \*.CLW -> \*.EXE, \*.DLL)
.
But when I run it I get the message:
File(\...\...\DAT.TPS) could not be opened. Error: Path Not Found(3). Press OK to end this application
And then - halt, File Access Error
In what may be the problem? Is it possible in the Clarion 5 IDE to reconfigure the path to the data files?
Generally, Clarion uses a data dictionary (DCT) as the center of persistent data (files) that will be used by the program. There are other ways you can define a table, but since you mentioned you compile from the APP, I'm concluding that your APP is linked to a DCT.
In the DCT you have the declarations for every file your application will use. In the file declaration you can inform both logic and disk file name. The error message says you have a problem in the definition of the disk file name.
The Clarion language separates the logic data structure definition from its disk file. A "file" for a Clarion programm, is a complex data structure, which conforms to the following:
structName FILE, DRIVER( 'driverType' ), NAME( 'diskFileName' )
key KEY( keyName )
index INDEX( indexName )
recordName RECORD
field DATATYPE
.
.
END
END
The above is the basic declaration syntax, and a real example would be like:
orders FILE, DRIVER( 'TopSpeed' ), NAME( 'sales.dat\orders' )
ordersPK KEY( id ), PRIMARY
customerK INDEX( customerID )
notes MEMO( 4096 )
RECORD RECORD
id LONG
customerID LONG
datePlaced DATE
status STRING( 1 )
END
END
orderItems FILE, DRIVER( 'TopSpeed' ), NAME( 'sales.dat\items' )
itemsPK KEY( orderID, id ), PRIMARY
RECORD RECORD
orderID LONG
id LONG
productID LONG
quantityOrdered DECIMAL( 10, 2 )
unitPrice DECIMAL( 10, 2 )
END
END
Now, with the above two declarations, I have two logic files that reside in the same disk file. This is a capability offered for some file drivers, like the TopSpeed file driver. It is up to the system designer to decide if, and which files will reside in the same disk file, and I can talk about that on another post, if it is the case.
For now, the problem may be arising from the fact that you probably didn't change the NAME property of the file declaration, and the driver you're using doesn't support multi-file storage.
Here's a revised file definition for the same case above, but targeting a SQL database.
szDBConn CSTRING( 1024 ) ! //Connection string to DB server
orders FILE, DRIVER( 'ODBC' ), NAME( 'orders' ), OWNER( szDBconn )
ordersPK KEY( id ), PRIMARY
customerK INDEX( customerID )
notes MEMO( 4096 ), NAME( 'notes' )
RECORD RECORD
id LONG, NAME( 'id | READONLY' )
customerID LONG
datePlaced DATE
status STRING( 1 )
END
END
orderItems FILE, DRIVER( 'ODBC' ), NAME( 'order_items' ), OWNER( szDBconn )
itemsPK KEY( orderID, id ), PRIMARY
RECORD RECORD
orderID LONG
id LONG
productID LONG
quantityOrdered DECIMAL( 10, 2 )
unitPrice DECIMAL( 10, 2 )
END
END
Now, if you pay attention, you'll notice the presence of a szDBconn
variable declaration, which is referenced at the file declarations. This is necessary to inform the Clarion file driver system what to pass the ODBC manager in order to connect to the dabase. Check Connection Strings for plenty of connection strings examples.
Check the DCT definitions of your files to see if they reflect what the driver expects.
Also, be aware that Clarion does allow mixing different file drivers to be used by the same program. Thus, you can adapt an existing program to use an external data source if needed.
Here is a complete Clarion program to transfer information from an ISAM file to a DBMS.
PROGRAM
MAP
END
INCLUDE( 'equates.clw' ) ! //Include common definitions
szDBconn CSTRING( 1024 )
inputFile FILE, DRIVER( 'dBase3' )
RECORD RECORD
id LONG
name STRING( 50 )
END
END
outuputFile FILE, DRIVER( 'ODBC' ), NAME( 'import.newcustomers' ), |
OWNER( szDBconn )
RECORD RECORD
id LONG
name STRING( 50 )
backendImportedColumn STRING( 8 )
imported GROUP, OVER( backendImportedColumn )
date DATE
time TIME
END
processed CHAR( 1 )
END
END
CODE
IF NOT EXISTS( COMMAND( 1 ) )
MESSAGE( 'File ' & COMMAND( 1 ) & ' doesn''t exist' )
RETURN
END
imputFile{ PROP:Name } = COMMAND( 1 )
OPEN( inputFile, 42h )
IF ERRORCODE()
MESSAGE( 'Error openning file ' & inputFile{ PROP:Name } )
RETURN
END
szDBconn = 'Driver={{PostgreSQL ANSI};Server=192.168.0.1;Database=test;' & |
'Uid=me;Pwd=plaintextpassword'
OPEN( outputFile, 42h )
IF ERRORCODE()
MESSAGE( 'Error openning import table: ' & FILEERROR() )
RETURN
END
! // Lets stuff the information thatll be used for every record
outputFile.imported.date = TODAY()
outputFile.imported.time = CLOCK()
outputFile.processed = 'N'
! //arm sequential ISAM file scan
SET( inputFile, 1 )
LOOP UNTIL EOF( inputFile )
NEXT( inputFile )
outputFile.id = inputFile.id
outputFile.name = input.name
ADD( outputFile )
END
BEEP( BEEP:SystemExclamation )
MESSAGE( 'File importing completed' )
Well, this example program serves only the purpose of showing how the different elements of the program should be used. I didn't use a window to let the user track the progress, and used Clarion's primitives, like ADD(), which work for sure, but inside a loop can represent a drag in performance.
Much better would be to encapsulate the entire reading in a transaction opened with outputFile{ PROP:SQ } = 'BEGIN TRANSACTION'
and at the end, issue a outputFile{ PROP:SQL } = 'COMMIT'
.
Yes, trhough the PROP:SQL one can issue ANY command accepted by the server, including a DROP DATABASE, so it is very powerful. Use with care.
Gustavo