Summary:
This simple example displays a text message to the screen, illustrating the structure of a BDL program.
Because Genero BDL is a structured programming language as well as a 4th generation language, executable statements can appear only within logical sections of the source code called program blocks. This can be the MAIN statement, a FUNCTION statement, or a REPORT statement. (Reports are discussed in Chapter 9.)
Execution of any program begins with the special, required program block MAIN, delimited by the keywords MAIN and END MAIN. The source module that contains MAIN is called the main module.
The FUNCTION statement is a unit of executable code, delimited by FUNCTION and END FUNCTION, that can be called by name. In a small program, you can write all the functions used in the program in a single file. As programs grow larger, you will usually want to group related functions into separate files, or source modules. Functions are available on a global basis. In other words, you can reference any function in any source module of your program.
The following example is a small but complete Genero BDL program, simple.4gl
Program simple.4gl |
|
Notes:
01
simply lists the filename as a comment,
which will be ignored by BDL. 03
indicates the start of the MAIN
program block.04
Within the MAIN program block, the
CALL statement is used to invoke the function named sayIt.
Although no arguments are passed to the function sayIt, the empty
parentheses are required. Nothing is returned by the function.05
defines the end of the MAIN
program block. When all the statements within the program block have been executed the
program will terminate automatically.07
indicates the start of the
FUNCTION sayIt.08
uses the DISPLAY
statement to display a text message, enclosed within double quotes, to the user.
Because the program has
not opened a window or form, the message is displayed on the command line.09
indicates the end of the FUNCTION.
The comment ( -- sayIt ) is optional. After the message is displayed, control in the program is returned to the
MAIN function, to line 05
, the line immediately
following the statement invoking the function. As there are no additional statements to be
executed (END MAIN has been reached), the
program terminates.BDL programs are made up of a single module, or modules, containing the program functions.
The following tools can be used to compile and execute the simple program from the command line.
fgldbsch -db custdemo
fglcomp simple.4gl
fglrun simple.42m
Programs consisting of multiple modules must be compiled and linked; this can be accomplished in one command using the following tool:
fgl2p -o myprog.42r simple.4gl newmodule.4gl
The resulting program is executed using the name of the output file that you specified:
fglrun myprog.42r
Tip:
fglcomp simple fglrun simpleYou can do this in one command line, adding the -M option for errors:
fglcomp -M simple && fglrun simple
You can use the command line debugger to search for programming errors. The command line debugger is integrated in the runtime system. You typically start a program in debug mode by passing the -d option to fglrun.
The following lines illustrate a debug session with the previous program sample:
fglrun -d simple (fgldb) break main Breakpoint 1 at 0x00000000: file simple.4gl, line 2. (fgldb) run Breakpoint 1, main() at simple.4gl:2 2 CALL sayIt() (fgldb) step sayit() at simple.4gl:6 6 DISPLAY "Hello, world!" (fgldb) next Hello, world! 7 END FUNCTION -- sayIt (fgldb) continue Program existed normally. (fgldb) quit
For more details, see the Debugger reference.
This program illustrates connecting to a database and retrieving data, defining variables, and passing variables between functions. A row from the customer table of the custdemo example database is retrieved by an SQL statement and displayed to the user.
A Database Connection is a session of work, opened by the program to communicate with a specific database server, in order to execute SQL statements as a specific user. To connect to a database server, most database engines require a name to identify the server, a name to identify the database entity, a user name and a password.
Connecting through the Open Database Interface, the database can be specified directly, and the specification will be used as the data source. Or, you can define the database connection parameters indirectly in the FGLPROFILE configuration file, and the database specification will be used as a key to read the connection information from the file. This technique is flexible; for example, you can develop your application with the database name "custdemo" and connect to the real database "custdemo1" in a production environment.
The CONNECT instruction opens a session in multi-session mode, allowing you to open other connections with subsequent CONNECT instructions (to other databases, for example). If you have multiple connections open, you can use the SET CONNECTION instruction to switch to a specific session; this suspends other opened connections. The DISCONNECT instruction can be used to disconnect from specific sessions, or from all sessions. The end of a program disconnects all sessions automatically.
The user name and password can be specified in the CONNECT instruction, or defaults can be defined in FGLPROFILE. Otherwise, the user name and password provided to your operating system will generally be used for authentication.
CONNECT TO "custdemo"
A Variable contains volatile information of a specific BDL data type. Variables must be declared before you use them in your program, using the DEFINE statement. After definition, variables have default values based on the data type.
DEFINE cont_ok INTEGER
You can use the LIKE keyword to declare a variable that has the same data type as a specified column in a database schema. The column data type defined by the database schema must be supported by the language. A SCHEMA statement must define the database name, identifying the database schema files to be used. The column data types are read from the schema file during compilation, not at runtime. Make sure that your schema files correspond exactly to the production database.
DEFINE store_name LIKE customer.store_name
Genero BDL allows you to define structured variables as records or arrays. Examples of this are included in later chapters.
Variables defined in a FUNCTION, REPORT or MAIN program block have local scope (are known only within the program block). The DEFINE statement declares the variables and causes memory to be allocated for them. DEFINE must precede any executable statements within the same program block. A variable with local scope can have its value set and can be used only within the function in which it is defined. Memory for the variable is allocated when the function is called by a program, and is released when the function ends.
A Variable defined with module scope can have its value set and can be used in any function within a single source-code module. The DEFINE statement must appear at the top of the module, before any program blocks. Memory for module variables is allocated when the program starts, and is released when the program ends.
A Variable defined with global scope can have its value set and can be used in any function within any modules of the same program. Memory for global variables is allocated when the program starts, and is released when the program ends.
For a well-structured program and ease of maintenance, we recommend that you use module variables instead of global when you need persistent data storage. You can include get/set functions in the module to make the value of the variable accessible to functions in other modules.
A compile-time error occurs if you declare the same name for two variables that have the same scope. You can, however, declare the same name for variables that differ in their scope.
Functions can be invoked explicitly using the CALL statement. Variables can be passed as arguments to a function when it is invoked. The parameters can be variables, literals, constants, or any valid expressions. Arguments are separated by a comma. If the function returns any values, the RETURNING clause of the CALL statement assigns the returned values to variables in the calling routine. The number of input and output parameters is static.
The function that is invoked must have a RETURN instruction to transfer the control back to the calling function and pass the return values. The number of returned values must correspond to the number of variables listed in the RETURNING clause of the CALL statement invoking this function. If the function returns only one unique value, it can be used as a scalar function in an expression.
CALL myfunc() CALL newfunc(var1) RETURNING var2, var3 LET var2 = anotherfunc(var1) IF testfunc1(var1) == testfunc2(var1) THEN ...
See the BDL stack discussion in Functions for additional information about passing and returning variables.
Using Static SQL, an embedded SQL SELECT statement can be used to retrieve data from a database table into program variables. If the SELECT statement returns only one row of data, you can write it directly as a procedural instruction, using the INTO clause to provide the list of variables where the column values will be fetched. If the SELECT statement returns more than one row of data, you must declare a database cursor to process the result set.
Note: The line numbers shown in the examples in this tutorial are not part of the BDL code; they are used here so specific lines can be easily referenced. The BDL keywords are shown in uppercase, as a convention only. The keywords also appear in green in this documentation.
Program connectdb.4gl |
|
Notes:
02
The SCHEMA
statement is used to define
the database schema files to be used as custdemo. The LIKE syntax has been used to define variables in the
module. 05
and
06
Using DEFINE
the local variable m_store_name
is declared as being LIKE the store_name column; that is, it has the same data type definition as
the column in the customer table of the custdemo database.08
A connection in multi-session mode is
opened to the custdemo database, with connection parameters defined in FGLPROFILE. Once connected to the database server, a current database session is
started. Any subsequent SQL statement is executed in the context of the
current database session.10
The select_name function is called, passing the
literal value 101 as an argument. The function returns a value to be stored in the local variable m_store_name.12
The value of m_store_name is displayed
to the user on the standard output.14
The DISCONNECT
instruction disconnects
you from the current session. As there are no additional lines in the program block, the program
terminates.
18
Beginning of the definition of the function select_name.
The value 101 that is passed to the function will be stored in the
local variable f_store_num.
19
thru 21
Defines multiple local
variables used in the function, separating the
variables listed with a comma. Notice that a variable must be declared with the same name and data type as
the parameter listed within the parenthesis in the function statement, to accept
the passed value.
23
thru 25
Contains the embedded SELECT ... INTO
SQL statement to retrieve the store name for
store #101. The store name that is retrieved will be stored in the f_store_name
local variable. Since the store number is unique, the WHERE clause ensures
that only a single row will be returned.
27
The RETURN statement causes the function to terminate, returning the value
of the local variable f_store_name. The number of variables returned matches the number declared in the
RETURNING clause of the CALL
statement invoking the function. Execution of the program
continues with line
12
.fgldbsch -db custdemo
fglcomp connectdb.4gl
fglrun connectdb.42m