diff -r d4f401b5f90c -r 4919c8098008 relpipe-data/examples-guile-filtering.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/relpipe-data/examples-guile-filtering.xml Thu Feb 07 11:52:32 2019 +0100 @@ -0,0 +1,202 @@ + + + Complex filtering with Guile + filtering records with AND, OR and functions + 01400 + + + +

+ For simple filtering, we can use relpipe-tr-grep. + But what if we need to write some complex query that contains AND and OR operators? + What if we need e.g. compare numbers – not only match texts against regular expressions? + There is a tool capable to do this and much more: relpipe-tr-guile! +

+ +

+ Guile is the GNU implementation of Scheme language (something like Lisp and also full of parenthesis). + The relpipe-tr-guile uses GNU Guile as a library, puts data in the Guile context and evaluates Guile expressions and then reads data from the Guile context back and generates relational output from them. + Good news are that it is not necessary to know Lisp/Scheme to use this tool. For the first steps, it can be used just as a query language – like SQL, just a bit Polish. +

+ +

Filtering numbers

+ +

+ We are looking for „satanistic“ icons in our filesystem – those that have size = 666 bytes. +

+ + + +

Well, well… here we are:

+ + + +

The --relation 'files.*' is a regular expression that says which relations should be processed in Guile – others are passed through unchanged.

+ +

+ The --where '(= $size 666)' is our condition. + The Polishsee Polish notation thing means that we write = $size 666 instead of $size = 666. + It seems a bit weird but it makes sense – the = is a function that compares two numbers and returns a boolean value – + so we just call this function and pass $size and 666 arguments to it. + And because it is a function, there are (parentheses). +

+ +

+ Relational attributes are mapped to Guile variables with same name, just prefixed with $. + (we considered + + symbol, but $ seems to be still more common on keyboards in 2019) + While relational attribute name is an arbitrary string, Guile variable names have some limitations, thus not all attributes can be mapped – those with spaces and some special characters are currently unsupported (this will be fixed in later versions by some kind of encoding/escaping). +

+ +

+ We can also look for + --where '(> $size 100)' which means „size is greater than 100“ + or + --where '(< $size 100)' which means „size is smaller than 100“. + The >= and <= also work as expected. +

+ +

Filtering strings

+ +

+ Scheme is strongly typed language and we have to use proper functions/operators for each type. + For strings, it is string= instead of = function: +

+ + + +

The Btrfs filesystems in our fstab:

+ + + +

+ There is also string-prefix? which evaluates whether the first string is a prefix of the second string: +

+ + + +

So we can find filesystems mounted somewhere under /mnt:

+ + + +

+ There are much more functions – can be found in the Guile documentation + – like case-insensitive variants (e.g. string-ci=) or regular expression search (string-match). +

+ + +

AND and OR

+ +

+ Like in SQL, we can join multiple conditions together with logical operators AND and OR. + In Guile/Scheme these operators are also functions – they are written in the same (fashion). +

+ +

+ So we can e.g. look for icons that are „satanistic“ or „Orwellian“: +

+ + + +

Files with sizes 666 bytes or 1984 bytes:

+ + + +

Or we can look for icons that are in SVG format and (at the same time) Orwellian:

+ + + +

Which is quite rare and we have only two such icons:

+ + + +

+ We can nest ANDs and ORs and other functions as deep as we need and build even very complex queries. + Prentheses nesting is fun, isn't it? +

+ + + + + +
+ +