Example: custdata.4gl (Function appupd_cust)
The function appupd_cust
, of the custdata.4gl
module, allowing the user to insert values for a new customer row or to update an existing
row.
Function
append_cust
(custdata.4gl): 1 PUBLIC FUNCTION append_cust(curr_cust t_cust_num) RETURNS t_cust_num
2 RETURN appupd_cust("A",curr_cust)
3 END FUNCTION
Note:
- This is a simple "wrapper" function defined for convenience, that calls the
appupd_cust
function with"A"
as parameter, and zero for the current customer number. - The function returns zero if the row creation has succeed, requiring a new query, or it returns the current customer number, if the user has canceled the record modification.
Function
update_cust
(custdata.4gl): 1 PUBLIC FUNCTION update_cust(curr_cust t_cust_num) RETURNS t_cust_num
2 RETURN appupd_cust("U",curr_cust)
3 END FUNCTION
Note:
- This is a simple "wrapper" function defined for convenience, that calls the
appupd_cust
function with"U"
as parameter, and the current customer number passed from the caller. The customer number is the primary key value that will be used - The function returns zero if the row update has succeed, requiring a new query, or it returns the current customer number, if the user has canceled the record modification.
Function
appupd_cust
(custdata.4gl): 1 PRIVATE FUNCTION appupd_cust(au_flag CHAR(1), curr_cust t_cust_num) RETURNS t_cust_num
2
3 IF au_flag == "A" THEN
4 MESSAGE "Append a new customer "
5 INITIALIZE mr_custrec.* TO NULL
6 LET mr_custrec.cust_num = 0
7 LET mr_custrec.cust_name = "<undefined>"
8 ELSE
9 MESSAGE "Update current customer"
10 SELECT * INTO mr_custrec.* FROM customer WHERE cust_num = curr_cust
11 IF SQLCA.SQLCODE == NOTFOUND THEN
12 ERROR "Customer record no longer exists in the database"
13 RETURN 0
14 END IF
15 END IF
16
17 LET int_flag = FALSE
18
19 INPUT BY NAME mr_custrec.* WITHOUT DEFAULTS ATTRIBUTE (UNBUFFERED)
20
21 BEFORE INPUT
22 IF au_flag == "U" THEN
23 IF cust_orders_count(curr_cust) > 0 THEN
24 CALL DIALOG.setFieldActive("cust_name",FALSE)
25 CALL DIALOG.getForm().setFieldComment("cust_name",
26 "Cannot update customer name referenced by orders")
27 END IF
28 END IF
29
30 AFTER FIELD cust_name
31 IF cust_name_exists(mr_custrec.cust_name, mr_custrec.cust_num) THEN
32 ERROR "Customer name already used"
33 NEXT FIELD CURRENT
34 END IF
35
36 END INPUT
37
38 IF int_flag THEN
39 LET int_flag = FALSE
40 MESSAGE "Operation cancelled by user"
41 RETURN curr_cust
42 END IF
43
44 IF au_flag == "A" THEN
45 SELECT MAX(cust_num)+1 INTO mr_custrec.cust_num FROM customer
46 DISPLAY BY NAME mr_custrec.cust_num
47 TRY
48 INSERT INTO customer VALUES (mr_custrec.*)
49 CATCH
50 ERROR SFMT("INSERT failed: %1",SQLERRMESSAGE)
51 RETURN 0
52 END TRY
53 MESSAGE "Row appended"
54 ELSE
55 TRY
56 UPDATE customer
57 SET cust_name = mr_custrec.cust_name,
58 addr = mr_custrec.addr,
59 city = mr_custrec.city,
60 state = mr_custrec.state,
61 zipcode = mr_custrec.zipcode,
62 contact_name = mr_custrec.contact_name,
63 phone = mr_custrec.phone
64 WHERE cust_num = mr_custrec.cust_num
65 CATCH
66 ERROR SFMT("UPDATE failed: %1",SQLERRMESSAGE)
67 RETURN 0
68 END TRY
69 IF SQLCA.SQLERRD[3] == 1 THEN
70 MESSAGE "Row updated"
71 ELSE
72 MESSAGE "Row no longer exists in the database"
73 END IF
74 END IF
75
76 RETURN 0
77
78 END FUNCTION
- Line
1
Defines the function with a flag and current customer number as parameter. The function accepts a parameter defined asCHAR(1)
. In order to use the same function for both the input of a new record and the update of an existing one. - Line
4
thru7
: When creating a new row, program variables for theINPUT
dialog are initialized with default values. - Lines
9
thru14
: When updating an existing row, we execute aSELECT
statement with the current customer number passed as parameter, to get fresh data from the database. The customer row may no longer exist since the last query was performed, so we need to test theSQLCA.SQLCODE
register forNOTFOUND
and show an warn the user if need. - Line
14
sets theint_flag
global variable toFALSE
prior to theINPUT
statement, so the program can determine if the user cancels the dialog. - Line
17
TheUNBUFFERED
andWITHOUT DEFAULTS
clauses of theINPUT
statement are used. TheUNBUFFERED
attribute insures that the program array the form fields are automatically synchronized for input and output. TheWITHOUT DEFAULTS
clause is used to get the value of the program variables when the dialog starts. - Lines
21
thru28
: Before starting theINPUT
, in case of update we check if the current customer is referenced in the orders table, and disable the customer name field if it's the case. We do not want customer name changes, if orders have already been issued for that customer. - Lines
30
thru34
implement anAFTER FIELD cust_name
control block that verifies if the customer name is already used by another record. If the name is already used, an error message is displayed and we force the focus to return in the current field. The user cannot leave that field until a unique customer name was entered. - Line
46
END INPUT
is required when any of the optional control blocks of theINPUT
statement are used. - Lines
38
thru42
: Theint_flag
register is checked to see if the user has canceled the input. If so, we leave the function by returning the current customer number passed as parameter, indicating to the caller that the user can continue to browse in the list. - Line
44
thru54
: When appending a new row, we execute aSELECT MAX(cust_num)+1
query to generate a new unique customer number, before creating a new row with theINSERT
statement. Best practice to generate unique numbers would be SQL sequences. - Lines
47
thru52
: TheINSERT
statement is executed in aTRY/CATCH
block, to catch potential SQL errors and display a message to the user. - Lines
55
thru68
: TheUPDATE
statement is executed in aTRY/CATCH
block, to catch potential SQL errors and display a message to the user. - Lines
69
thru73
check the value of theSQLCA.SQLERRD[3]
register, which contains the number of processed SQL table rows. Here we expect 1 rpw to be updated. If the number is zero, it means that the row has been deleted by another user. - Line
76
returns zero to indicate to the caller that the row creation or modification has succeeded, and needs a new QBE query to browser again in the list of customers.