databaseclarion

How to reconfigure path to the data files in Clarion 5 IDE?


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?


Solution

  • 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