faq | docs | tutorials | guide | reference | contact | home  

TUTORIAL - DATABASE Previous | Next | Tutorial Home

The FGL programming environment contains a tightly integrated internal database that provides high-performance and scalability with industry-standard relational and object technology. FGL also interfaces with a number of external database systems (see the documentation for details).

The internal database includes a highly optimized distributed architecture with a number of significant optimizations and xBase-like API. This is further enhanced through the use of FGL object components which provides a powerful method for using, interacting with, and providing abstraction layers for data.

FGL programs and Active Pages can use the internal database directly through the more than fifty available database functions, or preferably through the use of database object wrappers. Either way, FGL makes it easy to integrate advanced database functionality into your application. For example:

Simple database example:
<html>
<head>
 <title>Simple database example</title>
</head>
<body text=black bgcolor=white>
<[
    // specify the file names
    dbname = 'c:\fgl\data\temp\temp.db'
    dxname = 'c:\fgl\data\temp\temp.dx'
        
    if ( fileExists( dbname ) )
        // open the database, assign an alias, open the index
        dbuse( dbname, "mydb" )
        mydb->dbOpenIndex( dxname )
    else
        // define a database structure
        aStruct = {
            { "fname", "C", 30, 0 },
            { "lname", "C", 40, 0 },
            { "age", "N", 3, 0 }
        }
        
        // create the database
        dbcreate( dbname, aStruct )
        
        // open the database and assign an alias
        dbuse( dbname, "mydb" )
        
        // create an index file and open it
        mydb->dbCreateIndex( dxname, "upper( field->lname + field->fname )", 0 )
        mydb->dbOpenIndex( dxname )
        
        // add some records
        mydb->dbAppend( )
        mydb->fname = "Steve", mydb->lname = "Repetti", mydb->age = 45
        mydb->dbAppend( )
        mydb->fname = "Angela", mydb->lname = "Repetti", mydb->age = 48
        mydb->dbAppend( )
        mydb->fname = "Frank", mydb->lname = "Aiello", mydb->age = 38
        mydb->dbAppend( )
        mydb->fname = "Mark", mydb->lname = "Lustig", mydb->age = 47
        mydb->dbAppend( )
        mydb->fname = "Alex", mydb->lname = "Wexler", mydb->age = 29
        mydb->dbAppend( )
        mydb->fname = "Naira", mydb->lname = "Aiello", mydb->age = 28
        mydb->dbAppend( )
        mydb->fname = "Stephen", mydb->lname = "Muccione", mydb->age = 38
    end
    
    // list the records
    mydb->dbGoTop( )
    while ( ! mydb->dbEOF( ) )
        ! mydb->lname + ", " + mydb->fname + " (age " + mydb->age + ") "
        ! "[rec #" + mydb->dbRecNo( ) + "]<br>"
        mydb->dbSkip( )
    end
    
    mydb->dbClose( )
]>
</body>
</html>

The previous examples makes use of the alias operator to reference all open database transactions. Alternatively, FGL supports the concept of workareas which can be use instead of aliases, however in today’s multi-threaded programming environment workareas should generally be avoided.

In fact, even aliases are not recommended in situations where simultaneous access to data may be provided – such as through the web – since potentially two simultaneous threads could reference the same alias. The preferred method is through a database connection handle which is provided as a unique identifier when a database is opened. A variation of the previous example using connection handles looks like:

Database using connection handles example:
<html>
<head>
 <title>Database using connection handles example</title>
</head>
<body text=black bgcolor=white>
<[
    // specify the file names
    dbname = 'c:\fgl\data\temp\temp.db'
    dxname = 'c:\fgl\data\temp\temp.dx'
    
    // open the database, get the connector, open the index
    db = dbuse( dbname, "mydb" )
    (db)->dbOpenIndex( dxname )
    
    // list the records
    (db)->dbGoTop( )
    while ( ! (db)->dbEOF( ) )
        ! (db)->lname + ", " + (db)->fname + " (age " + (db)->age + ") "
        ! "[rec #" + (db)->dbRecNo( ) + "]<br>"
        (db)->dbSkip( )
    end
    
    (db)->dbClose( )
]>
</body>
</html>

The best way to interact with data is through an FGL database object wrapper which provides an abstraction layer between the data and your application. This provides your application with a method of accessing and interacting with data without knowing the underlying components of the data including the storage methodology and data location. For example:

Simple database wrapper example:
<[
    LIBRARY \fgl\libs\system.flb
    obj = new( "objDatabase", 'c:\fgl\data\temp\temp.db' )
]>
<html>
<head>
 <title>Simple database wrapper example</title>
</head> 
<body>
<[
    // open the database and operate on it through the wrapper
    obj.open( )
    obj.dbGoBottom( )
    while ( ! obj.dbbof( ) )
        // load the object with the current record information
        obj.get( )
        ! obj.fname + " " + obj.lname + " (" + obj.dbRecNo( ) + ")<br>"
        obj.dbskip( -1 )
    end
    obj.close( )
]>
</body>
</html>

The default FGL database object wrapper, objDatabase, provides access to a number of database functions through the predefined object methods, including:

  • open
  • close
  • seek
  • get
  • put
  • CreateNewRecord
  • GetRecord
  • SetRecord
  • dbOrder
  • dbGoto
  • dbGoTop
  • dbGoBottom
  • dbEOF
  • dbBOF
  • dbSeek
  • dbSkip
  • dbRecNo
  • dbRecCount
  • rlock
  • unlock
  • paging
  • PagingDisplay
FGL makes it easy to create advanced object wrappers through the use of the inheritance of the default objDatabase object contained in the SYSTEM.FLB library with the source in the DATABASE.FGL file. Database object wrappers can be fully customized by inheriting the default objDatabase class and adding your own database methods and functionality, as in:

Advanced database wrapper example:
<[
    LIBRARY \fgl\libs\system.flb
    
    CLASS myDatabaseObject
      PUBLIC:
        INHERIT objDatabase
        
        METHOD new( )
            ::dbFileName = 'c:\fgl\data\temp\temp.db'
            ::dbAlias = "temp"
            ::dbStructure = {
                { "fname", "C", 20, 0 },
                { "lname", "C", 30, 0 },
                { "age", "N", 3, 0 }
            }
            ::dbIndexes = {
                { "upper( field->lname + field->fname )", 0 }
            }
            return( 1 )
        END
        
        METHOD ListRecords( )
            local s
            
            s = new( "ServerBuffer" )
            
            ::open( )
            while ( ! ::dbeof( ) )
                ::get( )
                s += ::fname + " " + ::lname + " (" + ::dbRecNo( ) + ")<br>"
                ::dbskip( )
            end
            ::close( )
            
            return( s.str )
        END
    END
    
    obj = new( "myDatabaseObject" )
]>
<html>
<head>
 <title>Simple database wrapper example</title>
</head> 
<body>
<[
    ! obj.ListRecords( )
]>
</body>
</html>

FGL makes it easy to display complex data sets using the paging object objPage found in the SYSTEM.FLB library with its source located in the PAGING.FGL file. The next example combines the dbViewer object (also in SYSTEM.FLB) as the data source for the paging object, as in:

Database paging example:
<[
    LIBRARY \fgl\libs\system.flb
    
    session = new( "session" )
    
    // define the database and index file
    dbname = 'c:\fgl\data\temp\temp.db'
    dxname = 'c:\fgl\data\temp\temp.dx'
    
    // create a database viewing and paging object
    objViewer = new( "dbViewer", dbname, dxname )
    objPage = new( "objPage", session, objViewer )
    
    // configure the paging object
    objPage.UnderlineHeader = 1
    objPage.PageCounter = 0
    objPage.hdrClass = objPage.bodyClass = objPage.btnClass = "smtxtBLACK"
]>
<html>
<head>
 <title>Database paging example</title>
 <link rel='stylesheet' href='../style.css' type='text/css' media='screen,print'>
</head> 
<body class=smtxtBLACK>
<form name="input" action="sample9d.htm" method=get>
<[
    // display the paging object
    ! objPage.GetCurPage( ) 
]>
</form>
</body>
</html>

The example above uses the paging object to interact with a database. The paging object can be used in many other instances and with numerous other types of data sources to create unique, advanced, and completely customized interfaces for your data.

You can also use the embedded paging object in the objDatabase class. In this case you can simply call the PagingDisplay( ) method to handle all of the paging for the database. The PagingDisplay( ) method optionally takes a parameter referencing which database index, if any, the paging object should use. Access to all of the paging configuration options is available through the paging object variable within the objDatabase class, as in:

Database wrapper with paging example:
<[
    LIBRARY \fgl\libs\system.flb
    
    obj = new( "objDatabase", 'c:\fgl\data\temp\temp.db', 'c:\fgl\data\temp\temp.dx' )
    
    obj.paging.UnderlineHeader = 1
    obj.paging.PageCounter = 0
    obj.paging.hdrClass = obj.paging.bodyClass = obj.paging.btnClass = "smtxtBLACK"
]>
<html>
<head>
 <title>Database wrapper with paging example</title>
 <link rel='stylesheet' href='../style.css' type='text/css' media='screen,print'>
</head> 
<body class=smtxtBLACK>
<form name="input" action="sample9e.htm" method=get>
<[
    ! obj.PagingDisplay( 1 )
]>
</form>
</body>
</html>

#####