Genero FGL 学习
Genero FGL 简介
Genero FGL 开发(编译、连接、执行)
第一个程序 Hello World
变量与运算符
变量定义(DEFINE)
预定义变量
变量集合(RECORD )
数据结构(TYPE)
变量赋值(LET)、初始化(INITIALIZE)
常数(CONSTANT)
运算符(operators)
全局变量(GLOBALS)
变数的生命周期(LOCALE、MODULE、GLOBAL)
控制输出格式(USING)
函数、流程控制
IMPORT 引入链接库(跳过)
SCHEMA / DATABASE 声明数据库
MAIN 函数与设定区块
FUNCTION 函数
报表结构 REPORT 函数(跳过)
IF
CASE
FOR
WHILE
CONTINUE
EXIT
TRY…CATCH
SLEEP
LABEL 和 GOTO()
常用的内置函数(built-in functions)
Genero FGL 简介
Genero FGL 语言,为 Four J’s(http://www.4js.com)于 2004 年所发表。整体结构为承袭 INFORMIX 数据库的 4GL 管理语言而来,即 INFORMIX-4GL 。
INFORMIX-4GL 属于第四代架构的语言,其优点在于构成程序的语法和英文近似,可以大幅减少学习的时间,但仅能使用于 INFORMIX 数据库的控制上。
Four J’s 取其优点,为了能够应用于更多后端数据库,开发出 FGL 语言,并因应图型化,改版为Genero FGL,有以下特点:
- 切分为 Client、Server 架构(GDC 与 fgl),增进执行效率
- 以 XML Bsae 做为 Client 及 Server 端数据传递的架构
- 支援更多不同平台(OS)及数据库系统
- 可在运行时间动态调整画面输出的格式(Layout Styles)
- 引入基本的 对象(Object) 概念
在 Genero FGL 语言架构中,将 程序逻辑、画面 视为不同的项目,分别撰写。
Program(程序)= MODULE(逻辑代码) + FORM(画面代码)
由上图可知:
- Program 可由许多的 Module 与 Form 构成。
- 单一的 4GL 由一个或一个以上的 Function、Report 组成。
- 一个完整的 Program 中,必需指定一个『Main』作为程序执行入口。
Genero FGL 开发(编译、连接、执行)
当程序及画面编写完成后,还需经过编绎(Compile)、连结(Link),才能够被执行(Execute)。
编译需要 Genero Development License,连结及执行需要 Genero Runtime License。
编译流程
程序的原始文件后缀名为 .4gl,经过编译后会产生后缀为 .42m 的文件。
程序(Program)的编译:fglcomp [编译参数] 待编译文件名[.4gl]
编译前处理(preprcessor) ????????
GeneroFGL 可直接以 文字编辑程序如Vim 进行 文字格式(per 档)的开发;
也可使用 Genero Studio 内的『Form Design』功能开发 XML格式(4fd 档)的画面;
编译后都会产生后缀名为 .42f 的文件。
文字格式(per文件)编译:fglform [编译参数] 待编译文件名[.per]
XML 格式(4fd文件)编译:gsform [编译参数] 待编译文件名[.4fd]
连结流程
若该程序不需要使用其他 4gl 提供的功能,可以略过连接的程序,直接执行作业。
若该作业被切分成许多子程序,则可在执行连接前,先将子程序打包成一组动态链接函式库(Dynamic Link Library),后缀名为 .42x,打包完成后再与原始作业进行连接。
连接语法:fgllink -o 连结后的完整文件名 待连结文件1 [待连结文件2] ….
示例:
- fgllink -o test.42x test1.42m test2.42m test3.42m(生成42x文件)
- fgllink -o program.42r test.42x main.42m others.42m(生成42r文件)
注:画面文件不需要执行链接。
执行程序
执行程序前,需先开启使用者端的 Genero 桌面客户端软件(GDC:Genero Desktop
Client),以令主机端的 fglrun 可以与客户端的『GDC』进行沟通。
执行指令:fglrun [执行参数] 执行文件名[.42r]
当程序未使用到其他外部资源时,也可以直接执行含 MAIN 函数的 .42m 文件。
程序执行的过程中,所有逻辑运算均于主机端执行,只有画面异动数据会以连续的 XML 封包传递到客户端,经过 GDC 解译重组后,与使用者进行互动。
fglrun -V 可以查看 fgl 的版本号。
第一个程序 Hello World
MAIN
DISPLAY “hello world!!”
END MAIN
4GL中的 注释:
- { } 可以将某个范围做备注
- # 或 — 将某行做备注
变量与运算符
变量类型
变量定义(DEFINE)
直接定义变量:DEFINE 变量名 变量类型
定义变量对应数据库字段:DEFINE 变量名 LIKE 数据表.数据字段
# 直接定义 employee_no 变量, 类型是 CHAR(10)
DEFINE employee_no CHAR(10)
# 定义 p_employee_no 和数据库对应
DEFINE p_employee_no LIKE employee_file.employee_no,
p_team_no SMALLINT,
p_join_date, p_birthday DATE
预定义变量
Genero 的预定义变量及用途,可以直接使用。
变量集合(RECORD )
直接定义变量集合(Records)
例:直接定义 rec 这个 Records 中的各个变量类型。
DEFINE rec RECORD # 定义rec这个变量,它是个RECORD,是个变量集合
id INTEGER,
name VARCHAR(100),
birth DATE
END RECORD
定义变量集合对应数据库字段
例:定义 cust01 这个 Record 的变量与数据库中的 customer 这个 table 的字段有相同的名称及数据类型,有以下两种方法。
DATABASE example_database
MAIN
DEFINE cust01 RECORD LIKE customer.*
END MAIN
DATABASE example_database
MAIN
DEFINE cust02 RECORD
id LIKE customer.id,
name LIKE customer.name,
birth LIKE customer.birth,
sales LIKE salesman.name
END RECORD
END MAIN
数据结构(TYPE)
使用数据结构TYPE:[PRIVATE|PUBLIC] TYPE 变量名 变量类型
TYPE customer RECORD
cust_num INTEGER,
cust_name VARCHAR(50),
cust_addr VARCHAR(200)
END RECORD
DEFINE c customer
???????
PUBLIC TYPE rpt_order RECORD
order_num INTEGER,
store_num INTEGER,
order_date DATE,
fac_code CHAR(3)
END RECORD
MAIN
DEFINE o rpt_order #使用数据结构 rpt_order 并取名为 o
DECLARE order_c CURSOR FOR
SELECT order_num, store_num, order_date, fac_code FROM orders
START REPORT order_list
FOREACH order_c INTO o.*
OUTPUT TO REPORT order_list(o.*)
END FOREACH
FINISH REPORT order_list
END MAIN
变量赋值(LET)、初始化(INITIALIZE)
变量赋值:LET varibale = expression
MAIN
DEFINE c1, c2 CHAR(10)
LET c1 = “Genero”
LET c2 = c1
END MAIN
注:若变量形态为 CHAR 和 VARCHAR 时,指定给予的值有差异。
初始化变量集合(INITIALIZE)
用于初始化一组 RECORD 变量为 NULL,或者是初始化为数据库 Table 的默认值:
INITIALIZE 变量串行 { LIKE 字段串行 | TO NULL }
MAIN
DEFINE cr RECORD LIKE customer.*
INITIALIZE cr.cust_name TO NULL #初始化cr的cust_name字段为NULL
INITIALIZE cr.* LIKE customer.* #初始化cr的变量为customer表的值
END MAIN
常数(CONSTANT)
一些系统预定义常数:
定义常数:CONSTANT constant_id [data_type] = value
注:定义常数可以不指定类型;系统会自动判断类型,若指定错误则会纠正。
CONSTANT c1 = “Drink” — 自行定义为 STRING
CONSTANT c2 = 4711 — 自行定义为 INTEGER
CONSTANT c3 SMALLINT = 12000 — 自行纠正为 INTEGER
CONSTANT c4 CHAR(10) = “abc” — 按照定义为 CHAR(10)
运算符(operators)
比较运算符
`
MAIN
DEFINE a,b INTEGER
LET a = b := 10
DISPLAY a, b — 10 10
END MAIN
MAIN
DEFINE a,b INTEGER
LET a = b = 10
DISPLAY a,b — 0 0
END MAIN
逻辑运算符
数值运算符
MAIN
DEFINE i,j SMALLINT
LET i = 9
LET j = 2
DISPLAY i + j –DISPLAY 11
DISPLAY i – j –DISPLAY 7
DISPLAY i * j –DISPLAY 18
DISPLAY i / j –DISPLAY 4.5
DISPLAY j ** i –DISPLAY 512
DISPLAY i mod j –DISPLAY 1
END MAIN
字符串运算符
?????????
说明:表达式[start,end]表示从字符串中取出子字符串,此表示方式仅能用在 CHAR 或
VARCHAR 上,若变量型态为 STRING,则参照如下范例:
MAIN
DEFINE i,j STRING
LET i = “T100”
LET j = i.subString(1, 4)
DISPLAY j –T100
DISPLAY i.subString(1, 4) –T100
END MAIN
关联语法(Associative syntax) 运算符
日期运算符
对话框处理 (Dialog handling)运算符
全局变量(GLOBALS)
语法一:直接写定 GLOBALS 区块
GLOBALS
declaration-statement
[,…]
END GLOBALS
语法二:读入已写好的共同配置文件(外部档案)
GLOBALS “filename”
变数的生命周期(LOCALE、MODULE、GLOBAL)
LOCAL变量(Local Variables)
- 定义位置:定义在 Module 中的函式里 (MAIN、FUNCTION 等)
- 生命周期:只属于该定义的函式使用,离开此函式即不能再使用。
MODULE变量(Module Variables)
- 定义位置:Module 中,但不被任何的函式包围。
- 生命周期:为该 Module 中的共享变数。
GLOBAL变量(Global Variables)
- 定义位置:由 GLOBALS 及 END GLOBALS 所包围的变数。
- 生命周期:使用的所有 MODULE 的共享变量。
SCHEMA ds
GLOBALS
DEFINE g_employee CHAR(10) –GLOBAL
END GLOBALS
DEFINE g_tty CHAR(32) –MODULE
MAIN
DEFINE answer CHAR(1) –LOCAL
END MAIN
FUNCTION ins_employee()
DEFINE flag CHAR(1), –LOCAL
change SMALLINT –LOCAL
END FUNCTION
控制输出格式(USING)
针对 数值或日期 设定其 显示格式,设定时注意 溢出(overflow) 的问题。
数值格式标志
日期格式标志
???????????????????????
MAIN
DEFINE i,j SMALLINT
LET i = 12345
LET j = -12345
DISPLAY i
DISPLAY j
DISPLAY i USING”*******”
DISPLAY j USING”*******”
DISPLAY i USING”&&&&&&&”
DISPLAY j USING”&&&&&&&”
DISPLAY i USING”#######”
DISPLAY j USING”#######”
DISPLAY i USING”<<<<<<<”
DISPLAY j USING”<<<<<<<”
DISPLAY i USING”——-”
DISPLAY j USING”——-”
DISPLAY i USING”+++++++”
DISPLAY j USING”+++++++”
DISPLAY i USING”$$$$$$$”
DISPLAY j USING”$$$$$$$”
DISPLAY i USING”(######)”
DISPLAY j USING”(######)”
DISPLAY i USING”###,###.&&”
DISPLAY j USING”###,###.&&”
END MAIN
MAIN
DISPLAY TODAY
DISPLAY TODAY USING “yyyy-mm-dd”
DISPLAY TODAY USING “yy-mm-dd”
DISPLAY TODAY USING “yy-mmm-ddd”
END MAIN
函数、流程控制
IMPORT 引入链接库(跳过)
SCHEMA / DATABASE 声明数据库
使用 SCHEMA 声明数据库时,只会在编译过程中使用到声明的功能,执行程序时并不会与数据库进行实质联机。
使用 DATABASE 声明数据库时,编译时功能相同,但执行时即会链接数据库。
SCHEMA ds #声明数据库ds
MAIN
DEFINE lc_zz01 LIKE zz_file.zz01
SELECT zz01 INTO lc_zz01 FROM zz_file WHERE zz01=’tiptop’
END MAIN
???????????
注:使用 SCHEMA 指令,因此并未于实际登入数据库,执行时回报如下:
Program stopped at ‘test_schema.4gl’, line number 5.
SQL statement error number -1803 (-1). Connection does not exist.
MAIN 函数与设定区块
MAIN 函数是程序执行的入口,一个完整可执行的程序只能有一个 MAIN 函数。
最简单的完整作业:
MAIN
DISPLAY “hello world!”
END MAIN
MAIN 函数可简单写成如上,也可增加一些 设定区块。
DEFER 设定 可定义程序是否要拦截『当使用者按下中断(interrupt)或离开(quit)键』时所送出的系统讯号:DEFER {INTERRUPT | QUIT}
OPTIONS 设定 可变更系统默认的选项
Exceptions 设定 定义当遇到 SQL 错误时,系统要采什么操作。
语法格式:WHENEVER [ANY] ERROR { CONTINUE | STOP | CALL function | GOTO label }
复杂的 MAIN 函数示例:
MAIN
OPTIONS #改变一些系统默认值
INPUT NO WRAP, #输入的方式:不打转
# FORM LINE FIRST + 2, #画面开始的位置
# MESSAGE LINE LAST, #讯息显示的位置
# PROMPT LINE LAST, #提示讯息的位置
FIELD ORDER FORM #整个画面会依照 p_per 所设定的字段顺序
DEFER INTERRUPT
WHENEVER ERROR STOP #当发生 SQL Error 时即停止程序
DISPLAY “Change Exception!”
WHENEVER ERROR CALL chk_err #此处的 CALL 是没有括号的
END MAIN
FUNCTION chk_err( )
DISPLAY “Error Happened!”
END FUNCTION
FUNCTION 函数
语法:[PUBLIC | PRIVATE ] FUNCTION function_name( [arg [ , … ] ] )
当设定为 PRIVATE 时,只限本 4gl 文件内使用;连结时在 42x 或 42r 内无法看到该函数。
MAIN
CALL say_hello_public()
CALL say_hello_private()
END MAIN
FUNCTION say_hello_public()
DISPLAY “Hello, world!”
END FUNCTION
PRIVATE FUNCTION say_hello_private()
DISPLAY “Hello, Private!”
END FUNCTION
CALL 执行指定的函数,若有回传值,以 RETURNING 接回。
语法格式:CALL function ( [ parameter [,…] ] ) [ RETURNING variable [,…] ]
RETURN 返回函数所需的变量值,并停止此函式的执行。
回传单一值:
MAIN
DEFINE var1 CHAR(10)
DEFINE var2 CHAR(2)
LET var1 = foo()
DISPLAY “var1 = ” || var1 — var1 = Hello
CALL foo() RETURNING var2
DISPLAY “var2 = ” || var2 — var2 = He
DISPLAY “foo() = ” foo() — foo() = Hello
END MAIN
FUNCTION foo()
RETURN “Hello”
END FUNCTION
回传单一值(布尔):
MAIN
IF foo() THEN
DISPLAY “Choice is OK!”
END IF
END MAIN
FUNCTION foo()
RETURN TRUE
END FUNCTION
回传多个值: 可用 RETURNING 接收
MAIN
DEFINE var1 CHAR(15)
DEFINE var2 CHAR(15)
CALL foo() RETURNING var1, var2
DISPLAY var1, var2
END MAIN
FUNCTION foo()
DEFINE r1 CHAR(15)
DEFINE r2 CHAR(15)
LET r1 = “return value 1”
LET r2 = “return value 2”
RETURN r1, r2
END FUNCTION
文件之间互相调用:test1.4gl 调用 test2.4gl 中的函数,并且用命令行执行 test3.4gl
test1.4gl
MAIN
DISPLAY “MAIN FUNCTION”
CALL a1()
CALL a2()
RUN “fglrun test3” # 利用RUN执行命令行
END MAIN
FUNCTION a1()
DISPLAY “SUB FUNCTION a1()”
END FUNCTION
以上程序段会呼叫另外两个 Function,并且利用 RUN 指令执行一道 unix 指令
test2.4gl
FUNCTION a2()
# a2 function
DISPLAY “SUB FUNCTION a2()”
END FUNCTION
test3.4gl
MAIN
DISPLAY “This is test3.4gl”
END MAIN
报表结构 REPORT 函数(跳过)
这是一种专门用来设定报表打印格式的函数,后续章节有详细的介绍。
IF
语法:??????MATCHES 支持正则表达式?
IF condition THEN
statement
[…]
ELSE
statement
[…]
END IF
MAIN
DEFINE name CHAR(20)
LET name = “John Smith”
IF name MATCHES “John*” THEN
DISPLAY “The first name is too common to be displayed.”
IF name MATCHES “*Smith” THEN
DISPLAY “Even the last name is too common to be displayed.”
END IF
ELSE
DISPLAY “The name is ” , name , “.”
END IF
END MAIN
CASE
语法1格式:适用于判断式比较简单,如只需判断1个数字
CASE expression-1
WHEN expression-2
{ statement | EXIT CASE }
[…]
OTHERWISE
{ statement | EXIT CASE }
[…]
END CASE
MAIN
DEFINE v CHAR(10)
LET v = “C1”
CASE v
WHEN “C1”
DISPLAY “Value is C1”
WHEN “C2”
DISPLAY “Value is C2”
WHEN “C3”
DISPLAY “Value is C3”
OTHERWISE
DISPLAY “Unexpected value”
END CASE
END MAIN
语法2格式:适用于判断式较复杂
CASE
WHEN boolean-expression
{ statement | EXIT CASE }
[…]
OTHERWISE
{ statement | EXIT CASE }
[…]
END CASE
MAIN
DEFINE v CHAR(10)
LET v = “C1″
CASE
WHEN ( v=”C1″ OR v=”C2” )
DISPLAY “Value is either C1 or C2″
WHEN ( v=”C3″ OR v=”C4” )
DISPLAY “Value is either C3 or C4”
OTHERWISE
DISPLAY “Unexpected value”
END CASE
END MAIN
语法2注意:若有两种情况成立,系统仅会走第一条符合条件的路径。
下列代码只会显示:a is ok
MAIN
DEFINE a,b INTEGER
LET a = b := 10
CASE
WHEN a = 10 DISPLAY ” a is ok ”
WHEN b = 20 DISPLAY ” b is ok ”
OTHERWISE DISPLAY ” nothing is ok ”
END CASE
END MAIN
FOR
语法:默认情况 STEP = 1
FOR counter = a TO b [ STEP value ]
statement
[…]
END FOR
MAIN
DEFINE i, i_min, i_max INTEGER
LET i_min = 1
LET i_max = 10
DISPLAY “Look how well I can count from ” , i_min , ” to ” , i_max
DISPLAY “I can count forwards…”
FOR i = i_min TO i_max # 正序
DISPLAY i
END FOR
DISPLAY “… and backwards!”
FOR i = i_max TO i_min STEP -1 #反序
DISPLAY i
END FOR
END MAIN
WHILE
语法:执行程序直到条件不成立为止。
WHILE b-expression
statement
[…]
END WHILE
MAIN
DEFINE a,b INTEGER
LET a = 20
LET b = 1
WHILE a > b
DISPLAY a , ” > ” , b
LET b = b + 1
END WHILE
END MAIN
CONTINUE
语法:跳出本次循环。
CONTINUE { FOR | FOREACH | MENU | CONSTRUCT | INPUT | WHILE }
MAIN
DEFINE i INTEGER
LET i = 0
WHILE i < 5
LET i = i + 1
DISPLAY “i = ” || i
CONTINUE WHILE
DISPLAY “This will never be displayed !”
END WHILE
END MAIN
EXIT
语法:离开控制段。
EXIT { CASE | FOR | MENU | CONSTRUCT | FOREACH | REPORT | DISPLAY | INPUT | WHILE | PROGRAM }
MAIN
DEFINE i INTEGER
LET i = 0
WHILE TRUE
DISPLAY “This is an infinite loop. How would you get out of here ?”
LET i = i + 1
IF i = 100 THEN
EXIT WHILE
END IF
END WHILE
DISPLAY “Well done.”
END MAIN
TRY…CATCH
针对重要 SQL 指令可以预先设置专用的错误处理指令。
语法:
TRY
[待侦测是否会发生问题的程序段落]
CATCH
[处理问题或回报讯息的程序段落]
END TRY
示例:
MAIN
LET lc_a = ARG_VAL(1)
TRY
DATABASE lc_a
CATCH
DISPLAY lc_a,’ not in fglprofile, number:’, SQLCA.SQLCODE
END TRY
END MAIN
SLEEP
语法:程序依指定秒数暂停。
SLEEP seconds
注意:如果 seconds < 0 或 seconds IS NULL,则程序不会停止。
MAIN
DISPLAY “Please wait 5 seconds…”
SLEEP 5 #暂停5秒
DISPLAY “Thank you.”
END MAIN
LABEL 和 GOTO()
为了程序的易读性和结构性,请不要使用该指令。
MAIN
DISPLAY “Before GOTO”
GOTO: label_id1
DISPLAY “Never Been Displayed”
LABEL label_id1:
DISPLAY “After GOTO”
END MAIN
常用的内置函数(built-in functions)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43734095/article/details/112761278