+ All Categories
Home > Documents > Informix 4GL Statements

Informix 4GL Statements

Date post: 09-Sep-2015
Category:
Upload: ericholte837898188
View: 116 times
Download: 15 times
Share this document with a friend
Description:
In depth description of Informix 4GL statements
Popular Tags:
84
INFORMIX 4GL STATEMENTS This chapter deals in detail with the components of the INFORMIX-4GL language and their use, paying particular attention to the specialized programming statements that INFORMIX-4GL provides for dealing with the database and the screen display of database-bound information. From this point, you deal with a sample application for a fictitious company that specializes in recruiting long-haul truck drivers. This chapter uses two tables from this company's database, named recruiters, to illustrate the basic principles of INFORMIX-4GL program development. These tables are employers and states. The database schema can be extracted from the database by using the utility dbschema, which is provided with all Informix products. This is only one of a group of utilities provided by Informix for the purpose of migrating data between databases or engines. This utility creates an ASCII file that can be used to re-create the table with the same structure it had originally. The dbschema command is used as follows: dbschema {[-t <tabname>] [-s <user>] [-p <user>] -d <dbname> [-ss] [<filename>]} The options in this command are defined as follows:
Transcript

INFORMIX 4GL STATEMENTS

This chapter deals in detail with the components of the INFORMIX-4GL language and their use, paying particular attention to the specialized programming statements that INFORMIX-4GL provides for dealing with the database and the screen display of database-bound information.

From this point, you deal with a sample application for a fictitious company that specializes in recruiting long-haul truck drivers. This chapter uses two tables from this company's database, named recruiters, to illustrate the basic principles of INFORMIX-4GL program development. These tables are employers and states.

The database schema can be extracted from the database by using the utilitydbschema, which is provided with all Informix products. This is only one of a group of utilities provided by Informix for the purpose of migrating data between databases or engines. This utility creates an ASCII file that can be used to re-create the table with the same structure it had originally. Thedbschemacommand is used as follows:

dbschema {[-t ]

[-s ]

[-p ]

-d

[-ss]

[]}

The options in this command are defined as follows:

-t is the name of the table to extract or the wordto generate the schema for all tables in the database.

-s generatescreate synonymstatements fororfor all users.

-p generatesgrantstatements to grant permissions toorfor all users.

-d indicates the name of the database used to extract the schema files.

-ssgenerates server-specific syntax.

is the name of the ASCII file that receives the SQL statements generated. (It is a good practice to name this file.SQLso that you can deal with it as you do any other SQL script.)

NOTE:To distinguish options and arguments that are required in a command line or in a statement from those that are optional, I have enclosed the optional arguments in square brackets ([]), whereas the required arguments are not enclosed in brackets. I have used curly brackets ({}) to denote a grouping of items, and pointed brackets () to illustrate that the contents are to be filled in as appropriate.

The database schema for these tables is displayed in Listing 36.1.

Listing 36.1. Schema of employers and states tables.

{ TABLE "jose".employers row size = 179 number of columns = 16 index size = 78 }

create table "jose".employers

(

empl_code serial not null constraint "jose".n103_18,

employer char(35) not null constraint "jose".n103_19,

add_line1 char(35),

add_line2 char(35),

city char(18),

state char(2),

zip char(5),

phone char(10),

trl_len char(2),

freight char(10),

area char(15),

nbr_trks char(4),

authority char(1),

leased char(1),

dac char(1),

authorized char(1),

primary key (empl_code) constraint "jose".pk_employers

);

revoke all on "jose".employers from "public";

create index "jose".ix100_2 on "jose".employers (employer);

create index "jose".ix100_16 on "jose".employers (authorized);

{ TABLE "jose".states row size = 17 number of columns = 2 index size = 9 }

create table "jose".states

(

state char(2) not null constraint "jose".n101_4,

state_name char(15) not null constraint "jose".n101_5,

primary key (state) constraint "jose".pk_states

);

revoke all on "jose".states from "public";

The schema for these tables shows all permissions revoked from"public". The database administrator must grant connect permissions to the database and table permissions to the appropriate users before these tables are accessible to users.

What Should an INFORMIX-4GL Program Do?

Generally, an INFORMIX-4GL program should have a discrete, focused purpose and encompass only the tasks that are directly related either to the tables being processed or to the functional business process that the software serves. Try to apply to INFORMIX-4GL programs the same principles of normalization that you apply to relational databases. In the same way you don't create a single table to represent all aspects of your enterprise, you design the scope of your programs to facilitate the execution of a single business process. The larger the scope of your program, the larger the executables the compiler generates. Larger executables are slower to load into memory and usually more cumbersome for the user to navigate. An application in this scenario becomes a collection of limited, focused purpose programs, glued together by some form of menu system.

NOTE:It was once common practice to develop an application by first developing an INFORMIX-4GL program that provided only a cascading menu system. When the user selected a specific task from any of the submenus of this program, the program executed a call to run the selected task in a subshell, while the menu program went dormant waiting for its child to be completed. Current Informix database engines count both programs as separate users because both hold connections to the database engine. Keep this user count in mind when determining your user licenses, or perhaps use a different menu management strategy for your application.

In this chapter, you develop software to query and input data into the employers table. The fictitious company that recruits long-haul drivers needs software to support multiple business endeavors: managing potential employers, receiving applications from prospective drivers, and verifying employment histories of prospective drivers. Your application should strive to mimic the nature of your business and support each business function with separate programs. One program collects the functionality to support all tasks related to managing potential employers, and another program collects all functionality to receive applications from prospective drivers. This is not to say that the programs are completely isolated islands; the program that manages potential employers is likely to offer a peek at the prospective drivers that an employer hired but is unlikely to provide facilities for receiving new driver applications.

Basic Program Design

If you embrace the concepts that each program in your application should have a narrow, defined focus and that programs should be structured and modular so component reuse is facilitated, then it becomes important to organize the various programs, forms, and components of your application in such a way that sharing those components is simple. In this section, I suggest a directory structure that provides an adequate infrastructure in support of these principles.

Directory Structure

A possible organization of the UNIX directory structure to support these criteria for developing applications is as follows (with the indentation indicating hierarchy):

Application Directory

Module Directory Module Directory System Library

Program Directory Program Directory Module Library Module Screens

Module File #1 Module File #2 Module File #n

At the root of the tree is the application directory. This directory collects all the organized components that make up the application. Directly under the application directory, you find the module directories. A module directory contains a logical grouping of program directories and libraries, which contain programs that cooperate to perform various tasks of a business function. In the fictional company, the application directory could be named corporate accounting. The module directories could be accounts receivable, operations, general ledger, recruiting, and so on. The system library, located at this level in the hierarchy, contains components: source code module files and objects and form source files and objects that are used by all modules. For instance, the company-wide logo that is displayed whenever a specific program is loaded is an example of a component located here. Within the recruiting module, you might find a program directory named employers (the example developed in this chapter) that collects all the functionality that is needed to manage prospective employers. You might also have another program directory named drivers that collects all the information about the truck drivers and provides the required functionality to manage them: taking applications, verifying employment records, verifying driving records, and so on.

In a directory structure like this, executable files (*.4gior*.4ge) reside in the program directories. Source and compiled screen forms (*.perand*.frm) reside also in program directories but may be found in module screens directories and perhaps even in the system library. Source code modules (*.4gl) and object modules (*.4goor*.o) are located in the program directories, module libraries, and the system library. Each program directory also contains the error log file for the program it defines. Defining a program in any of the program directories requires that you identify the local globals file and local source code modules and you include other objects that are located in../or in../../.

Executing a program in any program directory requires that yourDBPATHvariable point to the directory where the executables are (usually the current directory), as well as to directories that contain forms that are called by the program. The definition ofDBPATH, in this directory structure, becomesDBPATH=$DBPATH:.:../:../../.

Libraries

In this context, libraries are defined as repositories of functions or reports that perform a specific task. These functions receive a collection of arguments and return a collection of values without interacting with the calling program in any way other than through arguments and returned values.

Libraries tend to be organized along the same criteria used to organize module directories. There are multiple library directories, both at the module and system levels, that collect similar types of objects. A library of error management routines collects all error detection, error display, and reporting mechanisms, as well as adequate responses depending on the severity of the runtime errors encountered. There may also be a library of common database delivery functions that collects source code modules that are defined to receive a key for a table and return some descriptive value from that table. (For example, upon receiving an employee code, it returns a string that concatenates the first name, middle initial, and last name of an employee with appropriate spacing.) There may also be a library of conversion functions that perform numeric-to-string conversions and vice versa while rounding or truncating the numeric values to the desired number of decimal places. There may also be a library of string-manipulation functions that collect functions that find substrings within a string or center or right justify a string.

Common Forms and Modules

In the context of a programming language that is designed to deal with database information, common forms and modules are defined as repositories of functions that perform a task that requires user and database interaction through query or input within a form or prompt. These functions respond to the user's action by returning a collection of values to the calling program. Common forms and modules tend to be organized within libraries along the same criteria used to organize module directories.

Many business applications require that you provide users with pop-up, zoom, or drill-down facilities to fill in values during data entry that have to exist in a parameter table. For instance, in the fictitious company, while entering the code for a state in an employer address, you want to make sure that the spelling of the state is correct and force the value entered to be validated against a table of valid state codes. If the user does not remember the state code or if he fails to provide a correct state code, you want to provide a pop-up window that allows the user to view the valid state codes and select the appropriate value, which is then returned to the calling program. The screen forms and source code modules for this type of zooming operation is used throughout an application and become prime candidates for a common library.

Accounting applications usually require the user to provide an account, or a pair of accounts, for recording or posting a business transaction. A pop-up window for providing the suggested defaults and allowing the user to alter the defaults is also a typical example of a screen form and its processing source code that are candidates for placement in a common access library.

Skeleton of an INFORMIX-4GL Program

The basic skeleton for an INFORMIX-4GLprogram consists of the following program blocks (placed in a single source code module file or in multiple source code module files):

[database ] --Required if the program interacts with a database

[globals] --Only one globals definition per program

end globals ]

[globals ""]

--Many global declarations per program

main --One, and only one, is required in a program

end main

[function () --A program may have many functions

[return ]

end function]

[report () --A program may have many reports

end report]

Each of these program blocks is defined in more detail in the following sections, except for reports, which are covered in Chapter 37, "4GL Development."

Database

Thedatabasestatement has the following syntax:

[database [exclusive]]

The options in this command are defined as follows:

is a database name on your database server.

[exclusive]opens the connection to the database in exclusive mode if there are no open connections and prevents any other user from connecting to the database.

Thedatabasestatement performs two functions. While developing the program, it provides the compiler with a database to use when you define variables by reference to database tables and columns. On execution, it opens a connection to a specific databaseand closes the connection to the database that was open prior to its execution.

The database nameused in this statement is a reference to a database in the database server (dbservername) that is referenced by your environment (INFORMIXSERVERsetting). You may specify a different server and establish a connection to a remote database by using the following notation@or`///'for the OnLine engine or`////'or`//@'for the SE engine.

Examples of thedatabasestatement are

database recruiters

database recruiters@on_fort_tcp

Globals

Theglobalsprogram block has two forms. The first version declares and defines the program variables that have global scope throughout the program. The second version identifies a file that contains global definitions to be used in the source code module that includes the statement.

The syntax for the first version of the statement is

[globals

end globals ]

It is useful to isolate theglobalsdefinitions in a source code module file that can then be referenced by the second version of the statement. It is convenient to include thedatabasestatement in the globals source code module so that it is inherited by the source code modules that use the second version of theglobalsstatement.

The syntax for the second version of the statement is

[globals ""]

An example of theglobals.4glfile used for the fictitious company is provided in Listing 36.2.

Listing 36.2. globals.4gl for the fictitious company.

database recruiters

##################################################################

globals

##################################################################

define p_employers record like employers.*,

is_valid smallint

end globals

The keywordsglobalsandend globalsencapsulate theglobalsprogram block. Within aglobalsprogram block, you include global variable definitions. Variable scope is discussed further in the section "Variables Definition, Initialization, and Scope," later in this chapter.

Main

Themainprogram block is required in a program. A program must have only onemainprogram block. This is the starting point in the execution of an INFORMIX-4GL program:

main

end main

The keywordsmainandend mainencapsulate themainprogram block. Within themainprogram block, you can include local variable definitions, function calls, and any other valid 4GL statement. Themainprogram block is usually kept very small and often limited to managing the flow of control for the application.

An example of amainprogram block is

main

call InitEnv()

call FlowOfControl()

end main

This sample program first calls a function calledInitEnvand then calls the functionFlowOfControl. The program then terminates when it reachesend mainunless it was terminated programmatically before reaching theend mainstatement.

Function

A function can be called within themainprogram block or within anotherfunctionorreportprogram block. The syntax for the call to a function, if the function returns more than one value, must be as follows:

call () [returning ]

The options are as follows:

identifies the function called.

is a list of values or variables passed to the function as arguments.

is a list of program variables that are loaded with the values returned by the function to the calling program.

If a function returns a single value, thecallstatement can be used to invoke it, but the function can also be invoked within another command-line argument without using the keywordcall.

For example, the functionMakeNameis defined to receive three arguments--first name, middle initial, and last name--and return a concatenated string with the structure, . The function could be invoked as follows:

call MakeName(p_employee.fname, p_employee.mi, p_employee.lname)

returning p_full_name

Because it returns a single value, theMakeNamefunction could be invoked as part of a statement involving other components, as follows:

let p_print_name = "Employee: ", MakeName(p_employee.fname, p_employee.mi,

p_employee.lname) clipped, " (", p_employee.emp_no, ")"

This statement concatenates the string"Employee: ", the string returned by theMakeNamefunction, removing trailing blanks (clipped),and it follows this with the string" (", followed by the employee code, followed by the string")".

A function definition has the following syntax:

[function ()

[return ]

end function]

The options in this definition are covered in detail later in this chapter. As an example, I define the functionMakeName:

function MakeName (fn, mi, ln)

define fn, mi, ln char(80),

full_name char(256)

let full_name = ln clipped, ", ", fn clipped, " ", mi

return full_name

end function

The order of the arguments in the calling clause and in the function definition is important because the first argument in the calling statement is passed to the first parameter in the function. This function returns a single value and therefore can be called in the two forms described. Functions that return multiple values can be invoked only by means of thecallstatement.

TIP:The function program block is reentrant, thereby allowing recursive programming; a function can call itself. INFORMIX-4GL manages the stack on your behalf.

Report

Thereportprogram block defines the format of a report. A report must be started (initialized) before it receives output and must be finished after all output is sent to the report. To manage a report, you must use the following logical sequence of statements:

start report [to {[]

[printer]

[pipe ]}

The options in this command are defined as follows:

is the specific report to initialize.

tois the destination of the report and supersedes the destination defined in the report program block.

sends the output of the report to a file.

printersends the output of the report to the default printer or the printer specified by yourLPDESTsettings.

pipe sends the output of the report to be processed by the program.

To continue with the example for functionMakeName, you can initialize a report that prints the name stored in variablep_print_nameand sends its output to the commandpg:

start report PrintName to pipe "pg"

After the report is initialized with the statementstart report, the program sends records to the report formatter within some form of a loop using theoutput tostatement as follows:

output to report ()

The options in this command are defined as follows:

is the specific report to send the record to.

is the list of variables or constants to be sent to the report formatter.

Within a loop, you invoke theoutput to reportstatement as follows:

let p_print_name = "Employee: ", MakeName(p_employee.fname, p_employee.mi,

p_employee.lname) clipped, " (", p_employee.emp_no, ")"

output to report PrintName (p_print_name)

The order of the arguments in theoutput to reportand in thereportdefinition is important because the first parameter in theoutput to reportstatement is passed to the first parameter in the report.

Finally, after all records are sent to the report, the report must be terminated with thefinish reportstatement as follows:

finish report

The options in this command are defined as follows:

is the specific report to finish.

After looping through all the employee records in the fictitious company that you want to print, you issue afinish reportstatement as follows:

finish report PrintName

A report definition has the following syntax:

[report ()

end report]

The options in this definition are covered in detail in Chapter 37. As an example, I define the reportPrintNamewith the simplest possible syntax in a report:

report PrintName (p_name)

define p_name char(256)

format every row

end report

Data Types, Operators, and Functions

Most of the data types available in INFORMIX-4GL are part of the basic set of data types that Informix engines support. The basic data types that Informix provides with its database engines were introduced in Chapter 30, "Data Management Using SQL." A summary of those basic data types is included in Table 36.1 for easy reference.

Table 36.1. Basic Informix data types by engine.

Type and Structure

SE

OnLine

char (n)

Y

Y

character (n)

Y

Y

dec (precision, scale)

Y

Y

decimal (precision, scale)

Y

Y

double precision (float precision)

Y

Y

float (float precision)

Y

Y

int

Y

Y

integer

Y

Y

money (precision, scale)

Y

Y

numeric (precision, scale)

Y

Y

real

Y

Y

serial (starting number)

Y

Y

smallfloat

Y

Y

smallint

Y

Y

date

Y

Y

datetime to

Y

Y

interval to

Y

Y

byte in

N

Y

text in

N

Y

varchar (, )

N

Y

INFORMIX-4GL offers two additional data types that are unique to 4GL. The declaration and definition of all data types is covered in detail in the next section. These additional INFORMIX-4GL-only data types are listed here to complete the list of available data types in INFORMIX-4GL:

record {[like .*]

[[ like ., ...]

[ , ...]]}

end record

array "[" [, [ , ] ] "]"

of

See the next section for the definitions and examples of these two types of variables.

Variables Definition, Initialization, and Scope

Variables of all types are declared and their data type is identified in thedefinestatement as follows:

define , ...

It is appropriate to apply to INFORMIX-4GL programs the same variable-naming conventions that are applicable in other programming environments at your organization. In lieu of any other naming conventions, a very simple naming arrangement uses ap_prefix to identify program variables, ans_prefix to define screen records in forms, perhaps apa_prefix to identify program arrays, and ansa_prefix to define screen records in forms. A more comprehensive naming set is shown in Table 36.2.

Table 36.2. Variable naming standards.

Variable Name

Used for

g_

Global variables

p_

Non-record program variables

r_

Record program variables

a_

Array program variables

ra_

Array of record variables

s_

Screen record in form definitions

sa_

Screen array of records in form definitions

No matter what your naming standards are, adherence to the standards greatly simplifies both development and maintenance tasks.

Examples of variable definitions have already appeared earlier in this chapter. Here are some more examples, particularly for record and array data types:

define p_print_name char(256),

is_valid smallint,

p_emp_count, p_counter integer

This declaration makesp_print_namea character string of a fixed 256-byte length. Theis_validvariable, defined as a small integer, does not follow the naming conventions illustrated earlier, but in the environment, it is always used as a Boolean test, so it has also become a standard. The variablesp_emp_countandp_counterare both defined as integers.

Variables can also match the data types of the columns in database tables that they represent. Thelikekeyword is used to match the declaration to a column data type as follows. (Please refer to the schema files for the fictitious company example, listed at the beginning of this chapter.)

define p_empl_code integer,

p_employer like employers.employer,

p_state like states.state

Thep_empl_codevariable is defined as an integer to match theserialdata type that the columnemployers.empl_codehas.p_employerinherits the data type and attributes of theemployers.employercolumn, andp_stateinherits fromstates.state. Because there is no reference to a database engine, INFORMIX-4GL attempts to find these variables in the database managed by the server defined by theINFORMIXSERVERsetting unless thedatabasestatement in your program specifically points to a remote database. To specifically define a variable from a remote database, while most of your variables are defined by the database in thedatabasestatement, use the same notation illustrated when defining thedatabaseblock:

define p_remote_empl_code like test@on_fort_tcp:employers.empl_code

test@on_fort_tcp uses the notation@, andemployersis the name of the table sought.p_remote_empl_coderefers to columnemployers.empl_codein the databasetestin database serveron_fort_tcp.

A record variable is a data structure that collects multiple members that can be addressed collectively or individually. One of the frequent uses of a record variable is to match an entire table definition in the database to a program variable in memory. This definition looks like

define p_employers record like employers.*,

p_states like states.*

The record variablep_employershas as many members as there are columns in the employers table. You can address members in a record singly or in groups as follows:p_employers.cityrefers to the elementcityof the recordp_employersand is often used in this form for testing, assigning, entering, or printing.p_employers.employerthroughphonerefers to all members included between theemployerandphonein the same sequence as they are defined in the database table and is often used in entering or when fetching records from the database.p_employers.*refers to all members of the record and is often used to enter or to retrieve records from the table.

You can also make up records for program-specific purposes and define their members individually as follows:

define p_address record

empl_code like employers.emp_code,

state like employers.state,

state_long_name like states.state_name,

employee_count integer,

regional_airport char(25)

end record

This record inherits data types from two tables for part of its members and uses basic data types for others.

A variable of typearrayis defined as follows:

define pa_calendar array [12] of date,

pa_employers array [500] of record like employers.*

Thepa_calendaris an array of up to 12 dates, but the arraypa_employersmay contain up to 500 elements, each of which has a record data structure that matches that of the table employers. To refer to a specific entry in an array, you indicate the position of the member in the array (the first member is identified by1) as inpa_employers[100].empl_code, which refers to theempl_codevalue of the 100th element of the arraypa_employers.

To initialize variables, INFORMIX-4GL uses the statementinitializeand at times the assignment statementlet(which is covered later). The syntax forinitializeis

initialize to null

An example is

initialize p_employers.* to null

initialize p_states.state_code to null

initialize is_valid to null

You can define variables in three places in an INFORMIX-4GL program: in globals, outside of any program block, or inside a program block (main, function, or report). The scope of a variable is determined by the position of thedefinestatement that declares it. Variables declared in the globals program block are available and visible throughout an entire program; their values can be altered anywhere and are preserved when the flow of control moves from program block to program block. Variables declared inside a program block, as in afunctionprogram block, are available and visible only within that program block. Variables defined outside all program blocks within a source code module are global to all functions and reports (and main) also defined in that source code module. When the name of a local variable is the same as the name of a global variable, the value of the local variable is used in preference over the value of the global variable within the local function. In general, when name conflicts occur, the most local variable wins.

Data Types and Implicit Conversions

INFORMIX-4GL supports assignments of variables of different data types and attempts to convert them implicitly as best it can. If it fails, it issues an error message.

Conversion between numeric data types is successful if the destination can actually store the value it receives. For instance, assigning an integer to a smallint fails if the magnitude of the integer exceeds 32,767, the value of the largest smallint. Numeric conversion always occurs within an arithmetic expression because INFORMIX-4GL performs all arithmetic with decimal data types of differing precision and scale.

Conversion between numeric data types and character data types is also possible in both directions. A numeric data type can be assigned to a character data type, and as long as the character string is large enough, the conversion functions. When the character variable is not large enough to receive the numeric value, truncation occurs and theSQLCArecord reports that action. Assigning a character data type to a numeric data type is acceptable as long as the characters are numbers or proper punctuation, such as a comma, period, or plus or minus sign.

Conversion between character data types of different size may result in truncation if the destination character variable is smaller than the original.

Dates are stored as integer values in INFORMIX-4GL and can be assigned to an integer variable without problems. The reverse assignment from integer to date is also possible. Dates start at 1/1/1900 (integer value 1 represents 1/1/1900; an uninitialized date variable is displayed as 12/31/1899). Values smaller than 1 yield dates earlier than 1/1/1900. Dates can also be converted to character, and as long as a character variable contains a valid date format, it converts properly to a date.

The most difficult conversions are from date or character to datetime and interval variables. A date variable can be converted to a datetime variable, but if the precision of the datetime is smaller than day, Informix fills the time units smaller than day with zeroes. A better method to convert date variables to datetime variables is to use theextendoperator and manage the conversion in your own terms. A character variable can be converted to a datetime as long as the format within the string matches the expectations of the datetime for the precision in its definition. The character variable requires a format likeyyyy-mm-dd hh:mm:ss.fffffwith a space between the date and the time or the appropriate portion of this format that matches the precision of the datetime variable. Converting character variables to interval variables requires the same formatting as the conversion between character and datetime variables.

Operators

INFORMIX-4GL supports operators that are also valid in SQL, such as those shown in Table 36.3.

Table 36.3. SQL operators supported in INFORMIX-4GL.

Operator

Functional Description

Mathematical Operators

+

Unary plus and addition

-

Unary minus and subtraction

*

Multiplication

/

Division

Relational Operators

=

Greater than or equal to

=

Equal

Not equal

!=

Not equal

[not] between

Inclusive range

Boolean Operators

not

Unary

and

Conditional and

or

Conditional or

String Operators

||

Concatenation

matches

Pattern matching

like

Pattern matching

Set Operators

[not] in

Value contained (or not) in list

[not] exists

True if at least one row is returned by subquery

all

True if all values returned by subquery are true

any

True if any values returned by subquery are true

some

True if some values returned by subquery are true

Null Operators

is [not] null

True if the argument is not null

In addition, INFORMIX-4GL also supports some operators that are not available in SQL. These are listed in Table 36.4.

Table 36.4. Additional INFORMIX-4GL operators.

Operator

Functional Description

**

Exponentiation

mod

Modulus (division remainder)

,

Concatenate strings

clipped

Clip trailing blanks from a string

using

Format data for display or report purposes

For example, the following statements result in the variablep_resultreceiving the value8:

let p_value1 = 2

let p_value2 = 3

let p_result = p_value1 ** p_value2

In the following code, the variablep_resultreceives the value3:

let p_value1 = 17

let p_value2 = 20

let p_result = p_value2 mod p_value1

In the following code, the character variablep_resultreceives the value"John Doe":

let p_string1 = "John "

let p_string2 = "Doe "

let p_result = p_string1 clipped, " ", p_string2

Formatting with theusingoperator allows you to display dates and numbers in the format you specify. For date values, theusingclause uses the strings identified in Table 36.5.

Table 36.5. Date formatting with using.

String

Results in a Display of

dd

Day of the month from 1 to 31

ddd

Day of the week: Sun, Mon, ...

mm

Month of the year from 1 to 12

mmm

Abbreviation of the month: Jan, Feb, ...

yy

Two-digit year

yyyy

Four-digit year

For example, to place the stringTue, Apr 15, 1997in the character variablep_result, you use a date variablep_datewith the appropriate value, as in the following code:

let p_date = "4/15/97"

let p_result = p_date using "ddd, mmm dd, yyyy"

using is used extensively in reporting and display statements. To format numbers, theusingclause uses the strings identified in Table 36.6.

Table 36.6. Number formatting with using.

String

Results in a Display of

#

Number or blank

&

Number or zero

*

Number or asterisk

|

}

The cursor is given the name, and it can be declared for a, for an, or for a preprocessed. If rows will be retrieved only sequentially, you can use a regular cursor, but if you want to navigate back and forth within the result set, you need to use thescrollclause to declare a scroll cursor. By default, after you open a cursor in INFORMIX-4GL, the system closes the cursor every time it completes a transaction. Thewith holdclause keeps the cursor open after ending a transaction. If you intend to update the current row, use thefor updateclause. Here are examples of adeclarecursor statement:

declare c_employers scroll cursor with hold for statement_1

declare c_employers2 scroll cursor with hold for statement_2

for update of freight

declare c_employers cursor for select * from employers order by empl_code

Now that the cursor is declared, you need to activate its result set by using theopenstatement, like this:

open [ using [ , ... ] ]

When the program invokes this statement, the server receives the SQL it represents for the first time. The server performs error checking, sets the SQLCA variable, and stops short of delivering the first row of the result set. If theselectstatement that was prepared contained placeholders (question marks) for replacement by program variables at execution time, theusingclause delivers these variables to theopenstatement. Here are examples of both forms ofopenstatements:

open c_employers

let p_state = "MO"

open c_employers2 using p_state

Now that the cursor is open, you can start retrieving records and placing them in program variables. Thefetchstatement serves this purpose, and its syntax is as follows:

fetch { next | previous | prior | first |

last | current |

relative |

absolute

} [ into ]

A sequential cursor (one declared without the scroll clause) can perform only afetch next, but a scroll cursor can use any of the positioning clauses indicated earlier. (The next and previous clauses are used in the example in Listing 36.7.) The record retrieved by thefetchis placed in program variables listed in theinto clause. Here's an example of this statement:

fetch first c_employers into p_employers.*

After you are finished using the cursor, you need to close it and free the resources it holds. Theclosestatement uses the following syntax:

close

Thefreestatement uses the following syntax:

free { | }

An alternative to theopen,fetch, andclosecombination is theforeachstatement, which performs all these functions on your behalf. Theforeachstatement is widely used in reports or when loading static arrays, and it is discussed in that context in Chapter 37.

To display the data placed in program variables to the form on the screen, you use thedisplaystatement as follows:

display { by name [ , ... ] }

[ attribute ( [ , ... ] ) ] |

[ , ... ] |

[ , ... ]

[ { to { [ , ... ] } |

["[""]"].*

at , }

[ attribute ( [ , ... ] ) ]

]

Thedisplaystatement is used to display program variables onto screen fields. You can also display ato a screen field. If the program variables and the screen fields use the same names, you can use theby nameclause; otherwise, you have to match the program variable and the screen field to display it with thetoclause. Theat , clause was covered earlier in this chapter.

Here are some examples of thedisplaystatement:

display by name p_employers.*

display p_employers.* to s_employers.*

To modify the program variables on the screen form and ultimately the database rows, you use theinputstatement. This statement is discussed in the section titled "Adding, Deleting, and Updating Records." Take some time to look at thefind.4glmodule in Listing 36.7, which covers the entire process described here in functionfind_it().

Finding Records and Displaying Records

The Find menu option in Figure 36.1 is designed to allow the user to create a query dynamically. After the user chooses the Find option, the cursor drops down to the form and allows the user to specify the criteria desired for any of the displayed screen fields. This process allows the user to create a Query-By-Example. A collection of characters is available to build the Query-By-Example. These special characters are listed in Table 36.8.

Table 36.8. The Query-By-Example special characters.

Character

Purpose

=

Equal to (if followed by nothing will look for null values)

>

Greater than

>=

Greater than or equal to


Recommended