file | csqll.4gl |
declaration | function sql_execute(i_query, touch, verbose, html, width, txtvar) define i_query char(K_scriptbuf), #the sql statemet(s) def_fd, #output stream flags, #various behavioural flags width integer, #text width txtvar text #where to store the output |
returns | sqlcode, integer, sql error returned by the script |
purpose | A sql interpreter with a number of syntax and formatting additions and an expansion facility |
example | none |
notes |
|
file | csqll.4gl |
declaration | function sql_execute2(i_query, touch, verbose, html, width, txtvar) define i_query text, #the sql statemet(s) def_fd, #output stream flags, #various behavioural flags width integer, #text width txtvar text #where to store the output |
returns | sqlcode, integer, sql error returned by the script |
purpose |
sql_execute2 offers a slight different interface to the
sql interpreter facility than
sql_execute
|
example | none |
notes |
|
file | cexpl.4gl |
declaration | function sql_explode(i_query, hash, verbose, state, s) define i_query char(K_scriptbuf), #the script buffer hash text, #variables hash verbose, #verbose flag state, #expansion state flag s smallint #starting column |
returns |
ts, smallint, start of unexpanded query text te, smallint, end of unexpanded query text txt, char(512), expanded text tr, smallint, scan resume point |
purpose | Implements the expansion facility |
example | none |
notes |
|
The Sql interpreter boosts a number of interesting features, including
Additional statements. Besides supporting multiple SQL statements (separated by semicolons), the following is supported
foreach <select statement>; <statement list>|break|continue done; |
for <variable> in <expression>[, <expression>...]; <statement list>|break|continue done; |
while <expression>; <statement list>|break|continue done; |
if <expression>; <statement list> [elif <expression>; <statement list> ...] [else <statement list>] fi; |
unload to <expression> [delimiter <expression>] <select statement>; |
load <expression> [delimiter <expression>]< insert statement>; |
let <variable>[<substring range>]=<expression>; |
display <expression>[, <expression>...]; |
append to <expression>|default; |
output to <expression>; |
pipe to <expression>; |
exit [<expression>]; |
whenever error continue|stop; |
<expression> can be just about anything listed in the "Condition" and
"Expression" segments of the IDS 7.3 syntax guide with the following
variations:
|
for , foreach and while loops can
be exited with a break statement, or their
reminder can be skipped with a continue statement. |
append , output and pipe all
instruct the interpreter to redirect its output.
The expression passed to append and output is a
name of a file (output will truncate it, append
will add to it), while pipe , as you would expect, pipes
the output to a child process.
In case of failure, the output is redirected to the deafult stream, and
the reason of the failure can be inspected via dbinfo("errno") .
append to default causes the new output generated by the
interpreter to be added to the default stream, which in the case of the demo
application is the viewer display, but can be defined to be a
file or pipe. |
Note finally that exit has different meanings depending
whether the process is the result of a FORK (the process
terminates) or not (the script terminates and the process resumes normal
operation). |
Data Storage. Foreach and plain select statements can assign values to variables. Use an
into variable[, variable...]
clause at the end of the statement to list the target variables.
Placeholders. As an alternative to the expansion facility (see below), it
is possible to use placeholders as you would on an open
or execute
statement. Use an
using variable[, variable...]
clause at the end of the statement to list the variables that should
substitute placeholders. This feature can be used to insert or update
(should you ever get a working version of the IFX_UPDDESC
feature)
text values on the fly.
Formatting. Queries and displays can be formatted. add the following clause at the end of the select statement:
format brief|{full|vertical [<expression>] [headers <expression list>]}
The brief format only outputs column values separated by commas, with no formatting whatsoever, vertical will output rows in a header/column fashion (formatting columns in the way), and lastly full formats rows as you would expect.
The first expression is a format specifier in which c and 4gl format specifiers
can be used. C formats are specified the usual way (see sprintf (3)
), while
4gl formats have to be enclosed in square brackets. format specifiers can
be interspersed with plain text, hard tabs & new lines, or \n
and \t
.
To ease header formatting (in case plain text appears in the format, in particular
for vertical formats), columns
can be separated with the pipe (|
) sign. This is not required though.
Special characters ([]%|
and the quotes in use) can be escaped by doubling
them. Note that the backslash has special significance only when followed
by either 't' or 'n'.
Note that there's no need to specify as many format specifiers as columns,
while with full format, more than needed will combine multiple rows into
a single format.
The header clause specifies a list of headers to be output as the first row of the query in full format, and preceding each column in vertical format. Headers will be padded to the length of the appropriate field (full format) or the largest header (vertical).
As for formats, there's no need that the number of headers matches that of the items being selected.An expansion facility caters for pick lists or query or application output
substitution anywhere in the script. Expansions are
performed whenever a <+ +>
pair is encountered, can be freely nested (up
to a depth of 10 at present), and can be any of the following:
READ file[ file...] |
displays the contents of multiple files |
EXEC pipe |
executes an arbitrary application |
get variable [, variable...] |
returns the contents of previously stored variables |
a select statement | displays the results of a query |
prefix the above with any of the following options to change expansion behavior:
[coded|lone|silent] |
Specifies which expansion should be performed.
coded will open a code/description pick list
(only the code is returned), lone will open
a description only pick list, while silent
will just do a plain expansion. |
[single|multi] |
Specifies whether the expansion should return one or more values. For pick lists, this controls whether multiple selections are allowed. For silent expansions, whether only the first or all values should be returned. |
put variable |
stores the output of the expansion in the variable specified. |
quotes <quoted string> |
Specifies quotes to surround each value returned by get or multiple expansions. Default is none. Enter two characters to specify differring start and end quotes. |
separator <quoted string> |
Specifies the entry separator between each value returned by get or multiple expansions. Default is blank. |
A few gotchas:
Expansions can be commented using a <* *>
pair. At par to <+ +>
pairs, such
comments can be nested. Expansions and comment tokens can be escaped with a
backslash. Note that the backslash does not escape anything else, thus you
don't need to escape it to use it in the context of a select statement or a
shell script.
Finally, feel free to use whichever comment mechanism you like, as long as it
makes sense within the context in which it is used, eg {}
or --<CR>
in
SQL statements, or #<CR>
in perl/awk/sh scripts.
The following query (find it in 4gwapps/4gwdemo/etc/demo1.fgw
) shows many of
the syntax additions:
display "Name", "Owner", "Type", "Cluster", "Column" format full "%-18s %-8s %-7s %-7s %-18s"; foreach select idxname, owner, idxtype, clustered, colname, part2, part3, part4, part5, part6, part7, part8 from <+lone put db select name from sysmaster:sysdatabases+>:sysindexes i, <+get db+>:syscolumns c where i.tabid=<+coded put tbl select tabid, tabname from <+get db+>:systables order by tabid+> and c.tabid=i.tabid and i.part1=c.colno order by idxname into name, owner, type, clustered, col1, part2, part3, part4, part5, part6, part7, part8; display name, owner, type, clustered, col1 format full "%-18s %-8s %3s %3s %-18s"; select colname from <+get db+>:syscolumns c where c.colno in (<+separator "," get part2, part3, part4, part5, part6, part7, part8+>) and c.tabid=<+get tbl+> format full "\t\t\t\t\t %-18s"; display ""; done;
Which yields: