Skip to main content
Version: 7.0

Utils

Utils is a system module that collects frequently needed helper properties and actions: file-system access, data conversion and encoding, string operations, arithmetic, JSON access, full-text search, server diagnostics, and so on. It is pulled in via REQUIRE Utils (System and Time are pulled in automatically).

File system

The (ISTRING path, ...) actions run on the server by default; the isClient = TRUE flag (or a separate client-side overload) performs the same operation on the client.

Action / propertyWhat it does
listFiles[ISTRING, BOOLEAN, BOOLEAN] and overloadslists files in a directory; writes the name, directory flag, modification time, and size into the local properties fileName, fileIsDirectory, fileModifiedDateTime, fileSize keyed by INTEGER
listFilesClient[…]same, on the client
fileExists[ISTRING] / fileExistsClient[ISTRING]existence check; result in fileExists[]
mkdir[ISTRING] / mkdirClient[ISTRING]create a directory
delete[ISTRING] / deleteClient[ISTRING]delete a file or directory
copy[ISTRING, ISTRING] / copyClient[…]copy
move[ISTRING, ISTRING] / moveClient[…]move
getFileSize[FILE]file size in bytes, written into fileSize[]
appendToFile[STRING, TEXT, STRING]append a line to a file with the given encoding

File contents and encoding

Property / actionWhat it does
stringToFile[TEXT, STRING, STRING]resultFile[]serialize a string into a FILE with the given encoding and extension
fileToString[FILE, STRING]resultString[]read a FILE as a string
linkToString[LINK] / richTextToString[RICHTEXT]cast a link / rich-text value to STRING
readResource[STRING, BOOLEAN]resource[]read a resource from the classpath
readResourcePaths[STRING, BOOLEAN]resourcePathslist resources matching a pattern
readProperties[RAWFILE]properties[STRING]parse a .properties file into a lookup property
encode[…, STRING] / decode[STRING, STRING]encode binary data into a STRING and decode it back into a RAWFILE; the second argument is the encoding format (base64, hex, escape); PG encode($1,$2) / decode($1,$2)
encodeBase64[…] / encodeBase64Unchunked[…] / decodeBase64[STRING]base64 for RAWFILE, STRING, FILE, NAMEDFILE
urlEncode[TEXT, TEXT]urlEncoded[] / urlDecode[…]urlDecoded[]URL encoding with the given charset
urlParse[] / urlFormat[] (over urlFormatted and urlParsed)parse a URL into parts and reassemble it
escapeJSONValue[TEXT] / escapeXMLValue[TEXT]escape a string for embedding into JSON / XML

Archives

ActionWhat it does
zipping[STRING] <- fileaccumulating files for the archive (STRING path inside the archive → contents)
makeZipFile[BOOLEAN]zipped[]build the archive; the flag controls whether to zero out file timestamps
unzipping[] <- fileset the archive to be unpacked
makeUnzipFile[]unzipped[STRING]unpack; result: STRING path inside the archive → file

Console and network

ActionWhat it does
cmd[TEXT, TEXT, BOOLEAN, BOOLEAN] and overloadsrun an OS command; result in cmdOut[] and cmdErr[]
cmdClient[TEXT, BOOLEAN] / cmdClient[TEXT]same, on the client
ping[TEXT, BOOLEAN] / pingClient[TEXT]host availability check; error in pingError[]

Excel

Property / actionWhat it does
protectExcel[EXCELFILE, STRING]protectedExcel[]password-protect a file
mergeExcel[EXCELFILE, EXCELFILE]mergedExcel[]merge two files
columnsCount[EXCELFILE, INTEGER]columnsCount[]number of columns on a sheet
sheetNames[EXCELFILE]sheetNames[INTEGER]sheet names

PDF and Word

Property / actionWhat it does
pagesCountPdf[PDFFILE]pagesCountPdf[]number of pages
pdfToString[PDFFILE, BOOLEAN]recognize text from PDF
wordToPdf[WORDFILE]convert Word to PDF

Strings

Almost all of these properties are declared with FORMULA and, on PostgreSQL, translate into a same-named SQL function or operator. Where a property maps directly to a PostgreSQL expression, it is given at the end of the description after ; PG ($1, $2, … are the parameters in order).

PropertyWhat it does
length[TEXT]string length in characters; PG length($1)
left[TEXT, INTEGER] / right[TEXT, INTEGER]first / last n characters of a string; for a negative n PostgreSQL drops the last / first |n| characters; PG left($1,$2) / right($1,$2)
substr[TEXT, INTEGER, INTEGER] / substrFrom[TEXT, INTEGER]substring of length len starting at position from (1-based) / substring from position from to the end; PG substring($1,$2,$3) / substring($1,$2)
substring[STRING, STRING]the first substring matching a POSIX regular expression; NULL if there is no match; PG substring($1, $2)
strpos[TEXT, TEXT]position of the first occurrence of the substring (1-based); 0 if not found; PG strpos($1,$2)
replace[TEXT, TEXT, TEXT]replace all occurrences of from with to; PG replace($1,$2,$3)
ltrim[…] / rtrim[…] / trim[TEXT]trim whitespace on the left / right / both sides; PG ltrim($1) / rtrim($1) / trim($1)
ltrim[TEXT, TEXT] / rtrim[TEXT, TEXT]trim, on the left / right, any of the characters listed in the second argument; PG ltrim($1,$2) / rtrim($1,$2)
lpad[TEXT, INTEGER, TEXT] / rpad[…]pad with fill on the left / right up to length len; if the source string is longer than len, it is truncated; PG lpad($1,$2,$3) / rpad($1,$2,$3)
repeat[TEXT, INTEGER]repeat the string n times; PG repeat($1,$2)
startsWith[…] / istartsWith[…] / endsWith[…]check the start / end of a string; the i-form is case-insensitive; PG $1 LIKE $2||'%' / $1 LIKE '%'||$2 (the i-forms use ILIKE)
isSubstring[…] / isISubstring[…]substring containment, case-sensitive / case-insensitive; PG $1 LIKE '%'||$2||'%' (isISubstring uses ILIKE)
isWordInCSV[…]splits the second argument by comma and checks the first argument for an exact match against one of the elements; PG string_to_array($2,',') + = ANY
getWord[TEXT, TEXT, INTEGER] / wordCount[TEXT, TEXT]getWord — the fragment numbered p3 (1-based) after splitting by the separator, NULL if out of range; wordCount — the number of fragments; PG (string_to_array($1,$2))[$3] / array_length(string_to_array($1,$2),1)
splitPart[STRING, STRING, INTEGER]the num-th fragment (1-based) after splitting by the separator; an empty string if out of range; PG split_part($1,$2,$3)
regexpReplace[STRING, STRING, STRING, STRING]replace, in source, matches of the POSIX pattern with replace; the fourth argument is flags (e.g. g — replace all occurrences, not only the first); PG regexp_replace($1,$2,$3,$4)
regexPatternMatch[TEXT, STRING]match of a string against a POSIX regular expression, case-sensitive; PG — the ~ operator
onlyDigits[TEXT]flag that the string (with surrounding whitespace trimmed) consists only of digits; PG trim($1) ~ '^[0-9]*$'
array[STRING, STRING, INTEGER]table-valued wrapper: unnests a delimited string into a row-keyed set of values; the row parameter is the iteration variable (as in array[JSON, INTEGER], see below); PG unnest(string_to_array($1,$2))

The predicate properties (startsWith, endsWith, isSubstring, isWordInCSV, regexPatternMatch, onlyDigits, and the like) are declared as FORMULA NULL BOOLEAN and return TRUE when the condition holds and NULL otherwise (not FALSE) — following the lsFusion convention for conditions.

For identifiers and the clipboard: generateUUID[]generatedUUID[], generatePassword[INTEGER, BOOLEAN, BOOLEAN]generatedPassword[], copyToClipboard[TEXT]; for cookies: getCookie[STRING]cookie[], setCookie[STRING, STRING, JSON].

Numbers

Some of these properties are wrappers around PostgreSQL numeric functions, others are pure arithmetic formulas that call no DBMS function. Where a property maps to a PostgreSQL expression, it is given at the end of the description after ; PG.

PropertyWhat it does
abs[…] / delta[…, …]absolute value / absolute difference of two values; PG abs($1) / abs($1-$2)
min[…, …] / max[…, …]minimum / maximum of two values; computed arithmetically, with no DBMS function call; PG ($1+$2-abs($1-$2))/2 / ($1+$2+abs($1-$2))/2
floor[…] / floor[…, …]round down; the two-argument form rounds down to a multiple of the step $2; PG floor($1) / floor($1/$2)*$2
ceil[…] / ceil[…, …]round up; the two-argument form rounds up to a multiple of the step $2; PG ceiling($1) / ceiling($1/$2)*$2
round[…, …], roundM1 / round0round6round a value cast to numeric to n decimal places; n may be negative (roundM1 = round(…,-1)), round0round6 fix n from 0 to 6; PG round(CAST($1 AS numeric),$2)
trunc[…, …]truncate to n decimal places without rounding; PG trunc($1,$2)
mod[…, …] / divideInteger[…, …] / divideIntegerNeg / divideIntegerRndremainder of division; divideInteger — integer division, divideIntegerNeg — integer division rounding toward zero for negatives, divideIntegerRnd — division with the result rounded to an integer; PG mod($1,$2) (the rest — casts to integer and round)
sqr[…] / sqrt[…] / power[…, …]square (with no DBMS function), square root, power (the result is DOUBLE); PG $1*$1 / sqrt($1) / power($1,$2)
ln[…] / exp[…]natural logarithm (DOUBLE) / exponential; PG ln($1) / exp($1)
percent[…, …] / share[…, …]percentage of a sum / share of the whole as a percentage; computed arithmetically, with no DBMS function call; PG $1*$2/100 / $1*100/$2
bitwiseAnd[…, …] / bitwiseOr[…, …] / bitwiseNot[…]bitwise AND / OR / NOT on integers; PG $1 & $2 / $1 | $2 / ~ $1
toInteger[…] / toNumeric[…] / toNumericNull[…]parse a value into INTEGER / NUMERIC[38,19]; for an unparseable value toInteger and toNumeric return 0, while toNumericNull returns NULL; PG convert_to_integer($1) / convert_to_numeric($1) / convert_to_numeric_null($1) — functions created by the platform in the DB
toChar[…, …]format a number or date into a string by a PostgreSQL template; PG to_char($1,$2)

Iteration

iterate[INTEGER, INTEGER, INTEGER] — recursive enumeration of an integer range from from to to. count[INTEGER, INTEGER] is a special case: iterate(i, 1, count). See the analogous iterate for dates in Time.

Color

colorToHexString[COLOR] — color representation as '#RRGGBB': the color is cast to an integer and converted to a hex string by to_hex, then the first two hex digits (the high byte — the alpha component) are dropped and a # prefix is added; PG '#'||substring(to_hex($1::integer),3).

Wrappers around PostgreSQL full-text search functions. Available on PostgreSQL only.

PropertyWhat it does
toTsVector[STRING, STRING] / toTsVector[STRING]build a TSVECTOR from text using a dictionary: the text is split into normalized lexemes (the first argument is cast to regconfig); the single-argument form uses the english dictionary; a NULL text is replaced with an empty string; PG to_tsvector($1::regconfig, coalesce($2,''))
toTsQuery[STRING, STRING] / toTsQuery[STRING]build a TSQUERY: the query text is parsed into a tree of lexemes and operators using the dictionary; the single-argument form uses english; PG to_tsquery($1::regconfig, coalesce($2,''))
setWeight[TSVECTOR, STRING]tag all lexemes of a vector with the weight label 'A''D' (the second argument is cast to the "char" type); PG setweight($1, $2::"char")
tsRank[TSVECTOR, TSQUERY] / tsRank[…, INTEGER]relevance ranking of a vector against a query by the frequency of matched lexemes (DOUBLE); the third argument is the length-normalization bitmask; PG ts_rank($1,$2) / ts_rank($1,$2,$3)
tsRankCD[TSVECTOR, TSQUERY] / tsRankCD[…, INTEGER]the same with the cover-density model — by the density of matches, accounting for lexeme proximity; the third argument is the normalization mask; PG ts_rank_cd($1,$2) / ts_rank_cd($1,$2,$3)
tsRankLN[TSVECTOR, TSQUERY, DOUBLE]tsRank with a logarithmic correction for vector length: tsRank(v,q) / (1 + ln(length of v) / ln(base)); a composite property, not a standalone DBMS function
numNode[TSQUERY]number of nodes (lexemes and operators) in a parsed query; PG numnode($1)

JSON access properties

This section collects the wrappers around PostgreSQL's jsonb_* functions that read values out of an existing JSON. They complement the JSON operator, which goes the other way and builds JSON from properties or from a form. Most are declared with the FORMULA operator.

PropertyWhat it returns
field[JSON, STRING]value at the given key, as JSON; PG jsonb_extract_path($1,$2)
field[JSON, STRING, STRING]value at the given two-key path, as JSON; PG jsonb_extract_path($1,$2,$3)
field[JSON, STRING, STRING, STRING]value at the given three-key path, as JSON; PG jsonb_extract_path($1,$2,$3,$4)
fieldText[JSON, STRING] / […, STRING, STRING] / […, STRING, STRING, STRING]same as field but as STRING; PG jsonb_extract_path_text(…)
array[JSON, INTEGER]array element at the given index, as JSON; the index parameter is also the iteration variable; PG jsonb_array_elements($1) — expands a JSON array into a set of rows
arrayText[JSON, INTEGER]same as array but as STRING; PG jsonb_array_elements_text($1)
arrayElement[JSON, INTEGER]array element at the given 1-based index as a raw string (jsonb → text); PG ($1)->($2-1) (the -> operator)
map[JSON, STRING]value for each key-value pair of a JSON object, as JSON; the key parameter is also the iteration variable; PG jsonb_each($1) — expands a JSON object into a set of key-value pairs
mapText[JSON, STRING]same as map but as STRING; PG jsonb_each_text($1)
merge[JSON, JSON]recursive merge of two JSON values: objects are merged by key recursively, and on a conflict of non-object values the second argument wins; PG jsonb_recursive_merge($1,$2) — platform function
canonicalizeJSON[JSONFILE, BOOLEAN] / canonicalizeJSON[JSONFILE]canonicalizedJSON[]canonical normalization of a JSON file; the short form is equivalent to canonicalizeJSON(file, TRUE) (encode unicode characters); an INTERNAL action, not a DBMS function

field[JSON, STRING ...] and fieldText[JSON, STRING ...] are scalar wrappers around jsonb_extract_path and jsonb_extract_path_text. They return the value at the given one-, two-, or three-key path. They differ only in the class of the result: field returns JSON for further composition (passing the result into array or into another field), while fieldText returns STRING directly. For paths deeper than three keys, compose field calls.

array[JSON, INTEGER] and arrayText[JSON, INTEGER] are table-valued wrappers around jsonb_array_elements and jsonb_array_elements_text. The INTEGER row parameter is not referenced in the SQL text, so the platform fills it with the row number from ROW_NUMBER() OVER () — a special shortcut for an unreferenced INTEGER parameter with exactly that name. In practice the parameter plays a double role: an index for direct access (array(j, 1) returns the first element) and the iteration variable in expressions like array(j, INTEGER o), where o is declared in place and walks every array index.

map[JSON, STRING] and mapText[JSON, STRING] are table-valued wrappers around jsonb_each and jsonb_each_text, returning (key, value) pairs of a JSON object. The STRING key parameter is unreferenced in the SQL text and therefore becomes the key column of the result; the name key matches the column name in the jsonb_each result.

arrayElement[JSON, INTEGER] is a separate shortcut for direct indexed access. It goes through the PostgreSQL -> operator, takes a 1-based index, and shifts it to 0-based on its own. It returns STRING — the textual representation of jsonb. Useful for logging and debugging, when a raw view of the element is needed rather than a parsed value.

Local file-class properties

Empty LOCAL properties for every common file class: file[], wordFile[], imageFile[], pdfFile[], dbfFile[], rawFile[], excelFile[], textFile[], csvFile[], htmlFile[], jsonFile[], xmlFile[], tableFile[]. Convenient as intermediate buffers for import/export without declaring an ad-hoc LOCAL.

Logging

printToLog[TEXT, STRING, STRING] and its overloads write a message to the server log. The parameters are the message text, the logger name (default 'system'), and the level (default 'info').

Dialog forms

dialogString, dialogDate, dialogInteger, dialogNumeric are ready-made single-object forms for prompting the user for a value of the corresponding class. They are used as DIALOG dialog<...> OBJECTS ... INPUT DO { ... }.

Runtime environment

serverAvailableProcessors[], serverFreeMemoryMB[], serverTotalMemoryMB[], serverMaxMemoryMB[] are filled by the readServerMemory[] action. They expose the server JVM parameters: number of available processors and three heap-size characteristics.

Language

  • JSON operator — building a JSON value from properties or from a form.
  • FORMULA operator — the syntax behind most properties of the module.
  • IMPORT operator — reading a JSON file into a form or through FIELDS … DO.

See also