Petstore Anatomy

Introduction

This section gives a broad overview of the Inq implementation of petstore. When referring to the script files, paths are relative to $INQHOME/app/examples/petstore.

In the sections that follow we look at particular areas of petstore's functionality and highlight the Inq features that support them.

Database Schema and Interfacing

Petstore runs against the jpetstore schema with a few additional columns marked as -- Added for inq in the schema creation file ./db/mysql/jpetstore-mysql-schema.sql

Here is the Entity Relationship diagram for it:

schema

Inq achieves a loose coupling between application logic and the database thanks to

  • the proliferation of SQL is prevented by its formalised use in typedef key definitions
  • joins are arbitrarily effected via keys using the Inq function aggregate and groupings with groupby (discussed in Building Node Structures).

Inq is therefore tolerant to schema changes, however the cornerstone of a well-structured application is a properly designed data model.

Mapping Tables to Entity Typedefs

The entity typedefs are named according to the Inq convention and defined in files like Account.inq. The primary key, which is commonly SQL server implementation specific, is defined in the files such as ./mysql/Account.pkey.sql, shown here:

/**
 * Account primary key include file - mysql
 */

auxcfg(map(
    // Use prepared stmt so that we can use '?' notation for column values
    // instead of having to define all the formatting.
    // NOTE: MAKE SURE WE KEEP KEY FIELDS IN THE SAME ORDER AS DEFINED IN THE TYPEDEF AND KEY FIELDS.
    "prepared", true,
    "select-stmt",
        "
        SELECT
            A.userid        AS \"Account\",
            A.email         AS \"Email\",
            A.firstname     AS \"FirstName\",
            A.lastname      AS \"LastName\",
            A.status        AS \"Status\",
            A.addr1         AS \"Addr1\",
            A.addr2         AS \"Addr2\",
            A.city          AS \"City\",
            A.state         AS \"State\",
            A.zip           AS \"ZIP\",
            A.country       AS \"Country\",
            A.phone         AS \"Phone\"
        FROM account A
        ",
    "read-sql",
        "
        {select-stmt}
        WHERE A.userid = ?
        ",
    "write-sql",
        "
        REPLACE account
        SET
            userid        = ?,
            email         = ?,
            firstname     = ?,
            lastname      = ?,
            status        = ?,
            addr1         = ?,
            addr2         = ?,
            city          = ?,
            state         = ?,
            zip           = ?,
            country       = ?,
            phone         = ?
        ",
    "delete-sql",
        "
        DELETE FROM account
        WHERE userid = ?
        "
))

When fetching instances, Inq uses the column name meta-data from the underlying SQL server to map columns to entity fields. Here we are using the simple mapping technique of renaming the columns using the <column> AS <name> syntax to interface Inq entity definitions with the existing jpetstore schema. The select statement defined in the ...pkey.sql files is reused for all other key definitions.

All the key examples use JDBC prepared statements, so writing entities to the database (the REPLACE statement in MySQL) and reading with other keys that define more than one field use position arguments that relate to the order of the entity and key field definitions.

Key Examples

Petstore exercises the following aspects of Inq's I/O Key functionality.

Key Examples
Typedef Key Name Where Used Notes

Order

Filter

psOrders.inq as create data when a new order is created.

gui/myOrders.inq as data underlying the components in the filter bar.

This key is cached and has uses logical expressions in its SQL, so has an eligibility expression to maintain cache integrity.

Item

Filter

gui/browseItems.inq as data underlying the components in the filter bar.

This key is not cached because its eligibility expression would be quite complex - see mysql/Item.Filter.sql.

Search

gui/newOrder.inq as data underlying the search text field and popup menu check buttons.

Used in conjunction with the reusable item chooser gui. Note that both Filter and Search are only referred to in the client. A key instance carries its name so can be used in the server without knowing what it is.

ByProductCheck

The destroy function in Product.inq checks whether there are still associated Item instances before allowing a Product to be deleted.

This key is capped to return at most one instance, since its function is only to determine whether there is at least one Item associated with a given Product.

Common Typedef Aliases - defs.inq

The defs.inq file contains various enums and aliases for types that are used in the entity definitions. This technique allows the data types (including the scale in the case of fixed precision decimals), any label, width hint and formatting information to be defined centrally and reused.

This information propagates to the client to be picked up by renderinfo, discussed in GUI Basics. It is also passed through to generated XML used to create reports, discussed elsewhere in this example. This is an important feature of Inq - by centralising this information the application is both more maintainable and concisely expressed when creating GUIs and printable reports. We'll return to this subject when looking more closely at those two aspects.

Server-Side Functionality

Together with the typedefs the server-side functionality is implemented in the remaining 10 files in the top-level petstore directory called ps<Something>.inq. The largest of these is psOrders.inq, containing the Order processing code, at about 500 lines including comments. Most are considerably smaller. This underlines Inq's conciseness of expression - there is almost no "artifact" code - that is code that relates to technology issues rather than the application itself.

Booting the Server With Petstore

We saw in the previous section how to load petstore into the Inq server. This process involves parsing all the server-side script that goes together to make up the application and a single file, psBoot.inq, does this. Having a "boot" script that loads an application is the common pattern for Inq server-side code.

The Petstore Client

The gui client is implemented in 8 files, the largest of which is newOrder.inq at a bit less than 850 lines overall. In a similar way to psBoot.inq the server returns the initial script gui/userStart.inq to the client after login (see psLogin.inq). This script fetches further client code from the server using Inq's loadclient function, runs any of the required utilities such as messagedialog.inq contained in the Inq environment and shows the initial window.

nextpage