4GL Concepts and Use
4GL Concepts and Use
4GL Concepts and Use
Note: Before using this information and the product it supports, read the information in the appendix entitled Notices.
This document contains proprietary information of IBM. It is provided under a license agreement and is protected by copyright law. The information contained in this publication does not include any product warranties, and any statements provided in this manual should not be interpreted as such. When you send information to IBM, you grant IBM a nonexclusive right to use or distribute the information in any way it believes appropriate without incurring any obligation to you. Copyright International Business Machines Corporation 1996, 2002. All rights reserved. US Government User Restricted RightsUse, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Table of Contents
Table of Contents
Introduction
In This Introduction . . . . . . . . About This Manual . . . . . . . . . Organization of This Manual . . . . Types of Users . . . . . . . . . Software Dependencies . . . . . . Assumptions About Your Locale. . . Demonstration Database and Examples Accessing Databases from Within 4GL. Enhancements to Version 7.31 . . . . . Documentation Conventions . . . . . Typographical Conventions . . . . Icon Conventions . . . . . . . . Additional Documentation . . . . . . Documentation Included with 4GL . . On-Line Manuals . . . . . . . . On-Line Help . . . . . . . . . On-Line Error Messages. . . . . . Related Reading . . . . . . . . Informix Welcomes Your Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 5 6 6 7 8 9 10 10 11 11 12 12 13 13 14 14
Chapter 1
Introducing INFORMIX-4GL
In This Chapter . . . . . . . . . . What Is 4GL? . . . . . . . . . . . 4GL Provides a Programmers Environment 4GL Works with Databases . . . . . . 4GL Runs in Different Environments . . . Informix Dynamic 4GL . . . . . . . Two Implementations of 4GL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3 1-3 1-3 1-4 1-5 1-5 1-5
Chapter 2
Interfaces of INFORMIX-4GL
In This Chapter . . . . . . . . . . . . . . . . . . . Database Access . . . . . . . . . . . . . . . . . . Access to Sequential Files . . . . . . . . . . . . . . . Report Output . . . . . . . . . . . . . . . . . . . User Access . . . . . . . . . . . . . . . . . . . . Using Forms and Menus . . . . . . . . . . . . . . . Summary . . . . . . . . . . . . . . . . . . . . . 2-3 2-5 2-5 2-6 2-6 2-8 2-9
Chapter 3
Chapter 4
Parts of an Application
In This Chapter . . . . . . . The Database Schema . . . . Form Specications and Form Files Form Design . . . . . . Field Entry Order . . . . Program Source Files . . . . . Organization of a Program . The Globals Files . . . . . Program Object Files . . . . . P-Code Object Files . . . . C-Code Object Files . . . . Example Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3 4-5 4-6 4-9 4-9 4-10 4-10 4-11 4-11 4-13 4-14 4-15
iv
Chapter 5
Chapter 6
Chapter 7
Table of Contents
How Query by Example Is Done . . . . . . . . . . . . . How 4GL Windows Are Used . . . . . . . . . . . . . . Alerts and Modal Dialog Boxes . . . . . . . . . . . . Information Displays . . . . . . . . . . . . . . . How the Help System Works . . . . . . . . . . . . . .
Chapter 8
vi
Working with Multiple Values . . . Assigning One Record to Another Passing Records to Functions . . Returning Records from Functions
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Chapter 9
Chapter 10
Creating Reports
In This Chapter . . . . . . . . . . . . . . . Designing the Report Driver . . . . . . . . . . . An Example of a Report Driver . . . . . . . . Designing the Report Denition . . . . . . . . . The REPORT Statement . . . . . . . . . . . The Report Declaration Section . . . . . . . . The OUTPUT Section . . . . . . . . . . . . The ORDER BY Section . . . . . . . . . . . One-Pass and Two-Pass Reports . . . . . . . . The FORMAT Section . . . . . . . . . . . Contents of a Control Block . . . . . . . . . Formatting Reports . . . . . . . . . . . . PAGE HEADER and TRAILER Control Blocks . . . ON EVERY ROW Control Block . . . . . . . . ON LAST ROW Control Block . . . . . . . . BEFORE GROUP and AFTER GROUP Control Blocks Default Reports . . . . . . . . . . . . . . Using Aggregate Functions. . . . . . . . . . END REPORT and EXIT REPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-3 10-4 10-5 10-6 10-8 10-9 10-10 10-12 10-13 10-15 10-16 10-17 10-18 10-19 10-19 10-20 10-21 10-21 10-24
Chapter 11
Chapter 12
Handling Exceptions
In This Chapter . . . . . . . . . . . Exceptions . . . . . . . . . . . . Runtime Errors . . . . . . . . . SQL End of Data . . . . . . . . . SQL Warnings . . . . . . . . . . Asynchronous Signals: Interrupt and Quit Using the DEFER Statement . . . . . . Interrupt with Interactive Statements . . Using the WHENEVER Mechanism . . . . What WHENEVER Does . . . . . . Actions of WHENEVER . . . . . . Errors Handled by WHENEVER . . . Using WHENEVER in a Program . . . Notifying the User . . . . . . . . . . Logging Runtime Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 12-4 12-4 12-5 12-6 12-6 12-7 12-8 12-10 12-11 12-11 12-12 12-13 12-15 12-15
Appendix A
Notices Index
Table of Contents ix
Introduction
Introduction
In This Introduction
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
3 3 3 5 6 6 7 8 9 10 10 11 11 12 12 13 13 14 14
About This Manual . . . . . . . . . Organization of This Manual . . . . Types of Users . . . . . . . . . Software Dependencies . . . . . . Assumptions About Your Locale . . . Demonstration Database and Examples Accessing Databases from Within 4GL . Enhancements to Version 7.31 . Documentation Conventions . Typographical Conventions Icon Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Additional Documentation . . . . Documentation Included with 4GL On-Line Manuals . . . . . . On-Line Help . . . . . . . On-Line Error Messages. . . . Related Reading . . . . . . Informix Welcomes Your Comments .
In This Introduction
This introduction provides an overview of the information in this manual and describes the conventions it uses.
quickly write sophisticated, portable, forms-driven, full-screen applications for data entry, data lookup and display, and report generation. The 4GL development environment provides all the tools necessary to design forms, construct and manage program modules, and compile source modules.
Introduction 3
What 4GL is. Part I covers the main features of 4GL, describes the kind of work it is meant to do, and the ways it is normally used:
Chapter 1, Introducing INFORMIX-4GL, describes what 4GL is used for and where the program can be run. Chapter 2, Interfaces of INFORMIX-4GL, describes how 4GL allows interactive forms, SQL databases, sequential les, and reports to work together. Chapter 3, The INFORMIX-4GL Language, introduces the procedural and non-procedural aspects of the language.
How 4GL is designed. Part II covers the fundamental ideas behind the design of 4GL so you will know its parts and how they t together:
Chapter 4, Parts of an Application, is an overview of the components of a 4GL application. Chapter 5, The Procedural Language, describes three basic 4GL language features: data denition, decisions and loops, and handling error conditions. Chapter 6, Database Access and Reports, examines the relationship between the data in a SQL database and 4GL reports.
Some partial coding examples are used to illustrate the main points. Read Part II before you begin using 4GL.
Types of Users
How to use 4GL. Part III explores 4GL in depth, using examples and discussion to show how its statements are used together to solve common programming tasks and build an application:
Chapter 7, The User Interface, reviews the major components of an interactive 4GL application. Chapter 8, Using the Language, details the data types available in 4GL, variables, data structures and use of arrays, and other, similar topics. Chapter 9, Using Database Cursors, overviews non-procedural, row-by-row, and dynamic methods of accessing an SQL database from a 4GL application. Chapter 10, Creating Reports, shows how to design 4GL report drivers and report formatters. Chapter 11, Using the Screen and Keyboard, takes a detailed look at the methods of specifying a screen form and managing 4GL windows. Chapter 12, Handling Exceptions, looks at the problem of handling anticipated and unanticipated situations when running a 4GL application. A Notices appendix describes IBM products, features, and services.
This manual has a companion, INFORMIX-4GL Reference, which shows every part of the language in great detail. INFORMIX-4GL Concepts and Use does not cover every feature of every statement, but provides you with the vocabulary and understanding necessary to use INFORMIX-4GL and INFORMIX-4GL Reference.
Types of Users
This manual is written for all 4GL users. You do not need database management experience or familiarity with relational database concepts to use this manual. A knowledge of Structured Query Language (SQL) however and experience with a high-level programming language would be useful.
Introduction 5
Software Dependencies
Software Dependencies
This manual is written with the assumption that you are using an Informix database server, Version 7.x or later. Informix offers the following two implementations of the 4GL application development language:
s
The INFORMIX-4GL C Compiler uses a preprocessor to generate INFORMIX-ESQL/C source code. This code is preprocessed in turn to produce C source code, which is then compiled and linked as object code in an executable command le. The INFORMIX-4GL Rapid Development System (RDS) uses a compiler to produce pseudo-machine code (called p-code) in a single step. You then invoke a runner to execute the p-code version of your application.
Both versions of 4GL use the same 4GL statements. For a description of the differences between the two versions, see INFORMIX-4GL Reference. You can easily use applications developed with an earlier version of 4GL, such as Version 4.0 or 4.1, with this version of 4GL. Also, if you have 4GL applications written for the Windows environment, you can compile and run the applications on a UNIX platform.
For instructions on how to specify a nondefault locale, additional syntax, and other considerations related to GLS locales, see the Informix Guide to GLS Functionality.
database called stores7 that contains information about a ctitious wholesale sporting-goods distributor. To create the stores7 database in the current directory, enter the following command:
dbaccessdemo7
Many (but not all) of the examples in the 4GL documentation set are based on the stores7 database. This database is described in detail in INFORMIX-4GL by Example. The examples are installed with your software in the $INFORMIXDIR/demo/fgl directory. For U.S. English, go to the en_us/0333 subdirectory; for other languages, go to the appropriate subdirectory under the fgl directory. To use the examples, change to a directory where you want the examples to reside, and enter the following command:
fglexcopy
Introduction 7
For most SQL syntax that was supported by Informix 4.1 database servers, you can directly embed SQL statements in 4GL source code. (Exceptions are the CREATE SCHEMA, DESCRIBE, INFO, SET ISOLATION, and SET LOG statements.) For all SQL statements that can be prepared, you can use the PREPARE feature of SQL to include SQL statements as text within prepared objects; see the description of PREPARE in INFORMIX-4GL Reference. For any SQL statement that your database server supports, you can use the SQL ... END SQL delimiters.
You must use one of the last two methods for SQL statements that include syntax that was introduced later than Informix 4.1 database servers. Such embedded, prepared, or delimited SQL statements are passed on to the database server for execution. For more information about using PREPARE and SQL ... END SQL delimiters, see INFORMIX-4GL Reference. For additional information on SQL statements, see the Informix Guide to SQL: Syntax.
The NCHAR and NVARCHAR data types are now recognized and supported. For information about the NCHAR and NVARCHAR data types, see INFORMIX-4GL Reference. For database servers that support long SQL identiers, your 4GL applications can reference SQL identiers that are up to 128 bytes in length. For more information about IFX_LONGID, see INFORMIX-4GL Reference.
IBM INFORMIX-4GL is compatible with IBM Informix Client SDK 2.70.xC3 and later. Client SDK components allow developers to write
applications in the language they are familiar with, whether it be Java, C++, C, or ESQL. For more information about Client SDK, see the documentation set at www.informix.com/answers.
Introduction 9
Documentation Conventions
Documentation Conventions
This section describes the conventions that this manual uses. These conventions make it easier to gather information from this and other volumes in the documentation set. The following conventions are discussed:
s s
Typographical Conventions
This manual uses the following conventions to introduce new terms, illustrate screen displays, describe command syntax, and so forth.
Convention KEYWORD italics italics
italics
Meaning All primary elements in a programming language statement (keywords) appear in uppercase letters in a serif font. Within text, new terms and emphasized words appear in italics. Within syntax and code examples, variable values that you are to specify appear in italics. Names of program entities (such as classes, events, and tables), environment variables, le and pathnames, and interface elements (such as icons, menu items, and buttons) appear in boldface. Information that the product displays and information that you enter appear in a monospace typeface. Keys that you are to press appear in uppercase letters in a sans serif font. This symbol indicates the end of product- or platform-specic information.
boldface boldface
10
Icon Conventions
Tip: When you are instructed to enter characters or to execute a command, immediately press RETURN after the entry. When you are instructed to type the text or to press other keys, no RETURN is required.
Icon Conventions
Throughout the documentation, you will nd text that is identied by several different types of icons. This section describes these icons.
Icon
GLS
Description Identies information that relates to the Informix Global Language Support (GLS) feature Identies information that is specic to Informix Dynamic Server and Informix Dynamic Server, Workgroup Edition Identies information or syntax that is specic to INFORMIX-SE
IDS
SE
These icons can apply to a row in a table, one or more paragraphs, or an entire section. A symbol indicates the end of the feature-specic, productspecic, or platform-specic information.
Additional Documentation
For additional information, you might want to refer to the following types of documentation:
s s s s s
Documentation included with 4GL On-line manuals On-line help On-line error messages Related reading
Introduction 11
INFORMIX-4GL Installation Guide describes how to install the various 4GL products. INFORMIX-4GL Reference is a day-to-day, keyboard-side companion for 4GL programmers. It describes the features and syntax of the 4GL language, including 4GL statements, forms, reports, and the built-in
programs. Each program is introduced with an overview; then the program source code is shown with line-by-line notes. The program source les are distributed as text les with the product; scripts that create the demonstration database and copy the applications are also included.
s
Guide to the INFORMIX-4GL Interactive Debugger is both an introduction to the Debugger and a comprehensive reference of Debugger commands and features. The Debugger allows you to interact with your 4GL programs while they are running. It helps you learn more about the 4GL language and determine the source of errors within your programs. Documentation notes, which contain additions and corrections to the manuals, and release notes are located in the directory where the product is installed. Please examine these les because they contain vital information about application and performance issues.
On-Line Manuals
The Informix Answers OnLine CD allows you to print chapters or entire books and perform full-text searches for information in specic books or throughout the documentation set. You can install the documentation or access it directly from the CD. For information about how to install, read, and print on-line manuals, see the installation insert that accompanies Answers OnLine. You can also access Answers OnLine on the Web at the following URL: www.informix.com/answers.
12
On-Line Help
On-Line Help
4GL provides on-line help; to invoke help, press CONTROL-W.
where msg_num indicates the number of the error message to display. Error messages range from -1 to -32000. Specifying the - sign is optional. For example, to display the -359 error message, you can enter either of the following:
finderr -359
or, equivalently:
finderr 359
The following example demonstrates how to specify a list of error messages. The example also pipes the output to the UNIX more command to control the display. You can also direct the output to another le so that you can save or print the error messages:
finderr 233 107 113 134 143 144 154 | more
A few messages have positive numbers. These messages are used solely within the application tools. In the unlikely event that you want to display them, you must precede the message number with the + sign. The messages numbered -1 to -100 can be platform-dependent. If the message text for a message in this range does not apply to your platform, check the operating system documentation for the precise meaning of the message number.
Introduction 13
Related Reading
Related Reading
The following Informix database server publications provide additional information about the topics that this manual discusses:
s
Informix database servers and the SQL language are described in separate manuals, including Informix Guide to SQL: Tutorial, Informix Guide to SQL: Syntax, and Informix Guide to SQL: Reference. Information about setting up Informix database servers is provided in the Administrators Guide for your particular database server.
Informix Press, in partnership with Prentice Hall, publishes books about Informix products. Authors include experts from Informix user groups, employees, consultants, and customers. Recent titles about INFORMIX-4GL include:
s s
Advanced INFORMIX-4GL Programming by Art Taylor (1995) Programming Informix SQL/4GL: A Step-by-Step Approach by Cathy Kipp (1998) Informix Basics by Glenn Miller (1998)
You can access Informix Press on the Web at the following URL: www.informix.com/ipress.
The name and version of the manual that you are using Any comments that you have about the manual Your name, address, and phone number
14
Write to us at the following address: Informix Software, Inc. Tools Technical Publications Department 4100 Bohannon Drive Menlo Park, CA 94025 If you prefer to send electronic mail, our address is: doc@informix.com We appreciate your suggestions. Important: The doc alias is monitored only by the Informix departments that create and maintain manuals and on-line documentation les. It is not an appropriate channel for technical support issues, sales inquiries, or questions about the availability of Informix products.
Introduction 15
Chapter
Introducing INFORMIX-4GL
1
. . . . . . . . . . . . . . 1-3 1-3 1-3 1-4 1-5 1-5 1-5
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
1-2
In This Chapter
This chapter contains a high-level overview of INFORMIX-4GL. Its aim is to orient you to the capabilities and typical uses of the product and to answer general questions such as what kind of software 4GL is and what is it used for.
What Is 4GL?
4GL is a full-featured, general-purpose, fourth-generation programming
Database query and database management using SQL Reports from a relational database or from other data sources Form- and menu-based multiuser applications
These special features make 4GL especially well-suited to developing large database applications.
compile, and maintain large, multi-module programs. Within the Programmers Environment, you can accomplish the following tasks:
s s s s
Create new program modules and modify existing modules Compile individual modules and entire applications Create and compile forms that the application uses Run compiled applications
Introducing INFORMIX-4GL 1-3
Use INFORMIX-SQL to interact with an Informix database (if you have the INFORMIX-SQL product) Get help at any time with the on-line help feature
You can also manage your applications by using commands at the operatingsystem prompt rather than by using the Programmers Environment.
They retrieve data from a relational database and process the data with logic that is more complicated than SQL alone permits. They present data using screen forms and allow users to construct queries against the database. They allow users to alter database records, often enforcing complex requirements for business rules, referential integrity, data validation, and security. They update a database with data processed from other databases or from operating system les. They generate multipage, multilevel reports based on data from a database or other sources, often letting the user set the parameters of the report and select the data for it.
With 4GLyou can program applications of these kinds more easily than with any other language. In addition, 4GL has an open, readable syntax that encourages good individual or group programming style. Programs written in 4GL are easily enhanced and extended. This, with its development environment, makes it easy for programmers to become productive quickly, no matter what programming languages they know.
1-4
display-compatibility across operating environments. Applications that you develop are portable to the different platforms subject to simple porting guidelines. You can run this version of 4GL on the following types of computers:
s
On UNIX character-based terminals provided by a wide variety of hardware vendors On UNIX workstations
The C Compiler, which uses a preprocessor to generate INFORMIX-ESQL/C source code. This code is preprocessed in turn to produce C source code, which is then compiled and linked as object code in an executable command le. The Rapid Development System, which uses a compiler to produce pseudo-machine code (called p-code) in a single step. You then invoke a runner to execute the p-code version of your 4GL application. This version is sometimes abbreviated as RDS.
For details about the differences between the two versions, see INFORMIX4GL Reference.
Introducing INFORMIX-4GL 1-5
Chapter
Interfaces of INFORMIX-4GL
2
. . . . . . . 2-3 2-5 2-5 2-6 2-6 2-8 2-9
. .
. .
. .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
2-2
In This Chapter
Multiuser application programs that you write using INFORMIX-4GL have the following four primary interfaces to other software:
s s s s
Accessing a database through an Informix database server Communicating with end users through a terminal Accessing sequential les through the host operating system Generating reports that can then be sent to several destinations
Interfaces of INFORMIX-4GL
2-3
This chapter describes these interfaces and their uses. Figure 2-1 is an overview of how they work.
Figure 2-1 Multiuser Application Programs
Database reports
4GL window
Database
2-4
Database Access
Database Access
Your 4GL programs can access relational SQL databases that appropriate Informix database servers support. The database can be located on the same computer as the 4GL application program, but more often, the application runs on a separate client system. After network connections are properly established, database access is transparent; you need not write any special code to make it happen. In fact, the same 4GL program can work with a local database server that is located on the same computer on one occasion, and over a network to a database server on another computer on another occasion.
The UNLOAD statement writes selected rows of data from a database table to a specied le. The LOAD statement reads a le and inserts its lines as rows into a specied database table. The START REPORT or the REPORT statement can send output from a report to a specied sequential le or to an operating-system pipe. The PRINT FILE statement can incorporate the contents of a specied sequential le into the output of a 4GL report. The DISPLAY statement can be used to write to the screen. Using the host operating system, you can also direct these lines to a le or to another program.
Interfaces of INFORMIX-4GL
2-5
Report Output
Report Output
Your 4GL program can generate powerful and exible reports, whose output is a series of print lines. Output can be directed to any of the following several destinations:
s s s s
A screen A printer A host system sequential le, specied by its pathname A UNIX operating-system pipe to another process
The logic for generating reports is the same in all cases. The destination can be coded into the program or selected at execution time. Report programming is covered in more detail in Part II, with examples in Part III of this book.
User Access
To provide for portability of code across different platforms, your program interacts with the user through display areas, called windows, that have a xed number of character-height rows and character-width columns. The user of your application can be using any of the following environments:
s
A terminal-emulation program on a personal computer or workstation that is connected to a UNIX network A character-based terminal connected to a UNIX system
No matter what the physical display device, the 4GL user interface is programmed for xed-size characters. A 4GL window can display a xed number of characters horizontally, and a xed number of characters vertically. You specify these two dimensions when you declare the 4GL window, typically with dimensions that are sufcient to display a specic 4GL screen form. Each 4GL window can display no more than one 4GL screen form.
2-6
User Access
Screen forms of 4GL are also portable across 4GL applications and platforms. You design screen forms through which your program can display data. Then you compile the forms separately from the other parts of the program. The resulting compiled forms can be used with different 4GL programs. You display a form with one program statement and ll it with data in another; you can prompt for user input to any or all elds with a third. You can easily open additional display areas for alerts and other information. Interaction through a hierarchical set of ring menus (horizontal menus) is also fully supported.
Interfaces of INFORMIX-4GL
2-7
MAIN MENU //// ///////// /////// ////////////// ////////// //////// ///////// //////// ////// ////////// /////////// /////// ////// ////// ////////////
CUSTOMERS: /// /// /// /////////// [ /////// [ [ ////// [ //////// ////// [ /////////// [ ] ///////// /// [ ] ] ] /////// [ ] ///////// [ ][ ] ] ]
ORDERS: /// /// /// /// /// /////// ////// [ ] //////// /// [ ] ///// /// [ ] ///// /// [ ] ///// ///// /// //////////// ///// //// /// [ ][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ] ////// //// [ ]
MANUFACT MAINT //////////// /// [ ] [ ] [ ] [ ] [ ] /////////// //// ] ] ] ] ] ///// /// //// //// [ ] [ ] [ ] [ ] [ ]
[ [ [ [ [
The 4GL program species which screen elements the user interacts with at any given time. This predictability leads to an easily maintained linear program structure and simple program logic.
2-8
Summary
Summary
You use 4GL to write programs that connect key elements in the following informational structure:
s s s s
The database The interactive users of the database Common data les Output from database reports
While working with the database, you use the industry-standard SQL, which you can augment with your program logic. As you will see in subsequent chapters, your programs have a simple method to access common sequential les, and nonprocedural, task-oriented methods for getting information from a database, and for dening and producing reports. You can use 4GL to program elaborate user interactions based on forms and menus. This user interface is character-oriented; that is, output is displayed in a xed number of evenly spaced lines, each of which contains a xed number of monospace characters. This approach allows applications written in 4GL to run without modication on supported platforms.
Interfaces of INFORMIX-4GL
2-9
Chapter
3
3-3 3-3 3-6 3-6 3-7 3-8 3-9
In This Chapter .
. .
. .
. .
. .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
A Nonprocedural, Fourth-Generation Language Database Access . . . . . . . . . . Report Generation . . . . . . . . . . User Interaction . . . . . . . . . . Summary . . . . . . . . . . . . . .
3-2
In This Chapter
This chapter provides a brief tour of INFORMIX-4GL as a language. The purpose is to give you an idea of what 4GL code looks like. Many short examples are given in the following chapters and several complete examples are supplied on-line with the product. For additional details on the 4GL programming language, see Chapter 8, Using the Language. As a programming language, 4GL has several important features:
s
It is a procedural language, with facilities for structured programming. It is a nonprocedural, fourth-generation language with regard to:
tasks:
s s s
Declare variables of different data types Calculate values and assign them to variables Declare and dene functions
s s
Also like other programming languages, 4GL has control statements that you can use to dene choices, loops, and statement blocks of code. Figure 3-1 shows a short, complete program in 4GL. It prompts the user for a number and displays the square, cube, and fourth power of the number.
Figure 3-1 Short Program Example Variables are declared by name and by data type.
DEFINE given, product FLOAT, power INTEGER MAIN PROMPT "Enter a decimal number: " FOR given LET product = given DISPLAY " Exponent value" FOR power = 2 TO 4 LET product = product * given DISPLAY power, product END FOR SLEEP 5 END MAIN
Every program must have a MAIN statement where execution begins. What the user types is converted to a FLOAT value that is stored in the given variable One of several types of loop statements. SLEEP 5 keeps the 4GL window open in Line mode for ve seconds.
Statements of 4GL that can contain other statements are called compound statements. The END FOR and END MAIN keywords respectively mark the end of the FOR and MAIN statements, which are compound statements. Like C, the 4GL language is free-form, with whitespace characters such as blank spaces, tabs, and linefeeds ignored in most contexts. You must, however, insert at least one blank space between consecutive keywords, identiers, or literal values that appear in the same line, unless some other separator is provided. You cannot include whitespace characters within a keyword or identier, and whitespace characters within literals are interpreted by 4GL as part of the literal.
3-4
statement. The use of only capital letters for language keywords such as DEFINE and MAIN is merely a convention used in these manuals, to help you to identify keywords. You can write keywords in lowercase, or in any combination of capitals and lowercase that you prefer. However, 4GL preserves the letter case of characters that are enclosed between quotation marks, such as in the quoted string of the PROMPT statement in the previous code example. The 4GL language supports structured programming. Its design encourages you to build your program as a family of simple, reusable functions with well-dened interfaces. The function in Figure 3-2 returns the lesser of two integers.
Function name Function arguments Figure 3-2 Simple 4GL Function
FUNCTION smaller (a,b) DEFINE a,b,z SMALLINT LET z = a IF z > b THEN LET z = b END IF RETURN z END FUNCTION
In these manuals, a module means an individual le. You cannot divide a single 4GL statement between two modules. This rule also applies to compound 4GL statements. As described in the next chapter, 4GL also has features that make it easy to assemble large programs from many small source code modules.
areas:
s s s
In these areas, you specify what is to be done, while 4GL (or the database server) takes care of the actual sequence of operations.
Database Access
4GL includes all SQL statements supported by Informix as native statements
of the language. The function in Figure 3-3 applies a change in price to all the items in the stock table that are purchased from a particular manufacturer. The function returns the number of rows changed to the calling routine.
Figure 3-3 Database Access Function
FUNCTION markup(PctChg, manuf) DEFINE PctChg FLOAT , manuf CHAR(3) UPDATE stock SET unit_price = unit_price * (1+PctChg) WHERE manu_code = manuf RETURN sqlca.sqlerrd[3] -- returns number of rows retrieved END FUNCTION
UPDATE statement SQL communications area is standard SQL. (SQLCA) is a global record.
It is the nature of many SQL statements to be nonprocedural. That is, you use the statements to specify what is to be done, and the database server then determines how to do it.
3-6
Report Generation
Using 4GL, however, you can write code that applies sophisticated logic to the results of the SQL statements. For example, the function in the preceding example could contain statements to validate the argument before applying the change, or to verify the authorization of the current user to perform such a change.
Report Generation
A 4GL report is a specialized program block that can display data from the database. Output from reports is typically tabular in form and can be designed for printing with page headers and footers. Some reports are produced by noninteractive, batch programs, perhaps run at night. Any 4GL program can produce report output if it contains the necessary logic for extracting and formatting the data, invoking the report, and sending the output to some destination (such as to a le, to a printer, or to the screen).
4GL divides the task of producing report output into two parts. One part that
might require procedural logic is the production of the rows of data that go into the report. The second part is the logic within the report itself, reecting your decisions as to the sequence of presentation, and how to format header and footer lines, detail lines, control breaks, and display subtotals. You write the logic of the report in a nonprocedural form, as a collection of code blocks that are called automatically as needed. For example, your code block for a group subtotal can be executed automatically on each change in the value of the group control variable. Your code block for a page footer is called automatically at the bottom of each page. As you design and code the logic of a report, you think about each part of the report in isolation. 4GL supplies the logical glue that passes control of program execution to the appropriate report sections as required. Examples of reports are shown in subsequent chapters, particularly in Chapter 10, Creating Reports. One key point: the report driver, which is the part of the 4GL program that produces the input records (the rows of data that the report processed) does not need to arrange the order of the extracted rows. 4GL can automatically collect input records and sort them before presenting them to the report code, if that is necessary.
User Interaction
User Interaction
4GL contains extensive support for writing interactive programs. You can ll
some or all of the elds of a form from program variables with a single statement. With another statement, you can open up form elds for user input with the entered data returned to program variables. For detailed validation, you can attach blocks of code to form elds. The code is executed when the cursor leaves or enters a eld. Figure 3-4 shows a typical screen form with a menu, together with the p-code that would be used to display it. (Example 19 in INFORMIX-4GL by Example contains the complete source code of this program.)
Figure 3-4 Screen Form with Menu
OPEN FORM f_cust FROM "f_cust" DISPLAY FORM f_cust MENU "New Customers" COMMAND "Query" CALL queryCust() COMMAND "First" CALL firstCust() COMMAND "Next" CALL nextCust() COMMAND "Last" CALL lastCust() COMMAND "Exit" KEY(Escape,CONTROL-E) EXIT MENU END MENU
Gets precompiled form from disk Displays form elds and labels on screen
Displays menu choices and species the code to execute when each choice is selected
3-8
Summary
You describe a screen form in its own source le and compile it separately from program code. Because forms are independent of 4GL programs, forms are easy to use with many different 4GL applications. You can open a 4GL window, optionally containing another form, above the current 4GL window, and then restore the original display. There is support for scrolling lists of data during display and editing. These features are covered in subsequent chapters.
Summary
4GL has all the features of a standard, structured programming language. It
goes beyond such languages as Pascal or C in that it supports nonprocedural, task-oriented ways of programming database access, report generation, and user interaction.
Chapter
Parts of an Application
4
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3 4-5 4-6 4-9 4-9 4-10 4-10 4-11 4-11 4-13 4-14 4-15
In This Chapter .
. .
. .
. .
. .
. .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
Form Specications and Form Files . Form Design. . . . . . . . Field Entry Order . . . . . . Program Source Files . . . . Organization of a Program . The Globals Files . . . . Program Object Files . . P-Code Object Files . C-Code Object Files . Example Programs . . . . . . . . . . . . . . . . . . . . . . . . .
4-2
In This Chapter
You typically use INFORMIX-4GL to build an interactive database application, a program that mediates interaction between a user and a database. The database schema that organizes data into relational tables gives shape to one side of the program. The needs of your user shape the other side. You write the program logic that bridges the gap between them. Such a program has many parts that you prepare with the help of the 4GL Programmers Environment. This chapter discusses the main parts of an application, which might include these les:
s
Form source les. You specify the user interface to your application, using editable les that specify the visual appearance of the form and the data types and attributes of the elds in the form. Form object les. Your form specications are compiled into a binary form by using FORM4GL, the 4GL form compiler. These are loaded by the 4GL program during execution. Message source les. You write the text of help and other messages separately from your 4GL programs. Programs can share a common set of messages, and you can change these (for instance, to support a different language) independently of the programs. Message object les. Your messages are indexed for rapid access by mkmessage, the 4GL message compiler. Like a form, a compiled message le can be used by many different programs. Program source les. You write your program as one or more les of 4GL source code. Program object les. Your sources are compiled into C code or pcode executable les, depending on the implementation of 4GL that you are using. For a brief description of the two implementations, see Two Implementations of 4GL on page 1-5.
Form specications
.per
.msg
.msg
Compiled form
.frm
.iem
.4go
Database schema
4-4
You can have program variables that have the same data types and names as database columns. 4GL makes this easy by letting you declare a variable as being LIKE a column in a table. When the program is compiled, the compiler queries the database for the appropriate data type. Your program can contain SQL statements that refer to names of tables and columns. Any change in the schema might require you to examine these statements and possibly change them. The logic of your program can depend on the schema. For example, if your program must change the schema of several tables to perform a certain operation, then you might want to use explicit database transactions. If only a single table needs changing, you can avoid this.
In general, before you start work on a large application, you should make sure that the database schema is workable and that you and others who will be using the database understand it well.
Fields
The end user of a program does not know about the database schema or your carefully designed program logic. As the user sees it, the forms and the menus that invoke them are the application. The arrangement of elds and labels, and the behavior of the forms as the user presses different keys and selects different menu options, create the personality of the program.
4-6
4GL form specication les are ASCII les. You can use an ASCII text editor to design the labels and elds for your form. The following example shows a portion of the form specication le that was used to create the preceding form:
SCREEN { Customer Number:[f000 ] Company Name:[f001 ] Order No:[f002 ] Order Date:[f003 ] PO Number:[f004 ] --------------------------------------------------------------------------Item No. Stock No Manuf Description Quantity Price Total [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] -------------Sub-Total: [f012 ] Tax Rate [f013 ]% [f014 ] Sales Tax: [f015 ] --------------------------------------------------------------------------Order Total: [f016 ] } TABLES customer orders items stock state ATTRIBUTES f000 = orders.customer_num; f001 = customer.company; ...
To view the entire text of this example, see Example 11 in INFORMIX-4GL by Example. After you specify a form, you compile it with FORM4GL, the 4GL form compiler, as illustrated in Figure 4-3. The result is a portable binary le that can be opened and displayed from any 4GL program on any platform that 4GL supports.
/////////////// //////////// ///////////// ///////// ////////////// //////////// ////////////////
.per
Form compiler
.frm
Compiled forms are independent of the programs that use them, so you can use the same forms in different applications for a consistent look and feel.
Because forms are so important to the users of your application, you should consider designing the main forms before any other part of the program. You can quickly prototype programs that display forms so that your users can give you their opinions. The following text is from the program that displayed the form Figure 4-2 on page 4-6:
MAIN OPEN FORM fx FROM "f_orders" DISPLAY FORM fx DISPLAY "2478" TO orders.customer_num DISPLAY "Overachievers, Inc" TO customer.company SLEEP 60 END MAIN
4-8
Form Design
Form Design
Designing a good user interface is integral to the success of your program. The forms you create to develop the user interface provide an interaction gateway between the end user and the database. Consider the following points when you create forms for your application:
s
Is the purpose of the form clear from its title and the title of the menu command that invokes it? Are elds in the form arranged in the same logical order that the user typically follows in transcribing or describing the information? Is the same information always given the same label in every form in which it appears? Are form labels consistent in style and content? Is the relationship between various forms as clear as possible? Is it obvious how to complete the form and what elds are required?
s s s
Organization of a Program
If you use the C Compiler version of 4GL, the les that contain executable 4GL statements require .4gl as the le extension; otherwise, the program compiler cannot nd them. If you use the Rapid Development System (RDS) implementation of 4GL, however, you can omit the .4gl le extension. Because 4GL is a structured programming language, executable statements can appear only within logical sections of the source code called program blocks. This can be the MAIN statement, or else a REPORT or FUNCTION statement. A function is a unit of executable code that can be called by name. In a small program, you can write all the functions used in the program in a single le. As programs grow larger, you will usually want to group related functions into separate les, or modules, with the declarations that they use. Each source le usually reects a self-contained unit of program logic. Source les are sometimes called source modules. Execution of any program begins with a special, required program block named MAIN. The source module that contains MAIN is called the main module. The following example is a small but complete 4GL program:
MAIN CALL sayIt() END MAIN FUNCTION sayIt() DISPLAY "Hello, world!" END FUNCTION
This single module contains the MAIN program block, delimited by the keywords MAIN and END MAIN, and one other function named sayIt().
4-10
A single function cannot be split across source modules. The preceding program example has two functions, however, so it could be split into two source modules. The rst would be the MAIN program block, as follows:
MAIN CALL sayIt() END MAIN
The second module could contain the three lines of function sayIt() just as shown above. It could also contain data or other functions related to sayIt(), if there were any. Functions and reports are available globally. For example, you can reference the sayIt() function in any source module of your program, provided that the function is dened somewhere in the program.
For the C Compiler implementation, c4gl, the command to invoke a C compiler, generates code that can be executed directly by the hardware of the computer after an executable program is created. For the RDS implementation, fglpc, the p-code compiler, generates hardware-independent pseudo-machine code, which is not directly executable by the operating system or GUI, but that can be interpreted by the 4GL p-code runner.
Both implementations can take the same 4GL source code as input. If the C code option is selected, the output is a C language object le. When this le is linked with other 4GL libraries (and optionally with C object modules), an independent executable program is produced. This process is illustrated in Figure 4-4. Because C code is not machine-independent, a compiled C version of a 4GL program must be recompiled before it can be executed on another computer system that uses a different C compiler.
/////////////// //////////// ///////////// ///////// ////////////// //////////// ////////////////
.4gl
Linkable .o le
If compilation to p-code is chosen, p-code intermediate object les are created that are executable under the 4GL runner. Both types of compiled les are binary. That is, the le is not printable or editable as text. All the modules of an application must be compiled to the same form. That is, the executable version of your program cannot mix C code and p-code units, although the p-code runner can be customized to call C object modules. For details of the steps that are required for compiling 4GL source les of all types, as well as for using C with 4GL, see INFORMIX-4GL Reference.
4-12
.4gl
P-code compiler
.4go
When your application is in several source modules, you rst compile each separate module to p-code, as shown in Figure 4-6. Then you can concatenate the individual p-code les using a utility (cat in UNIX environments) to make the executable .4gi program le. Tip: When you use the Programmers Environment to build and maintain your program, module linking is done automatically for you.
Figure 4-6 Steps to Creating an Executable Program Under the P-Code Runner
/////////////// //////////// ///////////// ///////// ////////////// //////////// ////////////////
.4gl
P-code compiler
.4gi
.4go
.4go
.4gi
To execute a .4gi le, you call the 4GL p-code runner. Use fglgo to execute the p-code instructions in the le as shown in Figure 4-7, activating your program.
.4gi
The module is translated to INFORMIX-ESQL/C source code. The ESQL/C processor converts that to C source code. The compiler translates to C object code for your computer.
.c
.4gl
C compiler
Native compiler
.o
4-14
Example Programs
From the operating-system command line, a single call to the c4gl command performs all the steps, or all these steps can be automatically accomplished through the Progammers Environment. On UNIX systems, the default extension is .4ge. However, it is not required. You can name your executable applications anything that you like, within the rules for valid lenames on your operating system and network. The C le from a single source module is compiled to an .o le. Several .o les for a multi-module application can be combined into a single executable le through the Programmers Environment or using another concatenation utility. In fact, the c4gl command line accepts any combination of .4gl les, .ec les, .c les, and .o les to produce a single .4ge executable le, as illustrated in Figure 4-9.
.o
Linker .4ge
Example Programs
Now that you know the parts of a 4GL program, you should look at a few of them to see what they are like. A number of programming examples are distributed with 4GL. INFORMIX-4GL by Example contains 30 complete and annotated 4GL programs.
Chapter
5
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3 5-3 5-3 5-4 5-5 5-6 5-7 5-8 5-9 5-10 5-11 5-12 5-12 5-12 5-13 5-13
In This Chapter .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
Declaration of Variables . . . . . Data Typing . . . . . . . . Automatic Data Type Conversion Data Structures . . . . . . . Records . . . . . . . . Arrays . . . . . . . . Memory Allocation . . . . . Scope of Reference. . . . . . Decisions and Loops . Statement Blocks . Comment Symbols . . . . . . . . . . . . . . .
Exceptions . . . . . . . . . . Kinds of Exceptions . . . . . Why Exceptions Must Be Handled How Exceptions Are Handled .
5-2
In This Chapter
INFORMIX-4GL is a fourth-generation programming language. However, it
uses some concepts based on procedural languages (such as Pascal and C). This chapter describes concepts that are based on procedural programming. In particular, it describes how to accomplish the following tasks:
s s s
Declare variables Organize statements for decisions and looping Handle exceptions
Declaration of Variables
4GL has a exible mechanism for declaring program variables. You specify a
data type for every variable, but there is automatic conversion between many data types. Data can be structured as records or arrays and can be allocated statically or dynamically. Variables can have either local or module scope.
Data Typing
4GL is a strongly typed language. That is, whenever you declare a program variable, you must specify its data type; for example, INTEGER or CHAR. The
compiler ensures that only data of that type can be stored in that variable. The following example is a declaration of several types of variables:
DEFINE aFloat FLOAT oneInt, anotherInt INTEGER, aString CHAR(20)
Data types that 4GL supports for program variables include all the primitive data types (except SERIAL) that are valid in columns of an Informix database, as well as BYTE and TEXT, the binary large object (blob) data types.
The Procedural Language 5-3
Every data type of 4GL can be classied into one of three logical categories:
s
Simple data types store a single value in the format of some primitive SQL data type. Every data type of 4GL except ARRAY, BYTE, TEXT, and RECORD is a simple data type. Large data types (BYTE and TEXT) can store blobs. Structured data types (ARRAY and RECORD) can store ordered sets of values.
s s
An important point to note is that 4GL denes a specic NULL value for every data type. NULL means unknown, rather than 0, which is a precise value. You can assign NULL to any variable, and you can test any variable for NULL content. This is necessary to support database operations, because NULL is a distinct value (or, to be more precise, a non-value) within a database table.
The LET statement is used for assignment. The rst of the preceding LET statements assigns a literal decimal number to a variable of the FLOAT data type. In this code fragment, the variables aFloat and oneInt are declared in the DEFINE statement example in Data Typing on page 5-3. In the second LET statement, a FLOAT value (which is the contents of the variable aFloat) is assigned to the INTEGER variable oneInt. 4GL converts the FLOAT value to an INTEGER to match the data type of the receiving variable. To do so, the fractional part of the oating point number is truncated. Another common data type conversion is that between a character value and almost any other data type.
LET aString = aFloat-- assigns "2.71828" to aString
This statement assigns a FLOAT value to a variable whose data type is CHAR (a character string). 4GL converts the numeric value to characters and then assigns that string value to the CHAR variable aString.
5-4 IBM Informix 4GL Concepts and Use
Data Structures
4GL will also attempt to convert a character string to a number or to some other data type. The second of the following LET statements assigns a string of numeric characters to a FLOAT variable:
LET aString = "3.141592" LET aFloat = aString-- assigns 3.141592 into aFloat
If the characters in the string can be interpreted as a literal value of the receiving data type, then the conversion is done. Most data types have a printable character representation, and 4GL converts automatically between the printable form and the internal form. Of course, there are some cases when conversion is not allowed. For example, the BYTE and TEXT data types cannot be converted into any other type. Such errors are typically detected at compile time. Some conversions, however, can only be found to be impossible at execution time. The following example fails in its attempt to convert a large oatingpoint number to an INTEGER data type.
LET aFloat = 2E12-- about 100 times the maximum integer size LET oneInt = aFloat-- this causes a runtime error
Anticipating them and inserting programmed tests to avoid them Trapping the error at execution time Letting the runtime error terminate the program with an appropriate message
For a table that identies all the pairs of data types for which 4GL supports automatic data type conversion, see INFORMIX-4GL Reference.
Data Structures
The structured data types enable you to organize program data into records and arrays, both of which are sometimes called data structures. These data types (ARRAY and RECORD) can store ordered sets of values of other 4GL data types. You can also declare an ARRAY variable whose elements are RECORD variables, or a RECORD variable that has ARRAY or RECORD members, but you cannot declare an ARRAY of ARRAY variables.
Data Structures
Records
The RECORD data type stores a group of values that are treated as a unit. Each member variable of a record has a name. Unlike blob or simple data types, you can use a RECORD variable to represent an entire row in a database table. The following code fragment declares a record:
DEFINE stockRow, saveStockRow RECORD stock_num INTEGER , manu_code CHAR(3) , description CHAR(15) , unit_price MONEY(8,2) , unit CHAR(4) , unit_descr CHAR(15) END RECORD
This statement denes two program variables. Their names are stockRow and saveStockRow. Each variable is a record with six members. The member named manu_code is a three-character string. You refer to this member of the stockRow record as stockRow.manu_code. The parallel member of the other record, saveStockRow, would be called saveStockRow.manu_code. Note the record.member notation, where a period ( . ) separates the record qualier. The members of these records are all simple data types. A record can contain members, however, that are other records or arrays. Another interesting aspect of this record is that it contains one member for each column in the stock table of the stores7 demonstration database. Because it is so common to dene a record that matches one-for-one to the columns of a database table, 4GL provides an easier way of doing this:
DEFINE stockRow, saveStockRow RECORD LIKE stock.*
This statement causes the 4GL compiler to refer to the database, extract the names and types of all the columns, and insert them in the program. In this way, you can ensure that the program will always match the database schema. (A previous DATABASE statement must identify the database.) You can also fetch a row of a database table into such a record:
SELECT * INTO stockRow.* FROM stock WHERE stock_num = 309 and manu_name = "HRO"
You can assign the contents of all the members of one record to another record with a single LET statement:
LET saveStockRow.* = stockRow.*
5-6
Data Structures
You can do this even when the two records are not dened identically. The assignment is done member-by-member. As long as the records have the same number of members, and data values from each member on the right can be converted to the data type needed by the corresponding member on the left, you can assign the contents of one record to another.
Arrays
Like RECORD, the ARRAY data type of 4GL does not correspond to any single primitive data type of SQL. The ARRAY data type stores an ordered set of values that are all the same data type, for every 4GL data type except ARRAY. You can declare one-, two-, or three-dimensional arrays. The elements of the array can be simple data types, blobs, or records, as the following example shows:
DEFINE stockTable ARRAY[200] OF RECORD LIKE stock.*
This array variable is named stockTable. It contains 200 elements, each of which is a record with as many members as there are columns in the stock table in the database. One of those columns is named stock_num. You would access the stock_num member of the 52nd element of the array by writing stockTable[52].stock_num. The rst element of any array is indexed with subscript 1. This differs from the C language, and some other programming languages, where the rst element is always zero. The subscript value that selects an element can be given as an expression. Expressions are described in Expressions and Values on page 8-22.
Memory Allocation
Memory Allocation
4GL supports the allocation of memory to program variables either statically,
as part of the executable program le, or dynamically, at execution time. You choose the method to use by the location of your DEFINE statement within the source module. In the program in Figure 5-1 on page 5-8, greeting and audience are static variables, whose memory is allocated during compilation, because they are declared outside of any program block. In the same example, message is a variable local to the sayIt() function in which it is dened; memory for message is allocated dynamically, when its function is invoked at runtime.
Figure 5-1 Examples of Static and Dynamic Memory Allocation for Variables
DEFINE greeting CHAR(5) DEFINE audience CHAR(5) MAIN LET greeting = "Hello" LET audience = "world" CALL sayIt() END MAIN FUNCTION sayIt() DEFINE message CHAR(40) LET message = greeting , " " , audience, "!" DISPLAY message END FUNCTION
The topics of data allocation, scope of reference, visibility, and program blocks are considered in detail in INFORMIX-4GL Reference. In summary:
s
Variables that you declare outside of any MAIN, REPORT, or FUNCTION statement have as their scope of reference the same module in which they are declared. Unless their names conict with the names of local variables, they are visible in the entire module. They can be referenced by any statement in the same source le that follows the denition. Memory for these module variables is allocated statically, at compile time, and become part of the program image. Variables that you declare within a function are local to the function. New copies of these variables are created each time the function is called. They are discarded when the function exits.
5-8
Scope of Reference
Scope of Reference
The scope of reference of a variable is where its name can be used in the program. Variables that you declare can have local or module scope:
s
Local variables declared within a program block are local to that program block. Their scope of reference is from the point of declaration to the end of the program block. Local variables are created each time that their FUNCTION, report, or MAIN statement is entered. They cease to exist when execution of that program block terminates. Module variables declared outside of any program block have a scope that extends from the point of declaration to the end of the module.
The GLOBALS ... END GLOBALS statement declares variables that are visible in any other module that includes the GLOBALS lename statement, where lename species the module that contains the GLOBALS ... END GLOBALS statement. (See Global Scope: Within Several Modules on page 8-16.) Certain built-in features of the 4GL language are global in scope, including the named constants TRUE, FALSE, and NOTFOUND; the global variables status; int_ag, and quit_ag; and the members of the SQLCA record.
computer languages. These statements are covered in Decisions and Loops on page 8-31 and in INFORMIX-4GL Reference. The following table gives a brief summary.
Statement Name IFTHENELSE CASE WHILE FOR Description Tests Boolean (TRUE/FALSE) conditions Makes multiple-choice decisions Is used for general loops controlled by a Boolean condition Is used for loops that iterate over an array
There is also FOREACH, a special loop used for database access, as described in Row-by-Row SQL on page 9-5. These control statements can be nested. A key point is that their syntax is simple and regular:
s
Most compound 4GL statements (those that can contain other statements) are closed by specic END statement keywords. Thus, the IF statement is closed with END IF, CASE with END CASE, and so on. Every looping statement has a specic EXIT option for early termination. You leave the WHILE statement with EXIT WHILE, you leave FOR with EXIT FOR, and so on. No special punctuation is needed in 4GL code. You do not need to put semicolons between statements as in C or Pascal, although you can do so if you prefer. Nor are you required to use parentheses around a Boolean condition, as in C. But again, you can do so if you prefer.
4GL also supports GOTO and LABEL statements, by which control of program
execution can jump from one statement to another within a program block.
5-10
Statement Blocks
Statement Blocks
Many 4GL statements such as LET and CALL are atomic; that is, they contain only themselves. Others are compound; that is, they can contain other statements. The most common compound statements include these, as the following table shows.
Statement Name Description
IFTHENELSE THEN and ELSE each introduce a block of statements. The ELSE block is optional. FOR WHILE CASE The body of a FOR loop is a block of statements. The body of a WHILE loop is a block of statements. WHEN and OTHERWISE each introduce a block of statements.
Statement blocks can be nested. That is, one compound statement can contain another. Figure 5-2 is a code fragment that contains a nested IF statement block from Example 9 in INFORMIX-4GL by Example.
Figure 5-2 Example of a Nested IF Statement Block The statement block begins.
IF int_flag THEN LET int_flag = FALSE CALL clear_lines(2, 16) IF au_flag = "U" THEN -- a compound statement LET gr_customer.*= gr_workcust.* DISPLAY BY NAME gr_customer.* END IF CALL msg("Customer input terminated.") RETURN (FALSE) END IF
Any statement block can be empty. That is, you do not need to supply any statements in contexts where 4GL syntax requires a statement block.
Comment Symbols
Comment Symbols
To comment your 4GL code, use double hyphens (--) or the sharp (#) sign for individual lines (as in the previous code example), or braces ( { and } ) for one or more contiguous lines of code. The compiler does not process comments. Comment symbols that appear between quotation marks (single or double) are treated as literal symbols, rather than as comments. Comments cannot be nested.
Exceptions
An exception (sometimes called an error condition or a runtime error) is an unplanned event that interferes with normal execution of a program. An exception is not expected to occur in the normal course of program execution, and special action is often required when an exception does occur.
Kinds of Exceptions
There are several kinds of exceptions. Most can be classied within one of the following categories:
s
Runtime errors. Errors in program statements detected by 4GL at runtime. These errors can be classied by the kind of statement in which they occur:
SQL error. Errors reported by the database server. File I/O. Errors using les managed by the host operating system. Screen I/O. Errors using the screen. Validation. Errors using the VALIDATE statement. Expression. Errors in evaluating 4GL expressions; for instance, a data conversion error or an invalid array subscript.
SQL end of data. Warnings that you have reached the end of a set of rows being fetched through a database cursor.
5-12
SQL warning. A warning condition reported by the database server, typically of lower severity than SQL errors. External signals. Events detected by the host operating system. An external signal is usually not directly related to 4GL program statements. Two common external signals that 4GL can handle are Interrupt (CONTROL-C) and Quit (CONTROL-\).
You are certain that there will be an end to any selection of rows. It is just that you do not always know which row will be the last. You are sure that some user will eventually try to cancel an operation, but you do not know when.
Even runtime exceptions must always be anticipated, no matter how carefully you write your code. Because program exceptions are sure to happen, you must design the program to handle them in a rational manner. But because they are of low probability, you want to handle them:
s
away from the main line of processing, so the code for the normal, expected sequence of events is clear and readable. with a minimum of overhead at execution time.
For many exceptions, the default response is correct. But you can anticipate and handle other types of exceptions with 4GL statements, including the DEFER and WHENEVER statements, as follows:
s
The DEFER statement can be used to instruct your executing program to set built-in global variables, rather than terminate the program, when an Interrupt or Quit signal is generated by the user. By testing the variable, you can determine when the user is ready to end a program, and respond accordingly in an orderly manner to the request.
s
WHENEVER ERROR
The WHENEVER ERROR statement establishes the policy of your program for handling SQL errors, screen I/O errors, and validation errors.
s
The WHENEVER ANY ERROR statement extends the WHENEVER ERROR policy to expression errors.
s
WHENEVER WARNING
The WHENEVER WARNING statement establishes the policy of your program for handling SQL warnings.
s
The WHENEVER NOT FOUND statement establishes the policy of your program for handling SQL end of data conditions. Not all runtime errors can be trapped by WHENEVER. For a list of fatal errors that always terminate program execution, see INFORMIX-4GL Reference. See also the DEFER and WHENEVER statement descriptions in INFORMIX-4GL Reference. When using 4GL to develop a new program or to modify an existing program, you might want to use one set of exception-handling policies during development, when your developers can read the error messages, but use another policy after the completed program is deployed, if your users are not likely to benet from reading the text of any runtime error messages.
5-14
Chapter
6
6-3 6-3 6-5 6-7 6-8
In This Chapter .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Using SQL in a 4GL Program . Creating 4GL Reports . . The Report Driver . . The Report Denition . . . . . .
6-2
In This Chapter
One main reason to use INFORMIX-4GL is the ease with which you can access and modify data in a database. SQL, the international standard for relational database access, is an integral part of the 4GL language. Another reason to use 4GL is the ease by which you can design and generate reports. This chapter describes how to use SQL to access data in a 4GL program and how to generate reports.
Incorporate nonprocedural SQL statements as 4GL program statements. Any SQL statement that does not return data to the program (for example, ALTER, CREATE, UPDATE, or REVOKE, among many), can be embedded within the program for execution in sequence with other 4GL statements. In many cases, you can use data from program variables as part of the statement. In addition, any SELECT statement that returns a single row of data can be written into the program and used to get data from the database and assign it to variables.
6-3
2.
Use a database cursor to retrieve a set of rows from the database, one row at a time. A cursor contains a SELECT statement that might return multiple rows of data. You use an OPEN statement to start the selection. You use FETCH statements to fetch one selected row at a time, assigning the column data to variables. In this way, your program can scan a selection of rows, or bring all or part of the selection into memory and store it in an array. The FOREACH loop is another mechanism that can be used to open a cursor and fetch rows in sequence.
3.
Use dynamic SQL to prepare new statements at execution time. You can assemble the text of an SQL statement and then pass it to the database server for execution. In this way, you can write an application that adapts to the schema of the database or to user selection criteria at execution time.
The concepts behind all three of these methods are discussed in greater detail in Chapter 9, Using Database Cursors, and Chapter 10, Creating Reports. Additional discussion and examples are provided in the Informix Guide to SQL: Tutorial. Tip: In this version of 4GL, you can directly embed most 4.1 SQL statements. If you want to include SQL syntax introduced after Version 4.1, you must prepare the statement before including it in the program. (You prepare a statement by using the PREPARE statement.) For a list of supported SQL statements, see the description of the PREPARE statement in INFORMIX-4GL Reference.
6-4
the reader can quickly nd an item. logically related items are near each other. groups of data with logically related values appear near one another, so that group totals and subtotals can be calculated and shown.
6-5
W E S T
C O A S T
W H O L E S A L E R S ,
I N C .
Report header
1400 Hanbonon Drive Menlo Park, CA 94025 Tue. Apr 30, 1991
Bill To:
Customer Number 104 Play Ball! East Shopping Cntr. 422 Bay Road Redwood City, CA 94026 Anthony Higgins
Ship Date: Tue. Apr 30, 1991 Ship Weight: 32.00 lbs. Shipping Instructions: UPS Blue
ATTN:
------------------------------------------------------------------------Item Stock Manuf Unit Item Number Number Code Description Qty Unit Price Total --------------------------------- ----------1 000005 ANZ tennis racquet 3 each $19.80 $59.40 2 000103 PRC frnt derailleur 2 each $20.00 $40.00 3 000104 PRC rear derailleur 2 each $58.00 $116.00 4 000009 ANZ volleyball net 1 each $20.00 $20.00 ------------------------------------------------------------------------Sub-total: $235.40 Sales Tax ( 6.500%): $19.72 Shipping Charge: $48.00 ------Total: $371.12
Invoice total
Invoice 0000001029
Page 1
Page footer
In 4GL, the program logic that species what data to report is separate from the program logic that formats the output from the report. Any 4GL program that produces output from a report must include a part that produces the data from a database (or from some other source), and a second part that formats the data as output from a report.
6-6
In these manuals, the part of the 4GL program that sends data to the report is called the report driver, and the part that species how to format and display the output from the report is called the report denition, as Figure 6-2 shows.
Figure 6-2 Process for Generating Output from a 4GL Report
Database
It can interact with the database and with the user. It ignores all formatting issues, such as page length. It can supply data for multiple reports simultaneously. Data that it sends to a report can come from sources outside any database; for example, productivity data from user commands.
The primary concern of the row-producing logic in a report driver should be the selection of data, rather than the arrangement or formatting of data. The report driver can use specialized 4GL statements to take the following actions:
1. 2. 3. 4.
Use START REPORT to initialize each report to be produced. Whenever a row of report data is available, use OUTPUT TO REPORT to send it as an input record to the report denition. If the report driver detects an error, use TERMINATE REPORT to bring the report generation process to an end. After the last row is sent, use FINISH REPORT to end the report.
6-7
The last two actions are mutually exclusive. Unless there is the need for an abnormal termination, FINISH REPORT terminates execution of the report. From the standpoint of the report driver, no other statements are required. The driver can concurrently produce input records for multiple reports. Although a database is the usual source of data for a report, input records can come from any source, including the user, calculations, or sequential les. Because the report driver pays no attention to issues of formatting, grouping, or totalling, it produces input records as a by-product of other activities. Your program is not required to produce input records in any special order. It is generally more efcient, however, to retrieve data from the database in the desired order, using the ORDER BY directive. You can, however, produce input records in any order, and leave the sorting to the report denition. The 4GL statements that logically make up a report driver can appear within a single program block, or they can be distributed across several functions.
REPORT prototype. This section declares the name of the report, and
list its formal arguments. This name must be unique among named program blocks.
s
DEFINE section. This section declares variables that are local to the
report, including its formal arguments and other variables (such as for calculated results).
s
OUTPUT section. This section denes the size and margins of the
report page. This section takes effect when the report is started.
s
ORDER BY section. This section species the order for the input
records, and whether or not they are provided to the report already ordered.
s
input records to produce and format the output from the report.
6-8
The control blocks that you write in the FORMAT section are the heart of the report denition, and contain all its intelligence. Statements in the control blocks of this section can specify actions to take in the following contexts:
s s s s s
Top (header) of the rst page of the report. Top (header) of every page after the rst. Bottom (footer) of every page. Each new row as it arrives. The start of a group of rows. (A group is one or more rows having equal values in a particular column.) This statement block is often used for clearing totals and other accumulated values. The end of a group of rows. In this block, you typically print subtotals and other aggregate data for the group that is ending. You can call on aggregate functions like SUM and MAX for this information. After the last row has been processed.
You can use most 4GL statements in the FORMAT section of a report. For example, you can call functions and interact with the user. Some statements of 4GL that are not valid within a report denition include the following:
s s
DEFER (which can only appear in the MAIN program block) MAIN, FUNCTION, and REPORT (which are each program blocks; you cannot nest one 4GL program block within another) RETURN (which can only appear in a FUNCTION program block)
Use EXIT REPORT, rather than RETURN, to terminate processing of input records from within a REPORT denition. EXIT REPORT resembles in its effect what TERMINATE REPORT does in a report driver. Use PRINT, rather than DISPLAY, to produce output within a REPORT denition.
4GL invokes the sections and control blocks within a REPORT denition non-
procedurally, at the proper time, as determined by the data that the report is processing. You do not have to write code to calculate when a new page should start. Neither do you have to write comparisons to detect when a group of rows has started or ended. All that you have to write are the statements that are appropriate to the situation, and 4GL supplies the glue to make them work.
Database Access and Reports 6-9
For more information about report drivers and report denitions, see Chapter 10, Creating Reports, in this manual, as well as INFORMIX-4GL Reference.
6-10
Chapter
7
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-3 7-3 7-5 7-6 7-8 7-9 7-9 7-9 7-10 7-13 7-14 7-14 7-15 7-15 7-16 7-16 7-16 7-17 7-18 7-19 7-20 7-23
In This Chapter .
. .
. .
. .
. .
. .
. .
. .
. .
Line-Mode Interaction.
Formatted Mode Interaction . . . . . . . Formatted Mode Display . . . . . . . Sample Code for Formatted Mode Display . Screens and Windows . . . . . . . . . The Computer Screen and the 4GL Screen The 4GL Window . . . . . . . . . How Menus Are Used. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
How Forms Are Used . . . . . . Dening a Form . . . . . . DATABASE Section . . . . SCREEN Section . . . . . TABLES Section . . . . . ATTRIBUTES Section . . . INSTRUCTIONS Section . . Displaying a Form. . . . . . Reading User Input from a Form. Screen Records . . . . . . . Screen Arrays . . . . . . . How the Input Process Is Controlled . How Query by Example Is Done . .
How 4GL Windows Are Used . . . Alerts and Modal Dialog Boxes . Information Displays . . . . . How the Help System Works . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
7-2
In This Chapter
Built into INFORMIX-4GL is a complete system of character-oriented user interaction. Because 4GL is character-oriented, the same 4GL applications can run on high-end workstations and on character-based terminals. 4GL enables you to create highly exible, portable, interactive, multiuser applications using screen forms and menus.
Line-Mode Interaction
A 4GL program can operate with its user interface in line mode or formatted mode. Line mode is the same typewriter-like mode of interaction that UNIX shell scripts use. You put the user interface in line mode by executing a DISPLAY statement that does not specify a screen location. The following example illustrates a simple program that operates in line mode:
MAIN DEFINE centDeg, fahrDeg DECIMAL(5,2) DEFINE keepOn CHAR(1) LET keepOn = "y" DISPLAY "Centigrade-to-fahrenheit conversion." WHILE keepOn == "y" PROMPT "Centigrade temp: " FOR centDeg LET fahrDeg = (9*centDeg)/5 + 32 DISPLAY "old-fashioned equivalent: ", fahrDeg PROMPT "More of this (y/n) ? " FOR CHAR keepOn END WHILE END MAIN
Because the rst DISPLAY statement does not give a screen row and column for output, the screen is put in line mode. Each line of display and each prompt displayed by PROMPT scrolls up the screen in the manner of a typewriter.
Line-Mode Interaction
When you execute this program, the interaction on the screen resembles the following example, in which data entry by the user has been underscored:
Centigrade-to-fahrenheit conversion. Centigrade temp: 16 old-fashioned equivalent: More of this (y/n) ? y Centigrade temp: 28 old-fashioned equivalent: More of this (y/n) ? n 82.40 60.80
You can use simple interactions of this kind for quick tests of algorithms. Line mode also has the virtue that you can redirect line mode output to disk from the command line. The following program displays two columns from the customer table using line-mode output:
DATABASE stores7 MAIN DEFINE custno LIKE customer.customer_num, company LIKE customer.company DECLARE cust CURSOR FOR SELECT customer_num, company FROM customer FOREACH cust INTO custno, company DISPLAY custno, company -- Line mode display END FOREACH END MAIN
You could execute this program from the command line, redirecting its output into a le, with a statement like the following one (assuming the program has been compiled to 4GL p-code in a le named dump2col.4gi):
fglgo dump2col | custcols.dat
The data could also be piped into another command, but there is no equivalent input statement; PROMPT only accepts input from a real keyboard.
7-4
These statements are described in detail in Screen and Keyboard Options on page 11-32 and in INFORMIX-4GL Reference.
Purpose Output and input of PROMPT statement Ring-menu display occupies two lines Output of the MESSAGE statement Top line of any form
Comment Explanatory text for current form eld Error Output of the ERROR statement
7-6
Figure 7-1 shows how the reserved lines are arranged on the screen when the default reserved line positions are in effect.
Figure 7-1 Default Reserved Line Positions
Prompt line FIRST Menu line FIRST Menu help MENU+1 Message line FIRST+1 Form line FIRST+2 Space for form Comment line LAST Error line LAST
To create this screen, a form was displayed using DISPLAY FORM; some data values were written into form elds using DISPLAYTO; and then a MENU statement was used to display a ve-option menu (the options Query through Exit). The line of hyphens with Press CONTROL-W for Help is literal text in the rst line of the form that was displayed.
This diagram makes the screen appear crowded with conicting uses. In reality, the dedicated lines are used at distinct times. For example, the Prompt line is used by the PROMPT statement and the Menu line by the MENU statement. The program cannot execute both PROMPT and MENU at the same time, so no conict is possible. By default, both lines are assigned to the rst 4GL window line. The assignment of specic rows to screen lines can be changed while the program is running (see Screen and Keyboard Options on page 11-32). The key point is that these lines exist and have assigned display positions.
7-8
Amusements:
Jokes
Laughter
Smiles
Exit
Laughs:
HaHa
Chuckle
Snicker
Main
Exit
In the illustration, the initial menu offers at least three basic emotions. The user can choose to enter the Amuse, Anger, or Make_sad ring menu or choose Exit to leave the program. If the user chooses Amuse, the second-tier ring menu replaces the rst. The Exit menu option moves the screen cursor to the pervious menu or, if you are already at the top tier of that menu, it exits from the program. Alternatively, you could create a ring-menu option that bypasses the natural hierarchal ring-menu structure. An example is shown in the third-tier menu, which offers the ability to jump back to the top tier by choosing Main. The number of ring-menu levels that you can create is limitless.
7-10 IBM Informix 4GL Concepts and Use
Figure 7-3 shows a simple menu-driven program. When the program runs, the menu shown in the lower portion will be seen by the end user.
Figure 7-3 Menu-Driven Program
MAIN MENU "Laughter" COMMAND "Haha" "A good laugh." CALL doLaugh(1) COMMAND "Chuckle" "A small laugh." CALL doLaugh(2) COMMAND "Snicker" "A smothered laugh." CALL doLaugh(3) COMMAND KEY("e",ESC,CONTROL-E) "Enough" "Stop it, youre killing me." EXIT MENU END MENU END MAIN
Menu help of current option is displayed. Menu title displays to the left of the Menu line. Each COMMAND line presents one option to the user.
This program presents a menu that contains four options: Haha, Chuckle, Snicker, and Enough. The user selects a menu option by typing its initial letter or by moving the cursor and pressing RETURN. You can also arrange for an option to be selected using other keys; for example, the option Enough can be chosen by pressing either ESCAPE or the CONTROL-E. When the user selects a menu option, 4GL executes the block of code that follows the COMMAND statement for that option. In this example, if the user selects the third option, Snicker, the code CALL doLaugh(3) will be executed. When all the code for that option has been executed (in this case, when the doLaugh( ) function returns), the MENU statement resumes execution and the user can pick another option (unless EXIT MENU is encountered, as in the case of Enough).
Figure 7-4 shows an implementation of doLaugh( ) and an example of the output that it produced when several menu options were selected.
Figure 7-4 Output Produced by doLaugh() Function
CONSTANT firstLaff = 3, lastLaff = 24 VARIABLE haha INTEGER = firstLaff FUNCTION doLaugh(laffnum INTEGER) CASE laffnum WHEN 1 DISPLAY "Ho ho ho hoo hoo ha hee ho. Hum." AT haha, 1 WHEN 2 DISPLAY "Tee hee hee hee hee! Scuse me." AT haha, 1 WHEN 3 DISPLAY "Snrt!snrt!snrt!mff!" AT haha, 1 END CASE LET haha = haha + 1 IF haha > lastLaff THEN LET haha = firstLaff END IF END FUNCTION
Menu line Menu help line Other lines used by DISPLAY statement
After a command block completes, 4GL redraws the Menu line and Menu Help line, and waits for the user to choose another menu option. Program control remains within the MENU statement until it executes an EXIT MENU statement within some COMMAND block. The program on the previous page executes EXIT MENU when the Enough option is chosen. You can write any number of lines of code in a command block. The example program shows a common style in which each command block contains a single function call, but you can use most 4GL statements in a command block. You can communicate with the user with MESSAGE, DISPLAY, or PROMPT statements, open additional 4GL windows, or even start another MENU statement.
7-12
You can change the appearance of a menu while the program is executing. Within the menu, you can execute the HIDE and SHOW commands to hide or display menu options. For example, you could test the level of privilege of a user within the current database, and then either HIDE or SHOW a choice such as Delete row, depending on whether the user has delete privilege. All these features are covered in detail in INFORMIX-4GL Reference.
Dening a Form
Dening a Form
The following two steps are involved in creating a form:
s
Specify the contents of a form in a form specication le, a text le that you create with any text editor that can generate ASCII text. Form specication lenames should be given the extension .per. Compile the form specication le. Compiled forms are usually given the le extension .frm.
The FORM4GL utility program is used to create .frm les. Once compiled, a 4GL form can be used by any 4GL program. The form specication le has several sections. The DATABASE, SCREEN, and ATTRIBUTES sections are required, while the TABLES and INSTRUCTIONS sections are optional. The order of appearance of the sections is xed. The sections of the form specication le are described next. After you have designed a form and compiled its specication, it is ready for use by a program. The form specication le that produces the form in Figure 7-5 on page 7-13 is considered in further detail beginning with Specifying a Form on page 11-3. Special syntax and keywords of form les are discussed in INFORMIX-4GL Reference.
DATABASE Section
The DATABASE section names a database from which column data types can be determined when the form is compiled. Alternatively, you can use the keyword FORMONLY to indicate that the form does not rely on a database. For example, you can identify the stores7 database as follows:
DATABASE stores7
7-14
Dening a Form
SCREEN Section
The SCREEN section contains an ASCII version of the form, including text labels establishing the size and location of form elds. Here elds are labeled by eld tags, internal names that are not displayed when the form appears at runtime. The following example is also the SCREEN section of the form in Figure 7-5:
SCREEN { Customer Number:[f000 ] Company Name:[f001 Order No:[f002 ] Order Date:[f003 ] PO Number:[f004 Item No. [f005 ] [f005 ] [f005 ] [f005 ] } END Stock No Manuf Description [f006 ] [f07] [f008 [f006 ] [f07] [f008 [f006 ] [f07] [f008 [f006 ] [f07] [f008 Quantity [f009 ] [f009 ] [f009 ] [f009 ] Price [f010 [f010 [f010 [f010 ] ] Total [f011 ] [f011 ] [f011 ] [f011 ]
] ] ] ]
] ] ] ]
TABLES Section
The TABLES section lists the tables or table aliases in the default database specied in the DATABASE section, or specied here by table qualiers, from whose columns the eld data types will be taken. An alias is required if an owner or database qualier of the table name is needed. For example, you can identify tables as follows:
TABLES customer orders items stock catalog
Displaying a Form
ATTRIBUTES Section
In the ATTRIBUTES section, you specify the characteristics of each eld: the eld name, the type of data that it will display, the editing rules applied during input, and any special display attributes, such as color. For example:
ATTRIBUTES f000 = customer.customer_num ; f001 = customer.company ; f002 = orders.order_num ; f003 = orders.order_date ; f004 = orders.po_num ; f005 = items.item_num , NOENTRY ; f006 = items.stock_num ; f007 = items.manu_code ; f008 = stock.description , NOENTRY ; f009 = items.quantity ; f010 = stock.unit_price , NOENTRY ; f010 = items.total_price, NOENTRY ; END
INSTRUCTIONS Section
In the INSTRUCTIONS section, you can group elds into screen records and screen arrays. These records and arrays can be displayed and read as logical units, as the following example shows:
INSTRUCTIONS SCREEN RECORD s_items[4] ( item_num , stock_num , manu_code , description , quantity, unit_price , total_price ) END
In the INSTRUCTIONS section, you can also change the default delimiters of form elds when they are displayed on character-based systems.
Displaying a Form
Your program can use a form in the following ways:
s
With OPEN FORM or OPEN WINDOW ... WITH FORM, you load the compiled form from disk into memory and make it ready for use. You can open as many forms as needed, subject only to the limits of memory and maximum number of open les on your platform.
7-16
With DISPLAY FORM, you draw the contents of a form (its labels and the outlines of its elds) in the current 4GL window. The picture of the form replaces any previous data values in that window. You can display a form as many times as necessary. You can display the same form in different 4GL windows. (The use of additional windows is described in How 4GL Windows Are Used on page 7-25.)
With DISPLAYTO, you can ll the elds with data from program variables.
You can also use the CLEAR FORM statement to empty the elds of data.
The program variables that are to receive data from the form The corresponding form elds in which the user will enter the data
When invoked, the INPUT statement enables the specied elds. The user moves the cursor from eld to eld and types new values. Each time the cursor leaves a eld, the value typed into that eld is deposited into the corresponding program variable. Other elds on the form are deactivated. The INPUT statement ends when the user does one of the following actions:
s
Uses the Accept key (by default, ESCAPE) to resume execution and examine and process the values the user has entered Uses the Cancel key (by default, CONTROL-C) to resume execution and ignore any changes made to the form Completes entry of the last eld, when eld order is set to
CONSTRAINED
This is the same as Accept. See Field Order Constrained and Unconstrained on page 11-30 as well as INFORMIX-4GL Reference.
Screen Records
Screen Records
In the form le, you can specify a group of elds as a logical screen record. During input, your program can associate a program record with a screen record, automatically lling the RECORD variable in memory with data from the form. Screen records can make your program shorter and easier to read, and can display all or part of a row from the database. You can use asterisk (wildcard) notation when referring to all the elds of the program record or the screen record. Suppose that your program denes a record variable in this way:
DEFINE itemRow RECORD LIKE items.*
This line declares a record variable with one member for each column of the items table. Now suppose that in the current form there are four elds that correspond to the last four columns of the items table. The schema of the stores7 demonstration database, which is used in the following discussion, is described in INFORMIX-4GL by Example. In the form le, these elds are grouped into a screen record with the following line in the INSTRUCTIONS section:
INSTRUCTIONS SCREEN RECORD itemDetail(stock_num, manu_code, quantity, total_price)
The program could take input from the four elds by specifying the elds and the corresponding record members individually:
INPUT itemRow.stock_num, itemRow.manu_code, item_row.quantity, itemRow.total_price FROM stock_num, manu_code, quantity, total_price
Or you can specify the last four members of the program record using THRU notation and all the elds of the screen record using an asterisk:
INPUT itemRow.stock_num THRU itemRow.total_price FROM itemDetail.*
But because the names of the members in the program record are the same as the names of the form elds, this can be further shortened to:
INPUT BY NAME itemRow.stock_num THRU itemRow.total_price
7-18
Screen Arrays
Screen Arrays
In the form specication, you can also specify a group of screen records as a screen array. During input, you can associate a program array of records with an array of form elds on the screen, as illustrated in Figure 7-6.
Figure 7-6 Screen Record Associated with a Screen Array
As Figure 7-7 shows, the program array typically has many more rows of data than will t on the screen.
Figure 7-7 Typical Screen Array Displaying Part of a Much Larger Program Array ARRAY [many] OF RECORD in memory. Screen array displays a few records from the array of RECORD variables in memory.
/////// //// ///////// //// ////////// / /////// //// ///////// //// ////////// / /////// //// ///////// //// ////////// / /////// //// ///////// //// ////////// /////// //// ///////// //// ////////// / /////// //// ///////// //// ////////// / /////// //// ///////// //// //////////
4GL lets the user scroll the array on the screen through the rows of the program array. The user can change the display using the 4GL PageUp
and PageDown logical keys or scroll through the array one line at a time by using the arrow keys. To add a record, the user can press the logical Insert key, and 4GL will open the display to create an empty screen record. When the user has lled this record, 4GL inserts the data into the program array. To delete data, the user can press the logical Delete key, and 4GL will delete the current record from the display and from the program array, and redraw the screen array so that deleted records will no longer be shown. Depending on how your program is written, you can also programmatically remove the record from the database. For a complete list of logical key assignments, see the description of the OPTIONS statement in INFORMIX-4GL Reference.
BEFORE INPUT
Just as the INPUT operation is starting, this block of code can display initial or default values, clear totals, and generally prepare the screen and program variables.
s
BEFORE FIELD
As the cursor is entering the specied eld, this block can take some action, such as initialize the contents of the eld, based on values in other elds.
s
AFTER FIELD
When input in the specied eld is complete, this block can validate what the user entered, or can initialize other elds, based on the value just entered.
7-20
ON KEY
When the user presses any of a list of keys that you specify, this block can give the user special assistance; for example, displaying a list of common values for the current eld.
s
BEFORE ROW
When the cursor is about to enter a new row of a screen array, this block can take some action, such as update other elds on the screen to reect the row being entered.
s
AFTER ROW
When the cursor is leaving a row of a screen array, this block can take some action, such as update the screen or the database to account for changes made in the row.
s
BEFORE INSERT
When the user has requested creation of a new row in a screen array, this block can take some action, such as initialize the new row with default values.
s
BEFORE DELETE
When the user presses the Delete key to remove a row from a screen array, this block can take some specied action before the row is deleted.
s
AFTER DELETE
When the user presses the Delete key to remove a row from a screen array, this block can take some specied action after the row is deleted.
s
AFTER INSERT
When the cursor is about to leave a newly inserted row of a screen array, this block can update totals based on the new data, and can insert the new row into the database.
s
AFTER INPUT
When the input operation is ending, this block can validate the entered data, check for required elds that might be missing, and erase any special usage messages.
You write these blocks as part of the INPUT or INPUT ARRAY statement. When the INPUT or INPUT ARRAY statement is executed, 4GL enables the screen for input and awaits user keystrokes. When the user presses a key that creates any of the situations described in the preceding list, 4GL automatically calls your block of code. You can include most executable 4GL statements in these blocks, as well as two special keyword clauses that can reposition the screen cursor:
s
NEXT FIELD
Use this clause in an AFTER FIELD or ON KEY block to direct the cursor to a specied next eld, or back to the same eld to correct an error in data entry.
s
NEXT ROW
Use this clause in an AFTER ROW or ON KEY block to move the cursor to a specied row of a screen array. 4GL scrolls the array as necessary to show the specied row.
NEXT FIELD and NEXT ROW should only be used in situations where the
program controls the order in which elds are visited by the user. For additional information on programming this type of user interaction, see Field Order Constrained and Unconstrained on page 11-30.
7-22
The 4GL statement that makes query by example possible is CONSTRUCT, as illustrated in Figure 7-8.
Program variable to receive the selection criteria Names of database columns that can be tested
CONSTRUCT boolExpStr ON customer_num, fname, lname FROM cust_num, first_name, last_name
The CONSTRUCT statement operates much like INPUT. The CONSTRUCT statement lists names of database columns and names of elds in the current form that correspond to those database columns. It also supports control blocks (including ON KEY, BEFORE FIELD, AFTER FIELD, BEFORE CONSTRUCT, and AFTER CONSTRUCT) that resemble in their names and functionality several of the INPUT statement control blocks. You provide a single program variable to hold the criteria for the query. When the CONSTRUCT statement executes, 4GL enables the form elds listed in this CONSTRUCT statement for input. The user can enter either specic values, or requirements such as >5 (meaning any value greater than 5) or ="Sm[iy]th*" (meaning any value beginning with Smith or Smyth).
When the user presses Accept, 4GL converts the input into a Boolean expression suitable for use in the WHERE clause of a SELECT statement. This character string is returned to the program variable. When the CONSTRUCT statement shown in the previous illustration has completed, the following character string might be stored in the program variable boolExpStr:
customer_num > 5 AND lname MATCHES "Sm[iy]th*"
Now it is up to your program to use the Boolean expression to fetch the database row, or rows, that the user wants to see. This fetch includes the following steps:
1.
Combine the Boolean expression string with other text to form a complete SELECT statement:
LET fullStmt = "SELECT * FROM customer WHERE " , boolExpStr
2. 3. 4.
What you do with the rows depends on the specic application. Often the reason for the CONSTRUCT is to select rows to be viewed by the user. In such a case, the program could display each row individually in a form, or grouped in a screen array. Or you might choose a set of rows for processing in a report or specify a set of rows to be deleted or updated, and so forth.
7-24
Additional 4GL windows can be created and further manipulated with the following statements.
Statement OPEN WINDOW Purpose Create a new window and make it the current window. You specify its size and location in relation to the upperleft corner of the screen. Close and discard a window by name. Empty the contents of a window, erasing anything displayed on it. Bring a window to the front if necessary, and make it current.
Only the current 4GL window has keyboard focus. This means that any interaction initiated by the user through the keyboard goes to the current 4GL window. The statements listed in the table in Formatted Mode Interaction on page 7-5 all operate upon the current 4GL window.
Open a 4GL window. Conduct a dialog with the user. Close the 4GL window.
Main 4GL window being used by MENU and DISPLAY Subordinate 4GL window being used for dialog via PROMPT
The domodal( ) function opens a subordinate 4GL window, prompts the user for a single-letter response, closes the window, and returns either TRUE or FALSE, depending on whether the response was the letter Y or not. A function like this can be used at almost any point within a program.
7-26
Information Displays
Information Displays
Another common use for a 4GL window is to display helpful information to the user during input. In Figure 7-10, you see a larger window that contains a form, partly covered by another 4GL window.
Figure 7-10 Subordinate Window Displayed During Input
The user is to enter a customer number in a eld of the form. Assume that user presses a designated key to ask for help. Within the INPUT statement, in the ON KEY block for that key, the program calls a function that does the following:
s s s
Opens a 4GL window Displays a form in that 4GL window Uses DISPLAY ARRAY to show a scrolling list of rows from the customer table, using the form in the current 4GL window
When the user presses Accept, the function will note the customer number in the last-current row. This value will be returned as the result of the function. Before the function returns, it will close the 4GL window it opened. That makes the larger 4GL window current again.
The User Interface 7-27
The ON KEY block will display the returned customer number in the form eld so the user will not have to enter it.
You might take the following typical steps in creating a useful help facility for an application:
1.
Think of each situation where the user might need detailed guidance and write a message that explains what to do at that point. The text can be as long as you want. Only printable characters, blank spaces, and tab characters are allowed.
2. 3. 4. 5. 6.
Assign to each message a unique positive integer number between 1 and 32700. Put the message texts with their numbers and optional comments into a text le. Compile the text le using the 4GL message compiler utility mkmessage. In your program source le, specify the name of the le of compiled help messages in an OPTIONS HELP FILE statement. In each interactive statement, specify the HELP number clause to name the help message number that you designed for that statement.
7-28
If the user presses the Help key (CONTROL-W by default) while the interactive statement is executing, 4GL displays the message whose number you specied. The display takes up the full current window, hiding the main window and any subordinate windows. Like a form le, a message le can be used with more than one program. You can use more than one message le within a program; executing the OPTIONS HELP FILE statement changes the active le at any time.
The User Interface 7-29
You can write a HELP number clause in any statement that requests input from the user: PROMPT, INPUT, or CONSTRUCT. You can specify a different help message number for each option of a MENU statement. In addition, you can start the help display from anywhere in the program by calling the library function showhelp(n), where n species the message number in the current help le. Using this function, you can start a help display from, for example, an ON KEY block of a DISPLAY statement.
7-30
Chapter
8
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-3 8-3 8-4 8-4 8-5 8-5 8-6 8-8 8-9 8-10 8-11 8-12 8-12 8-13 8-13 8-15 8-16 8-17 8-19 8-19 8-20 8-21 8-22
In This Chapter .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
Simple Data Types . . . . . . . . . . . . . . . . . Number Data Types . . . . . . . . . . . . . . . Differences Between DECIMAL and MONEY Data Types . Numeric Precision . . . . . . . . . . . . . . Time Data Types . . . . . . . . . . . . . . . Character Data Types. . . . . . . . . . . . . . . CHAR and VARCHAR Compared . . . . . . . . . Large Data Types . . . . . . . . . . . . . . . . Variables and Data Structures . . . . . . . Declaring the Data Type . . . . . . . . Creating Structured Data Types . . . . . Declaring an Array . . . . . . . . Declaring a Record . . . . . . . . Declaring the Scope of a Variable. . . . . Scope of Reference . . . . . . . . Time of Memory Allocation . . . . . Using Global Variables . . . . . . . . Global Variable Declaration . . . . . Using GLOBALS Within a Single Module Global Versus Module Scope . . . . . Initializing Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Expressions and Values . . . . . . . Literal Values . . . . . . . . . Values from Variables. . . . . . . Values from Function Calls . . . . . Numeric Expressions . . . . . . . Boolean Expressions . . . . . . . Character Expressions . . . . . . Null Values . . . . . . . . . . Null Values in Arithmetic . . . . Null Values in Comparisons . . . Null Values in Boolean Expressions
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
8-22 8-23 8-23 8-24 8-24 8-25 8-26 8-27 8-27 8-27 8-27 8-28 8-29 8-30 8-31 8-33 8-34 8-34 8-35 8-36 8-37 8-38 8-38 8-39
Assignment and Data Conversion . . . . . . . . . . . . . . Data Type Conversion . . . . . . . . . . . . . . . . Conversion Errors . . . . . . . . . . . . . . . . . . Decisions and Loops . . . . . . . . . . . . . . . . . . Decisions Based on NULL . . . . . . . . . . . . . . . Functions and Calls . . . . . . Function Denition . . . . Invoking Functions . . . . Arguments and Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Working with Multiple Values . . . Assigning One Record to Another Passing Records to Functions . . Returning Records from Functions
8-2
In This Chapter
INFORMIX-4GL has the features of a structured language such as Pascal or C
as well as advanced features of its own. This chapter surveys the basic features of 4GL as a programming language.
8-3
each of these data types describes a single item of information (as opposed to a collection or an array of items). The simple data types of 4GL are a robust subset of the data types for database columns of Informix database servers. Each of the simple data types is discussed in detail in INFORMIX-4GL Reference. There you will nd information on their minimum and maximum capacities, the proper format for literal values of each data type, and other details. The data types are summarized below as background material for the rest of the chapter.
FLOAT Binary oating-point numbers, with precision of C double DOUBLE PRECISION REAL SMALLFLOAT INT INTEGER SMALLINT Binary oating-point numbers, with precision of C oat Whole numbers, from -2,147,483,647 to +2,147,483,647 Whole numbers, from -32,767 to +32,767
8-4
Synonyms for the names of some data types, such as REAL for SMALLFLOAT, are supported to conform to the ANSI/ISO standard for SQL. The arithmetic operators of 4GL can manipulate and return number values, as the following table shows.
Operator Symbols Names of Operators Unary plus and unary minus operators Binary addition and binary subtraction operators Multiplication, division, and exponentiation operators Modulus operator
+, +,
*, /, **
MOD
Numeric Precision
Some 4GL number data types are implemented as standard C data types.
Data Type FLOAT SMALLFLOAT INTEGER SMALLINT Description Same as C double Same as C oat Same as C long Same as C short
A library of C functions for working with DECIMAL and MONEY data types is included with both 4GL and INFORMIX-ESQL/C.
8-5
A DATE value is stored internally as a count of days before or after midnight, 31 December 1899; that is, January 1, 1900, would be stored as 1. When it displays a DATE value to the screen or a report, 4GL formats it according to directions in the DBDATE environment variable, so your user can tailor the display of date values to match local conventions. You can also employ the USING operator to format DATE values.
GLS
By using the GLS features of 4GL, DATE values (and DATETIME values) can be displayed according to the cultural conventions of the current locale. You can also use the DBCENTURY environment variable to choose the present, previous, or next century. For details, see INFORMIX-4GL Reference and the Informix Guide to GLS Functionality. You can mix DATE values with integers when doing arithmetic (for example, subtracting 7 to get a date for the same day of the previous week). The difference between two DATE values, however, is an INTEGER value. You must use the UNITS operator to convert the difference to an INTERVAL value. A DATETIME value can have more or less precision than a DATE value: it can specify a date, a time, or both, and can be exact to a fraction of a second. An INTERVAL value represents a span of time, not a particular moment in time. For example, three hours is an interval; three oclock is a point in time. You can do arithmetic that mixes DATE, DATETIME, and INTERVAL values, yielding new DATETIME or INTERVAL values.
4GL does not support automatic conversion between INTERVAL values with YEAR or MONTH time units and INTERVAL values of smaller precision.
8-6
Some built-in operators accept or return DATE values. Built-in functions and operators are described in INFORMIX-4GL Reference.
Built-In Operator CURRENT DATE(expr) DAY(date-expr) EXTEND(date, qual) MDY(m, d, y) MONTH(date-expr) TIME TODAY int-expr UNITS qual Purpose Returns the current date and time as a DATETIME value Converts an integer or string value to DATE or DATETIME Returns the day of the month from a DATE or DATETIME value Changes the precision of a DATE or DATETIME value, returning a DATETIME value Composes a DATE value from integer values for month, day, year Returns the month from a DATE or DATETIME value Returns the current time of day as a character string Returns the current date as a DATE value Converts an integer to an INTERVAL value of specied precision
WEEKDAY(date-expr) Returns the day of the week from a DATE or DATETIME value YEAR(date-expr) Returns the year from a DATE or DATETIME value
These operators are identical in name and use to functions available in SQL statements. Used in SQL, they apply to values in the database. You can also use them in other 4GL statements, applying them to program variables.
DATE, DATETIME, and INTERVAL data types are discussed in detailed in INFORMIX-4GL Reference.
8-7
The most important of these is CHAR or its synonym CHARACTER, which is the default 4GL data type. TEXT can store strings, but it is classied as large (rather than character) data type, because 4GL manipulates TEXT values in a different way from CHAR or VARCHAR values.
NCHAR and NVARCHAR are both locale-sensitive character data types,and are interpreted and converted to CHAR or VARCHAR data types. When NCHAR and NVARCHAR data types are sent from the server to the client, they are converted to CHAR or VARCHAR data types, respectively. When CHAR or VARCHAR data types are sent from the client to the server, they are converted to NCHAR and NVARCHAR data types, respectively.
The following operators are among built-in operators of 4GL that can accept or return CHAR or VARCHAR values.
Operator variable [start, end] ASCII int-expr Purpose Species a substring from a CHAR or VARCHAR value Returns a specic ASCII character as a CHAR(1) value (1 of 2)
8-8
Purpose Returns a character value, without trailing blank spaces Returns the length bytes, disregarding trailing blank spaces Returns the string representation of a value, formatted to t a specied pattern (2 of 2)
Within a DISPLAY statement (that displays values to the screen) or a PRINT statement (that sends values to a report), you can use the COLUMN operator to set the beginning position of the value of the current line of output.
8-9
The data types BYTE and TEXT are collectively known as large or blob (binary large object) data types. They represent strings of data that can be of any length. The only difference between a BYTE and a TEXT data type is that a BYTE value can contain any combination of binary values, while TEXT data items contain any number of printable characters. Informix Dynamic Server supports blob data types. The LOCATE statement of 4GL must specify whether the contents of a blob variable are to be held in memory or in a le. You can change this location dynamically, as the program runs. Typical uses for blob variables are as follows:
s
To fetch blob values from the database and store them in program variables of the same data type When the receiving variable is located in a le, this is effectively a disk-to-disk copy from the database to the le.
To store blob values from program variables into the database When the source variable is located in a le, this is effectively a diskto-disk copy from the le to the database.
To view or modify a blob value, using some external program that understands the contents of the blob
Retrieve a blob consisting of a graphic from an Informix database and store it as a blob variable located in a disk le. Call a paint-type editing program, make changes in the graphic, save the changes, and exit from the editor. Reload the modied graphic in the database.
8-10
Data type. What kind of data value can it hold? A given variable can store data in a specic format (or range of formats) that is determined by the declared data type of the variable.
Structure. Does it contain only a single value or is it a collection of several values? If it is an aggregate, how can the individual simple values be accessed? For example, an array is a vector of values of the same data type. You access a single value by writing a subscript, as in custNumList[15].
Scope of reference. In what parts of the program can 4GL or the database server recognize its name? There are three possibilities, which are discussed in greater detail later in this chapter; they are local, module, and global.
Visibility. Within its scope of reference, is there any conict with other program variables that have the same name?
INFORMIX-4GL Reference discusses the visibility rules for 4GL variables whose names are not unique within their scope.
Time of allocation. When during the execution of the program is the variable created and initialized? There are two possible times: memory for the variable can be allocated at compile time, as part of the executable program le, or else at runtime, dynamically, while the program is executing.
8-11
State the data type of a variable after its name. In the preceding declaration, variables j and custNum are INTEGER; the data type of callDate is DATETIME YEAR TO SECOND, and the data type of sorryMsg is CHAR(40). Any of the simple data types that were listed earlier in this chapter can be used. You can also use the LIKE keyword to specify that the data type of a variable is the same as the data type of a specied column in an Informix database:
DEFINE custFname LIKE customer.fname
The advantage of using LIKE in this way for indirect typing is that if the database schema changes, you need only recompile your program to make sure that the data types of your variables match those in the database.
8-12
Declaring an Array
An array is a set of elements that are all of the same data type, ordered along one or more dimensions. The following two examples are array declarations:
DEFINE custNumTab ARRAY [2000] OF LIKE customer.customer_num DEFINE custByProd ARRAY [100, 25] OF MONEY(12)
The number of elements is specied in brackets. The example shows a single dimension array 2,000 elements long and a 100 by 25 (100x25) two-dimensional array. Three-dimensional arrays can also be created. All elements of an array have the same data type. This can be one of the simple or large data types, or it can be a record. You specify the data type of the array in the OF clause that follows the name of the array. You access an element of an array by naming the array with a subscript expression in brackets, as in custNumTab[175] or custByProd[j,prodNum].
Declaring a Record
A record is a collection of variables, each with its own data type and name. You put them in a record so you can treat them as a group, as follows:
DEFINE person RECORD honorific VARCHAR(40) , -- e.g. "Excellency" initial CHAR(1) , famName CHAR(30) END RECORD
You access a member of a record by writing the name of the record, a dot (known as dot notation), and the name of the member. For example, person.initial is the second member of the person record. You can declare a record that has one member for each column in a database table. The names of the members and their data types are derived from the database. The only exception is that SERIAL data types are converted to INTEGER data types. In the simplest form, you write:
RECORD LIKE tablename.*
As in the following:
DEFINE custRec RECORD LIKE customer.*
8-13
The statement creates a record named custRec having one member for each column of the customer table. Each record member has the name and the data type of the corresponding column in the table. You can augment table columns with other members. The following clause retrieves the names of columns and their types:
LIKE tablename.*
The preceding statement creates a record named custPlus having a member for each column of the customer table and two additional members. The member custPlus.row is an integer. The member custPlus.balanceDue is a decimal number. In this case, where the LIKE clause only generates some of the members of the record, you must use an END RECORD clause to nish the record denition. Because custPlus.customer is a record within the record, a reference to the lname member of the record is specied as:
custplus.customer.lname
8-14
If it is within a function, the scope is local to that function. The variable can only be referenced while the function is executing. (Functions are described in Functions and Calls on page 8-34.) If it is at the top of the source module and outside any MAIN, REPORT, or FUNCTION statement, the variable is considered a module variable. Its name can be used anywhere from that point to the end of the source module. If it is in a GLOBALS statement in a module separate from any other statements, the variable is available in that module (and in any other module that includes the GLOBALS "lename".4gl statement that denes that variable).
The context of the DEFINE statement also determines the following characteristics of a variable:
s
Scope of reference. This portion of the source code is where the 4GL compiler recognizes the variable name. Time of allocation. 4GL allocates memory for the variable at time of allocation.
4GL also supports recursion (a function calling itself). Each separate call to a function allocates its own copy of local variables.
8-15
Scope of Reference
The context of a DEFINE statement determines the scope of reference of the name of a variable, sometimes more briey referred to as its scope. During compile time, the scope of reference is that portion of the source code in which the 4GL compiler can recognize the name of the variable. Outside its scope, the name is unknown or might reference a different variable.
The module where the GLOBALS ... END GLOBALS statement appears Any other modules that include a GLOBALS "lename".4gl statement, where "lename".4gl is the module that contains the GLOBALS ... END GLOBALS statement that declares the variable.
Both the GLOBALS ... END GLOBALS and the GLOBALS "lename".4gl statements must appear at the beginning of a source module, before the rst program block, and before any executable statements.
8-16
Variable declaration tells the 4GL compiler the name and the data type of the variables so that the compiler can verify references to this variable in a given source code module. Variable denition allocates the memory for the global variable. For global variables, memory is allocated statically, as part of the program image.
8-17
The GLOBALS ... END GLOBALS statement denes the global variables. It also declares them so the compiler can verify references to a global variable in the same module where it is dened. To make a global variable visible in other modules of the program, you only need to declare these variables. You do not need to dene them because memory only needs to be allocated once and is done so with the GLOBALS ... END GLOBALS statement. To declare global variables in other modules, you must:
s
put the GLOBALS ... END GLOBALS statement in a separate source le. at the top of each source le that references a global variable, put the GLOBALS "lename".4gl statement, where "lename".4gl is the name of a le containing the GLOBALS ... END GLOBALS statement.
The following example declares global variables in the globs.4gl source le:
GLOBALS DEFINE a,b,c INT , x,y,z CHAR(10) END GLOBALS
To reference these variables in other source modules, you would put the following statement at the top of each source module using a global variable:
GLOBALS "globs.4gl"
8-18
If you use the LIKE keyword in any DEFINE statement, you must identify the database that contains the referenced database columns. You can do this in either of the following two ways:
Precede the GLOBALS ... END GLOBALS statement with a DATABASE statement specifying the database containing the referenced columns. Qualify each referenced column with its table name.
If a global variable dened within the GLOBALS ... END GLOBALS block has the same name as a local variable, then the local identier takes precedence within its scope of reference. A module variable in the same source module cannot have the same name as a global variable.
The following program segment denes a variable like the customer table of the stores7 demonstration database:
DATABASE stores7 GLOBALS DEFINE p_customer RECORD LIKE customer.* END GLOBALS
8-19
The 4GL compiler will generate an error if you dened a module variable with a name of arraysize, p_customer, p_state, or state_cnt in the same module containing the GLOBALS statement. However, used in this context, the GLOBALS statement simply denes variables with module scope. For other modules to be able to access the variables, they must use the GLOBALS "lename".4gl statement, and to do so, the GLOBALS ... END GLOBALS statement must appear in a separate source le.
8-20 IBM Informix 4GL Concepts and Use
sub1.4gl
GLOBALS "glob.4gl" LET taxrate = 1.085 DEFINE NYCtaxRate DECIMAL(4,3) LET NYCtaxrate = taxrate * 2
uninitialized
1.085
sub2.4gl
GLOBALS glob.4gl DISPLAY %tax is , taxrate AT 2,2
wildduck.4gl
DEFINE taxrate DECIMAL(4,3) LET taxrate = 1.15
1.085
1.15
In Figure 8-1, the source module glob.4gl declares a variable taxrate as a global variable. The current value of the global variable is available to any function in any module that references the global source module. Another source module, sub1.4gl, references the GLOBALS le glob.4gl, and assigns a value of 1.085 to taxrate. A third module, wildduck.4gl, denes a module variable named taxrate and assigns it a value. Because there is no reference to the globals le glob.4gl, this module-level assignment is permitted. No change in the value of taxRate in wildDuck.4gl will affect the current value of the global variable taxRate. Finally, a routine in a fourth module, sub2.4gl, displays the current value of the global variable taxrate, 1.085.
8-21
Initializing Variables
Initializing Variables
You initialize variables using the LET statement:
DEFINE Pi, TwoPi SMALLFLOAT LET Pi = 3.1415926 LET TwoPi = 2*Pi
The declaration of a variable must precede any executable statement in the same program block.
4GL programmers often initialize global variables at a single point in the program, such as immediately after the last DEFINE or DATABASE statement in the MAIN program block.
Function calls, to specify the arguments to functions Decision and looping statements, to control program ow Reports, to specify the values to print in the report
SQL statements, to specify values to be inserted into the database LET statements, to specify values to be assigned to variables
Every value has a data type, one of the simple or large data types that were listed earlier in this chapter. The 4GL compiler knows the data type of every component of an expression, so it can tell the data type of the returned value that the expression species. For a detailed discussion of 4GL and SQL expressions, see INFORMIX-4GL Reference.
8-22
Literal Values
Literal Values
The simplest kind of expression is a literal value, that is, a literal representation of a number, a date, a character string, or some other kind of data. Some literal numbers are: -7, 3.1415926, 1e-8. 4GL assumes any literal number with a fractional component has the data type DECIMAL(32), the most precise number data type available. Enclose literal character values in quotes: "Record inserted." You can use a single quote (' ) or double quotes ( " ) to delimit a character literal, but both delimiters of the same value must be the same. In single-byte locales, 4GL assumes that any literal character value has the data type CHAR(n), where n is the number of characters between the quotes. You can also write literal values of DATE, DATETIME, and INTERVAL data types. For details of these data types, see INFORMIX-4GL Reference.
Following these statements, you can use the name pi as an expression meaning 3.1415926 and having the data type SMALLFLOAT. The names j and prodNum are expressions meaning, the value that was last stored in this variable, and have a data type of INTEGER. References to a component of a structured variable are also expressions. The ARRAY element custByProd[j,prod_num] is an expression meaning, the value that was last stored in the subscripted element of this array. For the expression to be valid, both j and prod_num must have values that are positive integers within the declared dimensions of the custByProd ARRAY variable.
8-23
Numeric Expressions
You can write expressions that calculate numeric values. You can use the arithmetic operators to combine numeric literals and the names of numeric constants, variables, and functions to calculate new values. The following statement from an example in the preceding chapter contains several numeric expressions:
LET fahrDeg = (9*centDeg)/5 + 32
In this statement, 9, 5, and 32 are literals, and centDeg is the name of a variable. The expression 9*centDeg tells 4GL to produce a new value by multiplying two values, and (9*centDeg)/5+32 tells it how to produce another new value by dividing and then adding. As previously noted, 4GL carries intermediate results of calculations on numbers with fractional components in its most precise data type, DECIMAL(32). This helps prevent many errors due to rounding and truncation, and reduces the chance that an intermediate result will overow. However, it is still possible for a badly planned calculation to cause overow, round-off, or truncation errors. As with any computer language, you should think through the precision requirements of any critical calculation. Integer and numeric expressions are described in INFORMIX-4GL Reference.
8-24
Boolean Expressions
Boolean Expressions
In 4GL, the result of comparing two values by using any Boolean or relational operator is an integer value of 1 (if the result of the comparison is TRUE) or 0 (if the result is FALSE). Suppose the following variables have been declared and initialized:
DEFINE maxRow, rowNum INTEGER
The expression rowNum==maxRow is a Boolean comparison; that is, it is a Boolean expression with a value of either 1 or 0. Tip: You can write an equality comparison using either a single equals sign or a double one. If you have used the C language, you might prefer to write ==; if your experience has been with other languages you might prefer to use just one. Other Boolean operators include <> or != for not-equals, and LIKE or MATCHES for character pattern matching. Two especially important relational operators are IS NULL and IS NOT NULL. You can use these to test for the presence of a null value in a variable. (For more information on the use of null values, see Null Values on page 8-27 and INFORMIX-4GL Reference.) Most other Boolean operators of 4GL return FALSE if any operand is NULL. All these relational tests return 1 to mean true or 0 to mean false. The names TRUE and FALSE are predened 4GL constants with those values. You can combine numeric values with the Boolean operators AND, OR, and NOT. Often you use these to combine the results of relational expressions, writing expressions such as keepOn="Y" AND rowNum < maxRows. That expression means:
s s s
Take the value of the comparison keepOn="Y" (which is 1 or 0). Take the value of the comparison rowNum<maxRows (1 or 0). Combine those two values using AND to produce a new value.
Usually you write Boolean expressions as part of IF statements and other decision-making statements (for some examples, see Decisions and Loops on page 8-31). However, a comparison is simply a numeric expression. You can store its value in a variable, pass it as a function argument, or use it any other way that an expression can be used. For more on relational and Boolean expressions, see INFORMIX-4GL Reference.
8-25
Character Expressions
Character Expressions
You can express a character value literally (as a quoted string) or as an expression that returns a character string. In many contexts, 4GL can convert a value of any simple data type automatically to a string that a CHAR or VARCHAR variable of sufcient declared length can store. The following expressions return a character value:
s
The name of an initialized CHAR, VARCHAR, NCHAR, or NVARCHAR variable A call to a function that returns a CHAR, VARCHAR, NCHAR, or NVARCHAR value A substring of a literal, a variable, or the returned value from a function returning a CHAR, VARCHAR, NCHAR, or NVARCHAR value
A substring is written as one or two numbers in square brackets. The rst is the position of the rst character to extract, and the second is the position of the last. Suppose the following variable exists:
DEFINE delConfirm CHAR(11) LET delConfirm = "Row deleted"
Now you can write delConfirm[1,3] as an expression with the value Row and the expression delConfirm[5,8] is the value dele. The expression delConfirm[4] or delConfirm[4,4] is a single-space character. It should be noted that the substring expression uses the same notation as the subscript to an array. The following example shows an array of character values:
DEFINE companies ARRAY[75] OF CHAR(15)
The expression companies[61] produces the character value from the 61st element of the array. The expression companies[1,7] would cause an error at compile time because the array companies does not have two dimensions. However, the expression companies[61][1,7] accesses the 61st element and then extracts the rst through the seventh letters of that value.
8-26
Null Values
Null Values
For every SQL data type, the Informix database servers dene a null value. A value of NULL in a database column means do not know, or not applicable, or unknown. Because null values can be read from the database into program variables, 4GL also supports a null value for every data type. The keyword NULL stands for this unknown value. A variable of any data type can contain NULL, and a function can return a variable with a value of NULL. If a null value appears in a character expression, 4GL substitutes blank characters for the value.
8-27
The expression is (9*centDeg)/5+32. The LET statement causes 4GL to calculate the value of the expression and to store that value in the memory reserved for the variable fahrDeg. You can assign a value to a variable in the following ways:
s s
Use the LET statement. This assignment is the most common. Use the CALL RETURNING statement to call a function and store the value it returns:
CALL tempConvert(32) RETURNING fahrDeg
Use the INTO clause of an SQL statement to get a value from the database and assign it to a variable:
SELECT COUNT(*) INTO maxRow FROM stock
Other SQL statements that support INTO include SELECT, FETCH, and FOREACH.
s
Use the INITIALIZE statement to set a variable, or all members of a record, to NULL or to other values:
INITIALIZE custRow.* TO NULL
Use PROMPT to accept values that the user entered from the keyboard:
PROMPT "Enter temp to convert: " FOR centDeg
Use INPUT or INPUT ARRAY to get values from elds of a form and put them in variables:
INPUT custRec.* FROM customer.*
Use CONSTRUCT to get a query by example expression from a form and put it in a variable:
CONSTRUCT BY NAME whereClause ON customer.*
8-28
The second assignment statement asks 4GL to initialize chr, a character variable, from the value of num, a numeric variable. In other words, this statement asks 4GL to convert the value in num to a character. It does that using the same rules it would use when displaying the number, in this case producing the string 2.187810 (with all six declared decimal places of the fractional part lled in).
LET num = chr[1,3]
Given the initialization of chr to the string 2.187810, the expression chr[1,3] returns the characters 2.1. Because the receiving variable is of data type DECIMAL(8,6), 4GL converts the characters into the number value 2.100000 and assigns that value to num. For systems or locales that dene some symbol other than period ( . ) to represent the decimal separator, 4GL would use that symbol to replace the period in the converted string value.
8-29
Conversion Errors
Conversion Errors
Some data type conversions cannot be done. When 4GL can recognize at compile time that a particular conversion is illegal, it returns a compiler error.
4GL can convert BYTE to TEXT, and TEXT to BYTE, but it does not attempt to convert these to other data types because 4GL does not know enough about the internal structure of the values of these large data types to convert them.
Some conversions might prove to be impossible only at execution time. Then the error will be detected while the program is running. For example, the following program tries to assign a CHAR value to a SMALLINT variable:
DATABASE stores7 DEFINE a, b SMALLINT, c,d CHAR(10) MAIN LET c="apple" DISPLAY "This is c ", c AT 3,3 SLEEP 2 LET a=c DISPLAY "This is a ", a AT 5,5 SLEEP 4 END MAIN
8-30
The CASE(expr) statement implements multiple branches. This statement has two forms. The rst form is a simple form that compares one expression for equality against a list of possible values. For example:
CASE (WEEKDAY(ship_date)) WHEN 0-- Sunday DISPLAY "Will ship by noon Monday" WHEN 5-- Friday DISPLAY "Will ship by noon Saturday" WHEN 6-- Saturday already DISPLAY "Will ship by noon Monday" OTHERWISE IF DATETIME (12) HOUR TO HOUR < EXTEND(CURRENT,HOUR TO HOUR) THENDISPLAY "Will ship by 5 today"ELSE -- past noon DISPLAY "Will ship by noon tomorrow" END IF END CASE
The second form of CASE is effectively a list of else-if tests. No expression follows the keyword CASE, but a complete Boolean expression (instead of a comparison value) follows each WHEN keyword. For example:
MAIN DEFINE promptAnswer CHAR(10) PROMPT "Delete current row? " FOR promptAnswer CASE WHEN promptAnswer MATCHES "[Yy]" DISPLAY "Row will be deleted." AT 2,2
8-31
WHEN promptAnswer MATCHES "[Nn]" DISPLAY "Row not deleted." AT 2,2 WHEN promptAnswer MATCHES ("Maybe") DISPLAY "Please make a decision." AT 2,2 OTHERWISE DISPLAY "Please read the instructions again." AT 2,2 END CASE SLEEP 5 END MAIN
The WHILE statement provides for generalized looping. You can use the EXIT statement to break out of a loop early. For example:
LET j=1 WHILE manyObj[j] IS NOT NULL LET j = j + 1 IF j > maxArraySize THEN -- off the end of the array LET j = maxArraySize EXIT WHILE END IF END WHILE DISPLAY "Array contains ",j," elements."
An additional loop, the FOREACH loop, is discussed in Row-by-Row SQL on page 9-5.
8-32
IF NULL always executes the ELSE statements (if any). CASE (NULL) always executes the OTHERWISE statements (if any). WHILE NULL does not execute its loop statements at all.
Using a NULL value as either the starting or the ending number in a FOR loop results in an endless loop. The FOR loop ends when the control variable equals the upper limit, but a NULL value cannot equal anything; hence the loop never ends.
8-33
Function Denition
You dene a function when you specify the executable statements it contains. Figure 8-2 shows a denition for a simple function.
Function name Name of argument Variables local to function Figure 8-2 Simple Function Denition
FUNCTION fahrToCent(ftemp) DEFINE ftemp, FiveNinths FLOAT LET FiveNinths = 5/9 RETURN (ftemp - 32) * FiveNinths END FUNCTION
This example shows the important parts of a function denition. It contains the following statements:
s
The name of the function (fahrToCent in the example) How many arguments it takes (just one in the example)
A function program block, statements between the FUNCTION and END FUNCTION:
Executable statements do the work of the function. In the example there is only one, a RETURN statement.
Variables declared in the program block are local to the function. The variable named FiveNinths is local to this function; it is not available outside the function, although other FiveNinths variables can be declared at the module level, locally in other functions, or globally.
8-34
Invoking Functions
When the 4GL compiler processes a function denition, it generates the executable code of the function. Once dened, a function is available to any 4GL module in your program. That is, the scope of reference of the name of a function (or of a report) is global. The name of a function or report must not be the same as the name of one of its formal arguments, however, or else the local name (the argument) will occlude the visibility of the global name.
Invoking Functions
You cause a function to be executed by calling it. The two ways to call a function are:
s s
When a function returns a single value, you can call it as part of an expression. The fahrToCent( ) function described previously returns a single value, so it can be called in an expression that expects the data type of the returned value:
LET tmp_range = fahrToCent(maxTemp) - fahrToCent(minTemp)
This statement contains two calls to the function fahrToCent( ). The statement subtracts one of these values from the other, and assigns the result to the variable tmp_range of data type FLOAT. When a function returns no values or multiple values, you must use the CALL statement. Functions that return one value can be called in this way also.
CALL mergeFiles() CALL fahrToCent(currTemp) RETURNING cTemp
The useful ability to return more than one value from a function is considered further in Working with Multiple Values on page 8-37.
8-35
Variables local to the function are allocated in memory, including the those that represent the arguments. In the function fahrToCent( ), local variables are veNinths and ftemp, its argument. Each expression in the argument of the function call is evaluated. In the following call, the expression targetTemp + 20 is evaluated.
LET limitTemp = fahrToCent(targetTemp + 20)
Each argument value is assigned to its argument variable, as described earlier (Assignment and Data Conversion on page 8-28). When an argument value has a different data type from the argument variable, 4GL attempts to convert it, as in any assignment. The statements of the function denition are executed. The local variables, including the argument variables, are discarded and their memory is reclaimed.
s s
The key point is that the expressions you write in the call to a function are assignments to local variables of the function. Knowing this, you can answer some common questions:
s
Does a value passed to a function require a specic data type? No, because the value is assigned to the argument variable, and 4GL will attempt to convert it to the specic type. It is sufcient that the expression in the call and the function argument be of compatible data types.
Can a function assign new values to its arguments? Yes, because they are simply local variables. Does this change the contents of variables that appear in the call to the function? No, because the argument variables are local to the function.
8-36
This method of passing arguments to functions is known as call by value. An alternative technique, call by reference, is used in some other programming languages, but generally not by 4GL. The only calls by reference in 4GL are references to BYTE and TEXT data types. These are called by reference because passing blobs by value is not practical. The use of call by value has an effect on performance. Each argument value is copied into the functions variable. When the arguments are bulky character strings, the time such copying takes can be signicant. A common way of avoiding this time penalty is to use global variables.
The name of a record followed by a dot and an asterisk, record.*, also means a list of all the members of the record. You can select a range of members using record.rst THRU last, where rst and last are names of members of record.
These statements dene three record variables and declare a function that takes three arguments. The function takes3( ) is used in examples in subsequent sections.
8-37
You can assign one record to another using LET when they have the same number of members.
LET rSSS2.* = rSSS1.*
This statement assigns the three members of rSSS1 to the corresponding members of rSSS2. In other words, 4GL assigns members one at a time, with automatic data type conversion performed as required. The members must all have simple data types, and the data types must be the same, or else must be compatible. (As dened earlier, compatible means that data type conversion is possible.)
When calling a function, you can also mix record members and single expressions as arguments:
CALL takes3(17, rSSS1.f2 THRU rSSS1.f3)
8-38
The RETURN statement must match in number of values in the calling function.
8-39
A function like this one can be used in several ways. It can be used in a CALL RETURNING statement. You list variables to receive the values.
DEFINE balShort, balMed, balLong MONEY(10) ... CALL agedBalances(custNumber) RETURNING balShort, balMed, balLong
If you have a record with appropriate members of the appropriate number of data types, you can refer to it in the RETURNING clause of the CALL statement, as follows:
DEFINE balRec RECORD b1, b2, b3 MONEY(10) END RECORD ... CALL agedBalances(custNumber) RETURNING balRec.*
8-40
Chapter
9
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-3 9-3 9-4 9-5 9-5 9-8 9-9 9-9 9-10
In This Chapter .
. . .
. . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
Nonprocedural SELECT .
Row-by-Row SQL . . . . . . . . Updating the Cursors Current Row Updating Through a Primary Key . Updating with a Second Cursor . . Dynamic SQL. . . . . . . . . .
9-2
In This Chapter
In many ways, the SQL language can be considered a subset of the 4GL language because you can embed many SQL statements in a 4GL program. This chapter describes how to work with database cursors using SQL in a 4GL program.
created at compile timeor dynamic. Dynamic statements are composed during runtime, based in whole or in part on information supplied or selected by the user of the application. For additional information about the use of SQL in general and embedded in a 4GL program in particular, see the Informix Guide to SQL: Tutorial, and the Informix Guide to SQL: Syntax. For information on preparing SQL statements, see INFORMIX-4GL Reference. If you want to use an SQL statement that was not part of 4.10 SQL (such as CREATE TRIGGER) or a statement using features that were not in 4.10 SQL (such as CREATE TABLE with a fragmentation specication), then the statement must be prepared.
Nonprocedural SQL
Nonprocedural SQL
Figure 9-1 provides an example of SQL use shown earlier in this book. It denes a function named markup( ) whose purpose is to alter the prices of stock received from a specied manufacturer.
Figure 9-1 markup() Function Argument used in WHERE clause Argument used in SET clause
FUNCTION markup(manuf, changePct) DEFINE manuf CHAR(3) , changePct DECIMAL(2,2) UPDATE stock SET unit_price = unit_price * (1+changePct) WHERE manu_code = manuf RETURN sqlca.sqlerrd[3] -- number of rows affected END FUNCTION
The function takes two arguments. The rst, manuf, is the code for the supplier whose prices are to be changed. The second, changePct, is the fraction by which prices should be changed. The following example is a call to markup( ):
LET rowCount = markup("ANZ",0.05) DISPLAY rowCount, " stock items changed."
The SQL statement UPDATE in the denition of the markup( ) function causes a change in the unit prices of certain stock items in the database. The function argument values are used in this UPDATE statement, one in the SET clause and one in the WHERE clause. This function is an example of the nonprocedural use of SQL. The UPDATE statement will examine many rows of the stock table. It might update all, some, or none of them. The 4GL program does not loop, updating rows one at a time; instead it species the set of rows using a WHERE clause and leaves the sequence of events to the database server.
9-4
Nonprocedural SELECT
Nonprocedural SELECT
All 4.1-level SQL statements except the SELECT statement can be used by writing them in the body of a function. SELECT also can be used this way as long as only a single row is returned. The following function returns the count of unpaid orders for a single customer, given the customer name:
FUNCTION unpaidCount(cust) DEFINE cust LIKE customer.company , theAnswer INTEGER SELECT COUNT(*) INTO theAnswer FROM customer, orders WHERE customer.company = cust AND customer.customer_num = orders.customer_num AND orders.paid_date IS NULL RETURN theAnswer END FUNCTION
Because the SELECT statement returns only an aggregate result (a count), it can return only a single value. The argument variable cust is used in the WHERE clause. The result of the SELECT operation is assigned to the local variable theAnswer by the INTO clause.
SQL statements do not allow program variables in all contexts. You can refer to the syntax diagrams in Informix Guide to SQL: Syntax to nd out which ones
do not.
Row-by-Row SQL
When a SELECT statement can return more than one row of data, you must write procedural logic to deal with each row as it is retrieved. You do this in four or ve steps, as shown:
1.
If you want to generate your SQL statement dynamicallyfor example, using the 4GL CONSTRUCT statement to generate dynamic search criteriaplace your statement text in a CHAR variable and use the SQL PREPARE statement. For more information, see Dynamic SQL on page 9-10 and the Informix Guide to SQL: Syntax. You declare a database cursor, which is a name that stands for a selection of rows.
2.
Row-by-Row SQL
3.
You specify the rows using a SELECT statement. While you often specify a selection from a single table, you are free to specify rows formed by unions or joins over many tables, and including calculated values, literal values, aggregates, and counts. You use a FOREACH statement to automatically open the cursor, FETCH one row for each traversal of the FOREACH loop, and then close the cursor after you have processed the last row of the selection set.
4.
Alternatively, you can open the cursor, causing the database server to retrieve the rst of the specied set of rows, retrieve rows one at a time through the cursor using the FETCH statement (and process each one as it is produced), and then close the cursor, releasing the set of rows. Figure 9-2 on page 9-7 contains a SELECT statement that retrieves one row for each customer that has an unpaid order in the demonstration database. The selected data consists of the customer number and the total value of that customers unpaid orders. The DECLARE statement must be executed before FOREACH in showCustDue( ).
9-6
Row-by-Row SQL
A cursor represents a set of rows. The set of rows is dened by a SELECT statement.
FUNCTION showCustDue() DEFINE cust LIKE customer.customer_num, amt_owing MONEY(8,2) DISPLAY "Customer", COLUMN 15, "total unpaid" FOREACH custDue INTO cust, amt_owing DISPLAY cust, COLUMN 15, amt_owing USING "$$$,$$$.$$" END FOREACH END FUNCTION
The FOREACH loop iterates once per row from specied cursor.
Unless used in conjunction with a PREPARE statement, the SELECT statement is written within a DECLARE statement, which creates a database cursor. The cursor, when opened, represents the set of all selected rows. (For more on database cursors and active sets, see the Informix Guide to SQL: Tutorial.) The FOREACH statement in 4GL has three effects:
s s
It opens the database cursor. For every row in the selected set, FOREACH:
fetches the column values for that row. (In the example, it assigns the fetched values to local variables cust and amt_owing.) executes the statements in the body of the loop (a single DISPLAY in the preceding example).
This pattern is common for many programs: open a cursor, fetch the rows and process each row, and close the cursor. The step process each row, of course, can be elaborate, especially when you process a row by displaying it in a screen form for the user to read or change.
Make the cursor an update cursor, which locks the selected row. Indicate in your UPDATE statement that you want to update the current cursor row.
To make the cursor an update cursor, add the keywords FOR UPDATE to the cursor declaration; you can also limit the update to certain columns by specifying those column names in the FOR UPDATE clause. When using the cursor, you can update or delete the current row by writing an UPDATE or DELETE statement as usual and adding the clause WHERE CURRENT OF cursor, supplying the name of the cursor from which you fetched the row. The following function uses a cursor to scan the orders table and deletes any row for which the paid date is at least a month old. Note that the same task could more easily be accomplished by a nonprocedural UPDATE.
DECLARE oldOrder CURSOR FOR SELECT order_num, paid_date FROM orders no WHERE clause, all rows scanned FOR UPDATE FOREACH oldOrder INTO o_num, p_date IF 30 < (TODAY - o_num) THEN DELETE FROM orders WHERE CURRENT OF oldOrder END IF END FOREACH
The clause FOR UPDATE tells the database server that you can update or delete fetched rows. It is not required in an ANSI-compliant database.
9-8
Dynamic SQL
The answer is to use two cursors. The rst, primary cursor selects the rows of interest. You include in each row the primary key columns. The second cursor selects only one row based on its primary key and is declared FOR UPDATE. When the user chooses to update the current row, proceed as follows:
1. 2.
Open the second cursor. Fetch the one matching row into a temporary record. If the row with this ROWID value cannot be found, you know that another user must have deleted it while your user was looking at the screen display.
3.
Compare the second set of column values to the ones you displayed to the user. If any important ones have changed, you know that some other user has altered this row while your user was looking at the display. Notify your user and do not proceed.
4. 5.
Update the row through the second cursor using WHERE CURRENT OF. Close the second cursor.
Dynamic SQL
In the preceding examples, the SQL statements are static. That is, they were written into the program source, and hence are static in that their clauses are xed at the time the source module is compiled. Only the values supplied from program variables can be changed at execution time. You will need to generate the contents of the SQL statement itself many times while the program is running. For instance, you probably want users of your program to be able to retrieve records based on queries they devise during the day-to-day operation of their business. In other words, in real time. When you do this, you are using dynamic SQL.
9-10
Dynamic SQL
The following function uses dynamic SQL. It assembles the text of a GRANT statement and executes it. It takes the following three arguments:
s s s
The name of the user to receive the privilege. The name of a table on which the privilege is to be granted. The name of a table-level privilege to be granted (for example, INSERT), as follows:
FUNCTION tableGrant( whom, tab, priv ) DEFINE whom, tab, priv CHAR(20), granText CHAR(100) LET granText ="GRANT " , priv, " ON " , tab, " TO " , whom PREPARE granite FROM granText EXECUTE granite END FUNCTION
This function does nothing about handling the many possible errors that could arise in preparing and executing this statement. You can nd a version of the same program that does handle errors in Using WHENEVER in a Program on page 12-13.
Chapter
Creating Reports
10
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-3 10-4 10-5 10-6 10-8 10-9 10-10 10-12 10-12 10-13 10-13 10-14 10-14 10-15 10-16 10-17 10-18 10-19 10-19 10-20 10-20 10-21 10-21 10-22 10-23 10-23 10-24
In This Chapter .
. . .
Designing the Report Denition . . . . . . . . . The REPORT Statement . . . . . . . . . . . The Report Declaration Section . . . . . . . . The OUTPUT Section. . . . . . . . . . . . The ORDER BY Section . . . . . . . . . . . Sort Keys . . . . . . . . . . . . . . One-Pass and Two-Pass Reports . . . . . . . . Two-Pass Logic for Row Order . . . . . . . Two-Pass Logic for Aggregate Values . . . . . Further Implications of Two-Pass Logic . . . . The FORMAT Section . . . . . . . . . . . Contents of a Control Block . . . . . . . . . Formatting Reports . . . . . . . . . . . . PAGE HEADER and TRAILER Control Blocks . . . ON EVERY ROW Control Block . . . . . . . . ON LAST ROW Control Block . . . . . . . . BEFORE GROUP and AFTER GROUP Control Blocks Nested Groups . . . . . . . . . . . . Default Reports. . . . . . . . . . . . . . Using Aggregate Functions . . . . . . . . . Aggregate Calculations. . . . . . . . . . Aggregate Counts . . . . . . . . . . . Aggregates Over a Group of Rows . . . . . . END REPORT and EXIT REPORT . . . . . . .
10-2
In This Chapter
As explained in Creating 4GL Reports on page 6-5, a 4GL report program has the following parts:
s s
A report driver that produces rows of data A report denition that sorts the rows (if necessary), creates subtotals and other summary information, and formats the rows for output
When you design a 4GL report program, you can design these two parts independently. A report driver can produce rows for any number of reports. This chapter explains how to design the report driver and the report formatter to generate reports. The 4GL statements that you use for generating reports are covered in detail in INFORMIX-4GL Reference. You can also nd several examples of programs that produce reports distributed with 4GL.
Initialize the report using the START REPORT statement. This statement initializes the report denition. It can also specify the destination of output from the report, such as the screen, the printer, a le, or another program.
2.
Generate rows of data, sending each row using OUTPUT TO REPORT. This statement, which is similar to a function call, passes one row of data to the report. Although called a row, each group of data values need not come from a row of a database table. The values can come from any source, including calculations made by your program. It is equally valid to look at a row as an input record.
3. 4.
Totals and other aggregates are calculated, output from the report is sent to some destination, and any intermediate les are closed. These steps assume that no problems are encountered in processing the rows and in producing output from the report. If the report driver detects an error at any point, you can then use the TERMINATE REPORT statement (instead of FINISH REPORT) to abort the report.
10-4
Rows are generated in sorted order. Report is initialized; le destination can be a variable. Values for one row are passed like function arguments. Report output completed and le closed.
This function takes a lename (it might be a complete pathname) as its argument and produces a report with that destination. The values in each row describe one row of merchandise from the stores7 demonstration database. The values are produced by a database cursor dened on a join of the stock and manufact tables. They are produced in sorted order using the row-ordering capability of the database server. The name of the report, minStockRep(), appears in the START REPORT, OUTPUT TO REPORT, FINISH REPORT, and TERMINATE REPORT statements.
The CALL statement cannot invoke a report; attempting to do so produces a fatal error. Reports are not recursive. The results will be unpredictable if the START REPORT statement invokes a report that is already running. The Interactive Debugger cannot analyze a report denition. A report does not return anything to its driver. It is an error to include the RETURN statement within a report denition. The 4GL statements NEED, PAUSE, PRINT, and SKIP are valid in report denitions, but produce errors if they appear in a function:
s s
Although a report has the general form of a function, its contents are quite different. The body of a function contains whatever statements you specify, while the body of a report contains several independent statement blocks that must appear in a xed sequence, if they are present, and are executed as needed. The xed sequence for the statement blocks within the REPORT statement is:
s s s s
However, within the FORMAT statement block, statements can appear in any order. Figure 10-2 on page 10-7 shows the minStockRep() report denition that completes the preceding example. This code is examined in detail in the topics that follow.
10-6
Local variables created at START REPORT time; kept until FINISH REPORT.
States that rows are produced in sorted sequence. Statement blocks are called when necessary as rows are processed. Calculated COLUMN value is used to right-justify name. Logic to display manufacturer in rst line of group or at top of page. Semicolon suppresses new line after printing.
Figure 10-3 shows an excerpt from the output of this report. The page length was set to 20 for testing; it would normally be longer.
Figure 10-3 A Sample 4GL Report
Stock report 6
ProCycle101 bicycle tires$88.00 box 102 bicycle brakes$480.00 case 103 frnt derailleur$20.00 each
ProCycle
The report name is used to identify this report in the START REPORT, OUTPUT TO REPORT, FINISH REPORT, and TERMINATE REPORT statements within the report driver. This name cannot be the same as the identier of another report, or function, or global variable, that is dened in the same 4GL program.
10-8
The END REPORT keywords (described in a later section) terminate the report denition. The formal arguments to the report indicate the number of actual values that the report driver can pass to the report as one input record. This report takes ve arguments. For the purposes of this report, one set of these values makes a row. Within the body of the report, you must dene a local variable of the REPORT program block that corresponds to each argument. You can then refer to these variables to nd values of the current report row. When the report driver code executes OUTPUT TO REPORT, it sends another set of values (that is, another row), to the report for processing. The following statement is from An Example of a Report Driver on page 10-5:
FOREACH minStock INTO mn, sn, sd, sp, su OUTPUT TO REPORT minStockRep( mn, sn, sd, sp, su ) END FOREACH
Usage Number of spaces inserted to the left of every print line Total number of printed characters in any line, including left margin spaces (This statement is ignored unless the FORMAT EVERY ROW default report formatting option, or default WORDWRAP is used.) Number of blank lines to print above the page header. Number of blank lines to print after the page trailer (also known as a footer) Total number of lines per page, including margins and page header and trailer sections
These values must be expressed as literal integers. (Use the START REPORT statement, if you want to use variables to specify page dimensions.) The TOP OF PAGE specication in the OUTPUT section can specify a character value (as a quoted string) that 4GL can use to cause a page-eject. If you omit it, 4GL starts a new page by printing empty lines. The REPORT TO keywords can be followed by a default destination for output from the report. (But any destination in the START REPORT statement takes precedence over what REPORT TO species.) The destination must be specied as a quoted string (except that a named pipe destination can be a character variable).
10-10
PAGE LENGTH
Lines for PRINT output
Page trailer lines BOTTOM MARGIN LEFT MARGIN Space for PRINT output RIGHT MARGIN
The vertical arrows represent page dimensions that you specify in units of lines; the horizontal arrows represent page dimensions that you specify in units of monospace characters.
The order of the rows is not important; that is, the report is simply a list of rows in the order in which they happen to be generated. To choose this, omit the ORDER BY section entirely. When ORDER BY is not used, you should not process rows in groups or take aggregate values over them.
2.
The rows need to be generated in the order specied by the report driver. To choose this, specify ORDER EXTERNAL BY and list the eld on which the sort takes place. If the report driver code fails to generate the rows in their proper sequence, the report output will be incorrect.
3.
The rows need to be sorted, but the report driver does not produce them in the correct order. To choose this, you write ORDER BY and specify the elds to sort on. You do not use EXTERNAL in this case.
When rows are to be sorted, it is best if the report driver code can produce them in correct order. When the rows come from the database, you can use the ORDER BY clause of the SELECT statement. The database server has the most efcient ways of producing sorted rows. When it is necessary that the report itself order the rows, 4GL uses two-pass report logic, as discussed in One-Pass and Two-Pass Reports on page 10-13.
Sort Keys
The ORDER BY statement can specify the sort keys of the report. Here is the ORDER BY specication in minStockRep(). The EXTERNAL keyword species that rows should be sorted, and that they are produced by the report driver in sorted order, rather than sorted by minStockRep().
ORDER EXTERNAL BY manName,stNum
10-12
The priority of the sort keys decreases from rst to last; that is, the rst one named is the major sort key. In the example, rows are sorted on manName. Within groups that contain matching manName values, rows are sorted on the value of stNum. The sort keys are used to dene groups of rows. You can use the BEFORE GROUP and AFTER GROUP sections to take special actions on these groups.
One-pass. Rows are processed as they are produced. Each time a row is produced by an OUTPUT TO REPORT statement, it is processed and the resulting output is written to the report destination. Two-pass. Rows are collected, saved, sorted, and then processed. As rows are produced, they are saved in a temporary table in the current database. When FINISH REPORT is executed, all the saved rows are retrieved in sorted order and processed.
4GL chooses between these methods based on two things: how the report
rows are ordered and how the report uses aggregate functions.
When the report driver executes OUTPUT TO REPORT, the row value is saved in a temporary table, and the aggregate function values are accumulated in memory. When the report driver executes FINISH REPORT to indicate that no more rows will be produced, 4GL retrieves all the rows from the temporary table in their proper sequence and sends them to the report for formatting.
The values of the aggregate functions are now available while the rows are processed because they have been pre-computed.
10-14
A two-pass report builds a temporary table in the database that is current at the time START REPORT is executed. The same database must be open when OUTPUT and FINISH statements are executed. This places a restriction on the report driver: it cannot change databases (that is, execute the DATABASE statement or a CONNECT statement embedded in an ESQL/C function) during a two-pass report. An error also occurs if the report denition requires two-pass logic but no database is open when the report attempts to read or write a temporary table. Even if your report obtains all of its rows from some source other than a database, two-pass logic requires a database for the temporary tables. You must use caution, however, when writing code that refers to global variables or that interacts with the user. In a two-pass report, the formatting code is not called until all rows have been produced and FINISH REPORT has been executed. Global variables might not have the same values, and the screen might not display the same data as when the rows were produced.
Prints totals and other summary information following a group of rows with similar contents Formats and displays detail lines; accumulates totals and calculated values for use by AFTER GROUP blocks Displays nal totals and aggregate values over all rows (2 of 2)
4GL executes these control blocks automatically at appropriate times as rows are processed. For example, 4GL calls the PAGE TRAILER code block when it is time to print the page trailer. When that block completes, 4GL prints the blank lines corresponding to the BOTTOM MARGIN and prints the page-eject
string, if any. If additional information is written to the output from the report, 4GL prints the TOP MARGIN blank lines and calls the PAGE HEADER block.
You can, however, call functions that use these statements to interact with the user. You can even start other reports and send output to them.
10-16
Formatting Reports
Formatting Reports
Usually a block contains code to test and set the values of local variables, and code to format and print the input records (whose values are stored in the local variables corresponding to the REPORT statement argument list). The following report execution statements are available to display data.
Statement SKIP NEED PRINT FILE PRINT PAUSE Usage Inserts blank lines Forces a set of lines to appear on the same page Embeds the contents of a le in the output Writes lines of output Waits for the user to press RETURN, but only if the output is going to the screen; otherwise, it is not an option
It is with PRINT that you send report data to the output destination. Like the DISPLAY statement, PRINT accepts a list of values to display. Within a PRINT statement, you can use various features of 4GL to format the output, including the following operators.
Keyword ASCII CLIPPED COLUMN PAGENO SPACES USING WORDWRAP Usage Prints specied character values Eliminates trailing spaces from CHAR or NCHAR values Positions the data in the specied column Returns the current page number on report output Prints a specied number of spaces Formats dates, numbers, and currency amounts Displays long character strings in a multiple-segment eld
It prints a xed heading and a page number, and keeps count of the pages. A total of three lines is written, one line of heading and two blank lines. These lines are in addition to the TOP MARGIN lines specied in the OUTPUT section. If a FIRST PAGE HEADER block is present, then the PAGE HEADER block does not take control until the second page of output is started. The minStockRep() report contains this page trailer code:
PAGE TRAILER SKIP 2 LINES LET misc = 65 LENGTH(thisMan) PRINT COLUMN misc,thisMan LET showManName = TRUE
The report prints the manufacturer name from the last-processed group of rows, right-justied, on the last line of the page. The person reading the report can nd a manufacturer quickly by scanning the bottom-right corner of each page. The code also sets a ag that tells the ON EVERY ROW block to display the manufacturer name in the next detail line (because that will be the rst detail line of the next page). The FIRST PAGE HEADER section is similar to the PAGE HEADER except that 4GL calls it only once, before any other block. You can use it to display a cover or a special heading on the rst page. In a two-pass report, you could put code in this section to notify the user that report output is nally beginning.
10-18
The leading spaces are produced by the LEFT MARGIN statement in the OUTPUT section. This code suppresses the manufacturer name except in the rst row of a group or the rst row on a new page.
For the use of COUNT(*) and other aggregate functions, see Using Aggregate Functions on page 10-21.
initialize counts, totals, and other values calculated group-by-group. print group headings, use the NEED STATEMENT to ensure sufcient space on the page, or force a skip to a new page for the group. set ags and local variables used in the ON EVERY ROW block.
The BEFORE GROUP statement used in minStockRep() from Figure 10-1 on page 10-5 follows:
BEFORE GROUP OF manName LET thisMan = manName LET showManName = TRUE
The rst statement saves the manufacturer name from the rst row of the new group so it can be used in the page trailer, as described earlier. The second statement sets a ag that tells the ON EVERY ROW block to display the manufacturer name in the next detail line because that will be the rst detail line of this group. An AFTER GROUP block is called when the last row of its group has been processed by the ON EVERY ROW block. In it, you can put statements that calculate and print subtotals, summaries, and counts for the group.
Nested Groups
Each of the sort keys that you list in the ORDER section denes a group. In the report example there are two keys and therefore two groups:
ORDER EXTERNAL BY manName,stNum
10-20
Default Reports
These groups are nested in the sense that the rows in a major group can contain multiple groups of the minor group. In general, the BEFORE and AFTER blocks for minor groups will be called more times than those for major groups. The group for the last sort key you specify will change the most often. Only the ON EVERY ROW block will be executed more frequently.
Default Reports
The FORMAT section is required in every report denition, but you are not required to specify any control blocks. If it is useful for the report output to be simply a listing of every input record that was passed by the report driver, then you can specify EVERY ROW as the only FORMAT section specication. No other control blocks are valid when you specify EVERY ROW. Reports that use this simplied format for output are called default reports, and are seldom used in production code.
In the BEFORE GROUP block, initialize variables for the sum and the count to zero. In the ON EVERY ROW block, increment the count variable and add the current rows value to the sum variable. In the AFTER GROUP block, calculate the average and display it.
4GL contains built-in aggregate-value functions for most common needs. You
can, however, write your own statistical functions to calculate other values, or to avoid the need to do two-pass reporting, or both. For example, if you want to keep running totals or page totals, these must be hard-coded.
Aggregate Calculations
For sums, averages (means), and extremes, 4GL supplies these functions.
Function SUM(expression) AVG(expression) MIN(expression) MAX(expression) Usage Over Many Rows Accumulates a sum Calculates an average Finds a minimal value Finds a maximal value
For MIN( ) and MAX( ), the expression can be any 4GL expression. For SUM( ) and AVG( ), the expression must be a number or INTERVAL expression. Typically, the argument of an aggregate function is one of the arguments to the REPORT, but it can also be a literal value, a local variable, and even a function call. When using function calls or global variables, keep in mind that rows might all be processed at FINISH REPORT time. Also keep in mind that aggregates are accumulated separately from the code that uses them. Therefore, doing a calculation on a local variable and then aggregating it will not produce the answer you expect. Unless the argument is an aggregate function in a report parameter (which is not modied before any attempted aggregation), the results of the aggregate are not readily predictable. These aggregate functions can be qualied with a WHERE clause to select only a subset of rows. The WHERE clause typically applies criteria to the row values themselves, but you can employ any Boolean expression that is valid in an IF statement. For example, the following lines could be added to the LAST ROW block in Figure 10-1 on page 10-5:
PRINT "Lowest item price", MIN(stPrice) PRINT "Average low-cost item" , AVG(stPrice) WHERE stPrice < 100
These lines would display the minimum overall stPrice values, and the average of all stPrice values that were less than $100.
10-22
Aggregate Counts
For counts, 4GL supplies the COUNT(*) and PERCENT(*) functions. The value of COUNT(*) is the number of records processed by the report. You can see it in use in the ON LAST ROW control block in Figure 10-1 on page 10-5.
COUNT(*) can also be qualied with a WHERE clause, however, so as to count only a subset of rows. The following lines could be added to the ON LAST ROW control block of minStockRep():
PRINT "number of boxed items" , COUNT(*) WHERE stUnit = "box"
The PERCENT(*) function returns the value of one count as a percentage of the total number of rows processed:
PRINT "percent of case lots" , PERCENT(*) WHERE stUnit = "case"
This code displays a group count, which is simply a count of rows in that group, and an average. The average is taken over a subset of the rows of the group. When the subset is empty (when no rows have stUnit="each"), the value of the aggregate function is NULL. Otherwise, any null values are disregarded in calculating aggregate values.
The value of GROUP PERCENT(*) WHERE might not be what you expect. It returns the number of rows in the group that met the condition, as a percentage of the total number of rows in the entire report, not as a percentage of the rows in the group. Because it requires the total number of rows, GROUP PERCENT forces a report to use two-pass logic. To calculate a percentage within a group, you can use explicit code such as:
PRINT "Pct each items in group " , ( (100 * GROUP COUNT(*) WHERE stUnit = "each") / (GROUP COUNT(*) ) USING "<<.&&"
10-24
Chapter
11
In This Chapter .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
11-3 11-3 11-5 11-5 11-6 11-6 11-7 11-7 11-9 11-10 11-10 11-10 11-11 11-11 11-12 11-13 11-13 11-13 11-14 11-15 11-16 11-16 11-17 11-17 11-17 11-17 11-18
Specifying a Form . . . . . . . . . The DATABASE Section . . . . . . The SCREEN Section . . . . . . . Specifying Screen Dimensions . . Screen Records and Screen Arrays . Multiple-Segment Fields . . . . The TABLES Section . . . . . . . The ATTRIBUTES Section . . . . . The Field Name . . . . . . . The Field Data Type . . . . . . Fields Related to Database Columns Form Only Fields . . . . . . . Editing Rules . . . . . . . . Default Values . . . . . . . . The INSTRUCTIONS Section . . . . Field Delimiters . . . . . . . Screen Records . . . . . . . Screen Arrays . . . . . . . .
Using Windows and Forms . . . . . . . Opening and Displaying a 4GL Window . Opening Additional 4GL Windows . 4GL Window Names . . . . . . Controlling the Current 4GL Window. Clearing the 4GL Window. . . . . Closing the 4GL Window . . . . . Displaying a Menu . . . . . . . .
Opening and Displaying a Form . . . . . . Form Names and Form References . . . . Displaying the Form . . . . . . . . . Displaying Data in a Form . . . . . . . . Changing Display Attributes . . . . . . Combining a Menu and a Form . . . . . . Displaying a Scrolling Array . . . . . . . Taking Input Through a Form . . . . . . . Help and Comments. . . . . . . . . Keystroke-Level Controls . . . . . . . Field-Level Control . . . . . . . . . Field Order Constrained and Unconstrained Taking Input Through an Array . . . . . . Screen and Keyboard Options . . . . Reserved Screen Lines . . . . . Changing Screen Line Assignments . Getting the Most on the Screen . Runtime Key Assignments . . . . Dedicated Keystrokes . . . . Intercepting Keys with ON KEY. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
11-20 11-20 11-21 11-21 11-22 11-23 11-24 11-27 11-27 11-28 11-28 11-30 11-30 11-32 11-32 11-33 11-34 11-36 11-37 11-39
11-2
In This Chapter
The architecture of the INFORMIX-4GL user interface is described in Chapter 3, The INFORMIX-4GL Language. The concepts behind the statements described in this chapter are covered in The User Interface on page 7-3. This chapter details the way you program the user interface for your 4GL applications. Because screen forms are important to this, the rst topic explains how you specify a form. Then statements you use to open 4GL windows and ll them with forms and menus are discussed. At the end of the chapter, keyboard and screen line customization are discussed.
Specifying a Form
This section describes the contents of a form specication le in detail. The idea of managing screen forms in separate les was introduced in Form Specications and Form Files on page 4-6. An overview of how your programs use forms is given in How Forms Are Used on page 7-13.
11-3
Specifying a Form
4GL forms are traditionally designed in a WYSIWYG (what-you-see-is-whatyou-get) environment using an ASCII text editor. Each ASCII form specication contains several sections as summarized in the following table. Some are mandatory, others are optional. The order of the sections is signicant. Form Section DATABASE SCREEN TABLES Usage Species the database containing the tables and views whose columns are associated with elds in your form Species the arrangement of elds and text that will appear in your form after it is compiled and displayed Species which tables have columns associated with the elds in the form, and can declare aliases for tables that require qualiers Declares a name for each eld, and assigns attributes to it Species non-default delimiters and screen records
ATTRIBUTES INSTRUCTIONS
For more information on form specications and statements, see INFORMIX4GL Reference.
11-4
the data type for that column and will use that as the data type of the form eld. The rst line in the form specication le is a DATABASE specication. It tells the form compiler which database to use when looking for columns.
DATABASE stores7
Some forms use no database at all; that is, they have no elds that correspond to a database column. When this is the case, you can write:
DATABASE formonly
11-5
The square brackets ( [ ] ) delimit elds into which the program can later display data and take input. Text outside brackets is label text. It will be displayed exactly as typed. A eld consists of the spaces between brackets. If you need to make two elds adjacent, you can use a single pipe symbol ( | ) to separate the elds. Each form eld must contain a eld tag, a name used to link the eld in the SCREEN section to its attributes in the ATTRIBUTES section of the form specication. The rst eld in the SCREEN section of the previous example has the eld tag f000. When you use the same eld tag in more than one eld (the tag f009 appears four times in the preceding example), you indicate that the eld is really one part of a larger whole, either a multiple-segment eld or a screen array.
11-6
The process of displaying an array of data is discussed in Taking Input Through an Array on page 11-30.
Multiple-Segment Fields
To display a string that is too long to t on a single line of the form, you can create multiple-segment elds that occupy rectangular areas on successive lines of the form. The SCREEN section must repeat the same eld tag in each segment of the multiple-segment eld, and the ATTRIBUTES section must assign the WORDWRAP attribute to the eld. Your 4GL program treats a multiple-segment eld as a single eld. When it displays text, any string longer than the rst segment is broken at the last tab or blank character before the end of the segment. Thus, word boundaries are respected. The rest of the string is continued in the rst character position of the next segment. This process is repeated until the end of the last segment, or until the last character is displayed, whichever happens rst.
Any tables that contain columns named in the ATTRIBUTES section of the form (described in the next section of this chapter), must be listed in the TABLES section. The forms compiler will look for these tables in the database named in the DATABASE section. You can also assign aliases to table names in the TABLES section. For example, in the TABLES section you can write:
TABLES postings = financial.postings
This gives the short table name postings to the table known in full as nancial.postings. You must use the short name in the ATTRIBUTES section of the form.
11-7
You are using an ANSI-compliant database. In such cases, you must declare table aliaseseven if you are only drawing data from one tableunless the end user of your application is also the owner of every table in the TABLES section. This is because table owners must be specied when using ANSI-compliant databases. You are drawing data from several tables with the identical column names. The alias is necessary because you cannot qualify a form eld name with a table identier or owner name. You are accessing data from tables in remote databases. The alias is necessary because you are restricted in the attributes section to the following format:
table_identifier.column_name
You want a condensed way to refer to a table. The full name of a table can be quite lengthy because it can contain an owner name, a database name, and a site name. Aliases make referencing such tables more convenient and your form specication more readable.
Like the DATABASE section, the TABLES section is used only to get information needed by FORM4GL. It has no effect when the form is used by a program. The data you display in a form can come from any source, including any table in an Informix database.
11-8
11-9
This says that the eld shown in the SCREEN section with a eld tag of f000 is associated with the customer_num column of the orders table. As a result, the name of this eld is customer_num. To display data in this eld, you would write a statement such as:
DISPLAY max_cust_num+1 TO customer_num
In this example, all the elds with tag f009 (there are four in The SCREEN Section on page 11-5) take their name and data type from the quantity column of the items table. The items table must have been listed in the TABLES section of the form; also, a table of that name must exist in the database named in the DATABASE section at the time the form is compiled.
11-10
FORM4GL opens the named database and veries that it contains an items
table with a quantity column. It takes the data type of that column as the data type for the eld. The advantage is that, if the database schema changes the data type of a particular column, you can keep your forms consistent with the new schema simply by recompiling them.
The eld with tag f012 is given the name order_amount. In a program, you display data in the eld by using this name. FORM4GL cannot consult a database to see what the type should be, so you must tell it with a TYPE attribute clause. If you omit type information, the default is a character string equal in size to the number of spaces between brackets in the SCREEN section.
Editing Rules
You can specify editing rules for elds in the ATTRIBUTES section. Some of the rules you can apply to a eld are shown in the following table. (For details on form attributes, see INFORMIX-4GL Reference.)
Attribute DOWNSHIFT UPSHIFT INCLUDE Usage Changes the lettercase as the user types. (An example of the UPSHIFT attribute can be seen in The ATTRIBUTES Section on page 11-9.) Species a list of values permitted on input. (For example, you could limit entry to the letters M or F, or to a certain range of numbers.) (1 of 2)
11-11
Attribute PICTURE
Usage Species an edit pattern or format string, such as (###) ###-#### for a USA telephone number. (The user is allowed to type only letters or digits as the pattern dictates. The punctuation you supply, such as parentheses or hyphens, is lled in automatically as the user types.) Species that user is not allowed to press Accept without having entered some value to the eld. Makes the user enter data in the eld twice, checking that it is identical the second time. (2 of 2)
REQUIRED VERIFY
You can also program specic input-editing rules by writing AFTER FIELD blocks in the INPUT statement.
Default Values
In the ATTRIBUTES section, you can specify a default value for a eld. The value will be lled in automatically when an INPUT operation begins, and the user can replace it. Alternatively, you can DISPLAY data in elds prior to input, and use the displayed data as default values.
11-12
Field Delimiters
Normally when a form is displayed, elds are displayed with the same square brackets that you used in the SCREEN section to dene them. In the INSTRUCTIONS section, you can specify different delimiters. Most often this feature is used to change the delimiters to spaces, thus causing the elds to be drawn without any visible markers.
Screen Records
A screen record is a group of elds that you want your program to treat as a unit. A screen record, like a program variable that is a record, is a collection of named members. You can display all the members of a record variable in the matching elds of a screen record with a single DISPLAY statement. You can request input from all the elds of a screen record, and have the input values deposited in the matching members of a program variable, with one INPUT statement.
11-13
Screen Arrays
A screen array is a group of screen records that you want to treat as a scrolling table. The form shown on Figure 11-1 on page 11-4 has a screen array dened this way. Figure 11-2 on page 11-14 shows the relationship between array elds as they appear in the SCREEN section, the ATTRIBUTES section, and the INSTRUCTIONS section of a form.
Figure 11-2 Array Fields in SCREEN, ATTRIBUTES, and INSTRUCTIONS Sections of a Form
SCREEN { Customer Number:[f000 ] Company Name:[f001 ] Order No:[f002 ] Order Date:[f003 ] PO Number:[f004 ] ---------------------------------------------------------------------------Item No. Stock No Manuf Description Quantity Price Total [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ] [f005 ] [f006 ] [f07] [f008 ] [f009 ] [f010 ] [f011 ]
= = = = = = =
items.item_num, NOENTRY; items.stock_num; items.manu_code, UPSHIFT; stock.description, NOENTRY; items.quantity; stock.unit_price, NOENTRY; items.total_price, NOENTRY;
Field names are used to group elds into records and arrays.
INSTRUCTIONS SCREEN RECORD sa_items[4]( items.item_num, items.stock_num, items.manu_code, stock.description, items.quantity, stock.unit_price, items.total_price)
To use the array, your program must contain an array of records with similar members. It can use the DISPLAY ARRAY statement to display all the records in the array in the rows of the screen array.
11-14 IBM Informix 4GL Concepts and Use
The program is displayed on the 4GL screen. However, you can further control program output by creating additional rectangular areas within the connes of the screen. These can also be considered 4GL windows. The size and contents of 4GL windows within it, are under the control of your program. An application can have many 4GL windows. They can be the same size as or smaller than the 4GL screen. They can overlap. You can bring a particular window to the top, so that it is fully visible, or completely cover a particular window. And 4GL windows can be closed and opened, depending on the requirements of the application.
11-15
You can specify the following things when you open a new 4GL window:
s
Location. With the AT clause, you specify the location of the upperleft corner (1,1) of the new window in relation to the screen. The units are character positions. Size. In the WITH clause, you specify the size of the window in one of two ways: with a specic number of rows and columns, or by specifying a form. If you specify FORM or WINDOW WITH FORM, the screen dimensions of that form establish the size of the new 4GL window (see Specifying Screen Dimensions on page 11-6). Border. In the ATTRIBUTE clause, you can specify a border for the window. The statement in the preceding example opens a bordered window. Color. In the ATTRIBUTE clause, you can also specify a color for all text displayed in the window. You cannot specify a background color, only the foreground, or text, color. Line numbers. You can set the locations of the standard lines for the menu, messages, prompts, and comments. These lines are discussed in detail in Changing Screen Line Assignments on page 11-33.
11-16
Anywhere else in the program (even in another source module), you can write a statement that refers to the errorAlert window. To make a window current, you would enter:
CURRENT WINDOW errorAlert
Displaying a Menu
This means that if you are using a form or menu (and hence using the current window), and you call a subroutine that opens a window, uses it, and closes it again, the original window will again be current when the subroutine returns. This is the behavior you would expect. However, if you are using a window and call a subroutine that makes another window current and does not close it, the wrong window will be current when the subroutine returns, and an error might follow.
Displaying a Menu
The key concepts of menus are included in How Menus Are Used on page 7-10. That topic also includes an example of the code you use to create a menu. The details of the MENU statement are in INFORMIX-4GL Reference.
11-18
Displaying a Menu
When you execute the MENU statement, a ring menu is displayed on the assigned Menu line of the current window. Normally, you will display a menu across the top line of a window, usually above the display of a form. Other ways to use menus are as follows:
FUNCTION alertMenu(msg , op1 , op2 , op3) DEFINE windowWidth, indent SMALLINT , ret , msg , op1 , op2 , op3 CHAR(20) LET windowWidth = 40 LET indent = (windowWidth-LENGTH(msg))/2 OPEN WINDOW alert2 AT 10,20 WITH 5 ROWS, windowWidth COLUMNS ATTRIBUTE (BORDER, MENU LINE LAST) DISPLAY msg CLIPPED AT 3,1 MENU "Respond" COMMAND op1 LET ret = op1EXIT MENU COMMAND op2 LET ret = op2EXIT MENU COMMAND op3 LET ret = op3 EXIT MENU END MENU CLOSE WINDOW alert2 RETURN ret END FUNCTION
The alertmenu() function is given a short message and three choices, as the example shows.The choices would normally be keywords such as OK, NO, CANCEL, or SAVE. The function opens a small 4GL window. In the window, it displays the message line below a menu composed of the three choices. The choices in the menu are not constants as is usually the case, but variables, specically, the function arguments. An example of how the function could be called follows:
MAIN DEFINE ret CHAR(20) CALL alertMenu("alert message here" , "FIRST" , "SECOND" , "THIRD") RETURNING ret END MAIN
11-19
The function would display a window that looks like Figure 11-4.
RESPOND FIRST SECOND THIRD
Whichever menu option the user chooses is returned as the functions result. Note that although the function opens its window with the attribute MENU LINE LAST, the menu begins on the next-to-last line. See Changing Screen Line Assignments on page 11-33.
This statement causes 4GL to search for a compiled form le named forders.frm. The le sufx .frm is supplied automatically and must not be used. 4GL looks rst in the current directory and then in directories named in the DBPATH environment variable.
Anywhere else in the program (even in another source module), you can write a statement that refers to this form.
11-20 IBM Informix 4GL Concepts and Use
The current 4GL window is cleared from the Form line to the bottom. The elds and labels of the form are drawn on the current window, starting at the Form line. The elds are initially empty. The form must t within the current 4GL window, allowing for reserved lines. For more information, see Specifying Screen Dimensions on page 11-6 and Opening Additional 4GL Windows on page 11-16. By default, the Form line is the third line of the 4GL window, but you can change it. For more information, see Changing Screen Line Assignments on page 11-33. You can display a form repeatedly in one window or in different windows. However, you can only display one form per 4GL window.
More often, you display a list of expressions, in the form of variables, in a list of elds:
DISPLAYtheCustNum, theCustName, 0, 0 TO customer_num, company, order_amt, order_total
You can display all the elements of a record in the elds of a screen record with one statement.
11-21
A common technique is to use the names of database columns as the names of both the elds in a form and the members of a record. The following example shows how a record variable is dened to contain one member for each column in a table:
DEFINE custRow RECORD LIKE customer.*
If the form in the current window has a screen record with corresponding elds (see Screen Records on page 11-13), you can display all the members of this record variable in the elds of the screen record with one statement:
DISPLAY custRow.* TO custFields.*
Alternatively, when the current form has elds whose names are the same as the members of the record, you can display all the members this way:
DISPLAY BY NAME custRow.*
The BY NAME clause can be used whenever you want to display program variables in elds that have the same names.
colors when the output device supports them. These display attributes can be assigned to a 4GL window, to an entire form, or to one or more individual elds. The following techniques will help you make the best use of attributes:
s
To set display attributes for the entire 4GL application, use the OPTIONS statement before opening any windows. To set display attributes for all text in one window, use the ATTRIBUTE clause of the OPEN WINDOW statement. To set display attributes for all lines of a form without changing the attributes of other lines of the window, use the ATTRIBUTE clause of the DISPLAY FORM statement. To set specic display attributes for one eld of a form, use the REVERSE or the COLOR clause for that eld in the ATTRIBUTES section of the form specication le. The COLOR clause takes a WHERE keyword, so you can make the color of the eld dependent on its contents or on the contents of other elds. To override the display attributes of specic elds as you display data in them, use the ATTRIBUTE clause of the DISPLAY TO statement.
11-22
The preceding methods of setting visual attributes are the most important. There are others, and the precedence among methods is more complicated than this list shows. For more information on visual attributes, see INFORMIX-4GL Reference.
Set up a database cursor to represent the selected set of rows. Display a form that has elds for the columns of one row. Execute a MENU statement that includes an option such as Next to cause the display of the next row. In the COMMAND block for the Next menu option, you use:
s s
FETCH to get the next row from the cursor. DISPLAY to show the fetched values in the form.
Thus each time the user selects menu option Next, the program displays a new row. By using a SCROLL cursor (which supports backward as well as forward movement through the rows) you can easily provide menu choices for Prior, First, and Last row displays.
11-23
To implement a scrolling display like this, your program must do two things:
s s
Display a form containing a screen array of screen records. Dene an array of records, each record having members that correspond to the elds of the screen records.
11-24
In the example, these two things are accomplished in the manner shown in Figure 11-6.
Figure 11-6 Denitions of a Screen Array and a Record Array
INSTRUCTIONS SCREEN RECORD sa_cat[5] ( catalog_num, stock_num, manu_name, has_pic, has_desc, description) f011 = items.total_price, NOENTRY; DEFINE ga_catrows ARRAY[200] OF RECORD catalog_numLIKE catalog.catalog_num, stock_num LIKE stock.stock_num, manu_nameLIKE manufact.manu_name, has_picCHAR(1), has_descCHAR(1), descriptionCHAR(15) END RECORD
The screen array has 5 records; the array in the program has 200. The members of the records have the same names and appear in the same order.
11-25
The program uses a FOREACH loop to ll the array with rows fetched from the database (refer to Row-by-Row SQL on page 9-5). Once the program array has been loaded with data, the scrolling display can be started with the DISPLAY ARRAY statement. But rst the program must call the built-in function SET_COUNT( ) to tell 4GL how many records in the array have useful data, as illustrated in Figure 11-7. Only these rows will be shown in the display.
Figure 11-7 The SET_COUNT( ) Function and the ARR_CURR( ) Function
SET_COUNT( ) function tells
CALL SET_COUNT(cat_cnt) DISPLAY ARRAY ga_catrows TO sa_cat.* ON KEY (CONTROL-E) EXIT DISPLAY ON KEY (CONTROL-V,F5) CALL show_advert(arr_curr()) ON KEY (CONTROL-T,F6) CALL show_descr(arr_curr()) END DISPLAY
ARR_CURR( ) function returns the index of the array row whose contents are in the current screen row.
During a DISPLAY ARRAY statement, 4GL interprets the keystrokes used for scrolling (up and down arrows and others). It responds to them by scrolling the rows from the array in memory through the lines of the screen array. As shown in the previous example, you can write ON KEY blocks within DISPLAY ARRAY to act on specic keystrokes. In the example, if the user presses either CONTROL-V or F5, the program calls a function named show_advert( ). If you read Example 18 in INFORMIX-4GL by Example, you will see that this function opens a new window to display an expanded view of one column.
11-26
In this example, two eldsstock_num and item_qtyare enabled for input. Fields by these names must, of course, exist in the form displayed into the current window. The program waits while the user types data into the eld and presses the Accept key. (The Accept key is ESCAPE by default, but the actual keyboard assignment can be changed; see Runtime Key Assignments on page 11-36). The data is assigned into the program variables stockNum and quantity and the program proceeds.
INPUT supports the same shortcuts for naming records as DISPLAY does. You can ask for input to all members of a record, from all elds of a screen record, and you can ask for input BY NAME from elds that have the same names as the program variables.
11-27
Keystroke-Level Controls
Some programs require precise control over user actions during input. You can do this, too, by writing one or more ON KEY blocks as part of the INPUT statement. 4GL executes the statements in your ON KEY code block whenever the user presses one of the specied keys during input. A typical use for an ON KEY block is to display special assistance. You can tell your user something like Press CONTROL-P for a list of price codes. In an ON KEY block for the CONTROL-P key, you can open a 4GL window and display in it the promised list. After getting the necessary information, your user can nish entering data and terminate the INPUT statement by pressing the Accept or Cancel key.
Field-Level Control
Sometimes you want to make a form even more responsive to the user, or you might require more detailed control over the users actions:
s
To make a form seem lively and intelligent, you want to cause a visible response to the users last action, if possible anticipating the users likely next action. To catch errors early, saving the user time, you want to verify each value as soon as it is entered, with respect to values in other elds.
To achieve this level of control, write BEFORE FIELD and AFTER FIELD blocks of code as part of the INPUT statement. These are groups of 4GL statements that are called automatically as the user moves the cursor through the elds on the form.
11-28
You could get the same effect by writing the message as a COMMENT attribute for this eld in the form specication. But if you did that, the message would be displayed whenever the form is used. In this case, the popup list of customers is a service offered only within this particular INPUT statement. The same form might be used in other contexts where you do not mean to do anything special for an F5 key. A typical use of BEFORE FIELD is to prepare likely default values. As the cursor enters a shipping-charge eld, the program calculates, stores, and displays an estimated charge. This is done only if no value has previously been entered to the eld.
BEFORE FIELD shipCharge IF shipRec.shipCharge IS NULL THEN LET shipRec.shipCharge = shipEstCalc(shipRec.shipWeight,custRec.state) DISPLAY BY NAME shipRec.shipCharge END IF
Check the value of the eld for validity with respect to other form elds and with respect to the database. Display values in other elds as a result of the value just entered into this one.
The NEXT FIELD statement sends the cursor to the specied eld (in this case, back to the eld it had just left). It terminates execution of the AFTER FIELD block and starts execution of the BEFORE FIELD block of the destination eld. The block from which the preceding example is taken (Example 15 in INFORMIX-4GL by Example) does more. When a customer number is entered, it performs the following tasks:
Using the Screen and Keyboard 11-29
s s
Uses SELECT to read that customers row from a database table If no row exists, displays the fact and uses NEXT FIELD to repeat the input Initializes other elds of the form with data from the database row
You design a form containing a screen array of screen records. You dene a program array of records. The members of each record match the elds of the screen record.
11-30
3.
If the user can alter existing data, you pre-load data into the program array and use the built-in SET_COUNT() function to specify how many array items contain data. You execute an INPUT ARRAY statement, naming the program array as a receiving variable and the screen array as its corresponding eld.
4.
The same INPUT statement can also name ordinary program variables corresponding to ordinary form elds. The user directs the cursor through the elds as usual. When the cursor enters the screen array on the form, 4GL handles the scrolling of the array, allowing the user to edit and change the contents of the elds by using arrow keys to navigate through the cells of the screen array. You can control and monitor these changes with BEFORE and AFTER FIELD blocks as usual. The built-in ARR_CURR() function is available to tell you which array element is being changed. Besides the NEXT FIELD statement, you can execute the NEXT ROW statement to reposition the cursor to a different row.
4GL also supports an Insert key to open a new, empty row in the array, and a
Delete key to delete a row. You can monitor and control these actions with
BEFORE and AFTER INSERT and DELETE blocks. You can redene the Insert or Delete key using the OPTIONS statement.
11-31
Prompt line. The PROMPT statement prompts the user for input to one or more variables. It displays its prompt string on the specied line and the user types a response on the same line. Menu line. The MENU statement displays a ring (horizontal) menu on this line. The user moves the cursor from choice to choice with the TAB and arrow keys.
MENU and PROMPT can share the same line. Each clears the line and rewrites it as necessary.
11-32
Menu Help line. In the MENU statement, you can also write an explanatory phrase for each menu choice. As the user moves the cursor across menu options, the explanations are displayed on this line. The Menu line is always the line immediately below the menu. Message line. The MESSAGE statement is used to show a short message to the user. The Message line can share the line after the Menu line because the MENU statement rewrites its help line when it starts or resumes. The Message line could also be the same as the Comment line. Form line. The top line of a screen form is displayed on this line by the DISPLAY FORM statement. Comment line. When designing a screen form, you can specify an explanatory comment for any eld. As the user moves the cursor through the elds of the form, these explanations are displayed on the Comment line. Error line. The ERROR statement is used for providing the user with a message serious enough to warrant an audible warning. The Error line and the Comment line should not be assigned the same position. Otherwise, if an error message appears in a eld that has the COMMENTS attribute, comment text overwrites the error message.
The Error line is special in another way. All other reserved lines represent positions within the current 4GL window where text can be written, replacing previous text on that line. The Error line species a position where a one-line error message appears on the physical screen, without regard to the position or size of the current 4GL window.
With the OPTIONS statement, you can change the assignment of one or more lines for all windows. With the ATTRIBUTES clause of OPEN WINDOW, you can assign the logical lines for one window when you create it.
Using the Screen and Keyboard 11-33
There are, however, some line assignments you cannot change. For example, the Menu Help line always follows the Menu line, so the Menu line can never be last. If you specify MENU LINE LAST, 4GL treats it as if you had assigned LAST-1.
11-34
In this table, the word Yes means that the two intersecting types of screen lines can share the same screen row because the lines appear at different times, and each clears the row before using it. Potential problems are discussed in the following notes:
1.
The screen form is not automatically redrawn after it has been overwritten. If you display a prompt, menu, message, or comment in a line used by a form, the only way to restore the complete form is to redisplay the form and then redisplay the data in its elds. If you make the Message line the same as Menu or Menu Help, you must be careful when using the MESSAGE statement from within MENU. You must program a delay before resuming the menu operation. Otherwise the menu will replace the message text too quickly for the user to read it. If messages and menus are used at different times, there is no difculty having them using the same row. When you use both a menu and a form, you should probably not make the Comment and Menu lines the same. You can make the Comment line the same as the Menu Help line. Then both types of explanations appear on the same screen row.
2.
3.
The error text is always displayed on the designated Error line of the physical screen. When you design a 4GL window as described in How 4GL Windows Are Used on page 7-25, you do not need to allow for an Error line.
11-35
Interrupt
Insert
Delete
F2
Next
F3
Previous
F4
Help
CONTROL-W
You can change the assignment of the logical keys to physical keystrokes with the OPTIONS statement. The two common problems that require you to change them are:
11-36
The ESCAPE key is often a prex value for function keys. The operating system might wait a fraction of a second after ESCAPE is pressed, in order to make sure it is not the start of an escape sequence, before passing it to the program. On some systems, this can cause a delay in the response of your program to the Accept key.
The numbering of function keys is not consistent from one version of UNIX to another. Some terminals might have different physical keys than those dened in the termcap le.
Dedicated Keystrokes
The following physical keys have dedicated uses during some 4GL statements.
Use in INPUT, INPUT ARRAY, and CONSTRUCT Switches between overtype and insert modes Deletes from the cursor to the end of the eld During text entry, moves the cursor left one position (nondestructive backspace) Moves the cursor to the next eld, except in a WORDWRAP eld, where it inserts a tab or skips to a tab, depending on mode Moves the cursor to the next eld, except in a WORDWRAP eld, where it inserts a new line or moves down one line, depending on mode
Key Name
CONTROL-A*
Use in MENU None None Moves highlight to next option to the left None
CONTROL-D*
CONTROL-H*
(backspace)
CONTROL-I* or TAB*
CONTROL-J
(Linefeed)
11-37
Key Name
CONTROL-L*
Use in INPUT, INPUT ARRAY, and CONSTRUCT During text entry, moves the cursor right one position Completes entry of the current eld; cursor moves to next eld (if any; otherwise, same as Accept) Same as CONTROL-J Causes the screen to be redrawn
Use in MENU Moves the highlight to the next option to the right Accepts the option that is currently highlighted None Causes the screen to be redrawn
CONTROL-M or RETURN
CONTROL-N CONTROL-R*
Deletes the character under the cursor None Same as BACKSPACE Same as CONTROL-L Usually moves to the previous eld, except in a WORDWRAP eld, where it moves up one line in the eld, and in an INPUT ARRAY, it moves to the corresponding eld in the previous row Usually moves to the next eld, except in a WORDWRAP eld, where it moves down one line in the eld, and in an INPUT ARRAY, it moves to the corresponding eld in the next row Same as the logical Insert key Same as the logical Delete key Same as the logical Next key Same as the logical Previous key Same as BACKSPACE Same as CONTROL-L Moves the highlight to the next option to the left
DOWN ARROW
11-38
11-39
11-40
Chapter
Handling Exceptions
12
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 12-4 12-4 12-5 12-6 12-6
In This Chapter .
. . . . . .
. . . . . .
Exceptions . . . . . . . . . . . . . Runtime Errors . . . . . . . . . . SQL End of Data . . . . . . . . . SQL Warnings . . . . . . . . . . Asynchronous Signals: Interrupt and Quit
Using the DEFER Statement. . . . . . . . . . . Interrupt with Interactive Statements . . . . . . INTERRUPT with INPUT and CONSTRUCT . . Deferred INTERRUPT with the MENU Statement Using the WHENEVER Mechanism . What WHENEVER Does . . . Actions of WHENEVER . . . . Errors Handled by WHENEVER . Using WHENEVER in a Program Notifying the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. 12-7 . 12-8 . 12-8 . 12-10 . 12-10 . 12-11 . 12-11 . 12-12 . 12-13 . 12-15 . 12-15
12-2
In This Chapter
Exceptions, usually referred to as errors, are unusual occurrences that you might sometimes wish would never happen to your program. Of course, you know they will happen, and you know you need to write your programs so they behave in reasonable ways when errors and other unplanned for events occur. This chapter reviews the categories of exceptional conditions and how 4GL reacts to them when you do not specify what to do. It then details the mechanisms that 4GL gives you for handling them, as follows:
s
The DEFER statement allows you to convert asynchronous signals into synchronous ags that you can poll. The WHENEVER statement lets you change how 4GL responds to specic error conditions.
The following table summarizes the types of exceptions 4GL can recognize and the ags it can test and set in each case.
Error Type Interrupt signal Quit signal Runtime error, expression error, le error, display error, initialization error SQL error SQL warnings SQL end of data error Flag Checked int_ag quit_ag status
status, SQLCA.SQLCODE
SQLCA.SQLAWARN
status=NOTFOUND
or SQLCA.SQLCODE=NOTFOUND
Exceptions
Exceptions
You can write your 4GL program to recognize and respond to the following types of exceptions:
s s s s
Asynchronous signals, meaning signals from the keyboard or elsewhere, occurring at an unplanned for time
Runtime Errors
Runtime, or execution, errors are serious conditions that are detected by the database server or by 4GL at runtime. Although they are divided into several categories, these errors all have one thing in common: if they occur and the program does not explicitly handle them, the program will terminate immediately. To handle these types of errors, you must use the WHENEVER ERROR statement. For more information, see Using the WHENEVER Mechanism on page 12-10. A negative error code number is associated with every type of execution error. For every number, there is an error message. Error numbers and their associated messages are available on-line. In addition, your 4GL application can call a function, ERR_GET( ), to retrieve the message text for any error number. For more information, see INFORMIX-4GL Reference. Execution errors are divided into ve groups based on the kinds of program actions that can cause them:
s
Expression errors. These arise when 4GL attempts to evaluate an expression that violates the rules of the language. For example, error -1348 occurs when an attempt is made to divide by zero. Error -1350 occurs when 4GL cannot convert between data types. File errors. These arise when 4GL tries to access a le and the operating system returns an error code. For example, error -1324 means that a report output le could not be written.
12-4
SQL errors. These arise when the database server detects an error in an SQL statement. For example, error -201 results from a syntax error in an SQL statement, while error -346 shows that an attempt to
Screen errors. These arise when something goes wrong with a screen interaction. For example, error -1135 means that the row or column in a DISPLAY AT statement falls outside the current 4GL window. Initialization and validation errors. The INITIALIZE and VALIDATE statements are used to initialize or test program variables against a special database table, syscolval. Errors in the operation of these statements are in a separate category; you handle them apart from other errors.
FETCH
FOREACH SELECT
If the value of SQLCA.SQLCODE is greater than zero, there was no row available. Alternatively, your program can treat an end-of-data condition as an error condition so that when it occurs, your program is diverted to code that handles it. To change the default behavior of 4GL, use the WHENEVER NOT FOUND statement. For more information, see Using the WHENEVER Mechanism on page 12-10.
SQL Warnings
SQL Warnings
Some SQL statements can detect conditions that are not errors, but that can provide important information for your program. These conditions are called warnings and are signalled by setting warning ags in the SQLAWARN member of the SQLCA record. As with end of data, you have a choice in how to treat an SQL warning. By default, 4GL sets SQLCA.SQLAWARN and continues execution of the program. You can insert code after any SQL statement to test the SQLAWARN ag values. To change this default behavior, you can use the WHENEVER WARNING statement, described in Using the WHENEVER Mechanism on page 12-10.
12-6
For example, if you create a FOREACH or WHILE routine without a termination point, you cannot stop the routine without killing the process or rebooting the system. However, if interrupts are not trapped, pressing the Interrupt key (CONTROL-C by default) ends the program immediately. Later, once you have perfected the routine, any external signals can be deferred using the 4GL DEFER statement (described in the next section) and more polite mechanisms put in place to handle unanticipated user requests.
captures an Interrupt or Quit signal. sets the appropriate 4GL ag, allowing you to deal with the external signal programmatically.
The DEFER mechanism allows you to choose how to handle Interrupt or Quit signals. To enable this mechanism, you include the DEFER statement once, at the beginning of your 4GL program. This statement has two forms: DEFER INTERRUP and DEFER QUIT. With the DEFER INTERRUPT statement, the Interrupt key combination is trapped and TRUE is assigned to the built-in global variable int_ag. After it has been deferred, the Interrupt signal has no effect on most program statements, but it does terminate some interactive statements, as described in the next section. With the DEFER QUIT statement, the Quit key combination, CONTROL-\, is caught, and TRUE is assigned to the built-in global variable quit_ag. Some systems can deliver other external signals, but these are not handled by the DEFER mechanism of 4GL. There are also synchronous signals that represent runtime errors that are trapped by the operating system, usually for major program faults such as indexing past the end of an array. The DEFER statement can only appear in the MAIN statement. Its effect cannot later be undone. After its signal has been deferred, the physical Interrupt key or Quit key can be assigned to a logical key in an ON KEY clause.
Handling Exceptions 12-7
CONSTRUCT
PROMPT
12-8
LET cancelled = TRUE EXIT INPUT ...other clauses of INPUT... AFTER INPUT -- tests to see if an Interrupt has been received (is TRUE) IF int_flag THEN LET cancelled = TRUE ELSE ...post-process based on Accept key... END IF END INPUT IF cancelled THEN MESSAGE "Input cancelled at your request!" END IF
The code sample establishes three ways for the user to terminate the INPUT operation:
s
Accept key. Normal completion of INPUT is signaled by pressing the Accept key. The statements in the AFTER INPUT block are used to perform any nal validation of the entered data. Interrupt key. When the user generates an Interrupt signal, 4GL ends the INPUT operation, but in doing so it executes the AFTER INPUT block. The program checks the setting of int_ag. If TRUE, the INPUT operation is terminated. It exits the AFTER INPUT block early if it was entered due to an Interrupt signal.
CONTROL-E. The program establishes a logical Cancel key based on using an unassigned control key trapped by an ON KEY block.
The example code converts both cancellations, the built-in cancellation due to the Interrupt signal and the programmed signal based on CONTROL-E, into a TRUE value in a variable named cancelled. This is value cleared before the INPUT operation begins, and is tested afterward. When INTERRUPT is used in an ON KEY clause, INTERRUPT no longer terminates the operation, so the preceding example could be written in this way:
-- DEFER INTERRUPT run earlier LET cancelled = FALSE INPUT ... BEFORE INPUT MESSAGE "Use ctrl-E to cancel entry" ON KEY (control-E, Interrupt) logical cancel LET cancelled = TRUE
EXIT INPUT ...other clauses of INPUT... END INPUT IF cancelled THEN MESSAGE "Input cancelled at your request!" END IF
This explicit handling of INTERRUPT with an ON KEY statement prevents execution of AFTER INPUT following INTERRUPT. Logic of either type can also be used with CONSTRUCT.
Runtime errors from the database server or from the 4GL program Warnings from the database server or from the 4GL program
SQL end-of-data conditions
The WHENEVER directive is based on the ANSI/ISO standard for embedded SQL, which denes the keywords and basic operation of that statement. Informix has extended the standard syntax of WHENEVER to support additional keywords, conditions, and actions. Like the declarations of variables or DEFER, the WHENEVER directive is not an executable statement.
12-10
Here condition species some exceptional condition, and action species an action for the 4GL program to take when that condition is detected. One possible action is CONTINUE, which instructs 4GL to take no action. After you issue the WHENEVER directive, you can write your program logic as if the specied condition would never happen. For details on how to use WHENEVER, see INFORMIX-4GL Reference.
Actions of WHENEVER
You can specify the following four possible types of actions using variations of the WHENEVER statement:
s
WHENEVER CONTINUE species that if the exceptional condition happens, it is to be ignored. 4GL sets the status variable and attempts to continue executing the program. WHENEVER STOP species that if the exceptional condition
happens, the program terminates. Any uncommitted database transaction is rolled back and an error message is displayed.
s
condition occurs, then the specied function should be called. The function that you specify cannot have arguments.
s
condition occurs, then control of program execution should jump to a specied label within the same program block Including WHENEVER in a source module changes the way that the compiler produces code, starting with that line, and continuing to the end of the module, or to the next WHENEVER directive for the same condition. If you specify an action other than to do nothing (CONTINUE), then the compiler automatically generates code to test for the exceptional condition after each statement that might cause it, and to carry out the specied action if the specied exceptional condition occurs.
By default, 4GL executes a program that has no WHENEVER directives as if it contained the following WHENEVER directives:
WHENEVER NOT FOUND CONTINUE WHENEVER WARNING CONTINUE WHENEVER ANY ERROR CONTINUE
That is, all exceptions are ignored. Some errors, however, called fatal errors, cannot be trapped by WHENEVER; these errors are listed in INFORMIX-4GL Reference. A fatal error causes the program to terminate, regardless of what any WHENEVER directive species.
12-12
The WHENEVER directives are placed around the statements of interest. Here WHENEVER SQLERROR CONTINUE causes errors in the PREPARE or EXECUTE statements to be ignored. The only effect of an error will be to set a negative code in the SQL communications area and the status variable. The WHENEVER SQLERROR STOP directive terminates the program if an error occurs. If it were omitted, then the effect of the rst WHENEVER directive would continue to the end of the source module.
Ignore errors. Call a function. Jump to a label. Display a PROMPT statement to get more guidance from your user.
The WHENEVER ERROR directive is a condensed way of putting an IF statement after every SQL statement in order to establish what action should be taken when errors occur.
12-14
When you execute the ERROR statement to display a message that you composed When you execute the ERR_PRINT( ) function to display a message based on a 4GL error number When you execute the ERR_QUIT( ) function to display a message and terminate the program
In fact, the Error line is a one-line 4GL window that is automatically opened on the screen (see Opening and Displaying a 4GL Window on page 11-16). After an ERROR statement or call to ERR_PRINT( ), this window remains open and visible until a keystroke event occurs. Then it is closed, revealing any form or menu that might be hidden beneath it.
Call the built-in STARTLOG(" lename" ) function from the MAIN statement, where lename species the le (and can also include a pathname) in which error messages will be logged. After an error is detected, use the following assignment statement:
LET variable = ERR_GET(status)
2.
where variable is a variable declared as data type CHAR and is of sufcient length to hold the text of the error message.
3.
The last two steps are not needed if you are satised with the default error records that are logged automatically after STARTLOG( ) has been invoked. (If you do include the last two steps, then the rst step is not required.)
Handling Exceptions 12-15
In step 2, if lename matches no existing le specication, 4GL creates that le. If lename already exists, 4GL opens that le and positions the le pointer so that any subsequent error or warning message will be appended to this le. For your 4GL program to be portable, you should store lename in a variable, rather than calling STARTLOG( ) with a literal string as its argument. For details of the ERR_GET( ), ERRORLOG( ), and STARTLOG( ) functions and for the default format of STARTLOG( ) error records, see INFORMIX-4GL Reference.
12-16
Appendix
Notices
IBM may not offer the products, services, or features discussed in this document in all countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the users responsibility to evaluate and verify the operation of any non-IBM product, program, or service. IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 U.S.A. For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property Department in your country or send inquiries, in writing, to: IBM World Trade Asia Corporation Licensing 2-31 Roppongi 3-chome, Minato-ku Tokyo 106-0032, Japan
The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law:
INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or
implied warranties in certain transactions, therefore, this statement may not apply to you. This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice. Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk. IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you. Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact: IBM Corporation J74/G4 555 Bailey Ave P.O. Box 49023 San Jose, CA 95161-9023 U.S.A. Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee. The licensed program described in this information and all licensed material available for it are provided by IBM under terms of the IBM Customer Agreement, IBM International Program License Agreement, or any equivalent agreement between us.
A-2 IBM Informix 4GL Concepts and Use
Trademarks
Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot conrm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are ctitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. If you are viewing this information softcopy, the photographs and color illustrations may not appear.
Trademarks
AIX; DB2; DB2 Universal Database; Distributed Relational Database Architecture; NUMA-Q; OS/2, OS/390, and OS/400; IBM Informix; C-ISAM; Foundation.2000TM; IBM Informix 4GL; IBM Informix DataBlade Module; Client SDKTM; CloudscapeTM; CloudsyncTM; IBM Informix Connect; IBM Informix Driver for JDBC; Dynamic ConnectTM; IBM Informix Dynamic Scalable ArchitectureTM (DSA); IBM Informix Dynamic ServerTM; IBM Informix Enterprise Gateway Manager (Enterprise Gateway Manager); IBM Informix Extended Parallel ServerTM; i.Financial ServicesTM; J/FoundationTM; MaxConnectTM; Object TranslatorTM; Red Brick Decision ServerTM; IBM Informix SE; IBM Informix SQL; InformiXMLTM; RedBack; SystemBuilderTM; U2TM; UniData; UniVerse; wintegrate are trademarks or registered trademarks of International Business Machines Corporation. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Windows, Windows NT, and Excel are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
Notices
A-3
Trademarks
UNIX is a registered trademark in the United States and other countries licensed exclusively through X/Open Company Limited. Other company, product, and service names used in this publication may be trademarks or service marks of others.
B C
N O
V W
Index
Index
A
Accept key terminating INPUT operation 12-9 using 11-27 AFTER FIELD block 11-12, 11-29 AFTER GROUP block 10-23 AFTER GROUP control block 10-20 Aggregate functions 10-21 values 10-14 Alias of a table in a form 11-7 in the TABLES section 11-7 ANSI-compliant database table aliases in a form 11-8 update cursors 9-8 Application files 4-3 interactive database 1-4, 4-3 multi-user 2-3 Arithmetic operators 8-5 ARRAY data type 5-7 declaration 8-12 Array, screen 11-6 Arrow keys 7-20 Assign record 8-38 value 8-38 Asynchronous signals 12-6 ATTRIBUTES section of form specification commenting 11-27 multiple-table forms 11-7 using 11-9 to 11-12
B
BEFORE FIELD block typical use of 11-29 using 11-28 BEFORE GROUP control block 10-20 Binary Large Objects (blobs) 5-3 Blobs 8-10 Boldface type Intro-10 Boolean expressions 8-25 BY NAME clause, DISPLAY statement 11-22
C
C Compiler 1-5, 4-11, 4-14 C language 3-3, 3-4 C source code 1-5 c4gl command 4-11, 4-14 CALL statement 5-11, 8-28, 8-35, 8-38, 10-6 CASE keyword 8-31 CASE statement 5-11, 8-31 cat command 4-13 Character data types 8-8 to 8-10 Character-based terminal 7-3 Characters letter case 3-5 lowercase 3-5 uppercase 3-5 whitespace 3-4 Chronological data types 8-6 CLEAR WINDOW statement 11-17
CLOSE WINDOW statement 11-17 COBOL 3-3 Column connected to form fields 11-10 Command block 7-12 COMMAND statement 7-11 Comment symbols 5-12 Commenting form fields 11-27 Compatible data types 8-29 Compliance icons Intro-11 Compound 4GL statements 5-10 Compound statements 3-4 CONNECT statement 10-15 CONSTRUCT statement 7-5, 8-28, 9-5 effect of Interrupt signal upon 12-8 using 7-23 Contact information Intro-15 Control blocks, REPORT statement 6-9 CONTROL keys, default assignments 11-37 Control of execution 5-10 Control statements 3-4 Current window 7-9
D
Data data allocation 5-8 data conversion 5-4, 8-28 to 8-30 definition 5-3 to 5-9 records 5-6 structures 5-6, 8-11 to 8-27 Data type ARRAY 5-7 Binary Large Object (blob) 5-3 Binary Large Objects (blobs) 8-10 BYTE 5-3, 8-10 CHAR 5-3 character and string 8-8 to 8-10 chronological 8-6 conversion 5-3, 8-29 conversion errors 8-30 DATE 8-6 to 8-7 DATETIME 8-6 to 8-7 DECIMAL 8-4, 8-5
declaration 5-3 declaring 8-12 to 8-14 FLOAT 8-4 INTEGER 5-3, 8-4 INTERVAL 8-6 to 8-7 MONEY 8-4, 8-5 NCHAR 8-8 NUMERIC 8-4 NVARCHAR 8-8 REAL 8-5 RECORD 5-6 SERIAL 5-3 SMALLFLOAT 8-5 TEXT 5-3, 8-10 using 8-4 to 8-10 using NULL values 5-4 DATABASE section 11-5 specification in a form file 11-5 statement 11-5, 11-11 Database accessing 2-5 administrator (DBA) 4-5 interactive applications 1-4, 4-3 schema 4-5 server 2-5 DBDATE environment variable 8-6 DBPATH environment variable 11-20 Decision tree 5-10 DECLARE statement 9-6 Default argument values 11-12 Default locale Intro-6 DEFER statement 5-14, 12-3, 12-7 DEFINE statement 3-5, 5-6, 5-8, 8-15 to 8-17, 8-34 Delete key 7-20 Delete privilege 7-13 DELETE statement 9-8 Dependencies, software Intro-6 Display errors 12-5 field attributes 11-22 DISPLAY ARRAY statement displaying records in an array 11-14 effect of Interrupt signal upon 12-8 using 11-26, 11-30
DISPLAY FORM statement 11-21 DISPLAY statement 2-5, 6-9, 7-3 to 7-8 DISPLAY TO statement 11-21, 11-22 Displaying forms 7-16 Documentation, on-line manuals Intro-12 Documentation, types of related reading Intro-14 Dynamic 4GL 1-5 Dynamic SQL 6-4
E
END FOR statement 3-4 END MAIN statement 3-4 END REPORT keywords 10-24 END statement 5-10 Environment variables Intro-10 DBDATE 8-6 en_us.8859-1 locale Intro-6 Error conditions 5-12 conversion 8-30 line 12-15 runtime 5-12, 5-14 Error logging 12-15 ERROR statement 7-5, 11-33 ERRORLOG( ) function 12-15 Errors display 12-5 screen display 12-5 ERR_GET( ) function 12-15 Escape key 11-27, 11-37 ESQL/C 4-14 Example code 3-6, 3-8 Exceptions defined 5-12 handling, 5-12 to 5-14 types 5-12 EXIT REPORT statement 6-9, 10-24 Expressions Boolean 8-25 character 8-26 described 8-22 to 8-27 errors 12-4 numeric 8-24
F
FALSE 8-33 Feature icons Intro-11 FETCH statement 6-4, 9-6, 11-23 fglpc command 4-11 Field data type 11-10 delimiter 11-6, 11-13 multiple segment 11-6, 11-7 names in screen forms 11-9, 11-10 responding to entry or exit by user 11-28 tag, using 11-6 File errors 12-4 File extensions 4-15 .4gi 4-13 .4gl 4-10 .4go 4-13 File types form object 4-3 form source 4-3 globals 4-11 message object 4-3 message source 4-3 program object 4-3 program source 4-3 FINISH REPORT statement 6-7, 10-4 Flat files 2-5 FLOAT value 5-4 FOR statement 3-4, 5-11, 8-32 FOREACH statement 5-10, 6-4, 9-6 to 9-8, 11-26 Form compiler 4-3, 4-7 displaying 7-16, 11-20 field comments 11-27 line 11-21 name, specifying 11-20 object files 4-3 opening 11-20 opening and displaying 11-20 to 11-23 portability 2-7
source files 4-3 specification file 4-3, 4-6 to 4-9, 7-14 using 2-8, 3-8, 4-6 to 4-9, 7-14 to 7-22 Form specification file components 11-4 DATABASE 11-11 display attributes 11-22 FORM4GL utility 7-14 Formatted mode 7-5 to 7-8 Formatting reports 6-8, 10-17 FORMONLY field 11-11 Fourth generation language 3-6 Function calls, using 8-24 Function keys 11-37 FUNCTION statement 4-10, 10-6 Functions 8-34 to 8-37 returning values 8-39
INPUT ARRAY statement 8-28 Input record 6-7 Input records, as a synonym for a row 10-4 INPUT statement 8-28 defined 7-5 effect of Interrupt signal upon 12-8 using 7-20, 11-27 Insert key 7-20 INSTRUCTIONS section of form specification 11-13 to 11-14 Interface, character based 2-6, 2-9 Interrupt key, with AFTER INPUT 12-9 signal 12-7 Interrupt signals 5-13 INTO clause 8-28 ISO 8859-1 code set Intro-6
G
Global variable 5-9 GLOBALS keyword 4-11 GLOBALS statement 5-9, 8-15, 8-16 to 8-18 GOTO statement 5-10 Graphical terminals 7-3 GROUP keyword 10-23
J
Jump statements 5-10
L
LABEL statement 5-10 Language features database access 2-5 database schema 4-5 machine code 4-14 MAIN module 4-10 message file 4-3 nonprocedural programming 3-6 object module 4-15 overview of 4GL 1-3 procedural language 3-3 reports 2-6, 3-7 source code modules 4-3, 4-10 Large data types 5-4 LET statement 5-4 to 5-5, 5-6, 5-11, 8-22, 8-28, 8-38 Letter case 3-5 LIKE keyword 5-6, 8-19 using 8-12 Line mode 7-3 to 7-4 Literal value 8-23 LOAD statement 2-5
H
Header block 10-18 Help key 7-29 Help message, displaying 11-27 Help system, creating for an application 7-28
I
Icons compliance Intro-11 feature Intro-11 Indirect typing 8-12 Informix Dynamic 4GL 1-5 INFORMIX-SQL 1-4 INITIALIZE statement 8-28, 12-5
Index 3
Local variables 5-9 Locale Intro-6 LOCATE statement 8-10 Looping statement 5-10 Lowercase characters, using 3-5
Null values 8-33 NULL values, using 5-4 Numeric data type 8-4
O
Object module concatenating 4-13 machine code 4-11, 4-14 p-code 4-11, 4-13 using 4-11 to 4-15 ON EVERY ROW control block 10-19 ON KEY clause code block 11-28 using 11-39 ON LAST ROW control block 10-19 On-line Help for developers Intro-13 On-line manuals Intro-12 OPEN FORM statement 11-20 OPEN WINDOW statement 11-16 Operating-system pipe 2-5 Operating-system standard files 2-5 OPTIONS statement changing line assignments 11-33 setting window display attributes 11-22 ORDER BY statement 10-12 ORDER EXTERNAL statement 10-12 Organization of a 4GL program 4-10 OUTPUT Section 10-10 OUTPUT TO REPORT statement 6-7, 10-4 Owner name 11-8
M
Machine code 4-11, 4-14 MAIN module 4-10 MAIN statement 3-4, 4-10 Margins, setting report 10-10 Menu options 7-10 using 2-8, 3-8, 7-10 to 7-13 MENU statement 7-8, 7-10 displaying and using 11-18 to 11-20 effect of Interrupt signal upon 12-8 using 11-19 using DEFER INTERRUPT with 12-10 Message compiler 4-3 source files 4-3 Message compiler utility 7-28 MESSAGE statement 7-5, 11-33 mkmessage utility 7-28 Module 3-5 Module variables 5-9, 8-16 Monospace font 10-10 Motif 1-5 Multiple-segment fields 11-7 Multi-user application 2-3, 9-9
runner 4-14 pipe 2-6 PL/1 3-3 Primary Key 9-9 PRINT FILE statement 2-5 PRINT statement 6-9, 10-6, 10-17 Program array, in relation to screen array 7-20 Program flow statements 5-10 Prompt line 11-32 PROMPT statement 3-5, 7-3 to 7-8, 8-28, 12-8 Pseudo-code Intro-6 Pseudo-machine code (p-code) 1-5, 4-11 Punctuation in 4GL 5-10
Q
Query by example description 7-23 using the CONSTRUCT statement 7-23 Quit signals 5-13, 12-7
R
Rapid Development System 1-5, 4-11 Record defined 5-6 variables 7-18 RECORD keyword, defining screen arrays 8-12 Related reading Intro-14 Report code blocks 10-16 to 10-21 creating 10-3 to 10-24 creating and using 6-5 to 6-9 definition 10-3 designing 3-7 driver 6-7 to 6-8, 10-3 format section 10-15 formatting 6-8, 10-17 generating 3-7 headers 10-15 one-pass and two-pass 10-13 operating-system pipe 2-5
N
Named constants 5-9 Named pipe 10-10 NEED statement 10-6 Nested groups 10-20 Nesting statement blocks 5-11, 6-9 Network, interfacing to 2-5 NEXT FIELD keywords, INPUT statement 11-29 Nonprocedural use of SQL 9-4 NULL value 8-27
P
PageDown key 7-20 PageUp key 7-20 Pascal 3-3 Passing records 8-38 PAUSE statement 10-6 p-code object files 4-13
output 2-6 sort keys 10-12 trailers 10-15 user interaction 3-8 using aggregate values 10-14 REPORT definition 6-8 Report prototype 10-8 Report signature 10-8 REPORT statement 2-5, 4-10, 10-6 REPORT TO keywords 10-10 Reserved lines 7-6 RETURN statement 6-9, 10-6 Ring menu 7-10 Row passed to report driver 10-4 production by a report driver 10-5 Runner, using to execute pcode Intro-6 Runtime error 5-12, 5-14 Run-time errors 12-4 to 12-7
S
Scope of reference 5-9 Screen array description 11-6 Screen array, in relation to program array 7-20 Screen form portability 2-7 reserved line positions 11-32 Screen record 11-6 using 7-18 within a screen array 11-6, 11-13 SCREEN section of form specification field delimiters 11-6 using 11-5 Screen, defined 7-9 SCROLL cursor 11-23 Scrolling array 11-24 SELECT statement 6-3, 6-4, 9-5 Sequential files 2-5 Setting report margins 10-10 showhelp( ) function 7-30 Simple data types 5-4, 8-4 SKIP statement 10-6
Software dependencies Intro-6 Sort keys 10-12 Source code module 3-5 Source modules 4-3, 4-10 SQL language communications area 3-6 dynamic SQL 6-4 errors 12-5 nonprocedural use of 9-4 use of a second cursor 9-9 using in 4GL programs 2-9, 3-6, 6-4 using SQL statements in 4GL 9-3 to 9-10 SQLCA record 12-6 Standard file I/O 2-5 START REPORT statement 2-5, 6-7, 10-4, 10-6 STARTLOG( ) function 12-15 Statement blocks empty 5-11 nesting 5-11 Statements compound 3-4 control 3-4 String data types 8-8 to 8-10 Structured data types 5-4 Synchronous signals 12-7 System requirements database Intro-6 software Intro-6
V
VALIDATE statement 12-5 Validation errors 12-5 Value 8-22 to 8-27 Variables aFloat 5-4 aString 5-4 data typing 5-3 DBCENTURY 8-6 global 4-11, 8-17 to 8-21 initializing 8-22 int_flag 5-9 local 8-36 module 8-16 NULL values 5-4 oneInt 5-4 quit_flag 5-9 scope of reference 8-15 status 5-9 using 5-3 to 5-9, 8-11 to 8-27
W
WHENEVER statement 5-14 WHENEVER statement, using 12-3, 12-7, 12-10 to 12-13 WHILE statement 5-10, 5-11, 8-32 Whitespace characters 3-4 Window 4GL 11-16 current 4GL 7-9 defined 2-6, 7-9 opening and displaying 11-15 to 11-18 Windows 95 1-5 Windows NT 1-5 WORDWRAP attribute 11-7 workstations 7-3
T
TABLES section of form specification 11-7 Terminal character-based 2-6 emulation 2-6 TERMINATE REPORT statement 6-7, 10-4 TOP OF PAGE clause 10-10 Trailer block 10-18
U
UNLOAD statement 2-5 UPDATE statement 9-4
X
X11 protocol 1-5
Index 5