company logo

OShell Script comments

The OShell script in the example demonstrates some typical features. Besides elementary script commands as changing data sources (cd) or data collections (cc), OShell supports embedded OSI scripts. When you enter script data directly via console, blocks (beginning with .. .do or ... begin)are processed only after terminating the block with an end command. More details one may find in Database Utilities.

Selecting data source and collection

The first command (cd) selects the data source (Sample) as being defined as section in the .ini file. Thus, one may switch between different data sources by defining different data sources in the ini-file. After the data source has been opened, a collection (extent) is selected (cc). After selecting a data collection, one may browse data in the data collection or change to sub collections (references or relationships).

cd Sample

cc Company

List instances

Similar the li command lists the keys for all instances in the collection. Since the selected collection is the Company extent, a list of all company names will be displayed. We added the result of the command in the example below.

In order to run a command for all instances in a collection, the command to be executed might be preceded by an fa meta-command. Thus, the subsequent commands will list the number of cars and employees for each company in the collection. The lav command lists a single attribute value, which might be an access path, also.

li

  Any company

  Best company

  My company

  NO company

  Your company

fa lav cars.count

  cars.count=12

  cars.count=17

  cars.count=3

  cars.count=15

  cars.count=7

fa lav employees.count

  employees.count=100

  employees.count=92

  employees.count=105

  employees.count=114

  employees.count=89

Change to new data source

In order to change to a new extent, the path should start with a '/', which means to search from the database root rather than from the current collection. When the extent has been defined in a name space, a scoped name has to be passed. Since the syntax for command line parameters is restricted, it is save to add string delimiters for the collection path.

Finally, the collection has changed to Persons.

cc '/Person::Persons'

API function calls

Most API functions for Value and Property can be called directly from within OShell. Thus, the collection count could be retrieved by calling count as well as other interface functions. When passing parameters, those are parsed separated by spaces. Parameters always should be passed within quotes.

When calling API functions, those will print the function result on console. Function not returning a value just report successful termination.

Below, we replaced the sfc (set filter condition) command by the filter function from the Property API. The result is the same, but in this case the return value from the filter function will be displayed on console.

cc /Employee

count

  count returns: 500

// sfc "sex == 'male'" replaced by

filter "sex == 'male'"

  filter returns: sex == 'male'

relativeCount

  relativeCount returns: 258

cc '/Person::Persons'

count

  count returns: 1,000

Embedded OSI script

When embedding OSI script within OShell, the current collection is considered as the context, in which the script is running. In the example, this is the Persons extent with a filter condition. Simple OSI expressions can be called just preceding the operand by the osi meta command. Usually, however, the OSI script to be executed will be embedded in an osi do ... end block.

Such a do block (in contrast to an osi begin ... end block) creates a copy of the collection handle, i.e. the original settings in the selected OShell collection will be copied but not be affected by any operation in the OSI script (e.g. setting another filter).

This block may contain just some statements or, as in the example below, a VARIABLES and a PROCESS section. In order to write data to the console, Message() might be called.

osi do

VARIABLES

    int         child_count;

    int         distance = 0, dist = 0;

    int         min_dist = 100, max_dist = 0;

    int         dcount = 0;

PROCESS

    filter('age > 65 && employee.count == 0');

    Message('Persons probably retired (over 65 and not employed): ' + relativeCount);

    

    top();

    while ( next() )

        child_count += children.count;

    Message('Total number of children: ' + child_count);

    

    filter("");

    top();

    while ( next() )

        while ( children.next() ) {

            dist = age-children.age;

            if ( min_dist >= dist )  min_dist = dist;

            if ( max_dist <= dist )  max_dist = dist;

            distance += age-children.age;

            ++dcount;

        }

    Message('Average age distance between children and parents: ' + distance/dcount);

    Message('   Minimum/maximum distance is: ' + (string)min_dist + '/' + (string)max_dist);

end