WhoIsMrjQL - Copy (2)
WhoIsMrjQL - Copy (2)
Is
Mr.jQL?
By V.Kazimirchik, last update: Thu, 22 Jun 2017 04:00 UTC
1 Preface 4
2 Basics 5
2.1 List records in a table . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 VOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Record delimiters . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.5 Count number of records . . . . . . . . . . . . . . . . . . . . . . . . 10
2.6 List records that match a condition . . . . . . . . . . . . . . . . . . 10
2.7 Count records that match a condition . . . . . . . . . . . . . . . . . 11
2.8 Expand a condition ("or") . . . . . . . . . . . . . . . . . . . . . . . 11
2.9 Explicit "OR" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.10 Numeric / string comparison . . . . . . . . . . . . . . . . . . . . . . 12
2.11 Check if a field is populated in all records . . . . . . . . . . . . . 12
2.12 Sort the output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.13 Limit the output . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.14 Show several fields . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.15 Sort by several fields . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.16 If we don’t need the @ID in the output . . . . . . . . . . . . . . . . 14
2.17 Reverse sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.18 List several particular records . . . . . . . . . . . . . . . . . . . . 14
2.19 LIKE operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.20 EVAL usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.21 Totals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.22 Formatting the output . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.23 Aliases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.24 Breaks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.25 SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.26 Select lists saving and restoring . . . . . . . . . . . . . . . . . . . 28
2.27 Save something else than @ID . . . . . . . . . . . . . . . . . . . . . . 30
2.28 More EVAL usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.29 SELECT on SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.30 Negative SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.31 Reverse SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.32 Select concat files . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.33 More operation with saved SELECT lists . . . . . . . . . . . . . . . . 38
2.34 Copy records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.35 Delete records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.36 "Dump" a record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.37 Search for data in a table . . . . . . . . . . . . . . . . . . . . . . . 42
2.38 Brief statistics on file records . . . . . . . . . . . . . . . . . . . 43
3 Advanced usage 43
3.1 I-descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2 Address fields by numbers . . . . . . . . . . . . . . . . . . . . . . . 48
3.3 Default output for empty fields . . . . . . . . . . . . . . . . . . . . 49
3.4 Show records size . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.5 EVERY clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.6 Usage of standard jBC functions . . . . . . . . . . . . . . . . . . . . 52
3.7 Usage of custom jBC subroutines for EVAL . . . . . . . . . . . . . . . 56
3.8 Sort by EVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
// Page 2
3.9 Multi-valued output change with BY-EXP . . . . . . . . . . . . . . . . 59
3.10 Paragraphs with jQL statements . . . . . . . . . . . . . . . . . . . . 60
3.11 EXPLAIN keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.12 Get information from another table . . . . . . . . . . . . . . . . . . 64
3.13 Use other dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.14 User exits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
// Page 3
1 Preface
jQL is (a bit) SQL-like query language that is used in jBASE / TAFC to list, se-
lect and count data in tables (read: files).
Unfortunately jQL doesn’t have line continuation capability so to provide copy-
pasting of long examples from this book it’s advised to create a small jBC pro-
gram that will accept the manual input (or pasted several lines of output) and ac-
cumulate the query text until the empty line is entered:
* jql.b
the_req = ''
LOOP
PROMPT '>> '
INPUT chunk
chunk = TRIM(chunk, ' ', 'B')
IF chunk EQ '' THEN BREAK
IF chunk[1,2] EQ '//' THEN CONTINUE ;* page breaks in this book ;
the_req := ' ' : chunk
REPEAT
Example:
jsh modelbank ~ --> jql
>> LIST F.SPF
>> RUN.DATE SITE.NAME
>>
1 Records Listed
As you might have noticed, this example is from T24 Model Bank (as
// Page 4
2 Basics
Full list:
LIST F.USER
@ID................. PAYSUSER3
USER.ID............. PAYSUSER3
USER.NAME........... PAY USER
SIGN.ON.NAME........ PAYUSER3
END.TIME............ 2400
...
RECORD.STATUS.......
CURR.NO............. 1
INPUTTER............ 44958_INPUTTER__OFS_SEAT
DATE.TIME........... 1504241622
AUTHORISER.......... 44958_INPUTTER_OFS_SEAT
CO.CODE............. GB0010001
DEPT.CODE........... 1
AUDITOR.CODE........
AUDIT.DATE.TIME.....
SALT................
ROLE.COMPANY.RESTR..
USER.ROLES..........
OFFLINE.SMS.ROLE....
TXN.COMMIT.LOG......
@ID................. BUILDUSER98
@ID................. BUILDUSER98
USER.ID............. BUILDUSER98
USER.NAME........... BUILDUSER 98
SIGN.ON.NAME........ TELLER98
CLASSIFICATION...... INT
...
The output is long, press Q to stop it. Pause on each screen can be overridden
with "(N":
LIST F.USER (N
...
...
ROLE.COMPANY.RESTR..
USER.ROLES..........
OFFLINE.SMS.ROLE....
TXN.COMMIT.LOG......
// Page 5
List particular record:
LIST F.USER 'INPUTTER'
@ID................. INPUTTER
@ID................. INPUTTER
USER.ID............. INPUTTER
USER.NAME........... INPUTTER
SIGN.ON.NAME........ INPUTT
CLASSIFICATION...... INT
...
PAYSUSER3 44958_INPUTTER__OFS_SEAT
BUILDUSER98 21692_OFFICER__OFS_SEAT
BUILDUSER40 13788_OFFICER__OFS_SEAT
BUILDUSER8200 80099_OFFICER__OFS_SEAT
BUILDUSER34 19108_OFFICER__OFS_SEAT
...
In the latter case INPUTTER is field name rather than @ID so both
SYSTEM 13526_INPUTTER
LIST F.SPF 'INPUTTER'
** Error [ 202 ] **
Record 'INPUTTER' is not on file.
No Records Listed
2.2 VOC
Where is F.SPF located after all? It’s not in bnk.run... Instead there’s a jBASE
file called VOC where pointers to files are recorded (among other stuff).
// Page 6
Let’s see what’s inside:
LIST VOC
NAME.............................................. TYPE
F.DX.REVAL.DET.ENHANCED F
F.GENERATE.ENTRY.WRK F
F.RUN.GRP.PERF.TAKEON F
F.SA.RATIOS F
F.SC.CCY.RANK F
...
F.SPF ..\bnk.data\eb
\F_SPF
"*A2" means "field #2". Actually jQL doesn’t use a dictionary here
We can force jQL to work hard using some big field number; "time" will show us the
speed of execution:
time LIST VOC 'F.SPF' *A999999999
VOC......... *A999999999...
F.SPF
1 Records Listed
SYSTEM
1 Records Listed
In this example we don’t see fields, just an @ID. Why? See the next chapter.
// Page 7
2.3 Dictionary
How jQL knows there’s a field called INPUTTER? Every (or nearly every) table has
a dictionary (that is also a file). Its location is indicated in VOC entry (field
#3):
CT VOC F.SPF
F.SPF
001 F
002 ..\bnk.data\eb\F_SPF
003 ..\bnk.dict\F_SPF]D
"Pure" jBASE doesn’t create VOC entries for data files; when the file
searched not through VOC entry but with the usage of environment vari-
able JEDIFILEPATH.
INPUTTER
001 D
002 93
003
004 INPUTTER
005 40L
006 M
007
008
...
What we can see here is that this is multi-valued ("M" in field #6) data field ("D"
in field #1), 93 is field position; it is to be displayed as left-justified 40 char-
acters.
// Page 8
Dictionary for T24 applications are created automatically from con-
ate your own dictionary entries in the dictionary itself; for this
FILE.NAME......... SPF
-----------------------------------------------------------------------------
1.84 SYS.FIELD.NAME. INPUTTER
2.84 SYS.TYPE....... D
3.84. 1 SYS.FIELD.NO 93
4.84. 1 SYS.VAL.PROG IN2A
5.84 SYS.CONVERSION.
6.84 SYS.DISPLAY.FMT 40L
7.84 SYS.ALT.INDEX.. N
8.84. 1 SYS.IDX.FILE
9.84 SYS.INDEX.NULLS
10.84 SYS.SINGLE.MULT M
11.84 SYS.LANG.FIELD. N
12.84 SYS.GENERATED.. Y
13.84. 1 SYS.CNV.TYPE
14.84. 1 SYS.REL.FILE
-----------------------------------------------------------------------------
06 DEC 2016 21:50:21 USER (22 APR) VKAZIMIRCHIK [22410,IPAGE 73 >>91>>>
ACTION
AWAITING PAGE INSTRUCTIONS
VOC......... FIELD(@RECORD,@FM,3)
F.SPF ..\bnk.dict\F_SPF]D
// Page 9
EVAL keyword can be used for constructing the output on-the-fly. Many
@FM can be also addressed as @AM; there is also @TM - text mark (ASCII
COUNT FBNK.CUSTOMER
@ID................
76902
74764
75965
...
74737
65765
USD156000001
74799
75957
USD1415600010001
74721
USD156010001
25 Records Listed
// Page 10
When a multi-valued field content is queried, the result will contain records in
which at least one value matches the request:
LIST FBNK.ACCOUNT WITH ALT.ACCT.ID EQ 'GB65463' ALT.ACCT.ID FMT '25L'
@ID................ ALT.ACCT.ID..............
65463 GB65463
GB16NWBK60161300065463
25 Records counted
@ID............................................... K.USER...................
SG1/AM.BACKVALUE.SERVICE AUTHORISER
BNK/EB.CREATE.FILE.UPLOAD SEAT.USER
EU1/AM.BACKVALUE.SERVICE AUTHORISER
MF1/AM.BACKVALUE.SERVICE AUTHORISER
BNK/DW.BULK.PROCESSING AUTHORISER
BNK/DW.EXTRACT AUTHORISER
BNK/T24.UPLOAD.PROCESS SEAT.USER
EU1/OL.VAL.REPS AUTHORISER
SG1/OL.VAL.REPS AUTHORISER
MF1/OL.VAL.REPS AUTHORISER
10 Records Listed
// Page 11
2.9 Explicit "OR"
Do we need to put ’55’ into quotes? It’s not mandatory for numeric constants:
COUNT FBNK.ACCOUNT WITH ACCOUNT.OFFICER EQ 55 OR OTHER.OFFICER EQ 55
25 Records counted
65757
65765
74721
74737
74764
...
// Page 12
2.13 Limit the output
LIST FBNK.ACCOUNT WITH ACCOUNT.OFFICER EQ '55' ONLY SAMPLE 5
@ID................
76902
74764
75965
74818
76732
5 Records Listed
ples and secondly will sort them so it’s not the same as "TOP n" in
MS SQL.
LIST FBNK.ACCOUNT WITH CUSTOMER NE '' CUSTOMER CURRENCY BY CUSTOMER
BY CURRENCY
// Page 13
@ID................ CUSTOMER.. CURRENCY
66052 EUR
66052 GBP
66052 SGD
66052 USD
100100 GBP
100100 GBP
100100 USD
....
// Page 14
@ID............... AC
@ID............... AC
ABBREVIATION.CODE. AC
ORIGINAL.TEXT..... ACCOUNT
RECORD.STATUS.....
CURR.NO........... 2
INPUTTER.......... 1_201312m
DATE.TIME......... 1504211226
AUTHORISER........ 58929_INPUTTER_OFS_MB.OFS.AUTH
CO.CODE........... GB0010001
DEPT.CODE......... 1
AUDITOR.CODE......
AUDIT.DATE.TIME...
@ID............... FT
@ID............... FT
ABBREVIATION.CODE. FT
ORIGINAL.TEXT..... FUNDS.TRANSFER
RECORD.STATUS.....
CURR.NO........... 1
INPUTTER.......... 1_R14m
DATE.TIME......... 1504211226
AUTHORISER........ 58929_INPUTTER_OFS_MB.OFS.AUTH
CO.CODE........... GB0010001
DEPT.CODE......... 1
AUDITOR.CODE......
AUDIT.DATE.TIME...
@ID............... DC
@ID............... DC
ABBREVIATION.CODE. DC
ORIGINAL.TEXT..... DATA.CAPTURE
RECORD.STATUS.....
CURR.NO........... 1
INPUTTER.......... 78833_OFFICER__OFS_SEAT
DATE.TIME......... 1504241610
AUTHORISER........ 78833_OFFICER_OFS_SEAT
CO.CODE........... GB0010001
DEPT.CODE......... 1
AUDITOR.CODE......
AUDIT.DATE.TIME...
etition of the @ID. Also, why @ID is listed twice? The answers are
in the dictionary.
// Page 15
CT DICT F.ABBREVIATION ABBREVIATION.CODE
ABBREVIATION.CODE
001 D
002 0
003
004 ABBREVIATION.CODE
005 35L
006 S
Data field 0 is the @ID. We can use its name instead of @ID if we like. There’s
also a special record "@" in the dictionary that contains field names that are to
be output in the LIST command by default:
CT DICT F.ABBREVIATION @
@
001 PH
002 @ID ABBREVIATION.CODE ORIGINAL.TEXT RECORD.STATUS CURR.NO
INPUTTER DATE.TIME AUTHORISER CO.CODE DEPT.CODE AUDITOR.CODE
AUDIT.DATE.TIME
@ID is mentioned in this record so it’s repeated one more time (it wouldn’t be if
we use ID.SUPP).
For some applications "@" record isn’t properly populated in Model Bank. For ex-
ample:
CT DICT FBNK.FUNDS.TRANSFER @
@
001 PH
002 FT1
So:
LIST FBNK.FUNDS.TRANSFER
@ID...................... FT1.
FT15112TRNLJ ACIB
FT15112DKF1D OC
FT15112DV9G8 AC
FT15112WVXLX AC
....
// Page 16
2.19 LIKE operator
76902 1001
75067 1001
14095 1001
GBP1720507450001 17205
14087 1001
USD140300001 14030
USD1590599990001 15905
....
76902 1001
75067 1001
14095 1001
...
78174 1001
77186 1001
EUR144210001 14421
GBP1001199990001 10011
...
// Page 17
0X means "any number of any characters". Knowing that category number is always
numeric, we can rephrase this query to check only for numeric characters:
LIST FBNK.ACCOUNT CATEGORY WITH CATEGORY LIKE "'1'0N'1'"
And here we’ll output categories that start and end with "1" and have length of
@ID = 5:
LIST FBNK.ACCOUNT CATEGORY WITH CATEGORY LIKE "'1'3N'1'"
@ID................ CATEGORY
EUR144210001 14421
GBP1001199990001 10011
USD1404100010001 14041
EUR1444100010001 14441
USD144610001 14461
USD143010001 14301
USD143110001 14311
USD1122100010001 11221
GBP1000199990001 10001
GBP1444100010001 14441
...
List internal accounts (starting with 3 alpha characters followed by any number
of digits):
LIST FBNK.ACCOUNT ONLY WITH @ID LIKE "3A0N"
@ID................
GBP1720507450001
USD140300001
USD1590599990001
USD1405506800001
EUR150050001
GBP1430600790001
...
USD140300001
EUR150050001
EUR144210001
USD141950001
USD149550001
USD150200001
USD190050001
....
// Page 18
Now show only those that start with 3 alpha characters and contain "04" sequence:
LIST FBNK.ACCOUNT ONLY WITH @ID LIKE "3A...'04'..." BY @ID
@ID................
CHF1404400010001
CHF1418504500001
CHF1430400060001
CHF1430400110001
CHF1430400790001
EUR1404400010001
EUR1418504120001
EUR1430400060001
EUR1430400110001
...
To use several matches we’ll have to use "OR". Only if that’s an exact match we
can use a @VM-delimited dynamic array of values to match to:
LIST FBNK.ACCOUNT CATEGORY WITH CATEGORY MATCHES "1001" : @VM : "6001"
@ID................ CATEGORY
76902 1001
75067 1001
14095 1001
14087 1001
75938 6001
77763 6001
77933 1001
....
Not only we have "LIKE" - we have "UNLIKE" too (now we know where social networks
get their ideas :)
LIST FBNK.ACCOUNT ONLY WITH @ID UNLIKE "3A..."
@ID................
76902
75067
14095
14087
75938
77763
77933
77957
79103
81237
76748
...
// Page 19
If strings like "3A" etc are searched in the data, they have to be enclosed in quotes:
LIST FBNK.CUSTOMER WITH TOWN.COUNTRY LIKE "...EC3N..."
No Records Listed
LIST FBNK.CUSTOMER WITH TOWN.COUNTRY LIKE "...'EC3N'..."
@ID.......................... 100279
CUSTOMER.CODE................ 100279
MNEMONIC..................... CANTERFITZ
SHORT.NAME................... Canterfitzgerald
NAME.1....................... Canterfitzgerald
NAME.2.......................
STREET....................... 1 AMERICA SQUARE
TOWN.COUNTRY................. LONDON EC3N 2LT
...
It’s highly recommended to enclose matched expression in double quotes and lit-
eral strings in it in single quotes, otherwise there might be syntax errors:
LIST FBNK.CUSTOMER SHORT.NAME WITH SHORT.NAME LIKE T...
@ID....... SHORT.NAME.........................
LIST FBNK.CUSTOMER WITH SHORT.NAME LIKE T...(Uk)...
LIST FBNK.CUSTOMER SHORT.NAME WITH SHORT.NAME LIKE "T...'(Uk)'..."
@ID....... SHORT.NAME.........................
// Page 20
2.20 EVAL usage
GBP1720507450001 19.7
14087 -530000
75938 5100
USD1405506800001 -0.01
77957 -10000
GBP1430600790001 0
....
Note that the account GBP1430600790001 was included but its balance is 0.
Correct solution to this issue is something like:
LIST FBNK.ACCOUNT WITH WORKING.BALANCE NE '' AND WORKING.BALANCE NE '0'
WORKING.BALANCE
Hope we don’t get 0.00’s as well :)) Not in the first screen at least:
@ID................ WORKING.BALANCE....
GBP1720507450001 19.7
14087 -530000
75938 5100
USD1405506800001 -0.01
77957 -10000
79103 -500
USD1405503490001 -0.01
81237 14900
76748 203500
GBP1280000060001 -794261.24
...
// Page 21
@ID................ FMT(WORKING.BALANCE,"R2")
GBP1720507450001 19.70
14087 -530000.00
75938 5100.00
USD1405506800001 -0.01
77957 -10000.00
79103 -500.00
USD1405503490001 -0.01
....
@ID................ Balance............
GBP1720507450001 19.70
14087 -530000.00
75938 5100.00
USD1405506800001 -0.01
77957 -10000.00
79103 -500.00
USD1405503490001 -0.01
....
Now put a dollar sign before amounts (and limit selection only to diplay USD ac-
counts):
LIST FBNK.ACCOUNT WITH WORKING.BALANCE NE '' AND WORKING.BALANCE NE '0'
AND CURRENCY EQ 'USD' EVAL "FMT(WORKING.BALANCE,'R2$')" COL.HDR 'Balance'
@ID................ Balance............
USD1405506800001 $-0.01
77957 $-10000.00
79103 $-500.00
USD1405503490001 $-0.01
81237 $14900.00
82147 $500.00
76147 $12970.83
74098 $-350000.00
...
// Page 22
@ID................ Balance............
USD1405506800001 $-0.01
77957 $-10,000.00
79103 $-500.00
USD1405503490001 $-0.01
81237 $14,900.00
82147 $500.00
76147 $12,970.83
74098 $-350,000.00
USD1280001010001 $250,000.00
...
Trying to put "DB" after negative amounts but it looks like it works other way around
in this release:
LIST FBNK.ACCOUNT WITH WORKING.BALANCE NE '' AND WORKING.BALANCE NE '0'
AND CURRENCY EQ 'USD' EVAL "FMT(WORKING.BALANCE,'R2,D$')" COL.HDR 'Balance'
@ID................ Balance............
USD1405506800001 $0.01
77957 $10,000.00
79103 $500.00
USD1405503490001 $0.01
81237 $14,900.00DB
82147 $500.00DB
76147 $12,970.83DB
74098 $350,000.00
USD1280001010001 $250,000.00DB
...
@ID................ Balance............
USD1405506800001 $0.01DB
77957 $10,000.00DB
79103 $500.00DB
USD1405503490001 $0.01DB
81237 $14,900.00
82147 $500.00
76147 $12,970.83
74098 $350,000.00DB
USD1280001010001 $250,000.00
...
// Page 23
Changing "D" before a dollar to "C", we’ll get "CR" output after positive amounts,
again we need to multiply the amount by -1 to get the correct output:
LIST FBNK.ACCOUNT WITH WORKING.BALANCE NE '' AND WORKING.BALANCE NE '0'
AND CURRENCY EQ 'USD' EVAL "FMT(WORKING.BALANCE*-1,'R2,C$')"
COL.HDR 'Balance'
@ID................ Balance............
USD1405506800001 $0.01
77957 $10,000.00
79103 $500.00
USD1405503490001 $0.01
81237 $14,900.00CR
82147 $500.00CR
76147 $12,970.83CR
74098 $350,000.00
USD1280001010001 $250,000.00CR
...
2.21 Totals
LIST FBNK.ACCOUNT WITH CURRENCY EQ 'EUR' AND WORKING.BALANCE NE ''
AND WORKING.BALANCE NE '0' TOTAL WORKING.BALANCE
@ID................ WORKING.BALANCE....
14087 -530000
76748 203500
15307 -525000
EUR1720500190001 0.46
EUR1721000010001 3830.86
....
EUR1418507190001 -168517.87
36668 -36087268.95
14637 789071.88
11312 -40374.75
===================
*** 25536691.95
// Page 24
@ID................ WORKING.BALANCE....
*** 25536691.95
81 Records Listed
Another example:
LIST F.USER TOTAL ATTEMPTS.SINCE DET-SUPP
@ID............. ATTEMPTS.SINCE
*** 19
*** 0.1496
Page 1
@ID................ WORKING.BALANCE....
14087 -530000
76748 203500
15307 -525000
EUR1720500190001 0.46
EUR1721000010001 3830.86
...
Page 2
@ID................ WORKING.BALANCE....
74397 -100000
75256 6000000
76678 10000
...
// Page 25
Formatting the column width. Try 1:
LIST VOC TYPE SAMPLE 5
VOC......... TYPE
F.DX.REVAL.D F
ET.ENHANCED
F.GENERATE.E F
NTRY.WRK
F.GT.SYSTEM. F
PARAMETER$NA
U
F.RUN.GRP.PE F
RF.TAKEON
F.SA.RATIOS F
Correct (FMT):
LIST VOC @ID FMT "35L" TYPE SAMPLE 5 ID-SUPP
VOC................................ TYPE
F.DX.REVAL.DET.ENHANCED F
F.GENERATE.ENTRY.WRK F
F.GT.SYSTEM.PARAMETER$NAU F
F.RUN.GRP.PERF.TAKEON F
F.SA.RATIOS F
Company id
GB-001-0003
GB-001-0005
SG-001-0001
SG-002-0102
EU-001-0001
SG-002-0101
GB-001-0002
GB-001-0004
SG-002-0100
GB-001-0001
// Page 26
2.23 Aliases
LIST FBNK.ACCOUNT WITH CUSTOMER NE '' EVAL "CUSTOMER:'/':CURRENCY" AS SORTING
BY SORTING
@ID................ SORTING...
75132 66052/EUR
75183 66052/GBP
75213 66052/SGD
75043 66052/USD
77844 100100/GBP
78158 100100/GBP
74958 100100/USD
75302 100100/USD
...
2.24 Breaks
LIST FBNK.ACCOUNT BY ACCOUNT.OFFICER BREAK.ON ACCOUNT.OFFICER
@ID................ ACCOUNT.OFFICER
CAD1091500010001 1
CAD1591500010001 1
CADUSD1401600010001 1
...
USDSGD1401600010001 1
USDXAU1902200010001 1
XAUUSD1902200010001 1
***
75914 2
80756 2
80764 2
80772 2
80799 2
***
29823 3
74567 3
74586 3
...
// Page 27
Use break to calculate totals:
LIST FBNK.ACCOUNT WITH CURRENCY EQ USD TOTAL WORKING.BALANCE BY OPENING.DATE
BREAK.ON EVAL "OPENING.DATE[1,4]" COL.HDR 'Open year' DET-SUPP
5000 1998
0 2007
0 2008
0 2010
0 2013
0 2014
86068541.84 2015
===================
*** 86073541.84
2.25 SELECT
Change LIST clause to SELECT, in most cases that will work. Simple one:
SELECT FBNK.ACCOUNT WITH CURRENCY EQ 'EUR' AND WORKING.BALANCE NE ''
>
We don’t have any output like in SQL. Note that prompt has changed - we have an
active SELECT list. We can now enter another jQL command that will be applied to
selected IDs only (or whatever was saved to this list).
To clear the current select list the command CLEARSELECT can be used.
Sort is done the same way as in LIST (SSELECT sorts by @ID so the following 2 queries
will produce the same result):
SELECT FBNK.ACCOUNT WITH CURRENCY EQ 'EUR' AND WORKING.BALANCE NE '' BY @ID
SSELECT FBNK.ACCOUNT WITH CURRENCY EQ 'EUR' AND WORKING.BALANCE NE ''
Select lists can be saved to and retrieved from the directory on T24 application
server (bnk.run/&SAVEDLISTS& by default).
SELECT FBNK.ACCOUNT WITH CURRENCY EQ 'EUR' AND WORKING.BALANCE NE ''
// Page 28
>SAVE.LIST ACCT
GET.LIST ACCT
LIST FBNK.ACCOUNT WORKING.BALANCE SAMPLE 5
@ID................ WORKING.BALANCE....
14087 -530000
76748 203500
15307 -525000
EUR1720500190001 0.46
EUR1721000010001 3830.86
5 Records Listed
After the second command the prompt returns back to normal since we don’t have the
active SELECT list now.
Numbered lists can also be used, numbers can be from 0 to 9:
SELECT FBNK.ACCOUNT TO 1
Note that the prompt hasn’t changed - default SELECT list (0) isn’t populated.
SELECT FBNK.CUSTOMER TO 2
GET.LIST 1
>
Numbered SELECT lists are not persistent and are available only till
// Page 29
Relogin, try again:
GET.LIST 1
>SAVE.LIST CUST
CUST
001 100394
002 100283
003 100315
004 100100
005 190049
006 189992
007 100392
....
// Page 30
Note that it’s a text-like sort rather than numeric.
>CLEARSELECT
Concatenation:
SELECT FBNK.ACCOUNT WITH CUSTOMER NE '' AND WORKING.BALANCE NE ''
AND WORKING.BALANCE NE '0' SAVING UNIQUE EVAL "CUSTOMER:'*':CURRENCY"
>SAVE.LIST CUST2
SORT-LIST CUST2
Resulting list:
CUST2
001 10000083*USD
002 100100*GBP
003 100100*USD
004 100105*USD
005 100106*USD
006 100107*USD
...
// Page 31
Formatting:
LIST F.SPF EVAL "OCONV(ICONV(MAINTENANCE.DATE,'D'),'D')"
@ID... OCONV(ICONV(MAINTENANCE.DATE,"D"),"D")
Calculations:
LIST F.SPF EVAL "ICONV(MAINTENANCE.DATE,'D')-DATE()"
COL.HDR 'Days left to renew the T24 license' ID.SUPP
755
Basic syntax test (leaving as little non-relevant information on the screen as pos-
sible):
LIST . SAMPLE 1 EVAL "OCONV(DATE(),'D')" ID-SUPP
OCONV(DATE(),"D")
09 JUN 2017
// Page 32
09 JUN 2017
More tests:
LIST . SAMPLE 1 EVAL "TIMEDATE()" FMT "25L" ID-SUPP HDR-SUPP COL-HDR-SUPP
LIST . SAMPLE 1 EVAL "ABS(-42)" ID-SUPP HDR-SUPP COL-HDR-SUPP
42
LIST . SAMPLE 1 EVAL "FMT(42, 'R%7')" ID-SUPP HDR-SUPP COL-HDR-SUPP
0000042
LIST . SAMPLE 1 EVAL "'ABCDEFXYZ'[4,3]" ID-SUPP HDR-SUPP COL-HDR-SUPP
DEF
LIST . SAMPLE 1 EVAL "DOWNCASE('ABCDEFXYZ')[3]" ID-SUPP HDR-SUPP COL-HDR-SUPP
xyz
When we have an active SELECT list, we can apply other jQL command on top of it.
for example, we want to select accounts that present both in LIVE and HIS files
(note that in history @IDs have a suffix ";n", where n is record number hence the
EVAL in SAVING clause):
SELECT FBNK.ACCOUNT$HIS SAVING UNIQUE EVAL "FIELD(@ID,';',1)"
97 Records selected
>SELECT FBNK.ACCOUNT
...
** Error [ 202 ] **
Record 'USD141820001' is not on file.
** Error [ 202 ] **
Record 'USD140440001' is not on file.
52 Records selected
>
// Page 33
We still have the active SELECT list that we can save or use any other way.
To avoid "** Error [ 202 ] **" messages the option "(R" can be used
Consequent SELECT can be done on another table, provided that @IDs match:
SELECT FBNK.ACCOUNT LIKE "0N" SAVING UNIQUE CUSTOMER
>SELECT FBNK.CUSTOMER SAVING UNIQUE SECTOR
18 Records selected
>LIST FBNK.SECTOR ONLY
2001
2002
3501
2005
1001
1501
3001
3505
1503
3504
2000
1499
3503
3003
1002
3002
3502
1000
18 Records Listed
97 Records selected
// Page 34
>NSELECT FBNK.ACCOUNT
45 Records selected
No Records selected
SELECT FBNK.ACCOUNT WITH ACCOUNT.OFFICER EQ '55'
25 Records selected
Now select accounts that are not assigned to account officer 55:
>XSELECT FBNK.ACCOUNT
>
Concat files (like CUSTOMER.ACCOUNT) have all their data in a single field. For
example:
LIST FBNK.CUSTOMER.ACCOUNT
Though there’s only one line of output for each @ID, tt doesn’t mean that there’s
only one account opened for each customer.
// Page 35
@ID....... @ID....... CUSTOMER.CODE ACCOUNT.NUMBER..
190086
001 74012
002 74028
003 74039
004 74047
005 74055
100121
001 74063
100124
001 74098
100110
001 74136
100109
001 74117
002 74128
003 74152
...
If we want to select all the data in such tables we can use QSELECT:
QSELECT FBNK.CUSTOMER.ACCOUNT
Record Keys : *
>SAVE.LIST CA
CT &SAVEDLISTS& CA
// Page 36
CA
001 74012
002 74028
003 74039
004 74047
005 74055
006 74063
007 74098
008 74136
009 74117
010 74128
...
>SAVE.LIST LIM
CT &SAVEDLISTS& LIM
LIM
001 100285.0008300.01
002 120012.0002400.01
003 120012.0008100.01
004 120012.0008110.01
005 120016.0002400.01
006 120016.0008100.01
007 120016.0008110.01
008 100345.0002400.01
009 100345.0008100.01
010 100345.0008110.01
011 120019.0002100.01
012 120019.0002110.01
013 120019.0002400.01
014 111661.0010100.01.111660
015 111661.0011000.01.111660
...
// Page 37
2.33 More operation with saved SELECT lists
Compare active account officers list (i.e. ones that have assigned accounts) for
2 companies:
SELECT FBNK.ACCOUNT SAVING UNIQUE ACCOUNT.OFFICER
36 Records selected
>SAVE.LIST AOFF1
SELECT FEU1.ACCOUNT SAVING UNIQUE ACCOUNT.OFFICER
9 Records selected
>SAVE.LIST AOFF2
Looks like all 9 officers that have accounts in the company with mnemonic EU1 also
have accounts in the company BNK:
AND-LISTS AOFF1 AOFF2
9 Records selected
>
28 Records selected
>SAVE.LIST ACNAU
SELECT FBNK.ACCOUNT
>SAVE.LIST ACLIVE
// Page 38
1637 record(s) saved to list 'ACLIVE'
1 Records selected
>CLEARSELECT
>CLEARSELECT
>
1 records copied
// Page 39
'GB0010001' already exists
9 records copied
Force an overwrite:
COPY FROM F.COMPANY TO &TEMP& ALL OVERWRITING
10 records copied
Change target record name:
COPY FROM F.COMPANY TO &TEMP& GB0010001,GB-copy
1 records copied
C:\home\kzm\t24env\r15\bnk\bnk.run>dir "&TEMP&"
Directory of C:\home\kzm\t24env\r15\bnk\bnk.run\&TEMP&
type "&TEMP&\GB0010001"
// Page 40
Model Bank R15-AMR
18 Place De Philosophes,]CH 1205 Geneva,]Switzerland
BNK
1
N
1
AA.ACCOUNT.CLOSURE.DETAILS]AA.ARRANGEMENT.ACTIVITY]AA.SIMULATION.CAPTURE]...
...
82
55607_INPUTTER
1506091201
12987_AUTHORISER
GB0010001
1
acters, @VMs and @SMs stay as they are (@VMs in the output above were
extreme caution.
Delete the particular record (let’s clean up the mess from the previous example):
DELETE &TEMP& GB0010001
1 record(s) deleted.
4 Records selected
>DELETE &TEMP&
// Page 41
4 record(s) deleted.
INPUTTER^INPUTTER^INPUTT^INT^1^GB0010001]GB0010002]EU0010001]SG0010001]SG00201
00]GB0010005]GB0010003]GB0010004]SG0020101]SG0020102^1^20170101M0601^20150429^
20171231^0^2400^999^9^^^^ALL^ALL.PG^^A 2 B C D E F H I L P R S V^^^^^NO^NO^NO^
NO^DDMM^^20161020^141258^dgxip61waupu3EPi5qzqUKrhN9BQbMwNvwf7cWERgVw=^20160825
^^^^Y^^]^00^^^^^^^^,.^^^^^SUPER.USER^^^^^^^^^^^^^^1^^^^^kbB3GZav2O^^^^^^^^^^17
^60370_OFFICER__OFS_SEAT^1504291521^60370_OFFICER_OFS_SEAT^GB0010001^1^
4 Records selected
>
SEARCH F.EB.ERROR
String :E-100500
String :
Record Keys : *
1 Records selected
>LIST F.EB.ERROR
...
RESERVED1.3.....
RESERVED1.4.....
RESERVED1.5.....
NUMERIC.ID...... E-100500
// Page 42
2.38 Brief statistics on file records
STAT FBNK.STMT.ENTRY
jstat -v FBNK.STMT.ENTRY
3 Advanced usage
3.1 I-descriptors
They can be considered as "virtual fields". They also present in file dictionary
(type "I").
Examples from CUSTOMER:
Fields concatenation:
CT DICT FBNK.CUSTOMER NAME.ADDRESS
NAME.ADDRESS
001 I
002 SHORT.NAME:' ':NAME.1:' ':NAME.2:' ':STREET:' ':TOWN.COUNTRY
003
// Page 43
Usage - the same as "regular" fields:
LIST FBNK.CUSTOMER NAME.ADDRESS
@ID....... NAME.ADDRESS......................................
7 Records Listed
I-descriptor with logic:
CT DICT FBNK.CUSTOMER CHECK.LIAB
CHECK.LIAB
001 I
002 CUSTOMER.LIABILITY ; IF @1 NE "" AND @1 NE @ID THEN "" ELSE @ID
003
// Page 44
"@1" means "the result of the first expression"; expressions are de-
LIST FBNK.CUSTOMER EVAL "CUSTOMER.LIABILITY ; IF @1 NE ''
AND @1 NE @ID THEN '' ELSE @ID" COL.HDR 'Check Liab'
190113 190113
188888 188888
122122 122122
100362 100362
120110 120110
100436 100436
101001 101001
101013 101013
100341 100341
100263 100263
190063 190063
190071 190071
111803
...
Another example of multiple expressions - add 1 year to the current date (won’t
adjust for leap year of course, that would be a bit more complex):
LIST . SAMPLE 1 EVAL "OCONV(DATE(),'DG');(@1[1,4]+1);@2:@1[5,4]"
20180613
10
12
// Page 45
LAST.DATE.TIME
001 I
002 DATE.TIME<1,1> ; SUBR("FULL.DATE.TIME", @1)
003
LIST FBNK.CUSTOMER DATE.TIME LAST.DATE.TIME
CU.EFF.DATE
001 I
002 LOCAL.REF<1,2>
003
004 CU.EFF.DATE
005 11R
006 S
// Page 46
SECTOR.NAME
001 I
002 SECTOR; SUBR("ENQ.TRANS","SECTOR", @1, "SHORT.NAME")
003
@ID............ 190113
NAME.ADDRESS... DONALD DONALD DONALD 1
CHECK.LIAB..... 190113
LAST.DATE.TIME. 01504291604
CU.EFF.DATE....
SECTOR.NAME.... Unable to open F0.SECTOR
@ID............ 188888
NAME.ADDRESS... BBH Inhouse Custodian BBH Inhouse Custodian BBH...
CHECK.LIAB..... 188888
LAST.DATE.TIME. 01504241614
CU.EFF.DATE....
SECTOR.NAME.... Unable to open F0.SECTOR
...
Something went wrong... In fact, ENQ.TRANS requires the prior login to T24 (so
T24 COMMON areas are populated). Let’s do this, then go back to jsh, then repeat
this query:
@ID............ 190113
NAME.ADDRESS... DONALD DONALD DONALD 1
CHECK.LIAB..... 190113
LAST.DATE.TIME. 201504291604
CU.EFF.DATE....
SECTOR.NAME.... Individuals Particuliers
@ID............ 188888
NAME.ADDRESS... BBH Inhouse Custodian BBH Inhouse Custodian BBH Inhouse...
CHECK.LIAB..... 188888
LAST.DATE.TIME. 201504241614
CU.EFF.DATE....
SECTOR.NAME.... Broker Courtiers
@ID............ 122122
NAME.ADDRESS... PWM Relationship Manager PWM Relationship Manager model US
CHECK.LIAB..... 122122
LAST.DATE.TIME. 201504291601
CU.EFF.DATE....
SECTOR.NAME.... Staff Personnel
...
// Page 47
SECTOR.NAME is multi-valued (as per SECTOR dictionary) and if we don’t want the
second value to appear, it’s quite easy:
LIST FBNK.CUSTOMER NAME.ADDRESS CHECK.LIAB LAST.DATE.TIME CU.EFF.DATE
EVAL "EXTRACT(SECTOR.NAME,1,1)"
As it was already communicated, the notation "*An" (where n is field number) can
be used for that. This is called "A correlative".
See F.USER fields ##1, 2 and 3:
LIST F.USER *A1 *A2 *A3
such VOC records but they do not present for numbers bigger than 10.
LIST VOC WITH @ID LIKE "'F'0N"
NAME.............................................. TYPE
F9 D
F7 D
F4 D
F5 D
F2 D
F3 D
F10 D
F8 D
F1 D
F6 D
10 Records Listed
// Page 48
F9
001 D
002 9
003
004
005 15T
006 S
@ID 000
SECURITY.CODE 000
COMPANY.NAME 001
DESCRIPT 002
SHORT.NAME 003
MNEMONIC 004
COMPANY.DOMICILE 005
SECURITY.DOMICILE 006
...
GBP 826
CAD 124
LKR 144
SEK 752
TWD 901
CHF 756
...
@ID...................... OCONV(OVERRIDE,"S;*;"NULL"").......
// Page 49
FT15093FD0P2;1 NULL
FT150837LQQR;1 BNK.DIFF.CCY~}Intermediary not Resid
ent of Pay Ccy
ACCT.UNAUTH.OD~}Unauthorised overdra
ft of & & on account &.~{USD~}107693.
15~}20467~{USD~{107693.15~{20467~{100283
~{210~{~{
FT150836PKCL;1 NULL
FT1509014MCW;1 NULL
FT15093JDNY6;1 NULL
...
SYSTEM 649
SYSTEM 649
*A9999 and *A9998 are special numbers; the latter shows the number
of output line.
LIST FBNK.CURRENCY *A9998
@ID *A9998........
GBP 1
CAD 2
LKR 3
SEK 4
TWD 5
CHF 6
AZN 7
GEL 8
SAR 9
DKK 10
ZAR 11
...
// Page 50
Length of record can also be obtained using special notation "@RECORD" that we al-
ready used:
LIST F.SPF EVAL "LEN(@RECORD)"
SYSTEM 649
records where at least one value of this field satisfies the selec-
COUNT FBNK.CURRENCY WITH CURRENCY.MARKET EQ 1
34 Records counted
COUNT FBNK.CURRENCY WITH EVERY CURRENCY.MARKET EQ 1
28 Records counted
So we have 6 CURRENCY records that have at least one value of CURRENCY.MARKET other
than 1:
LIST FBNK.CURRENCY CURRENCY.MARKET WITH CURRENCY.MARKET NE 1
@ID CURRENCY.MARKET
GBP 1
10
CAD 1
10
EUR 1
10
SGD 1
10
NZD 1
10
USD 1
10
6 Records Listed
// Page 51
3.6 Usage of standard jBC functions
LIST . SAMPLE 1 EVAL "DOWNCASE('ABCDEFXYZ')" ID-SUPP HDR-SUPP COL-HDR-SUPP
abcdefxyz
LIST . SAMPLE 1 EVAL "'abcdefxyz' MATCHES DOWNCASE('ABCDEFXYZ')"
ID-SUPP HDR-SUPP COL-HDR-SUPP
1
LIST . SAMPLE 1 EVAL "OCONV(DATE(),'DG')" ID-SUPP HDR-SUPP COL-HDR-SUPP
20170612
LIST . SAMPLE 1 EVAL "ABS(-1000)" ID-SUPP HDR-SUPP COL-HDR-SUPP
1000
LIST FBNK.ACCOUNT EVAL "ISDIGIT(@ID)" ID-SUPP HDR-SUPP COL-HDR-SUPP
Error in attribute definition item ISDIGIT(@ID)
Error in Itype:
Cannot locate Basic subroutine ISDIGIT
...
81086 1
81698 1
USD143050001 0
78042 1
79747 1
17205 1
24732 1
USD1000115100001 0
LIST . SAMPLE 1 EVAL "CHAR(64)" ID-SUPP HDR-SUPP COL-HDR-SUPP
// Page 52
LIST FBNK.CUSTOMER$HIS EVAL "FIELD(@ID,';',1)"
100336;2 100336
100338;2 100338
190148;1 190148
100112;1 100112
190073;1 190073
111658;1 111658
111617;1 111617
100295;1 100295
100242;1 100242
...
LIST FBNK.CUSTOMER$HIS EVAL "CONVERT(';', '-', @ID)"
100336;2 100336-2
100338;2 100338-2
190148;1 190148-1
100112;1 100112-1
190073;1 190073-1
111658;1 111658-1
111617;1 111617-1
100295;1 100295-1
100242;1 100242-1
...
LIST FBNK.SECTOR SHORT.NAME EVAL "DCOUNT(SHORT.NAME,@VM)" AS values
We used CONVERT earlier to change semicolons to dashes; OCONV can also be used for
similar purpose, especially if we want to replace a substring with something of
a different length:
LIST FBNK.SECTOR EVAL "OCONV(SHORT.NAME,'MCC;':@VM:'; / ')"
COL.HDR 'Short names' FMT '35L'
// Page 53
@ID. Short names........................
LIST FBNK.ACCT.ACTIVITY EVAL "FIELD(@ID,'-',1)" COL.HDR 'Account '
EVAL "SUM(TURNOVER.DEBIT)" EVAL "SUM(TURNOVER.CREDIT)" ID.SUPP
LIST . SAMPLE 1 EVAL "ICONV('20161231', 'D') - ICONV('20151231', 'D')" ID-SUPP
HDR-SUPP COL-HDR-SUPP
366
LIST F.COMPANY EVAL "FMT(DATE.TIME,'##-##-## ##:##')"
LIST . SAMPLE 1 EVAL "INDEX('HayHayNeedleHayHay', 'Needle', 1)" ID-SUPP
HDR-SUPP COL-HDR-SUPP
// Page 54
LIST FBNK.ACCOUNT EVAL "LEN(@ID)"
@ID................ LEN(@ID)..
76902 5
75067 5
14095 5
GBP1720507450001 16
14087 5
75938 5
USD140300001 12
USD1590599990001 16
....
LIST FBNK.ACCT.ACTIVITY TURNOVER.CREDIT EVAL "MAXIMUM(TURNOVER.CREDIT)"
LIST . SAMPLE 1 EVAL "STR('*', 42)" ID-SUPP HDR-SUPP COL-HDR-SUPP
**********
**********
**********
**********
**
LIST . SAMPLE 1 EVAL "STR('*', 42)" FMT '42L' ID-SUPP HDR-SUPP COL-HDR-SUPP
******************************************
LIST . SAMPLE 1 EVAL "TIMEDATE()" FMT '42L' ID-SUPP HDR-SUPP COL-HDR-SUPP
LIST FBNK.CUSTOMER WITH EVAL "INDEX(NAME.1,' ',1)" GT 0 NAME.1
EVAL "TRIM(NAME.1,' ','R')"
// Page 55
@ID....... NAME.1............................. TRIM(NAME.1," ", "R")...
LIST FBNK.TARGET EVAL "DQUOTE(EXTRACT(DESCRIPTION,1,1))"
EVAL "SQUOTE(EXTRACT(DESCRIPTION,1,2))"
PID.....................................
3128
Screen Size.............................
144x56
Imagine that we want to show LIMIT records only for customers who have accounts
with certain categories. To fulfil a task like this let’s write and compile the
jBC subroutine that will prepare a @VM-delimited list for use in MATCH:
// Page 56
Note that the first parameter is a return one and it will be omit-
jQL query:
LIST FBNK.LIMIT WITH EVAL
"CUST.NO MATCHES ListGet
('SELECT FBNK.ACCOUNT WITH CATEGORY EQ 1001 1002 1003
SAVING UNIQUE CUSTOMER')"
EQ 1 ONLINE.LIMIT
@ID............................. ONLINE.LIMIT.......
100182.0012510.01.100182 1000000.00
100182.0018000.01.100182 1000000.00
111661.0015115.01.111661 3000000.00
111661.0005215.01.111661
188927.0015400.01.188928 20000000.00
...
Another example: list all SECURITY.MASTER records with "GOOD" ratings (backslashes
can be used as quotes as you can see):
LIST F.SECURITY.MASTER WITH EVAL "RATING MATCHES
ListGet('SELECT F.EB.RATING WITH SL.HVCRE.RATING EQ \GOOD\')" EQ 1 RATING
@ID......... RATING
100048-000 4
100027-000 2
100054-000 6
100062-001 4
100011-100 4
100059-000 5
600104-000 2
100015-000 5
000423-000 2
100063-000 5
...
// Page 57
Example:
LIST . SAMPLE 1 EVAL "EnvGet('TAFC_HOME')" FMT '40L'
COL.HDR 'TAFC home' ID-SUPP
TAFC home...............................
C:\home\kzm\t24env\r15\TAFC
Example with EVAL routine usage - sorted by the second part of @ID:
LIST FBNK.LIMIT WITH EVAL
"CUST.NO MATCHES ListGet
('SELECT FBNK.ACCOUNT WITH CATEGORY EQ 1001 1002 1003
SAVING UNIQUE CUSTOMER')" EQ 1 ONLINE.LIMIT
BY EVAL "FIELD(@ID,'.',2)"
@ID............................. ONLINE.LIMIT.......
M000000004.0000100.01.129034 100000.00
100182.0005200.01.100182
111661.0005200.01.111661
188919.0005200.01.188919
188919.0005205.01.188919
...
...
...
M000000001.0038300.01.100803 2000000.00
Another example where we use an alias to both show and sort by:
LIST FBNK.SEC.ACC.MASTER CONTRIBUTIONS WITHDRAWALS
EVAL "MAXIMUM(SUM(WITHDRAWALS):@FM:SUM(CONTRIBUTIONS))" AS summ
BY.DSND summ
@ID.............. CONTRIBUTIONS..... WITHDRAWALS....... summ...........
100472-950 0 0 7012041.07
7012041.07 707637.06
100461-940 0 0 4567231.68
633121.43 4567231.68
100472-940 0 0 3981892.51
1251657.27 3981892.51
111602-1 0 0 1366958.42
1366958.42 0.00
100297-2 0 0 1023662.78
1023662.78 350004.02
100292-1 0 0 960010.89
960010.89 241281.39
// Page 58
"AS" is sensitive to keywords; if we use "AS sum" we’ll get an er-
ror:
Error in AS clause.
Usual way:
LIST F.VERSION WITH EVAL "DCOUNT(AUTOM.FIELD.NO,@VM)" EQ 3 AUTOM.FIELD.NO
AUT.OLD.CONTENT AUT.NEW.CONTENT BY.DSND @ID
@ID............. VERSION,DESIGNER
AUTOM.FIELD.NO.. RECORDS.PER.PAGE FIELDS.PER.LINE LANGUAGE.CODE-1
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1 MULTI 1
@ID............. TRANS.DOCUMENT,RECORD.DOCUMENT
AUTOM.FIELD.NO.. STATUS STATUS.DATE DOC.SEQUENCE
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1 !TODAY 1
@ID............. TELLER.FINANCIAL.SERVICES,BILL.PAYMENT
AUTOM.FIELD.NO.. TRANSACTION-1 BENEFICIARY.ID-1 SURROGATE.AC-1
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. Bill-Pay BENEFICIARY>@ID BENEFICIARY>BEN.ACCT.NO
@ID............. TELLER,VAULT.TO.TILL
AUTOM.FIELD.NO.. TRANSACTION.CODE TELLER.ID.2 TELLER.ID.1
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 102 9999 !CURRENT.TELLER.1
...
With BY.EXP:
LIST F.VERSION WITH EVAL "DCOUNT(AUTOM.FIELD.NO,@VM)" EQ 3 AUTOM.FIELD.NO
AUT.OLD.CONTENT AUT.NEW.CONTENT BY.DSND @ID BY.EXP AUTOM.FIELD.NO
// Page 59
@ID............. VERSION,DESIGNER
AUTOM.FIELD.NO.. FIELDS.PER.LINE
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. MULTI
@ID............. VERSION,DESIGNER
AUTOM.FIELD.NO.. LANGUAGE.CODE-1
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1
@ID............. VERSION,DESIGNER
AUTOM.FIELD.NO.. RECORDS.PER.PAGE
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1
@ID............. TRANS.DOCUMENT,RECORD.DOCUMENT
AUTOM.FIELD.NO.. DOC.SEQUENCE
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1
@ID............. TRANS.DOCUMENT,RECORD.DOCUMENT
AUTOM.FIELD.NO.. STATUS
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. 1
@ID............. TRANS.DOCUMENT,RECORD.DOCUMENT
AUTOM.FIELD.NO.. STATUS.DATE
AUT.OLD.CONTENT.
AUT.NEW.CONTENT. !TODAY
...
Note that both BY.EXP and BY-EXP commands work; however it’s not al-
Paragraphs are records in VOC that can be used to run many commands or selects.
First line of such record should be "PA".
(There are also jCL paragraphs that start with "PQ / PQN" but they are almost out
of scope of this book.)
Example: list @IDs of customers which were edited but the changes were not yet
authorised (we don’t need to include records that were never authorised yet). Cre-
ate a VOC record SEE.CHANGED:
PA
SELECT FBNK.CUSTOMER$NAU
SELECT FBNK.CUSTOMER
LIST ONLY FBNK.CUSTOMER
// Page 60
Run it:
SEE.CHANGED
8 Records selected
** Error [ 202 ] **
Record '190122' is not on file.
** Error [ 202 ] **
Record '190117' is not on file.
** Error [ 202 ] **
Record '190108' is not on file.
** Error [ 202 ] **
Record '190089' is not on file.
** Error [ 202 ] **
Record '190142' is not on file.
** Error [ 202 ] **
Record '190115' is not on file.
2 Records selected
LIST ONLY FBNK.CUSTOMER$NAU PAGE 1 19:25:58 12 JUN 2017
@ID.......
100273
100407
2 Records Listed
To suppress the message "Record ’190115’ is not on file" we can use "(R" flag:
PA
SELECT FBNK.CUSTOMER$NAU
SELECT FBNK.CUSTOMER (R
LIST ONLY FBNK.CUSTOMER
Result:
8 Records selected
2 Records selected
LIST ONLY FBNK.CUSTOMER$NAU PAGE 1 19:40:57 12 JUN 2017
@ID.......
100273
100407
2 Records Listed
// Page 61
What if we want to proceed other tables as well? Ask user:
PA
DISPLAY <<TABLE>>
SELECT <<TABLE>>$NAU
SELECT <<TABLE>> (R
LIST ONLY <<TABLE>>
SEE.CHANGED
TABLE=FBNK.ACCOUNT
FBNK.ACCOUNT
28 Records selected
1 Records selected
LIST ONLY FBNK.ACCOUNT$NAU PAGE 1 14:53:54 12 JUN 2017
@ID................
21067
1 Records Listed
TABLE=FBNK.SECTOR
...
3503
4002
4601
5001
9999
48 Records Listed
Why so many? Scroll back, see what was selected in INAU file:
No Records selected
If we have no selection after first SELECT, the second one will - as it should -
select all records. To suppress this we can use REQUIRE.SELECT keyword:
PA
DISPLAY <<TABLE>>
SELECT <<TABLE>>$NAU
SELECT <<TABLE>> REQUIRE.SELECT (R
LIST ONLY <<TABLE>>
// Page 62
Now we have the following error message:
!!! Error message A Select list was required and not supplied.
not found !!!
Run:
SEE.CHANGED FBNK.ACCOUNT
PQN paragraph can be used to present a long jQL query on several lines, e.g.:
PQN
HSELECT FBNK.RE.CONSOL.SPEC.ENTRY WITH OUR.REFERENCE LIKE 'LD...'
H AND TRANSACTION.CODE EQ 'ACC' 'CAP' BY OUR.REFERENCE
H BY BOOKING.DATE BY DATE.TIME
P
Explain Plan
==============================================================================
file:
FBNK.ACCOUNT Type(20)
Scan all of the file, (jQLIDonlyFullFileSource)
Timings:
End.
// Page 63
2377 Records selected
Explain Plan
==============================================================================
file:
FBNK.STMT.ENTRY Type(20)
Scan all of the file, (jQLFullFileItemSource)
Timings:
End.
Show customer name in ACCOUNT listing (we use so-called "T correlative"):
LIST FBNK.ACCOUNT UNLIKE "3A..." EVAL "OCONV(CUSTOMER,'TFBNK.CUSTOMER;V1;2;2')"
@ID................ OCONV(CUSTOMER,"TFBNK.CUSTOMER;V1;2;2")
76902 Cadbury
75067 Helicks
14095 Merrill Lynch
14087 Merrill Lynch
...
Another example - list security ratings with additional information (in this ex-
ample - only the first RATING value if available):
LIST F.SECURITY.MASTER WITH SUB.ASSET.TYPE GE 200 AND SUB.ASSET.TYPE LE 299
EVAL "EXTRACT(RATING,1,1);OCONV(@1,'TF.EB.RATING;V;1;1'):'/'
:OCONV(@1,'TF.EB.RATING;V;3;3'); IF @2 EQ '/' THEN 'No rating' ELSE @2"
COL.HDR 'Rating' FMT '25L'
@ID......... Rating...................
300400-000 No rating
800000-011 No rating
000423-000 AA+.S&P/GOOD
000400-033 No rating
400300-001 AA+.S&P/GOOD
800000-016 No rating
200111-000 AA.S&P/GOOD
300300-000 No rating
// Page 64
400301-000 AA+.S&P/GOOD
200118-000 AA+.S&P/GOOD
400400-000 AAA.S&P/STRONG
400500-000 AAA.S&P/STRONG
500200-000 BBB.S&P/SATISFACTORY
300301-000 No rating
400300-000 AA+.S&P/GOOD
400200-000 AA-.S&P/GOOD
16 Records Listed
1 records copied
LIST &TEMP& 'SYSTEM'
@ID
SYSTEM
1 Records Listed
LIST &TEMP& 'SYSTEM' USING DICT F.SPF
@ID.................. SYSTEM
@ID.................. SYSTEM
SYSTEM.SPEC.......... SYSTEM
RUN.DATE............. 20150420
SITE.NAME............ Model Bank R15-AMR
OP.MODE.............. O
OP.CONSOLE........... OFF
MAIN.ACCOUNT......... ..\bnk.data
BACKUP.CYCLE.1.......
....
LIST &TEMP& 'SYSTEM' USING DICT F.ABBREVIATION
@ID............... SYSTEM
@ID............... SYSTEM
ABBREVIATION.CODE. SYSTEM
ORIGINAL.TEXT..... 20150420
RECORD.STATUS..... Model Bank R15-AMR
CURR.NO........... O
INPUTTER.......... OFF
DATE.TIME......... ..\bnk.data
// Page 65
AUTHORISER........
CO.CODE...........
DEPT.CODE......... R15
AUDITOR.CODE...... 1
AUDIT.DATE.TIME...
1 Records Listed
User exits are built-in codes starting from "U" that can be used in OCONV(). How-
ever, most of them can be easily replaced with EVAL.
Some examples:
Port number, user name:
LIST . SAMPLE 1 EVAL "OCONV('', 'U50BB')"
1 modelbank
Call stack:
LIST . SAMPLE 1 EVAL "OCONV('', 'U0016')" FMT '35L'
JQL_LISTCOLUMNAR LIST
"ABCDEFGHIJ"
.
SAMPLE
1
EVAL
"OCONV('', 'U20E0')"
FMT
'35L'
Encrypt a string:
LIST . SAMPLE 1 EVAL "OCONV('This Is How Globus Works', 'U3060')"
// Page 66
Ygh\{4$wmZ2}x)v]NSh29bB
Remove spaces:
LIST . SAMPLE 1 EVAL "OCONV('This Is How Globus Works', 'U01A9')"
ThisIsHowGlobusWorks
1504292128 21:28:16
1504291837 18:37:16
1504292051 20:51:00
1504292204 22:04:30
1504292237 22:37:14
8 Records selected
>SAVE.LIST SE-CNT
CT &SAVEDLISTS& SE-CNT
// Page 67
SE-CNT
001 104
002 106
003 100
004 52
005 107
006 91
007 2
008 101
D20150429267757645902 FORMATTED
D20150429469107521504 REPAIR
D20150430183750057912 FORMATTED
D20150429033096262402 FORMATTED
D20150429791836992805 FORMATTED
D20150429263236143001 FORMATTED
D20150504147773239909
D20150504147773239921 ACK
...
4.5 See on which work day an FT was created (based on its @ID)
LIST FBNK.FUNDS.TRANSFER$HIS
EVAL "OCONV(ICONV('20':@ID[3,2]:@ID[5,3],'DJ'),'D')"
COL.HDR 'CREATED' FMT '11L'
@ID...................... CREATED....
// Page 68
4.6 Get account balance history
21 Records selected
>SAVE.LIST ACT
SELECT FBNK.ACCT.ACTIVITY WITH @ID LIKE "10995..."
SAVING EVAL "FIELD(@ID,'-',1):';':FIELD(@ID,'-',2):';':DAY.NO:';':BALANCE"
BY @ID
2 Records selected
>SAVE.LIST ACT-SORTED
CT &SAVEDLISTS& ACT ACT-SORTED
ACT
001 10995;201504;01;11453030.73
002 02;11458094.98
003 03;11365993.17
004 06;11363057.06
005 07;11346375.83
006 08;11600192.31
007 09;11845509.75
008 10;11845458.37
009 13;11843702.81
010 14;11831258.2
011 15;11826883.2
012 17;12025233.2
013 20;12022297.09
014 21;12010095.7
015 22;13986696.11
016 10995;201503;24;3182275.69
017 25;3181000.69
018 26;3180840.69
019 29;1514174.02
020 30;1512981.24
021 31;1500720.73
// Page 69
ACT-SORTED
001 10995;201503;24;3182275.69]25;3181000.69]26;3180840.69]29;1514174.02
]30;1512981.24]31;1500720.73
002 10995;201504;01;11453030.73]02;11458094.98]03;11365993.17]06;11363057.06
]07;11346375.83]08;11600192.31]09;11845509.75]10;11845458.37
]13;11843702.81]14;11831258.2]15;11826883.2]17;12025233.2]20;12022297.09
]21;12010095.7]22;13986696.11
BNK/AA.SOD.PROCESS-AA.CREATE.NAU.ACTIVITIES D250 28
BNK/RE.BUILD.SLC-RE.UPDT.STAT.LINE.CONT R001 26
EU1/RE.BUILD.SLC-RE.UPDT.STAT.LINE.CONT R001 17
SG1/RE.BUILD.SLC-RE.UPDT.STAT.LINE.CONT R001 16
BNK/AA.EOD.PROCESS-AA.DELETE.NAU.ACTIVITIES S022 15
BNK/AA.EOD.PROCESS-AA.SERVICE.PROCESS S022 14
MF1/RE.BUILD.SLC-RE.UPDT.STAT.LINE.CONT R001 12
BNK/REPORT.PRINT.REPORTING-EB.EOD.REPORT.PRINT R999 11
BNK/TECPACK-BUILD.TECPACK O997 9
BNK/SL.END.OF.DAY-SL.EOD.PERFORM.ACCRUALS A100 7
SGP/DX.END.OF.DAY-DX.COB.CLEAR.MKT.HIST A100 7
...
VKAZIMIRCHIK 14:07:51
INPUTTER 14:06:28
2 Records Listed
// Page 70
4.9 See all active sessions in detail
C:\home\kzm\t24env\r15\TAFC\dev\PROC
1
001 1
002 2
003 1497878701
004 3128
005 modelbank
006 modelbank
007 vt220
008 vt220
009 default
010 CONIN$
011 en_US
012 1497878771
013 0
014 26263552
015 1
016 Normal
017 49747]100000
018 127
019 322
020 22
021 6
022 0
023 12
024 329
025
026 43
027 39
028 VKAZIMIRCHIK-0
029
030
031
032 1
033 0
034 3
035 0
036 0
037 13
038 1
039
040
// Page 71
041 jsh -]CT C:\home\kzm\t24env\r15\TAFC\dev\PROC
042 111]241
043 jsh.b]jutil.copycommand.b
044
045
046 Program performing EXECUTE/PERFORM]Program running normally
047 16]11
048 71.14]0.00
049 0.00]0.00
050 0.00]0.00
051 0.00]0.00
052 ]
// Page 72