FGL Features - Database

fgl language fgl.js web server database dev tools

FGL Database

The FGL Platform includes advanced integrated database technologies for applications requiring high levels of performance, scalability, flexibility, and security. The Platform maintains an internal message-based distributed hybrid object, relational, and key-value store platform seamlessly integrated with the FGL programming and execution environment.

Generated Database Abstraction Object:

  CLASS cContact
   PUBLIC:
    INHERIT objDataBase

    const ORDER_LNAME = 1

    METHOD new( )
        ::dbFileName = session( ).data( 'data_drive' ) + 
            '\fgllang\data\contact.db'
        ::dbAlias = 'contact'
        ::dbStructure = {
            { "fname", "C", 30, 0 },
            { "mname", "C", 30, 0 },
            { "lname", "C", 40, 0 },
            { "suffix", "C", 4, 0 },
            { "data", "B", 20, 0 }  // object store
        }
        ::dbIndexes = {
            { "upper( field->lname + field->fname + " +
            "field->mname )", 0 }
        }
        ::dbObjects = {
            { 'data', 'contact_data' }
        }
        ::init( )
        return( 1 )
    END
    ...
 
Database & Key/Value Interaction:

    // instantiate data wrapper instance
    ouser = new( "cUser" )

    // get the desired record
    if ( ! ouser.getRecord( userid ) )
        return( ouser.errmsg )
    end
    
    // access a value from the db
    origTitle = ouser.title
    
    // change a value
    ouser.title = "New Title"
    
    // write the change to the database
    ouser.setRecord( userid )
    
    println( ">>> old title: ", origTitle,
    	" new title: ", ouser.title 
    )
    
    // key/value based auto-counter
    nextVal = keyvalue.counter( "mycounter" )

    // more key/value fun
    for ( i=1; i<100; i++ )
        keyvalue.( "varname_" + x ) = rand( ) % 999
    end
 
Key Features
  • Hybrid relational/object database
  • Message-based distributed architecture
  • Integrated key/value store
  • High-speed indexing
  • Access any record out of 100's of millions in less than 1 second
  • Auto-generated data abstraction wrapper classes
  • Real-time data inspection
  • Pipelined replication
  • Real-time backups while applications are running
  • Supports complex data serialization
  • Embedded encryption and compression
  • Integrated query system
  • Automated template and report generation
  • Built-in Soundex support
  • Remote administration
  • Extensive tools, generators, and resources
Auto-Generated Data FILTERS
For easy high speed searching
METHOD dataFilter( index, searchstr, pglen )
    local a, opts

    opts = new( 'objFilterParams', index, searchstr )

    switch ( opts.index )
      case ::ORDER_LNAME
        opts.init( { 
            { 40 },
            { 30 },
            { 30 }
        } )
        a = {
            { 'index', opts.index },
            { 'key', opts.key },
            { 'filter', {
                    { 'lname', '=^', opts.p1 },
                    { 'fname', '=^', opts.p2 },
                    { 'mname', '=^', opts.p3 }
                }
            }
        }
        break

    end

    if ( pglen )
        a = ::dataFilterSet( a, 'pglen', pglen )
    end

    return( a )
END
Advanced Filter Commands
  =     equals (matches val length)
  =^    equals (matches val length) [converts strings to uppercase]
  ==    equals (matches field length)
  ==^   equals (matches field length) [converts strings to uppercase]
  *     contains
  *^    contains [converts strings to uppercase]
  <     less than
  <^    less than [upper]
  <=    less than or equal
  <=^   less than or equal [upper]
  >     greater than
  >^    greater than [upper]
  >=    greater than or equal
  >=^   greater than or equal [upper]
  !=    not equal
  !=^   not equal [upper]
  !*    not contained
  !*^   not contained [upper]
  ?     match wildcard
  ?^    match wildcard [upper]
  =&    soundex (of upper)
  Rx    upper( right ) 'x' chars
Auto-Generated Data TEMPLATES
For automated interactive report generation
METHOD dataTemplate( template )
    local a, x, o

    switch( lower( '' + template ) )
      case '' + ::ORDER_NAME
        a = {
            { 'tableClass', 'table defTbl' },
            { 'rowClick', "doClick('#id#');" },
            { 'fields', {
                    { 'name',, { |x,o| o.name + ", " + o.fname + 
                        " " + o.mname } },
                    { 'gender' },
                    { 'race',, { |x| self.raceDesc(x) } },
                    { 'age',, { |x,o| self.age(x,o) } },
                    { 'dob',, { |x| keytodate( x ) } },
                    { 'status',, { |x| self.statusDesc(x) } },
                    { 'edate',, { |x| keytodatetime(x,0,1) } },
                    { 'id', { { 'editType', 'hidden' } } }
                }
            }
        }
        break

    end

    return( a )
END
Simplified Querying & Reporting
Using auto-generated database wrapper components
// define a query
opts = ocontact.dataFilter( 
    ocontact.ORDER_NAME,     // index to use 
    "Smith,Fred,J",          // multiple filters 
    500                      // max # of results 
)

// perform the high-speed filtered query
a = ocontact.query( opts )

// render the results in an interactive table
! ocontact.list( a, opts, 
	ocontact.dataTemplate( ocontact.ORDER_NAME ) 
)
Process Query Results with Map Functions Map Processing:

! "Show Fields:\r\n"
a = aResults.map().fields()
! objToJSON( a ) + "\r\n"

! "Sum Some Data:\r\n"
a = aResults.aMapSum( "age;playingDays" )
! objToJSON( a ) + "\r\n"

! "Get Averages:\r\n"
a = aResults.aMapAverage( "age;playingDays" )
! objToJSON( a ) + "\r\n"

! "Accumulate Data by Groups:\r\n"
accumulator = aArray().add( { 
    { "France", {} }, 
    { "England", {} }, 
    { "Spain", {} } 
} )
a = aResults.aMapReduce( "soccerSortByCountry", accumulator )
! objToJSON( aArrayToJSON( a, 1 ) )
Map Results:
Show Fields:
[
    "GENDER",
    "NAME",
    "AGE",
    "CLUB",
    "COUNTRY",
    "DATA",
    "PLAYINGDAYS"
]

Sum Some Data:
{
    age : 165.0,
    playingDays : 949.0
}

Get Averages:
{
    age : 27.50,
    playingDays : 158.1666666670
}

Accumulate Data by Groups:
{
    England : [
        {
            gender : "M",
            name : "Riyad Mahrez",
            age : 25,
            club : "Leicester City FC",
            country : "England",
            data : {
                desc : "Riyad Mahrez, Leicester City FC, England"
            },
            playingDays : 132
        },
        {
            gender : "M",
            name : "Sofiane Feghouli",
            age : 26,
            club : "West Ham United",
            country : "England",
            data : {
                desc : "Sofiane Feghouli, West Ham United, England"
            },
            playingDays : 45
        }
    ],
    France : [
        {
            gender : "M",
            name : "Hatem Ben Arfa",
            age : 29,
            club : "PSG",
            country : "France",
            data : {
                desc : "Hatem Ben Arfa, PSG, France"
            },
            playingDays : 180
        },
        {
            gender : "M",
            name : "Radamel Falcao",
            age : 27,
            club : "AS Monaco FC",
            country : "France",
            data : {
                desc : "Radamel Falcao, AS Monaco FC, France"
            },
            playingDays : 22
        }
    ],
    Spain : [
        {
            gender : "M",
            name : "Karim Benzema",
            age : 29,
            club : "Real Madrid CF",
            country : "Spain",
            data : {
                desc : "Karim Benzema, Real Madrid CF, Spain"
            },
            playingDays : 200
        },
        {
            gender : "M",
            name : "Samir Nasri",
            age : 29,
            club : "Sevilla FC",
            country : "Spain",
            data : {
                desc : "Samir Nasri, Sevilla FC, Spain"
            },
            playingDays : 370
        }
    ]
}
Low-level Databases Access
Programatic control over every aspect of your data

Auto-generated database abstraction classes make it easy to interact with databases. However, FGL also provides low-level access to the database directly via a collection of databases functions.

// low-level database manipulation
ocontact = new( "cContact" )

ocontact.open( )
ocontact.dbOrder( ocontact.ORDER_NAME )

if ( ! ocontact.dbSeek( key ) )
    ocontact.close( )
    return( ocontact.errmsg )
end

if ( ! ocontact.rlock( ) )
    ocontact.close( )
    return( ocontact.errmsg )
end	

ocontact.get( )
ocontact.fname = "Fred"
ocontact.put( )

ocontact.unlock( )
ocontact.close( )


// now, the same example using auto-generated abstraction class
ocontact = new( "cContact" )
if ( ! ocontact.getRecord( key ) )
    return( ocontact.errmsg )
end
ocontact.fname = "Fred"
ocontact.setRecord( key )


#####

Copyright © 2020-2024 by the FGL Foundation, All Rights Reserved



12 ms