=================================
RELEASE NOTES
FOR
INFORMIX 6.00.UE1 PRODUCT RELEASE
DATE: 05/13/94
=================================
TABLE OF CONTENTS
I. OVERVIEW OF RELEASE NOTES
II. PRODUCTS CONTAINED IN THE 6.00 TOOLS RELEASE
III. SPECIAL CONSIDERATIONS FOR DEVELOPERS USING 6.00 RELEASE SOFTWARE
A. Information for Everyone -- Special Topics for this Release
B. Selected Notes from Earlier Releases
IV. BUGS FIXED IN THIS RELEASE
V. KNOWN PRODUCT DEFICIENCIES
I. OVERVIEW OF RELEASE NOTES
The purpose of these release notes is to inform the user of changes
in products that might affect existing applications. The release notes
contain information on changes from previous releases, known problems, and
work-arounds. Bug identification numbers are assigned to known problems to
assist you in identifying the problems to Technical Support.
This document is not all-inclusive but is a tool to assist you in
the update process. Please consult Informix product manuals for additional
information on product features and for clarification of product behavior.
The 6.00 Tools release is basically a 4.12 release that can work
with the 6.00 engines directly (avoiding the overhead of using the Relay
Module) and with NLS functionality added. However, the 6.00 tools will not
work with any engines earlier than the 6.00 engines. The two releases have
occurred at approximately the same time. We expect that customers who need
to work with 6.00 engines, or who need NLS functionality, will probably
skip right over the 4.12 release altogether.
For this reason, the 4.12 release notes have been combined with the
6.0 release notes for the 6.0 release. Customers who have both releases
will see the duplications in the release notes.
II. PRODUCTS CONTAINED IN THE 6.00 TOOLS RELEASE
The following products are contained in the 6.00 tools release:
Product Name
------------
INFORMIX-4GL
INFORMIX-4GL Runtime Facility
INFORMIX-4GL/Rapid Development System
INFORMIX-4GL/Rapid Development System Runtime Facility
INFORMIX-4GL/Interactive Debugger
INFORMIX-SQL
INFORMIX-SQL Runtime Facility
III. SPECIAL CONSIDERATIONS FOR DEVELOPERS USING 6.00 RELEASE SOFTWARE
NOTATION
--------
I4GL refers to (compiled) Informix-4GL.
RDS refers to the Informix-4GL Rapid Development System.
ID refers to the Informix-4GL Interactive Debugger.
4GL refers to any of the Informix-4GL products.
ISQL refers to Informix-SQL.
ESQL/C refers to Informix-ESQL/C.
I4GLC1 6.00 I4GL Phase 1 compiler
I4GLC2 6.00 I4GL Phase 2 compiler
I4GLC3 6.00 I4GL Phase 3 compiler
I4GLC4 6.00 I4GL Phase 4 compiler
FGLC 6.00 I4GL Shell script for Phases 1 and 2.
FGLC2 6.00 I4GL Shell script for Phases 3 and 4.
fglc 4.xx I4GL Phase 1 compiler
fglc2 4.xx I4GL Phase 2 compiler
fglc3 4.12 I4GL Phase 3 compiler
I4GL/PE I4GL Programmer's Environment
R4GL/PE RDS Programmer's Environment
C4GL I4GL Shell script that invokes the compilers.
INSTALLATION
------------
It is recommended that the 6.00 Tools are installed in a new
directory, along with the 6.00 Engines, rather than being installed on top
of previous versions of Informix products. Many files have been relocated
or renamed. It will be much easier to remove redundant files if the old
$INFORMIXDIR directory can be removed completely (after testing the new
installation, of course) than if you have to spend time removing old files
manually.
A. Information for Everyone -- Special Topics for this Release
COMPATIBILITY
=============
The two main reasons for the introduction of 6.x tools are 1)
to avoid the overhead of the Relay Module that dynamically translates
older applications to use the 6.x engines properly, and 2) to use new NLS
functionality.
The 6.x database engines are a *major* product upgrade from the
4.x versions; as an unfortunate but inevitable result, most applications
developed using 4.x (or earlier) INFORMIX tools will have to be recompiled.
This is because ESQL/C, our 6.x tools interface to the backend, now
makes a distinction between prepared cursors (now called "statements") and
declared cursors. In 4.x and earlier versions of ESQL/C, an examination
of the C code generated from ESQL/C would show that the generated code
would use the same static cursor for both prepared cursors (cursors defined
with "prepare") and "declared" cursors (cursors defined with "declare").
All information for both kinds of uses would be contained within the same
structure.
However, 6.x engines functionality has been improved so that, for
example, multiple declared cursors can be associated with the same prepared
statement. Additionally, there is new functionality called "dynamic
cursors", that allows the user to create cursors as needed with dynamically
created names and features; this functionality simply cannot be supported
by ESQL/C's old method of statically allocating cursors.
For the vast majority of ESQL/C users, this upgrade will be
transparent, but for certain applications with specialized knowledge,
such as the RDS interpreter, the distinction is important, and creates
compatibility constraints (see below).
THE RELAY MODULE
----------------
4.x applications can be run against 6.0 engines without being
recompiled using the new Relay Module. You would need to set the SQLEXEC
environment variable to SQLRM. (See the sections on the environment
variables SQLEXEC and SQLRM in "Informix Guide to SQL: Reference, Version
6.0.")
C Shell: setenv SQLEXEC sqlrm
Bourne or Korn Shell: SQLEXEC=sqlrm; export SQLEXEC
However, you will get better performance when accessing the
database if your 4GL programs and linked ESQL/C modules are recompiled
using the 6.0 tools. (There is no need to recompile linked in c modules
that were not generated from INFORMIX preprocessors.)
Note that any attempt to mix modules compiled with 4.xx tools with
modules compiled with 6.x tools will result in undefined behavior. The
program may fail to link, but it will more probably link and run and then
fail in mysterious ways. You must either recompile all the modules in a
program using the 6.x tools, or do not recompile any of them and use the
Relay Module to access the 6.x engine.
I4GL
----
You must recompile all your I4GL source code, and any related
ESQL/C code, to avoid using the Relay Module and to gain access to the NLS
functionality. You do not have to recompile form files or message files.
Do not try mixing code compiled with any earlier version of I4GL with code
compiled with version 6.0 of I4GL. You can recompile using either the C4GL
script or the I4GL/PE program.
RDS & ID
--------
You should recompile all your RDS source code to avoid using the
Relay Module and to gain access to the NLS functionality. You do not have
to recompile form files or message files. You can recompile using either
the FGLPC program or the R4GL/PE program.
The output of 6.x fglpc is level 10 pcode, and cannot be run by any
fglgo runner, customized runner or ID runner earlier than 6.0; nor can any
6.x fglgo runner, customized runner, or ID runner run modules compiled with
an fglpc of a version earlier than 6.0. Attempts to do so will get error
messages specifying that you are running the wrong level of pcode.
If you use custom runners, you will need to recompile them to avoid
using the Relay Module. If your runner is built with any ESQL/C modules,
you should recompile the ESQL/C code as well as relinking the runner, using
the 6.x cfglgo and cfgldb scripts.
ISQL
----
If you use customized ACE or PERFORM runners, you will need to
recompile them to avoid using the Relay Module and to gain access to the
NLS functionality. It is not necessary to recompile the reports or forms
themselves.
USING MAKE
----------
You will find that all the libraries and headers have been moved
under $INFORMIXDIR, and that the list of libraries has changed. If you
use MAKE or an equivalent program and you list the Informix headers or
libraries which are linked into any executable (whether it is a custom
runner or an I4GL program), then you will have to update your makefile.
Alternatively, do not list the Informix libraries or headers in the
makefile as the file list may change with any release of Informix products.
UPSCOL, DEMOS, ETC.
-------------------
You should not need to change any features of the UPSCOL or DEMOS
to work with 6.x tools. However, if you have INFORMIX DEMOS that were
compiled under 4.x, you will need to use the Relay Module. Recompile these
under the 6.x environment to use the faster direct access functionality.
DATABASES
---------
Your old databases will automatically be updated when you first use
them with the new 6.x engine. See the manuals and release notes for the
engine products for more information about this.
EMBEDDED LANGUAGES
------------------
ESQL/Ada and ESQL/Fortran have not been upgraded to 6.x level, so it
will not be possible to run 6.x 4GL programs linked with ESQL/Ada or
ESQL/Fortran modules. You will have to run these modules linked with 4.x 4GL
programs through the Relay Module.
There are 6.x versions of ESQL/Cobol and ESQL/C. If you recompile
4GL programs to take advantage of the functionality and speed of the 6.x
tools, you must recompile these linked modules as well.
LOCALE INFORMATION
==================
Software for non-English languages requires special handling in
order to behave correctly for a non-English user. All of the basic notions
of a language must be built into the product if the software is to appear
to work correctly for a non-English language. Essential notions like
sorting order, capitalization, and numeric display format do not come for
free. Each extra language that you wish to support must come equipped with
its own code-set (i.e. the set of all valid characters for that language),
and its own collation tables (i.e. the "dictionary" order). Extra code
must be added to the tools in order to read and interpret this information.
The 4.12 release of tools does not come equipped with support
for German, French, etc. in the sense mentioned above. The 4.12 release
(and all previous releases) are equipped with the ability to store and
display any of the 256 possible characters that one byte can hold (except
'\0'). Version 4.12 endows these characters with purely English semantics.
Notions of capitalization, sorting, and numeric format are all oriented
towards standard U.S. expectations. Since the code was not originally
designed to handle characters like á, è, ö, þ, ø, and ð; it will not be
able to properly capitalize them, nor will it be able to properly compare
strings that use these characters. In fact, any behavior that involves the
expected semantics of characters which are not in the English alphabet is
not guaranteed to work.
There are a limited number of exceptions to this broad rule. Since
4.12 is 8-bit clean, we can expect that this tool set will be able to
handle simple storage and display of data employing non-U.S. characters
(assuming that the display device itself is capable of displaying the
relevant characters). One more exception to the above mentioned rule is
that 4.12 implements the "identity semantics" of all characters. This
means that two strings which look identical are compared identically (i.e.
the string "ðéþ" and "ðéþ" compare for equality as "True"). If two strings
are identical except for case (relative to some particular language) there
is simply no way for pre-6.00 tools to recognize any similarity. If two
strings do not look identical but in some language they are supposed to be
identical, no pre-6.00 tool will be able to tell the difference.
Locales
-------
Be aware that some of the locales supplied by some platforms
are incorrect. Bad locale files result in symptoms ranging from minor
formatting errors (e.g. incorrect decimal separators) to data corruption in
columns of type CHAR and VARCHAR.
Also be aware that the "C" locale (provided as a default on many
systems) is not a valid locale for most uses of Informix products. The "C"
locale gives no information concerning numeric or currency format. Use
of the "C" locale can cause 4GL to complain about input errors even when
the input has been typed correctly. If you want to use the standard U.S.
format that 4GL and ISQL employ, do one of the two following things:
1) set DBNLS to zero (thus turning off NLS functionality),
or 2) obtain a locale for the U.S. and set LANG to refer to this locale
(e.g. setenv LANG En_US). Note that many systems come configured
with the C locale as the default.
Another potential danger relating to locales is found in
heterogeneous client/server environments. If the client and server are
ostensibly running with the same language but with slightly different
collation orders, counter-intuitive results may appear. This situation is
possible if the locale files that represent the language are different on
the client and server sides.
STTY settings
-------------
In order to use NLS characters, you will need to set your display
device to allow the entry of 8-bit characters with the stty command
(typically using "stty cs8"). If you are using the terminal emulator on a
workstation as your display device, make sure it can display international
characters correctly. For example, the default font for some versions of
xterm does not display legible glyphs for non-ASCII characters.
CHANGES TO THE COMPILATION SYSTEM
=================================
There are some significant differences in the way that Version 6.00
of I4GL compiles 4GL source code compared with all previous versions. Here
is a summary of the changes; the details follow in the numbered sections:
------------------------------------------------------------------
1. The 5-phase I4GL compilation process.
2. FGLC and FGLC2 shell scripts for backward compatibility.
3. I4GL/PE always uses the C4GL script to do compilations.
4. C4GL uses the new "-phase" option.
5. C4GL uses the new "-keep" and "-nokeep" options.
6. C4GL uses the new "-z" option.
7. C4GL uses the new "-globcurs" option.
8. C4GL uses the INFORMIXC and CC environment variables.
9. C4GL uses the C4GLFLAGS environment variable.
10. The I4GL libraries and header files have been moved.
11. Future Changes.
12. I4GLC4.
-------------------------------------------------------------------
1. The 5-phase I4GL compilation process.
To make I4GL independent of ESQL/C, an extra process has to be
introduced into the compilation sequence compared with the Version 4.12
compilation process (or two extra steps compared with versions earlier
than 4.12). The five compilation phases in the Version 6.00 compilation
are shown diagrammatically on the next page, and they are compared with
the equivalent steps for the version 4.12 compilation, and for the 4.11 or
earlier compilation. The five phases are:
I4GLC1: converts a 4GL source file with ".4gl" extension into a
file with ".4ec" extension. It parses the 4GL language and
generates C code to handle function and report definitions,
computations, and function calls. It generates extended ESQL/C
statements to handle forms, menus, input statements, and
display statements, and pure ESQL/C to handle SQL statements
and variable declarations. I4GLC1 is the same as 4.xx fglc,
except for the fact that I4GLC1 generates a ".4ec" file instead
of a ".ec" file.
I4GLC2: is a simplified version of 4.xx fglc2. Where fglc2 translated
both the extended ESQL/C statements and pure ESQL/C statements
into pure C, I4GLC2 only translates the extended form, menu,
input, and display statements to pure C code, but leaves
variable declarations and SQL statements unchanged. I4GLC2
accepts a ".4ec" file generated by I4GLC1 as input and produces
a ".ec" file containing pure ESQL/C.
I4GLC3: is a copy of the standard 6.00 ESQL/C compiler. I4GLC3 accepts
a ".ec" file (which may have been produced by I4GLC2 or written
as pure ESQL/C), and produces a ".c" file. The declarations
and the SQL statements are mapped to pure C.
Version 6.00: Version 4.12: Version 4.11 or earlier:
file.4gl file.4gl file.4gl
| | |
v v v
+--------+ +--------+ +--------+
| I4GLC1 | | fglc | | fglc |
+--------+ +--------+ +--------+
| | |
v v v
file.4ec file.ec file.ec
| | |
v v v
+--------+ +-------+ +-------+
| I4GLC2 | | fglc2 | | fglc2 |
+--------+ +-------+ +-------+
| | |
v | |
file.ec | |
| | |
v | |
+--------+ | |
| I4GLC3 | | |
+--------+ | |
| | |
v | |
file.c file.c |
| | |
v v |
+--------+ +-------+ |
| I4GLC4 | | fglc3 | |
+--------+ +-------+ |
| | |
v v v
file.c file.c file.c
| | |
v v v
+-------+ +-------+ +-------+
| CC | | CC | | CC |
+-------+ +-------+ +-------+
| | |
v v v
file.o file.o file.o
or or or
file.4ge file.4ge file.4ge
I4GLC4: is the same as the 4.12 program fglc3. It converts C code
which may contain international characters in variable names
into de-internationalized names. This step is necessary
to ensure that defining a record like table.* or a field
like table.column will not produce C code which contains
international characters as very few C compilers will accept
these characters in variable names.
C Compiler: Informix uses the system C compiler to convert the C code
generated by I4GLC3 or I4GLC4 into object files and executable
programs.
2. FGLC and FGLC2 shell scripts for backward compatibility.
The FGLC and FGLC2 shell scripts are provided for backwards
compatibility. Since the compilers fglc and fglc2 reside in
$INFORMIXDIR/lib in 4.xx, the new shell scripts will take their place in
the same directory in the 6.00 I4GL product.
As fglc converted a ".4gl" file into a ".ec" file, it corresponds
to the job done by I4GLC1 and I4GLC2. The ".ec" file generated by FGLC is
different from the one generated by fglc because the output of FGLC is a
pure ESQL/C program, whereas the output from fglc contained extended ESQL/C
statements such as $MENU, $DISPLAY, and $INPUT, but these only appear in
.4ec files now.
Similarly, fglc2 converted an (extended) ESQL/C file into a pure
C file, so it corresponded to the job done by I4GLC3 and I4GLC4. The
difference is that the ".ec" file in 4.xx contained a mixture of forms
statements and ESQL/C statements, whereas in 6.00 the ".ec" file will be
pure ESQL/C. The script FGLC2 executes C4GL with the argument "-phase 34"
to perform the steps I4GLC3 and I4GLC4 for producing a ".c" file.
3. I4GL/PE always uses the C4GL script to do compilations.
Prior to 4.12, I4GL/PE used built-in knowledge about what commands
need to be executed to convert a ".4gl" file into a ".ec" file, and a ".ec"
file into a ".c" file, and a ".c" into a ".o" file or executable file. This
has included details such as the list of library names and special options.
With the advent of Version 6.00 Engines, the 6.00 version of I4GL
has to take into account that the database, table and column names could
contain international characters. These will not be accepted in variable
names by most C compilers, so the I4GLC4 process maps the international
characters so that they will be accepted by C compilers. This meant that
I4GL/PE had to be changed.
To simplify the changes required, and to simplify the code stream
so that there is no difference between the 6.00 and 4.12 I4GL/PE programs,
the compilation scheme was revised so that I4GL/PE invokes C4GL to do the
compilation, using the "-phase" option described below.
I4GL/PE now runs "c4gl -phase 12" (I4GLC1 and I4GLC2) as its own
phase 1, followed by "c4gl -phase 34" (I4GLC3 and I4GLC4) as its own phase
2, and finally it runs "c4gl -phase 5" (the C compiler) as its own phase 3.
There has never been a facility to allow the user to specify array
bounds checking (using the "-a" flag) for compilations done by way of
I4GL/PE. However, because the C4GL script is used for the compilations,
the C4GLFLAGS environment variable (see below) can be used with I4GL/PE
too.
4. C4GL uses the new "-phase" option.
C4GL needed some new options to support the new behavior of I4GL,
but, in general, the old behavior has been retained as the default.
C4GL now recognizes the 5 phases of compilation outlined above.
There is a new option "-phase" that takes an argument separated from
"-phase" by one or more spaces. This argument can contain any contiguous
sequence of numbers between 1 and 5 (that is, 1, 2, 3, 4, 5, 12, 23, 34,
45, 123, 234, 345, 1234, 2345, 12345), with the default being 12345. The
older "-e" option has been retained and corresponds to "-phase 1234". The
old "-c" option implies "-phase 12345" , but the C compiler will only
generate the object files and not link them to produce an executable.
5. C4GL uses the new "-keep" and "-nokeep" options.
C4GL, by default, removes the intermediate files that it generates
when the compilation is successful. This is a change from 4.12 and
earlier versions. Thus, the ".c", the ".ec", and the ".4ec" files that
are generated are removed when the compilation completes successfully.
If the compilation fails for any reason, or is interrupted, then all the
intermediate files are left intact.
The new "-keep" option explicitly specifies that the intermediate
files are to be retained. The "-nokeep" option specifies that the
intermediate files are to be removed, and is the 6.00 default. The ".o"
file will be retained if the "-c" flag is specified. However, if an
executable is produced, the ".o" file will be kept or removed depending on
the C compiler in use. Some will retain the ".o" file; others will remove
it; and the behavior may depend on what other files are specified on the
command line.
Note that if the script is commanded to do "-phase 1234", the ".c"
file is no longer an intermediate file and is retained. Similarly, if
phase 1 is requested, the ".4ec" is no longer an intermediate file and is
retained. Unless compilation is successful, no intermediates are removed.
6. C4GL uses the new "-z" option.
C4GL recognizes the "-z" option which allows a single function to
be invoked with a variable number of arguments without I4GLC1 complaining
at compile time.
Although the "-z" option was supported by 4.xx versions of fglc,
the C4GL shell script ignored the option so it was not possible to use the
standard script to compile programs with such functions. Note that it is
dangerous to use this option as it suppresses all error messages for all
functions with variable numbers of arguments; there are generally very few
(if any) of these functions in a program.
7. C4GL uses the new "-globcurs" option.
In 4.xx I4GL and ESQL/C, all cursor and statement names were local
to a single file, and reusing the same name in different files did not lead
to any problems. In 5.0x and 6.x ESQL/C, all cursor and statement names
are global by default. This means that the cursor c_query in filea.ec is
the same as the cursor c_query in fileb.ec. To preserve the old behavior
(in both I4GL and RDS), all cursor and statement names are mangled by the
compiler, using the same algorithm in both compilers. The mangled name
is always 18 characters long. The first half is derived from the inode
number of the 4GL source file, and the second half is derived from the
user-supplied name, using the algorithm shown below. It is possible that
two distinct names in the same file may end up with the same mangled name,
which could lead to a variety of problems. The algorithm is documented so
that if you run into problems, you can at least find out what the trouble
is. Please let Informix know of any pairs of cursor or statment names that
are mangled to the same value. The workaround is to change one of the
cursor or statement names.
The new option "-globcurs" is provided to allow the programmer to
make the cursors global to the entire program. Note that the compilers
still insists that the cursor is declared in the module before it is used
for any other purpose in the module, so this option will seldom be useful.
However, it may help in debugging as the cursor names are not modified.
Note: "-globcurs" can also be used with FGLPC.
The hashing scheme used by I4GL is identical to the one used by
RDS. The code snippet which hashes a cursor name is shown below:
...
sprintf(mangled_name, "I%08X_%08X", inode_number,
hash_cursorname(cursor_name));
...
static unsigned long hash_cursorname(name)
char *name;
{
unsigned long uhash = 0x14C1BC85;
unsigned long g;
unsigned char *s;
unsigned char c;
for (s = (unsigned char *)name; (c = *s) != '\0'; s++)
{
uhash = (uhash << 4) + (c);
if ((g = uhash & 0xF0000000L) != 0)
{
uhash = uhash ^ (g >> 24);
uhash = uhash ^ g;
}
}
return(uhash);
}
Note that the cursor name mangling scheme makes it difficult for
an ESQL/C module to use cursors or statements from an I4GL module. Since
it was impossible to share the cursors in 4.xx, there is no existing code
which is affected. Also note that Version 6.00 4GL still works in terms of
4.xx rules, so cursors cannot be created in one 4GL module and referenced
in another.
8. C4GL uses the INFORMIXC and CC environment variables.
C4GL uses the INFORMIXC and CC environment variables (defaulting
to "cc" on most machines) to do the final stage of compilation. This
allows users to substitute any C compiler as desired by setting one of
these environment variables. Note that CC is acknowledged by many versions
of MAKE as well, so this environment variable is compatible with other
programs, as well. The Bourne shell code used to determine the compiler
used is equivalent to:
${INFORMIXC:=${CC:-cc}}
This means that if there is an INFORMIXC environment variable which is not
empty, use the value of that for the compiler; if not, use the (non-empty)
value of the CC environment variable; if neither of those exist, default to
cc.
Note for users of GCC: Informix assumes that strings are writable,
so you will need to compile using the "-fwritable-strings" option. Failure
to do so will have unpredictable results, possibly including core dumps.
9. C4GL uses the C4GLFLAGS environment variable.
C4GL acknowledges the C4GLFLAGS environment variable as extra
default options. The flags "-keep", "-a," and "-ansi" can be specified,
and all compilations will occur with flags as specified in C4GLFLAGS.
Users should not specify "-phase", "-e," or "-c" (or, for the C
compiler, "-P", "-E", "-S") in this environment variable as it will prevent
the compilations from completing. For example, if you specify "-e" in
the C4GLFLAGS environment variable, you will always stop compiling after
producing a .c file; you will never produce object or executable files.
10. The I4GL libraries and header files have been moved.
The I4GL libraries and header files are located in new directories
and are separate from the libraries and header files used by ESQL/C, even
though the common files are identical. All the libraries used by 6.00
family of tools are located in $INFORMIXDIR/lib/tools. Similarly, all the
header files used by 6.00 tools family are in $INFORMIXDIR/incl/tools.
The compilers I4GLC1, I4GLC2, I4GLC3, and I4GLC4 are all located in the
$INFORMIXDIR/lib/tools directory, whereas in 4.1x, the corresponding files
were located in $INFORMIXDIR/lib.
If the programmers explicitly list the headers from the Informix
directories in the dependency lines in their makefiles, then the dependency
lines need to be modified. Also, if the makefiles explicitly listed
the libraries to be linked, then those lists need changing. Not only
are the libraries in a different directory, but also both the number
and the names of the libraries have changed. On the other hand, if the
programmers do not list the I4GL libraries and they simply use C4GL to
do the linking, then no change is needed. C4GL has always been portable
across the releases. The most reliable way to compile a ".4gl" file to an
object file is using "c4gl -c". Similarly, the most reliable way to link a
program is using "c4gl -o".
11. Future Changes.
The compilation system used in 6.00 may change again in a number
of ways in later releases. However, if you only use the C4GL script to
produce object (.o) files using the "-c" option, or you use the "-o"
option to link programs, then the changes will not affect you. If you use
the "-phase" options you may be required to make some small changes in the
future.
12. I4GLC4.
The information in this section is to help people who use source
code debuggers with I4GL programs. The primary conversion done by I4GLC4
is required for to ensure that the generated C code will compile when I4GL
is used with an NLS database. In an NLS database, the table and column
names can contain non-ASCII characters in the range 128..255. You can
define variables using RECORD LIKE Table.* referring to these names, but
C compilers don't normally allow such characters to be used in variable
names. To avoid compilation problems in the C compiler, the code is
adjusted by I4GLC4.
To make the variable names safe, we replace any non-ASCII
characters that occur outside quoted strings (which will only happen in
variable or function names) with a mapped value. For values in the range
0xA0 to 0xFF, we use the hexadecimal value for the character, printed in
uppercase hexadecimal. Characters in the range 0x80 to 0x8F are mapped
to G0 to GF, and values in the range 0x90 to 0x9F are mapped to H0 to HF.
All ordinary I4GL identifier names are converted to lowercase, so there
should be no chance of producing a naming conflict. Also, by the time
this translation occurs, the names of tables and columns in SQL statements
will not be mangled; the names passed to the engine are protected by
quotes. I4GLC4 does one other translation, and that only inside strings;
it converts y-umlaut (hex 0xFF) into the escape sequence \377. This is
because some C compilers are not fully internationalized and read this
character as EOF.
Note that the P-code compiler, does not do this mapping.
Using the ESQL/C compiler for phase 3 introduces yet another
complication to the compilation process. Informix-4GL uses a different
view of the SQLCA record from ESQL/C -- the warning flags are a series
of single characters in ESQL/C but are treated as a string in 4GL code.
The ESQL/C compiler automatically includes the header ahead of
any user-defined code, which means ahead of the I4GL declaration of the
SQLCA record. This would lead to two discrepant definitions of the SQLCA
record, and the compilations would fail, unless the C4GL script handled
this. To overcome this problem, I4GLC1 emits a line which starts "#define
I4GL_SQLCA" just before the declaration of the SQLCA record. This is
passed through by I4GLC2 and I4GLC3. If the ".c" file to be processed by
I4GLC2 contains this definition, but does not contain the line "#define
SQLCA_INCL", then C4GL passes an extra flag to I4GLC4, and it then prepends
the line "#define SQLCA_INCL" in front of the C file it translates. This
is handled by the C preprocessor so that the contents of the
header are ignored, leaving just the I4GL version of the SQLCA record
visible to the C compiler.
If required, I4GLC4 can be used on its own; it takes the arguments:
-V print version information (does not process any files)
-D emit '#define SQLCA_INCL' as the first line of output
-s ext create backup file with the extension ".ext"
-o overwrite input files
By default, I4GLC4 writes the mangled file(s) to standard output,
but the original file can be overwritten using the "-o" option, or the
original file can be backed up with an extension of the user's choosing.
There is no default extension. Note that I4GLC4 automatically inserts a
"." between the name and the extension. The -o and -s options are mutually
exclusive and require a filename argument. Otherwise, I4GLC4 processes any
files specified, or standard input if there are no files.
CC MUST EXIST ON PATH FOR I4GL
------------------------------
The programmer's environment, I4GL/PE, still checks to see whether
it can locate the C compiler cc when you first try to compile something.
It does not handle all possible values for the INFORMIXC or CC environment
variables, so if you do not have cc on you machine, you may get unnecessary
error messages. A simple cure for that is to ensure that there is an
executable shell script called cc somewhere on your path.
SHARED LIBRARIES
================
Introduction
------------
Effective with the 6.00 release of (compiled) Informix-4GL, a
shared library implementation of the 4GL program libraries is provided
on many platforms. Use of the shared library provides reduced memory
consumption, faster program start-up, and reduced program file sizes
(thereby saving file system space).
Shared library support is provided for compiled 4GL only.
Informix-SQL and Informix-4GL RDS runners (fglgo or custom runners) are
inherently shared, since all active users are running the same executable
file. This feature will be most useful for those installations which have
a variety of compiled 4GL applications: the 4GL library code will exist
in only one place in memory and does not have to be added to each 4GL
executable file. On a system with a large number of 4GL programs, the disk
space and memory savings can be substantial.
Unfortunately, Informix cannot provide a shared library
implementation on all platforms. On some platforms, shared librararies are
simply not available, and on others, the operating system implementation of
shared libraries is simply not compatible with the Informix codestream.
To determine if your platform has a shared library implementation
of Informix-4GL, look at the C4GL help messages. These are displayed
when you run "c4gl" with no arguments. There will be a help line for the
shared option that contains one of these two messages:
-shared Use dynamic linking and shared libraries
Or:
-shared (Not available on this platform)
If the former message is the one given for your platform, then a 4GL Shared
Library implementation is provided, and the -shared option is available for
your use.
You can demonstrate the memory and file size savings for your
platform by compiling the Informix-4GL demonstration program ("demo4") with
and without the -shared flag, and comparing the outputs of "ls" and "size"
for each program:
i4gldemo
c4gl -shared d4_*.4gl -o demo4.shared
c4gl d4_*.o -o demo4
ls -l demo4*
size demo4*
Some platforms provide commands that shows the dependencies of
a compiled program on the shared libraries. For instance, on some Sun
platforms, the command to do this is "ldd".
For more technical information about shared library concepts,
please refer to your operating system documentation. If your system has
"man pages" (on-line manuals), the man page for "ld" may direct you to the
appropriate area of your system documentation.
Usage of the Shared Library Facility
------------------------------------
To compile a 4GL program for shared library execution, simply add
the -shared parameter to your C4GL command line:
c4gl -shared d4_*.4gl -o demo4.shared
If you attempt to use the -shared option on a platform for which no shared
library support is provided, a warning message is displayed to standard
error, and compilation continues with the normal static libraries.
Many platforms require that dynamically linked (shared library)
programs be compiled with position-independent code production from
the C compiler. The C4GL script automatically takes care of this for
you. One issue that you do need to be aware of is that mixing normal and
position-independent code can produce errors. The only thing you need to
be careful of is that when you compile with the "-shared" flag, you must
recompile all modules from the ".4gl" source if you had previously compiled
any without the "-shared" flag.
Consider the following example:
c4gl myprog.4gl myutil1.4gl myutil2.4gl -o myprog
c4gl -shared myprog.o myutil1.o myutil2.o -o myprog.shared
Doing this can produce errors, as the objects will not have been compiled
with the position-independent option. On the other hand, the following is
perfectly acceptable, as the myutil objects will have been compiled with
position-independent code (if applicable to your platform):
c4gl -shared myprog.4gl myutil1.4gl myutil2.4gl -o myprog.shared
c4gl -shared myprog.4gl myutil1.o myutil2.o -o myprog.shared
Note: for some platforms, the system linker (ld) enforces much stricter
name collision constraints when shared libraries are used. If you
have multiple functions in your program with the same name, you
may get errors when compiling with shared libraries even if the
program links successfully with the static libraries. In such
a case, you will need to rename one of the functions to eliminate
the name collision.
Technical Details
-----------------
The name and location of the Informix-4GL shared library will vary
depending on the version of Informix-4GL you have, the naming convention
for shared libraries on your platform, and the ability of the linker on
your platform to locate shared libraries in nonstandard directories.
The name of the shared library begins with "lib4gsh" and continues
with a three-digit version indicator (e.g. "600" for the 6.00 release).
The suffix is platform-dependent; common values are ".so" and ".a".
In most cases, the 4GL shared library is located with the
other 4GL libraries in $INFORMIXDIR/lib/tools. If your platform does not
allow shared libraries in nonstandard directories, your
system administrator may have to copy the library to a standard system
directory such as /lib or /usr/lib. If this is necessary, this fact should
be mentioned in the machine-specific notes for your platform. Note that
most, if not all, platforms require that any programs that change their
user-id dynamically while running (often referred to as "setuid programs")
*and* use shared libraries can *only* access those shared libraries in
standard system directories. Therefore, if you have a setuid 4GL program
that uses the 4GL shared library, your system administrator must copy or
link the 4GL shared library to a standard directory.
Run-time Requirements
---------------------
Unlike static-linked I4GL programs, I4GL programs that use the
shared library must have that library accessible at run time. Most
platforms provide an environment variable that instructs the operating
system's linking program loader to add one or more nonstandard directories
to its shared library search list. Common examples of this variable are
LD_LIBRARY_PATH and LPATH. The machine-specific notes provided with I4GL
should confirm the appropriate variable name for your platform. All users
who wish to run your shared library I4GL application(s) must have this
variable set properly in their shell environment. A typical example would
be:
Bourne or Korn Shells:
LD_LIBRARY_PATH=$INFORMIXDIR/lib/tools; export LD_LIBRARY_PATH
C Shell variants:
setenv LD_LIBRARY_PATH ${INFORMIXDIR}/lib/tools
Be sure that all potential users set their environments accordingly,
and/or update global environment scripts as applicable for your site.
If you develop 4GL applications that are sent out to other systems,
those systems must also have the shared library available. All platforms
that have 4GL shared library support also have the 4GL shared library
included in corresponding runtime versions of Informix-4GL. Be sure to
notify your remote users and runtime customers of the environment variable
needs mentioned above.
DOUBLY-DEFINED GLOBAL VARIABLES
===============================
The overview of GLOBALS in the I4GL Reference Manual defines two
forms of the GLOBALS statement: one defines variables, the other refers
to the file where global variables are defined. The first note clearly
states "You may have at most one GLOBALS statement where global variables
are defined." This is because I4GL translates the code on the left into,
more or less, the C on the right (Sequence A):
filea.4gl filea.c
========= =======
GLOBALS
a DATETIME YEAR TO SECOND, dtime_t a;
b CHAR(20), char b[21];
c DECIMAL dec_t c;
END GLOBALS
MAIN main()
{
END MAIN }
fileb.4gl fileb.c
========= =======
GLOBALS
a DATETIME YEAR TO SECOND, dtime_t a;
b CHAR(20), char b[21];
c DECIMAL dec_t c;
END GLOBALS
FUNCTION f() f()
{
END FUNCTION }
When you link filea.o and fileb.o together, this strictly leads to
doubly defined variables, as filea.c and fileb.c both define the variables
a, b, and c. However, the vast majority of linkers actually allow this
doubly definition, as long as at most one of the definitions includes an
initializer. This means that you normally get away with it.
What you're supposed to do, of course, is define a file which
contains the GLOBALS definitions, and then use that file where you need to
refer to those GLOBALS, like this (Sequence B):
fileg.4gl fileg.c
========= =======
GLOBALS
a DATETIME YEAR TO SECOND, dtime_t a;
b CHAR(20), char b[21];
c DECIMAL dec_t c;
END GLOBALS
filea.4gl filea.c
========= =======
GLOBALS "fileg.4gl" extern dtime_t a;
extern char b[21];
extern dec_t c;
MAIN main()
{
END MAIN }
fileb.4gl fileb.c
========= =======
GLOBALS "fileg.4gl" extern dtime_t a;
extern char b[21];
extern dec_t c;
FUNCTION f() f()
{
END FUNCTION }
Now when you link filea.o, fileb.o and fileg.o, there are no doubly
defined variables to cause any linker any problems.
So much for the theory. What's behind this? The problem is that
the Version 6.00 ESQL/C compiler (aka I4GLC3) will generate initializers
in both filea.c and fileb.c in Sequence A for each variable which either
is a DATETIME or INTERVAL variable or is a compound structure (RECORD or
ARRAY or ARRAY of RECORDS) that includes DATETIME or INTERVAL variables.
Further, it must do so to ensure that the rest of the code in the file
uses the correct type information when accessing the DATETIME or INTERVAL
values. However, any 4GL code written in the style of Sequence A no longer
links because the global variables are doubly defined. In this example,
a would be doubly defined, because the definitions in both filea.c and
fileb.c would contain initializers.
This means that any Version 4.1x 4GL code which uses Sequence A to
define sets of global variables that include DATETIME or INTERVAL variables
will compile under Version 6.00, but will not link successfully. The only
cure is to use some variation on the correct Sequence B to define and
reference the global variables.
Legitimate variations
---------------------
There are various ways of using globals which look similar to the
problematic Sequence A but are actually quite distinct. One of these is the
use of module variables. The variables defined with other_stuff are module
variables, the equivalent of a static variable in C. The variable other_stuff
can be accessed in any function in this file, but it cannot be accessed by any
function outside this file.
GLOBALS "globals.4gl"
DEFINE
other_stuff INTEGER
Another more complex sequence is possible using multiple source
files. It also requires a slightly more flexible interpretation of the
statement in the manual "You may have at most one GLOBALS statement
where global variables are defined." If you have 5 files, xglobs.4gl,
bglobs.4gl, lib.4gl, filex.4gl and fileb.4gl
xglobs.4gl
==========
GLOBALS
DEFINE i DATETIME YEAR TO FRACTION
END GLOBALS
yglobs.4gl
==========
GLOBALS
DEFINE j DATETIME YEAR TO FRACTION
END GLOBALS
lib.4gl
=======
GLOBALS
DEFINE i DATETIME YEAR TO FRACTION
DEFINE j DATETIME YEAR TO FRACTION
END GLOBALS
FUNCTION lib_function()
END FUNCTION
filex.4gl
=========
GLOBALS "xglobs.4gl"
FUNCTION x()
END FUNCTION
filey.4gl
=========
GLOBALS "yglobs.4gl"
FUNCTION y()
END FUNCTION
Provided that your link phase does not try to link either xglobs.o
or yglobs.o into an executable which also uses lib.o, then there will be no
problems combining filex.o, filey.o and libs.o along with the file defining
the MAIN function. The definitions of i and j are in lib.o; filex.o refers
to, but doesn't define, i; similarly, filey.o refers to, but doesn't
define, j. There are no double definitions, so the program is perfectly
legitimate. However, the manual statement needs to be refined; it should
read "You may have at most one GLOBALS statement where any particular
global variable is defined."
Using this technique, or variations on it, programs can be designed
to link correctly without double definition problems. The problem is that
4GL does not support multiple GLOBALS files being included in a single 4GL
source file. This means that you can end up with a proliferation of files
like xglobs.4gl which define a subset of the global variables used by a
program. However, this is typically preferable to the alternative scenario
of a single monstrous globals file which defines every possible variable
and array which could be used by any program in the suite of programs.
BUG FIXES
=========
Bug 1857: ERROR -4518 DUE TO NOT FREEING TEMPORARY STRING SPACE
===============================================================
Error -4518 (The 4GL program cannot allocate any more space for
temporary string storage) has been eliminated.
Error -4517 (String of length >512 cannot be returned from function
calls) has also been eliminated.
You should not run into any problem with partially evaluated string
expressions and so on fouling up the program. You may, eventually, run
out of memory (Error -4339) instead, but the temporary string space (TSS)
is recovered whenever a function is exited, or at the completion of a
statement with a USING clause or string concatenation operation, so the TSS
does not get continuously filled as it used to.
The internal operation of the memory allocation system has been
completely rewritten. Some internal I4GL routines and structures have
been removed as a result of the rewrite of the memory allocation system.
Since these are internal routines and structures, their use is undocumented
and unsupported. However, it is theortetically possible that some user
programs rely on these routines and structures.
Any code that relies on the function acdealloc() will fail --
that function has been eliminated. Any code that relies on being able
to access alloctab will fail as that structure has been eliminated too.
If necessary, you can supply a dummy version of acdealloc() that does
nothing -- "acdealloc(){}". You will have to revise any code that accesses
alloctab, but you should be able to convert those routines into dummies
too.
It is difficult to write a program that uses up all the memory,
and it would almost certainly have to use a recursive function, such as
the Ackerman function on the next page. This code has a deliberate bug
in it because it uses a string as the return value, whereas it should be
DECIMAL(32,0) -- effectively a giant INTEGER -- to be consistent with the
arguments. The program fails under Version 4.11 or earlier versions, but
runs successfully under Version 6.00 or 4.12.
MAIN
DEFINE
i DECIMAL(32,0),
j DECIMAL(32,0),
a CHAR(60)
LET i = 3 -- Be wary about increasing this
LET j = 3
LET a = "Result of ACKERMAN(",
i USING "&", ",", j USING "&", ") = ",
Ackerman(i, j)
DISPLAY a CLIPPED
END MAIN
FUNCTION Ackerman(m, n)
DEFINE
m DECIMAL(32,0),
n DECIMAL(32,0),
k CHAR(32)
CASE
WHEN (m = 0)
LET k = n + 1
WHEN (n = 0)
LET k = Ackerman(m - 1, 1)
OTHERWISE
LET k = Ackerman(m - 1, Ackerman(m, n - 1))
END CASE
RETURN k
END FUNCTION
This code demonstrates the removal of the limits imposed by error -4517.
MAIN
CALL func1()
END MAIN
FUNCTION func1()
DEFINE
str CHAR(2048),
i SMALLINT
LET str = "A"
FOR i = 2 to 2048
LET str[i] = "A"
END FOR
LET str = func2(str)
DISPLAY "String = ", str
END FUNCTION
FUNCTION func2(str)
DEFINE
str CHAR(2048),
i SMALLINT
DISPLAY "String = ", str CLIPPED
LET str = "B"
FOR i = 2 to 2048
LET str[i] = "B"
END FOR
RETURN str
END FUNCTION
INTERRUPTS AND FOREACH LOOPS
============================
The problem of attempting a FETCH on an unopened cursor is resolved
in 6.00 by changing the generated C-code and P-code to check the STATUS
after opening the cursor.
In Version 4.11 4GL and earlier, the FOREACH loop was effectively
translated to the equivalent code shown here:
OPEN cursor
WHILE (1)
FETCH cursor
IF STATUS == NOTFOUND THEN
EXIT WHILE
END IF
...Body of FOREACH loop...
END WHILE
CLOSE cursor
If the prevailing error handling is WHENEVER ERROR CONTINUE, and if
for some reason the cursor is not opened successfully, then this code does
not check for the STATUS and attempts to FETCH from the unopened cursor,
generating error code -400 (Fetch attempted on unopen cursor).
One cause of an OPEN failing is the user hitting the interrupt key.
If the I4GL program is waiting for a response from the engine when this
happens, then error code -213 (Statement interrupted by user) is generated.
This code causes the interrupt status to be lost.
Note that if interrupt and quit have been deferred, the variable
INT_FLAG is always set if the interrupt key is hit, and the variable
QUIT_FLAG is set if the quit key is hit.
If the interrupt occurs while the application is waiting for a
response from the engine, then SQLCA.SQLCODE is set to -213. If, however,
the interrupt occurs while the application is doing its own processing and
is not waiting for the engine, then error -213 is not necessarily returned,
and the data being fetched is valid. Under some circumstances, several
rows of data are sent from the engine at a time, and subsequent fetches
will not need to wait for the engine.
The problem of attempting to implicitly fetch (via FOREACH) on
an unopened cursor is resolved in 4.12 by changing the generated C code
and P-code for FOREACH to check the STATUS after opening the cursor. The
equivalent code is now:
OPEN cursor
IF STATUS == 0 THEN
WHILE (1)
FETCH cursor
IF STATUS == NOTFOUND THEN
EXIT WHILE
END IF
...Body of FOREACH loop...
END WHILE
CLOSE cursor
END IF
Thus, neither the FETCH nor the CLOSE is executed when the
OPEN fails. This avoids modifying the SQLCA structure and losing the
information in case of a failure.
What happens if the implicit FETCH statement in a FOREACH loop
fails? We need to consider the behavior for each of the various WHENEVER
ERROR statements which the user can choose for the application:
WHENEVER ERROR STOP
The program stops with an error, so the CLOSE is not executed.
WHENEVER ERROR CONTINUE
The program allows the programmer to test STATUS or SQLCA.SQLCODE
at the top of the body of the FOREACH loop. The body of the loop
is not entered if the OPEN fails, so the only condition tested
at the top of the body of the loop is FETCH failures. If the
FETCH set STATUS to NOTFOUND, the program will exit the loop
automatically and will execute the CLOSE. On a FETCH error, the
programmer can optionally CLOSE the cursor and return from the
function, or can execute EXIT FOREACH to close the cursor.
WHENEVER ERROR GOTO
The program goes to the label. The cursor can be explicitly closed
by the programmer, who has presumably thought about this before
using WHENEVER ERROR GOTO. The CLOSE is not executed by generated
code.
WHENEVER ERROR CALL
The program calls the function. If the function returns, the code
will continue as usual, which means in the same general way as
WHENEVER ERROR CONTINUE.
This shows that the CLOSE statement is not executed in a context in
which it clobbers SQLCA or STATUS unexpectedly, so the code does not have
to worry about preserving SQLCA or STATUS.
Note that the CLOSE statement does unavoidably lose the information
contained in SQLCA.SQLERRD[3] about the number of row processed by the
SELECT statement. The workaround is to have the program count the number
of rows processed. Note that the information may not be reported when the
last row is fetched, but at some earlier time, depending on whether the
rows are sent from the engine in batches.
SUPPORT FOR NESTED RECURSIVE INPUT/DISPLAY STATEMENTS
=====================================================
4GL statements such as CONSTRUCT, DISPLAY ARRAY, INPUT, INPUT
ARRAY, and PROMPT use a common underlying data structure called the Input
Control Block (ICB). These statements are collectively referred to as ICB
statements. Both Version 6.00 and Version 4.12 now support nested and
recursive ICB statements in which the parent and the child ICB statements
use the same form for accepting and displaying the data. In the case of
recursive ICB statements, the parent and the child statements could be the
same.
4.12 supports both Direct and Indirect nesting of the ICB
statements, where the level of nesting is limited only by the availability
of the resources. Direct nesting involves embedding the child ICB
statement in one of the clauses such as ON KEY, BEFORE FIELD, AFTER FIELD,
etc. of the parent ICB statement. The following code illustrates Direct
nesting of INPUT statements:
MAIN
DEFINE r1, r2 RECORD
f1, f2, f3 CHAR(30)
END RECORD
DATABASE nestedinputDB
DEFER INTERRUPT
OPEN FORM nest_form FROM "nested_input"
DISPLAY FORM nest_form
LET INT_FLAG = FALSE
IF NOT INT_FLAG THEN
INPUT BY NAME r1.* WITHOUT DEFAULTS --Parent INPUT stmt
BEFORE INPUT
MESSAGE "BEFORE INPUT STATEMENT 1" SLEEP 1
BEFORE FIELD f1
MESSAGE "Input Statement 1 -- BF1" SLEEP 1
AFTER FIELD f2
MESSAGE "Input Statement 1 -- AF1" SLEEP 1
--Child INPUT Statement
INPUT BY NAME r2.* WITHOUT DEFAULTS --Child INPUT stmt
BEFORE INPUT
MESSAGE "BEFORE INPUT STATEMENT 2" SLEEP 1
AFTER INPUT
MESSAGE "AFTER INPUT STATEMENT 2" SLEEP 1
ON KEY (CONTROL-W)
MESSAGE "IP2: HELP IS NOT AVAILABLE" SLEEP 1
END INPUT --End of Child INPUT stmt
LET r2.f1 = "Child INPUT Statement -- ", r2.f1 CLIPPED
INSERT INTO table_2 VALUES(r2.*)
AFTER INPUT
MESSAGE "AFTER INPUT STATEMENT 1" SLEEP 1
ON KEY (CONTROL-W)
MESSAGE "IP1: HELP IS NOT AVAILABLE" SLEEP 1
END INPUT --End of Parent INPUT stmt
END IF
LET r.f1 = "Parent INPUT Statement -- ", r1.f1 CLIPPED
INSERT INTO table_1 VALUES(r1.*)
MESSAGE "Input Statement -- complete" SLEEP 1
END MAIN
In the above nested INPUT statements, the parent and the child
statements use the same form for entering data. After the user
enters data in fields f1 and f2 for the parent INPUT statement,
control is transferred to the child INPUT statement. Once the
child INPUT statement is executed, data entered for the child is
inserted in table_2. Then control is returned to the parent, and
fields f1 and f2 are restored to their original values.
Indirect nesting involves invoking a function, which contains the
child ICB statement, from the parent ICB statement. Once again,
the parent and the child ICB statements use the same form for data
entry. The following code illustrates Indirect nesting of INPUT
statements:
MAIN
DEFINE r1 RECORD
f1, f2, f3 CHAR(30)
END RECORD
DATABASE nestedinputDB
DEFER INTERRUPT
OPEN FORM nest_form FROM "nested_input"
DISPLAY FORM nest_form
LET INT_FLAG = FALSE
IF NOT INT_FLAG THEN
INPUT BY NAME r1.* WITHOUT DEFAULTS --Parent INPUT stmt
BEFORE INPUT
MESSAGE "BEFORE INPUT STATEMENT 1" SLEEP 1
BEFORE FIELD f1
MESSAGE "Input Statement 1 -- BF1" SLEEP 1
AFTER FIELD f2
MESSAGE "Input Statement 1 -- AF1" SLEEP 1
--Indirect Nesting
CALL child_inputstmt()
AFTER INPUT
MESSAGE "AFTER INPUT STATEMENT 1" SLEEP 1
ON KEY (CONTROL-W)
MESSAGE "IP1: HELP IS NOT AVAILABLE" SLEEP 1
END INPUT --End of Parent INPUT stmt
END IF
LET r.f1 = "Parent INPUT Statement -- ", r1.f1 CLIPPED
INSERT INTO table_1 VALUES(r1.*)
MESSAGE "Input Statement -- complete" SLEEP 1
END MAIN
FUNCTION child_inputstmt()
DEFINE r2 RECORD
f1, f2, f3 CHAR(30)
END RECORD
LET INT_FLAG = FALSE
IF NOT INT_FLAG THEN
INPUT BY NAME r2.* WITHOUT DEFAULTS --Child INPUT stmt
BEFORE INPUT
MESSAGE "BEFORE INPUT STATEMENT 2" SLEEP 1
AFTER INPUT
MESSAGE "AFTER INPUT STATEMENT 2" SLEEP 1
ON KEY (CONTROL-W)
MESSAGE "IP2: HELP IS NOT AVAILABLE" SLEEP 1
END INPUT --End of Child INPUT stmt
END IF
LET r2.f1 = "Child INPUT Statement -- ", r2.f1 CLIPPED
INSERT INTO table_2 VALUES(r2.*)
END FUNCTION
It is also legal to perform heterogeneous nesting where the parent
and the child statements are entirely different. For example, one can have
CONSTRUCT as the parent statement and INPUT as the child statement.
Recursive ICB statements were not supported prior to the 4.12
release of I-4GL. This feature provides an extra flexibility to the 4GL
programmers while developing their applications. The following sample code
illustrates the use of the recursive INPUT statement:
MAIN
DEFINE r RECORD
f1, f2, f3 CHAR(30)
END RECORD
DEFINE z INTEGER
DATABASE recinputDB
DEFER INTERRUPT
OPEN FORM recurs_form FROM "recursive_input"
DISPLAY FORM recurs_form
LET z = 0
CALL recursive_input(z, r)
END MAIN
FUNCTION recursive_input(z1, r1)
DEFINE r1 RECORD
f1, f2, f3 CHAR(30)
END RECORD
DEFINE z1 INTEGER
LET INT_FLAG = FALSE
LET z1 = z1 + 1
IF z1 > 3 THEN
RETURN
END IF
MESSAGE "Recursive Cycle: ", z1 SLEEP 1
IF NOT INT_FLAG THEN
INPUT BY NAME r1.* WITHOUT DEFAULTS
BEFORE INPUT
MESSAGE "BEFORE INPUT STATEMENT 1" SLEEP 1
BEFORE FIELD f1
MESSAGE "Input Statement 1 -- BF1" SLEEP 1
AFTER FIELD f2
MESSAGE "Input Statement 1 -- AF1" SLEEP 1
CALL recursive_input(z1, r1) --Recursive call
AFTER INPUT
MESSAGE "AFTER INPUT STATEMENT 1" SLEEP 1
ON KEY (CONTROL-W)
MESSAGE "IP1: HELP IS NOT AVAILABLE" SLEEP 1
END INPUT
END IF
LET r.f1 = "Recursive Cycle -- ", z1, r1.f1 CLIPPED
INSERT INTO table_1 VALUES(r1.*)
MESSAGE "Input Statement -- complete" SLEEP 1
END FUNCTION
For every recursive invocation of the function recursive_input(),
the same form is used for data entry. A recursive call is made after the
user enters data in fields f1 and f2 for each invocation. Before making a
recursive call, context is stored in dynamically allocated variables and
pushed onto the stack. When the terminating condition for recursion is
satisfied, context is popped out of the stack and the form fields f1 and f2
are restored to their original values.
It is legal to combine nesting in all its flavors such as Direct,
Indirect, heterogeneous, and homogeneous with recursive ICB statements. It
is necessary to recompile and re-link applications that use ICB-related
statements with 4.12 software to avoid anomalous behavior.
WARNING
-------
The new nested input features (in particular) allow some operations
that can lead I4GL to clean up incorrectly during INPUT, INPUT ARRAY,
DISPLAY ARRAY, CONSTRUCT, MENU, and FOREACH loops. Essentially, for any
nested statements, an early exit from inside one of the inner statements to
one of the outer statements, or a RETURN, means that I4GL does not clean up
any statement except the innermost.
To illustrate this problem, consider the code below, which is
excruciating to read, not to mention of no practical use, but which does
show how nested INPUT statements could be used in theory. (There are 9
levels of nested statements in the code.) It also illustrates some of the
problems caused by early exits from nested statements. For example, when
you do an EXIT FOREACH from inside an INPUT statement nested inside two
MENU statements, a FOR loop and a WHILE loop (as shown by the first EXIT
FOREACH statement below), then the intervening menus ("ABCDEF" and "XYZ")
are not cleaned up correctly, though the INPUT statement itself is handled
correctly, and the FOREACH loop cursor is closed correctly.
In a future release of I4GL, the nested EXIT, CONTINUE, and
RETURN statements may have correct clean-up code generated. This may
require a lot of extra code, so early exits from nested statements are not
encouraged.
Note that GOTO statements, including WHENEVER ERROR GOTO or
WHENEVER WARNING GOTO, will not be dealt with properly. If this is a
concern, do not use GOTO (see "Go To Statement Considered Harmful" by Edsger
Dijkstra, CACM, March 1968).
-- @(#)Torture test for I4GL compilers
-- @(#)Also a torture test for people reading the C code
-- @(#)Also a torture test for C code reformatting programs
MAIN
CALL f()
END MAIN
FUNCTION f()
DEFINE s CHAR(300)
DEFINE y INTEGER
DEFINE i INTEGER
DEFINE t INTEGER
DEFINE a ARRAY[10] OF INTEGER
DECLARE c CURSOR FOR
SELECT Tabid FROM Systables
OPEN WINDOW w AT 1, 1 WITH FORM "xxx"
LET y = 0
FOREACH c INTO t
FOR i = 1 TO 10
WHILE y < 1000
MENU "ABCDEF"
BEFORE MENU
HIDE OPTION "B"
COMMAND "A" "Absolutely"
SHOW OPTION "B"
IF a[1] THEN EXIT MENU END IF
IF a[1] THEN CONTINUE MENU END IF
NEXT OPTION "E"
COMMAND "B" "Beautiful"
MESSAGE "Thank you"
COMMAND "C" "Colorful"
MESSAGE "Thank you"
COMMAND "D" "Delicious"
MESSAGE "Thank you"
COMMAND "E" "Exit"
EXIT MENU
COMMAND "F"
MENU "XYZ"
COMMAND "X"
EXIT MENU
COMMAND "Y"
INPUT BY NAME y WITHOUT DEFAULTS
AFTER FIELD y
IF a[1] THEN EXIT FOR END IF
IF a[1] THEN CONTINUE FOR END IF
IF a[1] THEN EXIT FOREACH END IF
IF a[1] THEN CONTINUE FOREACH END IF
IF a[1] THEN EXIT WHILE END IF
IF a[1] THEN CONTINUE WHILE END IF
IF a[1] THEN RETURN END IF
IF a[1] THEN EXIT MENU END IF
IF a[1] THEN CONTINUE MENU END IF
IF a[1] THEN EXIT INPUT END IF
IF a[1] THEN CONTINUE INPUT END IF
IF a[1] THEN GOTO End_Label END IF
IF a[1] THEN GOTO Mid_Label END IF
CONSTRUCT BY NAME s ON y
AFTER FIELD y
IF a[1] THEN EXIT FOR END IF
IF a[1] THEN CONTINUE FOR END IF
IF a[1] THEN EXIT FOREACH END IF
IF a[1] THEN CONTINUE FOREACH END IF
IF a[1] THEN EXIT WHILE END IF
IF a[1] THEN CONTINUE WHILE END IF
IF a[1] THEN RETURN END IF
IF a[1] THEN EXIT MENU END IF
IF a[1] THEN CONTINUE MENU END IF
-- EXIT INPUT is not allowed by the compiler (error 4488)
-- IF a[1] THEN EXIT INPUT END IF
-- CONTINUE INPUT is not allowed by the compiler (error 4488)
-- IF a[1] THEN CONTINUE INPUT END IF
IF a[1] THEN EXIT CONSTRUCT END IF
IF a[1] THEN CONTINUE CONSTRUCT END IF
IF a[1] THEN GOTO End_Label END IF
IF a[1] THEN GOTO Mid_Label END IF
CALL SET_COUNT(3)
DISPLAY ARRAY a TO a.*
ON KEY (F3)
IF a[1] THEN EXIT FOR END IF
IF a[1] THEN CONTINUE FOR END IF
IF a[1] THEN EXIT FOREACH END IF
IF a[1] THEN CONTINUE FOREACH END IF
IF a[1] THEN EXIT WHILE END IF
IF a[1] THEN CONTINUE WHILE END IF
IF a[1] THEN RETURN END IF
IF a[1] THEN EXIT MENU END IF
IF a[1] THEN CONTINUE MENU END IF
IF a[1] THEN EXIT DISPLAY END IF
-- CONTINUE DISPLAY is not allowed by the compiler
-- IF a[1] THEN CONTINUE DISPLAY END IF
-- EXIT INPUT is not allowed by the compiler (error 4488)
-- IF a[1] THEN EXIT INPUT END IF
-- CONTINUE INPUT is not allowed by the compiler (error 4488)
-- IF a[1] THEN CONTINUE INPUT END IF
-- EXIT CONSTRUCT is not allowed by the compiler (error 4488)
-- IF a[1] THEN EXIT CONSTRUCT END IF
-- CONTINUE CONSTRUCT is not allowed by the compiler (error 4488)
-- IF a[1] THEN CONTINUE CONSTRUCT END IF
IF a[1] THEN GOTO End_Label END IF
IF a[1] THEN GOTO Mid_Label END IF
INPUT ARRAY a FROM a.*
AFTER FIELD y
IF a[1] THEN EXIT FOR END IF
IF a[1] THEN CONTINUE FOR END IF
IF a[1] THEN EXIT FOREACH END IF
IF a[1] THEN CONTINUE FOREACH END IF
IF a[1] THEN EXIT WHILE END IF
IF a[1] THEN CONTINUE WHILE END IF
IF a[1] THEN RETURN END IF
IF a[1] THEN EXIT MENU END IF
IF a[1] THEN CONTINUE MENU END IF
IF a[1] THEN EXIT INPUT END IF
IF a[1] THEN CONTINUE INPUT END IF
-- EXIT DISPLAY *is* allowed by the compiler (despite error 4488)
IF a[1] THEN EXIT DISPLAY END IF
-- CONTINUE DISPLAY is not allowed by the compiler
-- IF a[1] THEN CONTINUE DISPLAY END IF
-- EXIT CONSTRUCT is not allowed by the compiler (error 4488)
-- IF a[1] THEN EXIT CONSTRUCT END IF
-- CONTINUE CONSTRUCT is not allowed by the compiler (error 4488)
-- IF a[1] THEN CONTINUE CONSTRUCT END IF
IF a[1] THEN GOTO End_Label END IF
IF a[1] THEN GOTO Mid_Label END IF
LABEL Mid_label:
MESSAGE "You got here? How?"
NEXT FIELD y
END INPUT
END DISPLAY
END CONSTRUCT
END INPUT
COMMAND "Z"
MESSAGE "Sucker!"
CONTINUE MENU
END MENU
END MENU
END WHILE
END FOR
END FOREACH
LET y = 0
LABEL End_label:
CLOSE WINDOW w
END FUNCTION
PROMPT STATEMENT
================
The PROMPT statement has changed in a couple of minor ways.
LENGTH OF DISPLAY LIST
----------------------
In 4.12, the user assumes the onus of ensuring that the length of
the display list for the PROMPT statement is smaller than the number of
columns on the active window. If the display list is greater than or equal
to the number of columns, then error -1146 is generated at runtime.
OPTIONS PROMPT LINE
-------------------
If the value of the PROMPT LINE specified by the user, using the
OPTIONS statement, exceeds the number of rows on the active window then
PROMPT LINE is set to its default value, that is, the first row of the
window. Consider the following 4GL code that increments the value of the
PROMPT LINE in the WHILE loop:
MAIN
DEFINE ans CHAR(1)
DEFINE pline INTEGER
DEFINE flag CHAR(1)
LET pline = 7
OPTIONS PROMPT LINE pline
WHILE pline <> 10
OPEN WINDOW wdw AT 4,6 WITH 7 ROWS, 60 COLUMNS ATTRIBUTE (BORDER)
DISPLAY "Rows = 7, PROMPT LINE is set to ", pline at 2, 6
PROMPT "123456789012345678901234567890abcdef" FOR CHAR ans
CLOSE WINDOW wdw
LET pline = pline + 1
OPTIONS PROMPT LINE pline
END WHILE
END MAIN
In the above 4GL code, the variable pline is set to 7 and PROMPT
LINE is set to the value held in pline. Also, a window with 7 rows and
70 columns is opened within the WHILE loop and the value of pline is
incremented. Then the user tries to set PROMPT LINE to 8 using the OPTIONS
statement. While opening the window in the next iteration, 4GL notices
that the value of PROMPT LINE is greater than the maximum number of rows
available. Therefore, 4GL silently sets the value of PROMPT LINE to the
default value, that is, the first row of the window.
UNLOAD STATEMENT SUPPORT FOR HOST VARIABLES
===========================================
The UNLOAD statement has been modified to support host variables in
the WHERE clause of the embedded SELECT query. The previously recommended
workaround for this problem, which dynamically builds the SELECT statement
for UNLOAD, is still valid. Following is an example of the workaround that
was earlier recommended:
DATABASE stores
MAIN
DEFINE hostvar SMALLINT
DEFINE tempsel CHAR(200)
LET hostvar = 103
LET tempsel = "select * from customer ",
"where customer_num = ", hostvar
UNLOAD TO "custfile" DELIMITER ";" tempsel
END MAIN
Under the new scheme of things, UNLOAD can be done as shown below:
DATABASE stores
MAIN
DEFINE hostvar SMALLINT
LET hostvar = 103
UNLOAD TO "custfile" DELIMITER ";"
SELECT * FROM customer WHERE customer_num = hostvar
END MAIN
Do not substitute question marks (?) in place of the host variables
to make the SELECT statement dynamic. For example, the following 4GL code
is not recommended because it has binding problems:
FUNCTION func_unload()
DEFINE query CHAR(250)
DEFINE file CHAR(20)
DEFINE del CHAR(1)
DEFINE i INTEGER, j INTEGER, k INTEGER
LET i = 100
LET j = 30
LET k = 400
LET del = ";"
LET file = "/dev/tty"
LET query = "select * from systables where tabid >= ?"
" and ncols >= ? and rowsize >= ?"
UNLOAD TO file DELIMITER del query
END FUNCTION
WORDWRAP BUG FIXES
==================
The semantics of WORDWRAP have been altered in forms, in CONSTRUCT,
and in reports, and the changes are discussed in this section. There is
also a brief note concerning AUTONEXT in CONSTRUCT.
WORDWRAP in Forms
-----------------
This is a change to default behavior. In release 4.10.UC1, it was
found that form fields with the WORDWRAP attribute and with the WORDWRAP
COMPRESS attributes behaved in a similar fashion. It was also found
that the routine used to perform compression was not consistent with the
specification.
In order to preserve backward compatibility, both Version 6.00 and
Version 4.12 has changed the DEFAULT behavior of WORDWRAP fields without
any keyword after WORDWRAP; these now behave the same as WORDWRAP COMPRESS.
If the attributes for a field reads either WORDWRAP COMPRESS or just
WORDWRAP, compress mode is active. If users do not want the compress mode
to be active, they must use the new attribute WORDWRAP NONCOMPRESS.
After taking into account the change in the default behavior, the
wordwrap input routines were modified to implement the behavior specified
in the documentation. All user-typed blanks are retained in both COMPRESS
and NONCOMPRESS mode. In COMPRESS mode, only line-padding (editor) blanks
are eliminated.
This change was forecast in the release notes for 4.11.UC1. These
changes were made to fix PTS bug number 15434. Also see bug numbers 10166,
14540, and 14179.
WORDWRAP in CONSTRUCT
---------------------
In version 4.11, when CONSTRUCT was working on a multi-segment
field with the WORDWRAP attribute set, the initial input would be displayed
in the first segment of the field. When the input no longer fit in the
first segment, it would overflow into the second and subsequent segments of
the field. However, it also cleared the overflow line at the bottom of the
screen, even though no data was displayed there.
In both Version 6.00 and Version 4.12, the behavior has been
revised so that multi-segment fields are treated the same as single-segment
fields; when the first segment is full, the overflow line is used to
display the extra data. The extra segments of a WORDWRAP field are not
used during CONSTRUCT. Only the first segment and the overflow line are
used. This should provide sufficient space for query input. This was bug
14033.
Any form field with the WORDWRAP attribute is allowed to span
several lines. During work on release 4.12, it was discovered that if
the segments of a multi-segment wordwrapped field are not aligned in a
single column, then moving backwards from a later segment could cause the
cursor to skip some segments entirely, or leave the cursor in odd places
inside the segment. Users are advised to avoid overly complex placement of
word-wrapped fields. Form field configurations like:
[f001 ][f001 ]
[f001 ]
will probably yield counter-intuitive cursor movement. Columnar form field
configurations like the one below will give predictable results.
[f001 ]
[f001 ]
[f001 ]
WORDWRAP in REPORTS
-------------------
In release 4.11 of RDS, the WORDWRAP attribute in reports did not
yield correct results. Any report that attempted to use a PRINT statement
in conjunction with WORDWRAP could produce the following symptoms:
1) B13589: Misaligned output. The output would begin at the wrong column.
2) B07942: Extra trailing spaces. This made the PRINT statement appear to
ignore the CLIPPED attribute even when it had been specified.
3) B07942: Incorrect default right margin. The correct right margin is
position 132. The user is now provided with the full 127 characters of
width that are promised in the documentation.
All these bugs have been fixed in both Version 6.00 and Version 4.12.
AUTONEXT in CONSTRUCT
---------------------
When entering criteria during a CONSTRUCT into a field with the
AUTONEXT attribute, keying past the form field delimiter does not take the
cursor to the next field. During CONSTRUCT, AUTONEXT is ignored so that
the user can query for large ranges, alternatives, and so forth. Although
the original 4.xx documentation does not mention it, this is the intended
behavior of the product.
BEHAVIOR CHANGE OF CONSTRUCT WHEN INTERRUPTED
==============================================
Version 6.00 (and Version 4.12) of I4GL and RDS introduces a change
in the output of CONSTRUCT statements interrupted by the user striking the
interrupt key (usually CTRL-C or DEL) or the quit key (sometimes CTRL-\,
but often another character). Obviously, this applies only to programs
that have executed DEFER INTERRUPT or DEFER QUIT or both; otherwise, an
interrupt or quit keystroke terminates the application immediately.
In 4.10 and prior releases, interrupting a CONSTRUCT statement
(with an interrupt or quit keystroke) produced an output query string
that contained the contents of the field buffer at the time the interrupt
keystroke was hit. Therefore, if the program did not carefully check
the value of int_flag before proceeding, it could miss the fact that the
CONSTRUCT had been interrupted and proceed with a bad query.
In late 4.10.UE* releases and 4.11, a bug fix changed this behavior
such that the output query string reverted to its previous value. This
was also somewhat counterintuitive, and if the program failed to check
int_flag and take appropriate action, it would repeat the previous query
(or fail upon PREPARE if there was no previous uninterrupted execution of
that CONSTRUCT).
With this release, the behavior has been changed so that a
CONSTRUCT interrupted by an interrupt or quit keystroke produces a NULL
query string. This minimizes the chance that an unchecked interrupt
condition will proceed undetected. Also, the only way a CONSTRUCT can
produce a NULL query string is if it was interrupted; this gives an easy
means of detecting that an interrupt or quit occurred without having to
check both int_flag and quit_flag. (Recall that a successful CONSTRUCT for
which the user entered no criteria before striking the Accept key produces
the string " 1=1", not a null string.)
STATUS VALUE FROM "RUN ... RETURNING"
=====================================
The behavior of the value returned from a 4GL "RUN ... RETURNING"
clause was different on different machines. Because of OS limitations
(see exit(2) or wait(2) in the Unix Programmer's Manual), a range of only
256 values can be returned by the exit status of a command. However, the
operating system uses the low order 8 bits of a 16-bit integer for its own
information, and the 256 exit status values are stored in the high order 8
bits of the 16-bit integer.
When this 16-bit value is stored in a 4GL INTEGER variable, it is
always treated as an unsigned quantity, whereas previously it could be
treated as either signed or unsigned depending on platform. If the status
is stored in a SMALLINT, any exit status between 128 and 255 (and an exit
status of -1 is equivalent to 255) is stored as a negative number. For
portability, always store the status of the command in an INTEGER. You
need to divide the value saved by 256 to get the actual exit status. The
low order bits are only non-zero if the shell which ran the command was
killed by an unexpected signal.
NEW BUILTIN OPERATOR: ORD()
===========================
Overview:
This function evaluates the first character of a passed character
string argument as the corresponding integer number.
Syntax:
ORD (string-expr)
Explanation:
ORD is a required keyword.
string-expr is a string expression.
NOTES:
4GL only evaluates the first character of the passed string.
Non-string parameters return the value 0. The parentheses are
required.
Example:
The following assignment assigns the value 66 to the integer ord1.
LET ord1 = ORD ("Belladonna")
ENVIRONMENT VARIABLES
=====================
A number of environment variables have either been added or changed their
meaning slightly, or have existed but have not been documented previously.
These are documented in this section. You should also look at the environment
variables chapters in both the "Informix Guide to SQL: Reference Version 6.0"
manual and in the ISQL and 4GL manuals.
DBESCWT
-------
The environment variable DBESCWT has existed since Version 4.00,
and can be used to control the way the Informix tools interpret the
sequence of characters sent by the function and arrow keys on some types
of terminals. When you press a function key, many terminal types send a
sequence of characters that starts with the ESC character. Some terminals
send a sequence starting with ESC when the user hits an arrow key.
Informix software normally uses the ESC character as the ACCEPT key. This
means that after reading an ESC character, the software has to read another
character to see whether it is one of the ones that makes up a function or
arrow key sequence. But it shouldn't wait indefinitely, and the delay is
configurable using DBESCWT.
DBESCWT is set to a value between 1 and 60, and it is the number
of seconds that the software will wait after receiving the ESC (or ESCAPE)
character from the keyboard before deciding that the user has hit ESC
rather than having hit a function key or arrow key.
When escape sequences are generated by function and arrow keys,
they are normally delivered to the application faster than a touch-typist
can type so that the application can make a distinction between the special
keys and the user typing the characters in the escape sequence.
DBESCWT was initially implemented to help customers who had very
slow machines. This meant their function keys were seen as escape with a
character echoed to the screen. This also occurred intermittently over
a slow network. By setting this to a higher number the wait would be
longer and the product knows the function key as an escape sequence. This
variable should be used sparingly and only on systems with poor response
times, or where the software is misinterpreting arrow key sequences.
DBLANG: CHANGE OF BEHAVIOR
--------------------------
The DBLANG environment variable in version 6.0 uses a different
search method from that employed by pre-6.0 versions. In addition, if NLS
is enabled and DBLANG is not set, environment variable LANG also affects
the search order; in pre-6.0 versions, LANG does not play any role in
locating message files.
For a full explanation of the new behavior, see the DBLANG entries
in either the 4GL or ISQL Version 6.0 manuals.
DBFORM: CHANGE OF BEHAVIOR
--------------------------
The DBFORM environment variable, introduced in version 4.12,
behaves differently in version 6.0 with respect to the search method used
for locating form files. In addition, if NLS is enabled and DBFORM is
not set, the environment variable LANG also affects the search order; in
version 4.12, LANG does not play any role in locating form files. The
change mirrors the change made in handling DBLANG.
Please note that, as in version 4.12, DBFORM does not affect 4GL
programs written by the user; it is solely used by INFORMIX products when
accessing internal forms. DBPATH is used to control the location of form
files for user programs.
For a full explanation of the new behavior, see the DBFORM entries
in either the 4GL or ISQL Version 6.0 manuals.
SPERISOL and SACEISOL
---------------------
Version 4.11 of INFORMIX-SQL provided the ability to run PERFORM
forms using dirty read isolation with an OnLine backend. In Version 4.12,
this feature has been extended to allow ACE reports and PERFORM forms to
run in any isolation level.
This feature is of interest to you only if you are running ISQL
with OnLine, and is provided mainly to provide compatibility for those who
upgrade from Standard Engine to OnLine. The following description assumes
an understanding of "levels of isolation" in OnLine databases; you can find
this information in the "Informix Guide to SQL: Syntax Version 6.0" manual.
The Standard Engine always runs in a mode approximately equivalent
to dirty read mode; the default isolation level for OnLine databases
with no logging is dirty read, for MODE ANSI databases the default is
repeatable read, and for databases with transaction logging the default is
committed read. Each mode has a different tradeoff between isolation and
concurrency.
When you upgrade from a Standard Engine to OnLine, the isolation
level automatically changes, as described above. Usually, the new default
isolation level is more suitable than the old; however, in some cases, it
is preferable if the concurrency level remains the same under OnLine as it
was under Standard Engine.
This can be accomplished in 4GL by adding code that sets the
isolation mode to dirty read, and it can be similarly accomplished in ISQL
scripts. To set the isolation level for PERFORM, set the environment
variable SPERISOL to one of the following values; similarly, to set the
isolation level for ACE, set the environment variable SACEISOL to one of
these values:
dirty read
committed read
cursor stability
repeatable read
In Bourne Shell or Korn Shell, use:
SPERISOL="dirty read"; export SPERISOL
In C Shell, use:
setenv SACEISOL "repeatable read"
The isolation level can be specified in uppercase or lowercase
(or mixed case), but only a single space is allowed between the words, and
there must be no leading or trailing spaces. If the value in the variable
is unrecognized, the variable is silently ignored, as is the error from
Standard Engine. The environment variables must be set before running the
ISQL program (or SPERFORM or SACEGO); trying to set it using a shell escape
from within ISQL has no effect.
You can use different isolation levels for reports and forms by
setting the two environment variables to different values. Note that
setting the isolation to dirty read in PERFORM does not allow the user to
update a row that is locked by another user, but it would allow the user to
see a row that another user has locked.
DOCUMENTATION ISSUES
====================
There are a number of issues raised by bug reports which show that
some information is missing from the documentation. This section tries to
address some of these issues.
Three-valued Logic in 4GL
-------------------------
The three-valued logic (TRUE, FALSE, NULL) used by 4GL is fully
documented in the "Informix-4GL Reference Manual", but some people have
not understood all the consequences. This section elaborates on the
implications nulls in conditional expressions. In the manual, it is stated
that the THEN branch of an IF statement is only executed if the expression
evaluates to TRUE. It also points out that if there are NULL values
involved, then many of the simple tautologies of 2-valued Boolean logic no
longer apply.
To amplify on what this means, consider some code. For the
purposes of this discussion, variables v1, v2, and v3 are all of type
INTEGER, but the comments apply for any type, and for many mixtures of
types.
-- Example 1
IF v1 = 3 THEN
-- Code 1A
ELSE
-- Code 1B
END IF
If v1 is not null, then it either does equal 3, in which case code
1A is executed, or it doesn't, in which case code 1B is executed. If v1 is
null, then the condition evaluates to UNKNOWN, and since this is not TRUE,
code 1B is executed. Now consider this attempt at inverting the logic of
example 1:
-- Example 2 (faulty inverted logic for example 1)
IF v1 != 3 THEN
-- Code 1B
ELSE
-- Code 1A
END IF
When v1 is not null, then the code in example 2 achieves the same
effect as example 1. However, when v1 is null, the expression evaluates to
UNKNOWN again, and therefore the ELSE clause is executed. Thus, this is
not the direct inverse of example 1. Another way of viewing example 1 is
as if it is written with an implicit NOT NULL qualifier on the variable v1:
-- Example 3 (equivalent to example 1)
IF (v1 IS NOT NULL) AND (v1 = 3) THEN
-- Code 1A
ELSE
-- Code 1B
END IF
In example 3, if v1 is null, the first part of the condition
evaluates to FALSE, the second part evaluates to UNKNOWN, and the overall
expression evaluates to FALSE. Applying one of De Morgan's Theorems:
NOT (A AND B) == (NOT A) OR (NOT B)
to example 3 yields the correct inverted logic for example 1:
-- Example 4 (correct inverted logic for example 1)
IF (v1 IS NULL) OR (v1 != 3) THEN
-- Code 1B
ELSE
-- Code 1A
END IF
This code executes in exactly the same way as example 1: if v1 is
precisely 3 then code 1A is executed; otherwise, code 1B is executed.
This implicit NOT NULL qualifier is the cause of many problems with
inverting logic conditions in 4GL. Now consider a slightly more complex
condition:
-- Example 5
IF v1 = v2 THEN
-- Code 5A
ELSE
-- Code 5B
END IF
Clearly, if both v1 and v2 contain the same non-null value, code
5A will be executed; otherwise, code 5B will be executed. Note that the
description shows that there are implicit NOT NULL qualifiers on both v1
and v2, so the condition is equivalent to:
-- Example 6 (equivalent to example 5)
IF (v1 IS NOT NULL) AND (v2 IS NOT NULL) AND (v1 = v2) THEN
-- Code 5A
ELSE
-- Code 5B
END IF
Supplying the inverted logic for example 5 requires us to invert
the condition expressed in example 6, so the correct logic for the inverted
condition is:
-- Example 7 (correct inverted logic for example 5)
IF (v1 IS NULL) OR (v2 IS NULL) OR (v1 != v2) THEN
-- Code 5B
ELSE
-- Code 5A
END IF
This is significantly different from, and much more convoluted
than, the simple 2-value logic inversion of example 5:
-- Example 8 (faulty inverted logic for example 5)
IF (v1 != v2) THEN
-- Code 5B
ELSE
-- Code 5A
END IF
Extending the condition still further, consider:
-- Example 9
IF (v1 >= v2) AND (v1 <= v3) THEN
-- Code 9A
ELSE
-- Code 9B
END IF
By direct analogy with what has gone before, this is equivalent to:
-- Example 10 (equivalent to example 9)
IF ((v1 IS NOT NULL) AND (v2 IS NOT NULL) AND (v3 IS NOT NULL) AND
(v1 >= v2) AND (v1 <= v3)) THEN
-- Code 9A
ELSE
-- Code 9B
END IF
And the corresponding inverted condition is:
-- Example 11 (correct inverted logic for example 9)
IF ((v1 IS NULL) OR (v2 IS NULL) OR (v3 IS NULL) OR
(v1 < v2) OR (v1 > v3)) THEN
-- Code 9B
ELSE
-- Code 9A
END IF
CASE Statements
---------------
The CASE statement is equivalent to a series of IF/THEN/ELSE
statements. Thus the code in example 12 is equivalent to the code in
example 13
-- Example 12 (CASE statement type 1)
CASE
WHEN v1 < v2
-- Code 12A
WHEN v1 > v3
-- Code 12B
OTHERWISE
-- Code 12C
END CASE
-- Example 13 (direct equivalent to example 12)
IF v1 < v2 THEN
-- Code 12A
ELSE
IF v1 > v3 THEN
-- Code 12B
ELSE
-- Code 12C
END IF
END IF
Suppose the requirements change such that code segments 12A and 12B
are modified and become the same code; call it code 12D. It then seems
logical to rewrite the code as:
-- Example 14 (faulty reworking of example 12)
IF v1 BETWEEN v2 AND v3 THEN
-- Code 12C
ELSE
-- Code 12D
END IF
However, careful analysis of the cases where v1, v2, or v3 are NULL
shows that the code in 12C is only executed in a subset of the cases where
it used to be executed There are two ways of reworking the code correctly.
-- Example 15 (correct reworking of example 12)
IF v1 NOT BETWEEN v2 AND v3 THEN
-- Code 12D
ELSE
-- Code 12C
END IF
-- Example 16 (alternative correct reworking of example 12)
IF (v1 IS NULL OR v2 IS NULL OR v3 IS NULL OR v1 BETWEEN v2 AND v3) THEN
-- Code 12C
ELSE
-- Code 12D
END IF
Again, the implicit IS NOT NULL qualifiers make life much more
difficult than they otherwise would be.
The I4GL compilers (both C4GL and FGLPC) accept CASE statements
with WHEN clauses of the form:
CASE variable
WHEN "A" OR "B"
The condition is translated to:
if (variable == ("A" or "B"))
and not, as some people have supposed,
if (variable == "A" or variable == "B")
The compilers also accept code of the form:
CASE variable
WHEN (variable = "A" OR variable = "B")
that is translated to:
if (variable == (variable == "A" or variable == "B"))
This is a legitimate test (though the result is false unless the value of
variable is 0), but it is not what the coder intended. The only method of
achieving the required result is to repeat the code as shown:
CASE variable
WHEN "A"
-- code --
WHEN "B"
-- code --
Obviously, this should be reduced to the minimum possible, typically by
calling a function.
Processing of a single field during INPUT or INPUT ARRAY
--------------------------------------------------------
The Informix-4GL manuals contain a detailed description of the
sequence in which the various BEFORE FIELD and AFTER FIELD control blocks
(and for INPUT ARRAY, the BEFORE and AFTER ROW or INSERT or DELETE control
blocks), but there is no single point which describes what happens while
the cursor is in a single field.
There are many things to consider. These include:
-- Data type
-- Underlying database column
* NULLS allowed, NOT NULL
-- Attributes in the form
* REQUIRED
* NOENTRY
* UPSHIFT/DOWNSHIFT
* WORDWRAP NONCOMPRESS, WORDWRAP COMPRESS
* PICTURE
* FORMAT
* WITHOUT NULL INPUT
The data type for the field controls the range of acceptable input.
The acceptable values for the various data types is documented in many of
the Informix manuals. See for example the Informix Guide to SQL Reference
Version 6.0, Chapter 3 (and also Chapter 4 for information on environment
variables which modify the set of acceptable values).
Whether the column accepts nulls or not determines whether the
field will allow you to enter a null value, although this can be overridden
by the program. If the column does not accept nulls, then the field may
not be left null (blank) when the accept key is hit. If one field is blank
but shouldn't be, then the cursor is returned to that field with the
message "This field requires an entered value". This effect can also
be achieved by adding the REQUIRED attribute to the form. This can be
valuable when dealing with FORMONLY fields which should have data entered.
You can override this effect by using EXIT INPUT in an AFTER FIELD clause.
Note that a required field can be left blank until the ACCEPT key is hit.
If the field may not be left blank after the cursor has entered it, then
the AFTER FIELD block must enforce this.
Note that if a field is left blank, or with precisely the image of
the PICTURE attribute, it is treated as NULL and the input variable is set
to NULL, unless of course the REQUIRED attribute is effective.
A field can be specified as NOENTRY. Even if this field is listed
in an INPUT statement, the cursor will not enter this field but will skip
over it. Note that fields associated with SERIAL columns are automatically
NOENTRY fields. The NOENTRY attribute does not stop the field being used
by CONSTRUCT.
The UPSHIFT or DOWNSHIFT attribute forces all characters entered in
a field to either upper case or lower case.
The WORDWRAP attribute is discussed elsewhere in this document.
The PICTURE attribute controls the input format for a field, and
has no effect on the data displayed in the field. If the user does not
type anything into the field, it is treated as NULL. However, once any
data has been typed into the field, there is no way in general to leave the
field without entering a valid value (B12412).
By contrast, the FORMAT attribute controls the display format for a
field and does not constrain the input format. For example, a data could
be entered as 940506 and displayed as 1994-05-06.
WITHOUT NULL INPUT is an attribute of the form rather than of a
field. If the form contains this attribute, then all non-blob fields will
have a default value substituted in place of NULL at the end of the input.
The REQUIRED attribute overrides this default. The default value is 0 for
numbers and intervals, blank for character strings, 31 December 1989 for
dates, and 1989-12-31 23:59:59.99999 for datetime year to fraction(5).
This was introduced primarily as a transition measure with ISQL 2.00
(upgrading from ISQL 1.10) and I4GL 1.00 (a new product), but has survived
ever since. See B12268 below.
Number of Keys in a COMMAND KEY Clause
--------------------------------------
MENU has always had a limit on the number of keys that can be
bound to a given COMMAND KEY() clause, but this limit was never properly
documented. This limit is four keys per command clause. For example:
MENU "Main Menu"
COMMAND "Option 1" "Option 1 Description"
...
COMMAND KEY("a", "up", CONTROL-F, F35) {LEGAL}
...
COMMAND KEY("b", "down", CONTROL-B, F36, F10) {ILLEGAL - 5 keys}
...
If you exceed this limit, RDS returns error -4457 at compile time.
I4GL returns an error at phase 2 of the compile of the form:
i4glc2: file "cmkey.ec", line 31: You may have at most 4 keys in the key list
In a future release, the limit may be expanded; even if it is not
expanded, a more helpful error message will be produced by compiled 4GL.
Using the FREE Statement
------------------------
The FREE statement can be used to release space acquired for blobs
and for releasing the space associated with statements and cursors. The
handling of blobs has not changed.
In 6.00 4GL, you should FREE both statements and cursors to
release all the space they use. You can FREE a statement after a cursor
has been declared from it, and you can still use the cursor. See the
"Informix Guide to SQL: Syntax Version 6.0" manual on FREE. Note that the
example does not show freeing both the statement and the cursor, but the
accompanying text makes it clear that you should, and experiments with
memory monitors support this.
The USING Clause and the FORMAT Attribute
-----------------------------------------
In 4GL it is possible to specify the output format of numbers and
monetary values via the USING clause or by the FORMAT attribute. These
programming constructs have been tested and do work for all European
locales; however, there are some bugs in the interaction of these
features and DBFORMAT. When DBFORMAT is set to a value that specifies a
leading currency symbol that is longer than 5 characters, a USING clause
(or equivalently a FORMAT attribute) for money (e.g. "$$$,$$$.##" or
"###,###.##@@") can result in output that is missing some of the least
significant digits.
Several work-arounds exist. One is to consider whether the
currency symbol is appropriate, preferably switching to an alternative of 5
characters or less. The preferred solution is to switch over to a purely
locale-based formatting environment. This solution involves obtaining
the appropriate locale and the setting LANG to refer to this locale (e.g.
setenv LANG de) and then turn off DBFORMAT (e.g. unsetenv DBFORMAT). If
you still want to use DBFORMAT, you may simply add more digits to the USING
clause (e.g. "$$$,$$$.###" instead of "$$$,$$$.##").
Behavior of ISQLDEMO
--------------------
Bug No. Effect Short Description
_______ ______ _________________
23158 MALFUN ISQLDEMO DOES NOT INSTALL ALL THE REQUIRED FILES AND
LIBRARIES, NOR DOES IT DESCRIBE HOW TO COMPILE AND INSTALL
FUNCTIONS
Bug 23158 was logged against isqldemo but was found to be a
documentation issue. The ISQLDEMO script does not try to build the 4
different custom runners that would be required to enable the user to run
the 4 forms and reports that need custom runners. The information on how
to compile these custom runners is contained in the INFORMIX-SQL Reference
Manual. The reports that will not run are a_ex1.ace and a_ex2.ace; the
forms that will not run are p_ex1.per and p_ex2.per. The ISQL program
cannot run those forms or reports directly. The nearest that can be
achieved is to use either the shell escape or to run them from a User Menu
option (which would have to be of type "P"). You can compile them without
error, but when you try to run them, you will get an error message stating
that some functions have not been defined.
Behavior of STARTLOG
====================
Bug No. Effect Short Description
_______ ______ _________________
14426 MALFUN STARTLOG() DOESN'T RETURN MODULE NAME OR LINE# FOR ERROR -4500
19764 MALFUN CALL STARTLOG NOT DISPLAYING MODULE OR LINE NUMBER IN I4GL
Bugs 14426 and 19764 were logged against the STARTLOG function,
but were found to be a documentation issue, and are effectively duplicates
of each other. The documentation states that the error record will always
contain the line number and module name where the error occur, as well as
the date and time when the error occurred. In some circumstances, such as
error -4500, which occurs inside an operating system function called by
I4GL, the line number and module name is not available. By contrast, this
information is always available in RDS.
GUIDELINES ON 4GL REPORT WRITING
================================
This section documents certain practices that are prohibited or
are at least heartily discouraged within report functions, and it gives
some guidelines with respect to usage of module global or program global
variables within reports.
Note that the compilers do not allow the following statements
within report functions. However, these statements can be executed by
functions that are called from within the body of a report:
* PROMPT
* INPUT
* INPUT ARRAY
* DISPLAY ARRAY
* CONSTRUCT
Using RETURN in a Report is not Appropriate
-------------------------------------------
The RETURN statement is not appropriate for use in a REPORT
function at any time; it is designed for use in regular 4GL functions only.
The compilers do, however, allow the programmer to use RETURN in a REPORT.
If you wish to stop processing of a given report without aborting the
program altogether, the best method is to set a global flag that is tested
in your report driver function (where the OUTPUT TO REPORT statement(s) are
located). If the flag value indicates a problem, finish the report and
ignore the output.
If your report uses ORDER BY (without the EXTERNAL keyword), or if
you use a WHERE clause with any aggregate (as described in the Informix-4GL
Reference Manual), or if you use non-GROUP aggregates in any control block
other than the ON LAST ROW control block, the report is processed as a
"multi-pass" report. This means that the report function's control blocks
do not execute until all data has been gathered and the FINISH REPORT
statement has been reached in the report driver function. At this point,
from the 4GL programmer's perspective, the report function executes as a
unit, and it cannot be programmatically aborted from within (since you
cannot use the RETURN statement).
Better methods for allowing the 4GL programmer to abort report
processing are being studied for implementation in a future release.
Parameterless Reports
---------------------
Parameterless reports are not illegal and are occasionally useful
for very specialized reports, but their behavior is not intuitively
obvious. In particular, aggregates only work reliably when applied to
parameters to reports, and not when they are applied to global or local
variables. Additionally, ordering has to be done on parameters.
Global Variable Usage
---------------------
The use of module global or program global variables in reports
is legal, and prudent use of globals can provide performance benefits.
However, the use of globals in multi-pass reports may yield unexpected
results. Some guidelines are presented here:
If you know that your report is not a multi-pass report (as defined
above), and you refer to variables that are not used as control information
in the report (e.g., they are not referenced in BEFORE/AFTER GROUP OF
clauses or in aggregates; they are merely printed), any such variables can
be global variables. In fact, passing long character strings as global
variables instead of report parameters can result in an improvement in
performance, if these other conditions are met. Also, any global variables
that will not change in value while generating the report may be freely
used even in multi-pass reports if these other conditions are met.
In a multi-pass report, most references to a global variable use
the value of the variable when the FINISH REPORT statement is executed.
This yields unexpected results if the global variable value changes between
OUTPUT TO REPORT statements.
Temporary Tables Created by Multi-pass Reports
----------------------------------------------
A multi-pass report creates a temporary table to hold the data as
rows are sent to the report by OUTPUT TO REPORT statements. The temporary
tables are created by prefixing the report name with "t_".
In version 4.11 and earlier versions, a report that had a name of
17 or more characters resulted in an attempt to create a temp table with
19 or more characters in its name, leading to a runtime error from the
engine. This is no longer a problem in version 4.12 because the names of
the temporary tables are truncated at 18 characters. The names of reports
that run concurrently should still be distinct within 16 characters, as
otherwise the second one started will encounter "table exists" errors.
You should also be wary of designing a database with tables whose
names start "t_" as this restricts the names that can be used for report
functions in a non-obvious way. Note that the temporary tables are
inherently private to the user running the report, so there is no conflict
with multiple users running the same report, nor with the same user running
the same report in different windows.
B. Selected Notes from Earlier Releases
Notes from the 4.11 Release
===========================
CONSIDERATIONS FOR FUTURE RELEASES
----------------------------------
Informix Software's internal Compatibility Guidelines recommend
that features evolving or being made obsolete be documented in the
release notes of the previous release. Our existing policy states that
undocumented features are unsupported in the current release and may
"disappear" in future releases. It is too early to categorically list such
candidate features, but we can indicate some areas of functionality that
may be altered in a future release:
1. User calls to the "_ef..." functions in the 4GL libraries
libforms.a and libnforms.a. These may be replaced by more
fully-featured and supported user-accessible library, supported in
both compiled 4GL and RDS. This includes _eflastkey, an
undocumented feature which is often used by developers, and that
has now been fully implemented as the 4GL fgl_lastkey() function.
_eflastkey still works in 4.10, but may not in a future release, so
we strongly encourage conversion to the supported function.
2. Direct calls to our curses implementation (e.g., waddch(), wmove(),
wrefresh()) may not be supported in a future release.
3. User identifiers should never begin with an underscore, to avoid
conflicts with Informix's (or another product's) library naming
conventions (e.g., C functions and variable names).
Note that all features and recommendations described here are subject to
change without notice.
COMPILE-TIME AND LIBRARY FUNCTIONS: NAMING CONVENTIONS
-------------------------------------------------------
The 4.10 release of 4GL introduced several compile-time and library
functions that are fully documented in the Informix-4GL Version 6.00
manuals. 4GL developers should avoid using the "fgl_" prefix, to forestall
any future library function name conflicts. In future releases, this
prefix may be reserved.
API macros 4GL Functions
---------- -------------
fgl_call() fgl_getenv()
fgl_end() fgl_keyval()
fgl_exitfm() fgl_lastkey()
fgl_start() field_touched()
get_fldbuf()
Notes from the 4.10 Release
===========================
Compatibility Issues
--------------------
Using Version 4.10 and Older Versions of INFORMIX-4GL and INFORMIX-SQL
----------------------------------------------------------------------
This section discusses general improvements or corrections
to the products that may affect existing applications.
The topics largely address the areas of ANSI-compliant
syntax and general error handling behavior.
1. The 4.10.UC1 version of the database engines introduced enforcement
against redundant specifications of table names in INSERT and
UPDATE statements, per ANSI requirements. For example, the
following statements were allowed in 4.00 and earlier but would
produce syntax errors due to the redundant table names when used
with a 4.10 and higher database engine:
INSERT INTO tab1(tab1.col1, tab1.col2) VALUES (val1,val2)
^^^^ ^^^^
UPDATE tab1 SET (tab1.col1, tab1.col2) = (a,b)
^^^^ ^^^^
This change was made effective for both MODE ANSI and non-MODE ANSI
databases.
Effective with version 4.10.UE1 of the database engines, the
redundant table name no longer produces error messages in
non-MODE ANSI databases. This helps avoid problems for users
who are migrating existing applications to the 4.10 engines.
However, we recommend against including redundant table names,
since these do not provide any benefit and can limit portability of
your applications to MODE ANSI environments.
Therefore, the above examples should be corrected to read:
INSERT INTO tab1 (col1, col2) VALUES (val1,val2)
UPDATE tab1 SET (col1, col2) = (a,b)
2. A change was made in the behavior of MODE ANSI so that cursors not
explicitly declared "FOR UPDATE" are still treated as update
cursors. This is correct ANSI behavior. However, if the cursors
are not declared for update, no update lock is put on the row when
it is read. As a result, users may get lock errors when they try
to update the row.
3. For MODE ANSI databases, if any statement returns no rows (ie, no
rows meet the search criteria), the return code is now 100, instead
of 0 as it is for databases that are not MODE ANSI.
4. The ANSI standard requires that all identifiers, including owner
names and login names, be in uppercase letters. In MODE ANSI, you
must enclose lowercase and mixed-case identifiers in quotes if you
want to preserve the case. Otherwise, all owner and login names
(except informix and public) are shifted to uppercase.
5. Cursor Manipulation
The following rules are adhered to in the 4.10 release and
are in effect for all later releases:
CLOSE CURSOR
---------------
Cases that result in an error:
a. Closing a cursor that has been declared but never opened.
b. Closing an already closed cursor in a MODE ANSI database.
Cases that do NOT result in an error:
a. Closing an already closed cursor in a non-MODE ANSI database.
FREE CURSOR/STATEMENT ID
------------------------
Cases that result in an error:
a. Closing a FREEd cursor.
Cases that do NOT result in an error:
a. FREEing a cursor or statement-id more than once.
b. FREEing a cursor that has been declared but never opened.
Additional Rules
----------------
In addition to the preceding rules, the following also apply:
a. A statement-id that has been FREEd must be
PREPAREd again in order to be used again.
b. A cursor that has been FREEd must be
DECLAREd again in order to be used again.
6. CONSTRUCT/END CONSTRUCT within INPUT
If the current application is using a CONSTRUCT within an INPUT
statement, the CONSTRUCT statement needs to be terminated with an
END CONSTRUCT statement, to properly assign ON-KEY clauses to their
INPUT statements. Here is an example:
INPUT BY NAME col1, col2, col3
...
ON KEY (CONTROL-M)
CONSTRUCT BY NAME query on col1, col2
END CONSTRUCT -- Needed
ON KEY (CONTROL-Y)
...
END INPUT
USE OF USER MENU WITH MODE ANSI DATABASES
-----------------------------------------
Because of the owner identification of objects in MODE ANSI
databases, the person who first creates the user menu in ISQL by choosing
the Modify option is the only user who can change the menu. All others
attempting to modify the user menu receive an error message.
USE OF UPSCOL WITH MODE ANSI DATABASES
--------------------------------------
By using UPSCOL, a user can store default attributes and validate
data in syscolval and syscolatt only for tables owned by the user. A form
that refers to tables owned by other users uses the defaults and attributes
defined by the other users. Similarly, the INITIALIZE statement uses the
defaults defined by the owner of the table in which the column resides.
IV. BUGS FIXED IN THIS RELEASE
A total of 160 bugs which had previously been visible to customers
were fixed in Version 6.00. This includes 125 bugs also fixed in 4.12.
It excludes bugs which were never seen by customers (bugs found during
development and testing), and also bugs which were fixed in an earlier
version than 4.12 but which were not shown to be fixed until after 4.12 was
released. There are quite a lot of bugs in both categories.
The following bugs were fixed in 4GL:
Bug No. Effect Short Description
_______ ______ _________________
01857 MALFUN ERR -4518 DUE TO NOT FREEING TEMP STR SPACE
02731 WKARND .4GE PERMISSIONS NOT CONSISTENT I4GL/C4GL.
03705 COSM I4GL SCREEN IS NOT REFRESHED AFTER RETURNING FROM
QUERY LANGUAGE.
07360 MALFUN UNLOAD STMT WITH HOST VARIABLES IN WHERE CLAUSE FAILS
W/-202 ERR
09874 RESULT C4GL GENERATES CHAR STRINGS OF LEN 1 IF DEFINE LEN >
32767
10465 WKARND CONTINUE INPUT DOES NOT RETURN THE CURSOR TO THE SAME
FIELD
10509 MALFUN NO DISPLAY WHEN FORM LINE 1 AND FIRST FIELD IS
WORDWRAP
10622 CORRPT NATIONAL CHARS IN FORM DISPLAYED INCORRECT WHEN
REENTERING FIELDS
10624 CORRPT DATA ENTRY NOT MANDATORY IF FIELD REQUIRED AND
DATABASE NOT NULL
10739 RESULT 4GL ROUNDS UP MONEY TYPE AND SHIFTS OUTPUT TO RIGHT 1
POSITION
10978 MALFUN FGLPC DOES NOT CLOSE DATABASE BEFORE COMPILING NEXT
FILE
11336 WKARND ERROR LINE REAPPEARS AFTER BEING OVERWRITTEN BY FORM
ERROR
11350 WKARND PREVIOUS ATTRIBUTE KEPT ON LONG CHAR DISPLAY USING
WORDWRAP
11580 RESULT EXTRA HEADER ON SECOND REPORT IF SKIP TO TOP OF PAGE
ON LAST ONE
11959 MALFUN 4.0 RDS AND C4GL COMPILERS ADD QUOTES TO OWNER NAMES.
12071 RESULT INCONSISTENT VALUES FROM "RUN ... RETURNING" -
SOMETIMES SIGNED
12342 MALFUN LAST WORD IN WORDWRAP FIELD IS NOT ACCESSIBLE WITH
ARROW KEYS
12524 MALFUN GRANT PRIVILEGES TO QUOTED USER OF MODE ANSI DB FAILS
IN 4.00
12836 MALFUN DEFER QUIT DOES NOT WORK
13266 MALFUN MOD BY ZERO PRODUCES CORE DUMP
13330 MALFUN DISPLAY WITHIN BEFORE INPUT CAUSES FIELD_TOUCHED TO
REPORT TRUE
13977 MALFUN COMPILED 4GL CORE DUMPS WHEN ENCOUNTERING AN EMPTY
MENU TITLE
14033 MALFUN WORDWRAP FIELD IN CONSTRUCT DISPLAYS UNNECESSARY
OVERFLOW LINE
14260 CORRPT INPUT ARRAY INSERT LEAVES PREV VALUES IN INSERTED ROW
14847 MALFUN 4GL DOES NOT USE "DBLANG" TO ACCESS ITS HELP MESSAGES
15051 WKARND UNLOAD STATMENT IN 4GL DOESNT RECOGNIZE VARIABLES IN
WHERE CLAUSE
15059 CORRPT INPUT ARRAY WITHOUT DEFAULTS: F1 & F2 COPY OLD DATA
INTO NEW ROW
15148 NA FEATURE REQUEST: INTRODUCE A 'DBLANGFORM'
ENVIRONMENTAL VAR.
15246 MALFUN 203 PRINT SUM() STATEMENTS IN THE ON LAST ROW WON'T
COMPILE
15379 MALFUN TERMCAP WITH SG#=1 CAN OPEN WINDOWS WITH 77 AND LESS
COL NOT 78
15381 MALFUN OPEN WINDOW X AT ROW, COL WHERE COLUMN IS 1 THRU N NOT
2 THRU N
15410 RESULT TENTH DIGIT GETS SQUASHED ON MONEY DATA TYPE IN 4.1,
NOT IN 4.0
15434 CORRPT EDITOR BLANKS NOT STORED WHEN USING UNCOMPRESSED
WORDWRAP IN FORM
15710 RESULT FGL_KEYVAL WITH SUBSTRING CAUSES CHAR AFTER SUBSTRING
TO BE NULLL
15930 WKARND START REPORT .. TO PIPE CLEARS SCREEN IN 4.10
15976 MALFUN CLOSE WINDOW GETS -1141 AFTER INTERRUPT IN CONSTRUCT
16188 MALFUN USE OF INVALID STRUCT EFWINDOW BY 4GL C CODE GENERATOR
16763 MALFUN UNABLE TO READ THE COMPILED VERSION OF A FORM.
17795 WKARND WITHOUT NULL INPUT CLAUSE IN FORM REQUIRES INPUT
17956 MALFUN ERROR 4322 FROM COMPILE OF COMPLICATED PROGRAM
W/MULTIPLE TABLES
17975 WKARND CANNOT DISPLAY 80-COLUMN WINDOWS
18456 MALFUN CORE DUMPS ON ENTRY INTO FIELD WITH DEFAULT & INCLUDE
ATTRIBUTE
18673 WKARND DELETING LAST ROW OF INPUT ARRAY DOESN'T ERASE UNTIL
UP-ARROW".
18762 WKARND COLUMN NAMES STARTING WITH "_" WILL NOT COMPILE
18993 WKARND DBFORMAT DOESN'T WORK CORRECTLY WITH INCLUDE ATTRIBUT
19472 WKARND CANNOT INTERRUPT FOREACH WITH OPTIONS SQL INTERRUPT ON
19557 WKARND THE COMMENT LINE IS BLANKED OUT WITH WORDWRAP ATTRIB.
ON CONSTRUC
19617 WKARND REPORT TO PIPE NAMED "LPR" REVERTS TO DBPRINT/DEFPRINT
SETTING
19768 WKARND PICTURE ATTR ON DATETIME FIELD DOESN'T ALLOW NULL
INPUT
20073 MALFUN INVISIBLE ATTR DEFINED IN FORM DOES NOT WORK DURING
INPUT STMT
20646 ERRMSG BYTE BLOB WITH NO PROGRAM = SAYS USE ! WHEN ! HIT
20652 WKARND PRINT STR WORDWRAP RIGHT MARGIN X WITH X INTEGER
TRIGGERS ASSERT
20900 WKARND C4GL REPORTS PRINT (LEFT MARGIN) SPACES ON FIRST LINE
OF TOP MARG
20940 MALFUN DUFF C GENERATED: FOR LOOP HAS INCREMENT/DECREMENT &
TYPE INTEGER
21202 MALFUN F4GLC GENERATES ERRONEOUS ESQL/C FOR LET X = F(R.A
THRU R.N)
21272 WKARND FGLPC ALLOWS TIME(X) AND NOW AS BUILT-IN FUNCTIONS;
FGLC DOESN'T
21330 MALFUN FGLPC ACCEPTS DISPLAY ASCII 3; FGLC2 DOESN'T
21358 WKARND UNDOCUMENTED KEYWORD NOW DOESN'T WORK
21359 WKARND BUILT-IN FUNCTION TIME ACCEPTS ARGS IN RDS BUT NOT
C4GL
21360 WKARND UNDOCUMENTED KEYWORD NOCR ACCEPTED BY C4GL BUT NOT RDS
21362 NA MISSING INVERSE FUNCTION OF ASCII
21479 WKARND RUN "SLEEP 30; SOMETHING ELSE" WITHOUT WAITING WAITS
30 SECONDS
21480 WKARND FGLGO ALLOCATES BUT DOES NOT FREE MEMORY WHENEVER A
CMD IS RUN
21484 WKARND FGLC ALLOWS: RUN CMD WITHOUT WAITING RETURNING VAL;
FGLPC DOESN'T
21729 CORRPT BLOB VARIABLES UNUSABLE AFTER BEING INITIALIZED TO
NULL
21737 MALFUN REPORT OF 17 OR MORE CHARS WITH INTERNAL SORT FAILS AT
RUNTIME
21747 MALFUN CONSTRUCT BY NAME GIVES A CORE DUMP, IF THE FLD IS NOT
DEFINED
21750 MALFUN CORE DUMP W/INPUT FROM ONE FORM, DISPLAY ANOTHER THEN
EXIT INPUT
21823 WKARND USING VARCHARS RESULTS IN NULL CHARACTERS IN 4GL
REPORTS.
21825 WKARND UPSHIFT/DOWNSHIFT READ BEYOND ALLOCATED SPACE
21970 MALFUN CORE DUMP WITH INPUT ON SAME STRUCTURED FORM
21975 MALFUN UNLOAD COMMAND CAUSING CONCATENATION PROBLEMS IN 4GL
22112 WKARND 4GL REPORTS: PRINTING A NULL DATETIME OR INTERVAL
PRINTS NO SPACE
22198 RESULT REVERSE ATTRIBUTE IN A FORM YIELDS THE DISPLAYED
VALUES INVISIBLE
22303 CORRPT SETTING A VARCHAR IN A FUNCTION LINKED IN AT COMPILE
TIME (A .O FILE) DOES NOT CONTAIN THE VALUE WHEN IT
RETURNS TO THE CALLING FUNCTION
22426 MALFUN IF SUBSTRING RETURNED FROM FUNCTION IS CONVERTED TO
DECIMAL, PURIFY REPORTS ABR AND ABW
22489 MALFUN BLOB VARIABLES UNUSABLE AFTER BEING INITIALIZED TO
NULL
22610 CORE ORDER EXTERNAL BY WITH MORE THAN 8 FIELDS CORE DUMPS
IN RDS. DUP OF B13346.
22697 CORE INTERRUPT IN CONSTRUCT CLOBBERS ICB, YIELDS SEG FAULT
IF CONSTRUCT RERUN, ALSO GIVES OLD QUERY STRING BACK.
22738 ERRMSG ERR_GET DOES NOT RETURN TABLE NAME WHEN SQLCODE PASSED
IS -206
23186 MALFUN STATUS IS STILL SET TO ZERO WHEN UNLOAD STATEMENT IS
FAILED
23262 MALFUN PROMPT WITH NO INPUT SUPPLIED GIVES UMR FROM PURIFY
23468 MALFUN THE DATETIME LIMITS ON A DATETIME VARIABLE USED IN A
STRUCTURE WITH A LET X.* = Y.* CORRUPTS THE DATETIME
VARIABLE IN STRUCTURE X
23560 WKARND C4GL FAILS TO CATCH A SYNTAX ERROR IN "DECLARE XX
CURSOR ... FOR UPDATE OF"
23705 MALFUN DECIMAL VALUE SELECT FROM TABLE ASSIGNS WRONGLY TO
LARGER PRECISION/SCALE VARIABLE
23707 MALFUN REVERSE AND INVISIBLE ATTRIBUTES USED TOGETHER ON
SCREEN FIELD WILL CAUSE INVISIBLE NOT TO WORK IF
SCROLL BACK TO THE FIELD - BOTH RDS/4GL
24040 RESULT THE DEFAULT VALUE OF THE SCREEN FORM FOR DATA TYPE
"DECIMAL" SUBSTITUTES A VALUE OF ZERO "0" FOR THE
NUMBER IN THE THIRD DECIMAL PLACE.
24079 ERRMSG 4GL DOES NOT RETURN CONSTRAINT NAME IF VIOLATED
REFERENTIAL CONSTRAINT.
24162 MALFUN FORM FIELDS IMPROPERLY DISPLAYED ON VT100 TERMINAL
EMULATION
24748 MALFUN USING "<>" AS DELIMITER IN A FORM CAUSES PROBLEMS WITH
REVERSE