relpipe-data/examples-guile-filtering.xml
branchv_0
changeset 316 d7ae02390fac
parent 258 2868d772c27e
equal deleted inserted replaced
315:d4c2968a391f 316:d7ae02390fac
     1 <stránka
     1 <stránka
     2 	xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
     2 	xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
     3 	xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
     3 	xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
     4 	
     4 	
     5 	<nadpis>Complex filtering with Guile</nadpis>
     5 	<nadpis>Complex filtering with Scheme</nadpis>
     6 	<perex>filtering records with AND, OR and functions</perex>
     6 	<perex>filtering records with AND, OR and functions</perex>
     7 	<m:pořadí-příkladu>01400</m:pořadí-příkladu>
     7 	<m:pořadí-příkladu>01400</m:pořadí-příkladu>
     8 
     8 
     9 	<text xmlns="http://www.w3.org/1999/xhtml">
     9 	<text xmlns="http://www.w3.org/1999/xhtml">
    10 		
    10 		
    11 		<p>
    11 		<p>
    12 			For simple filtering, we can use <code>relpipe-tr-grep</code>.
    12 			For simple filtering, we can use <code>relpipe-tr-grep</code>.
    13 			But what if we need to write some complex query that contains AND and OR operators?
    13 			But what if we need to write some complex query that contains AND and OR operators?
    14 			What if we need e.g. compare numbers – not only match texts against regular expressions?
    14 			What if we need e.g. compare numbers – not only match texts against regular expressions?
    15 			There is a tool capable to do this and much more: <code>relpipe-tr-guile</code>!
    15 			There is a tool capable to do this and much more: <code>relpipe-tr-scheme</code>!
    16 		</p>
    16 		</p>
    17 		
    17 		
    18 		<p>
    18 		<p>
    19 			<a href="https://www.gnu.org/software/guile/">Guile</a> is the GNU implementation of Scheme language (something like Lisp and also full of parenthesis).
    19 			<a href="https://www.gnu.org/software/guile/">Guile</a> is the GNU implementation of Scheme language (something like Lisp and also full of parenthesis).
    20 			The <code>relpipe-tr-guile</code> 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.
    20 			The <code>relpipe-tr-scheme</code> reference implementation uses GNU Guile as a library, puts data in the Scheme context and evaluates Scheme expressions and then reads data from the Scheme context back and generates relational output from them.
    21 			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.
    21 			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.
    22 		</p>
    22 		</p>
    23 		
    23 		
    24 		<h2>Filtering numbers</h2>
    24 		<h2>Filtering numbers</h2>
    25 		
    25 		
    27 			We are looking for „satanistic“ icons in our filesystem – those that have size = 666 bytes.
    27 			We are looking for „satanistic“ icons in our filesystem – those that have size = 666 bytes.
    28 		</p>
    28 		</p>
    29 		
    29 		
    30 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
    30 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
    31 	| relpipe-in-filesystem \
    31 	| relpipe-in-filesystem \
    32 	| relpipe-tr-guile --relation 'files.*' --where '(= $size 666)' \
    32 	| relpipe-tr-scheme --relation 'files.*' --where '(= $size 666)' \
    33 	| relpipe-out-tabular]]></m:pre>
    33 	| relpipe-out-tabular]]></m:pre>
    34 	
    34 	
    35 		<p>Well, well… here we are:</p>
    35 		<p>Well, well… here we are:</p>
    36 		
    36 		
    37 		<m:pre jazyk="text"><![CDATA[filesystem:
    37 		<m:pre jazyk="text"><![CDATA[filesystem:
    52  │ /usr/share/icons/gnome/22x22/status/weather-overcast.png              │ f             │            666 │ root           │ root           │
    52  │ /usr/share/icons/gnome/22x22/status/weather-overcast.png              │ f             │            666 │ root           │ root           │
    53  │ /usr/share/icons/gnome/16x16/actions/go-home.png                      │ f             │            666 │ root           │ root           │
    53  │ /usr/share/icons/gnome/16x16/actions/go-home.png                      │ f             │            666 │ root           │ root           │
    54  ╰───────────────────────────────────────────────────────────────────────┴───────────────┴────────────────┴────────────────┴────────────────╯
    54  ╰───────────────────────────────────────────────────────────────────────┴───────────────┴────────────────┴────────────────┴────────────────╯
    55 Record count: 13]]></m:pre>
    55 Record count: 13]]></m:pre>
    56 
    56 
    57 		<p>The <code>--relation 'files.*'</code> is a regular expression that says which relations should be processed in Guile – others are passed through unchanged.</p>
    57 		<p>The <code>--relation 'files.*'</code> is a regular expression that says which relations should be processed in Scheme – others are passed through unchanged.</p>
    58 		
    58 		
    59 		<p>
    59 		<p>
    60 			The <code>--where '(= $size 666)'</code> is our condition. 
    60 			The <code>--where '(= $size 666)'</code> is our condition. 
    61 			The Polish<m:podČarou>see <a href="https://en.wikipedia.org/wiki/Polish_notation">Polish notation</a></m:podČarou> thing means that we write <code>= $size 666</code> instead of <code>$size = 666</code>.
    61 			The Polish<m:podČarou>see <a href="https://en.wikipedia.org/wiki/Polish_notation">Polish notation</a></m:podČarou> thing means that we write <code>= $size 666</code> instead of <code>$size = 666</code>.
    62 			It seems a bit weird but it makes sense – the <code>=</code> is a function that compares two numbers and returns a boolean value – 
    62 			It seems a bit weird but it makes sense – the <code>=</code> is a function that compares two numbers and returns a boolean value – 
    63 			so we just call this function and pass <code>$size</code> and <code>666</code> arguments to it.
    63 			so we just call this function and pass <code>$size</code> and <code>666</code> arguments to it.
    64 			And because it is a function, there are <code>(</code>parentheses<code>)</code>.
    64 			And because it is a function, there are <code>(</code>parentheses<code>)</code>.
    65 		</p>
    65 		</p>
    66 		
    66 		
    67 		<p>
    67 		<p>
    68 			Relational attributes are mapped to Guile variables with same name, just prefixed with <code>$</code>.
    68 			Relational attributes are mapped to Scheme variables with same name, just prefixed with <code>$</code>.
    69 			(we considered <code>
    69 			(we considered <code>
    70 				<abbr title="Bitcoin">₿</abbr>
    70 				<abbr title="Bitcoin">₿</abbr>
    71 			</code> symbol, but <code>$</code> seems to be still more common on keyboards in 2019)
    71 			</code> symbol, but <code>$</code> seems to be still more common on keyboards in 2019)
    72 			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).
    72 			While relational attribute name is an arbitrary string, Scheme 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).
    73 		</p>
    73 		</p>
    74 		
    74 		
    75 		<p>
    75 		<p>
    76 			We can also look for 
    76 			We can also look for 
    77 			<code>--where '(&gt; $size 100)'</code> which means „size is greater than 100“
    77 			<code>--where '(&gt; $size 100)'</code> which means „size is greater than 100“
    86 			Scheme is strongly typed language and we have to use proper functions/operators for each type.
    86 			Scheme is strongly typed language and we have to use proper functions/operators for each type.
    87 			For strings, it is <code>string=</code> instead of <code>=</code> function:
    87 			For strings, it is <code>string=</code> instead of <code>=</code> function:
    88 		</p>
    88 		</p>
    89 		
    89 		
    90 		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
    90 		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
    91 	| relpipe-tr-guile --relation 'fstab' --where '(string= $type "btrfs")' \
    91 	| relpipe-tr-scheme --relation 'fstab' --where '(string= $type "btrfs")' \
    92 	| relpipe-out-tabular]]></m:pre>
    92 	| relpipe-out-tabular]]></m:pre>
    93 	
    93 	
    94 		<p>The Btrfs filesystems in our <code>fstab</code>:</p>
    94 		<p>The Btrfs filesystems in our <code>fstab</code>:</p>
    95 
    95 
    96 		<m:pre jazyk="text"><![CDATA[fstab:
    96 		<m:pre jazyk="text"><![CDATA[fstab:
   104 		<p>
   104 		<p>
   105 			There is also <code>string-prefix?</code> which evaluates whether the first string is a prefix of the second string:
   105 			There is also <code>string-prefix?</code> which evaluates whether the first string is a prefix of the second string:
   106 		</p>
   106 		</p>
   107 
   107 
   108 		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
   108 		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
   109 	| relpipe-tr-guile --relation 'fstab' --where '(string-prefix? "/mnt" $mount_point)' \
   109 	| relpipe-tr-scheme --relation 'fstab' --where '(string-prefix? "/mnt" $mount_point)' \
   110 	| relpipe-out-tabular]]></m:pre>
   110 	| relpipe-out-tabular]]></m:pre>
   111 		
   111 		
   112 		<p>So we can find filesystems mounted somewhere under <code>/mnt</code>:</p>
   112 		<p>So we can find filesystems mounted somewhere under <code>/mnt</code>:</p>
   113 
   113 
   114 		<m:pre jazyk="bash"><![CDATA[fstab:
   114 		<m:pre jazyk="bash"><![CDATA[fstab:
   128 
   128 
   129 		<h2>AND and OR</h2>
   129 		<h2>AND and OR</h2>
   130 		
   130 		
   131 		<p>
   131 		<p>
   132 			Like in SQL, we can join multiple conditions together with logical operators AND and OR.
   132 			Like in SQL, we can join multiple conditions together with logical operators AND and OR.
   133 			In Guile/Scheme these operators are also functions – they are written in the same <code>(</code>fashion<code>)</code>.
   133 			In Scheme these operators are also functions – they are written in the same <code>(</code>fashion<code>)</code>.
   134 		</p>
   134 		</p>
   135 		
   135 		
   136 		<p>
   136 		<p>
   137 			So we can e.g. look for icons that are „satanistic“ or „Orwellian“:
   137 			So we can e.g. look for icons that are „satanistic“ or „Orwellian“:
   138 		</p>
   138 		</p>
   139 		
   139 		
   140 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
   140 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
   141 	| relpipe-in-filesystem --file path --file size \
   141 	| relpipe-in-filesystem --file path --file size \
   142 	| relpipe-tr-guile --relation 'files.*' --where '(or (= $size 666) (= $size 1984) )' \
   142 	| relpipe-tr-scheme --relation 'files.*' --where '(or (= $size 666) (= $size 1984) )' \
   143 	| relpipe-out-tabular]]></m:pre>
   143 	| relpipe-out-tabular]]></m:pre>
   144 	
   144 	
   145 		<p>Files with sizes 666 bytes or 1984 bytes:</p>
   145 		<p>Files with sizes 666 bytes or 1984 bytes:</p>
   146 
   146 
   147 		<m:pre jazyk="text"><![CDATA[filesystem:
   147 		<m:pre jazyk="text"><![CDATA[filesystem:
   170 
   170 
   171 		<p>Or we can look for icons that are in SVG format and (at the same time) Orwellian:</p>
   171 		<p>Or we can look for icons that are in SVG format and (at the same time) Orwellian:</p>
   172 		
   172 		
   173 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
   173 		<m:pre jazyk="bash"><![CDATA[find /usr/share/icons/ -type f -print0 \
   174 	| relpipe-in-filesystem --file path --file size \
   174 	| relpipe-in-filesystem --file path --file size \
   175 	| relpipe-tr-guile \
   175 	| relpipe-tr-scheme \
   176 		--relation 'files.*' \
   176 		--relation 'files.*' \
   177 		--where '(and (string-suffix? ".svg" $path) (= $size 1984) )' \
   177 		--where '(and (string-suffix? ".svg" $path) (= $size 1984) )' \
   178 	| relpipe-out-tabular]]></m:pre>
   178 	| relpipe-out-tabular]]></m:pre>
   179 	
   179 	
   180 		<p>Which is quite rare and we have only two such icons:</p>
   180 		<p>Which is quite rare and we have only two such icons:</p>